From 99450317d83f7b77ab192aed7071432785337789 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Fri, 27 Mar 2026 15:21:44 -0700 Subject: [PATCH 001/137] feat(firebaseai): deprecate imagen (#18148) * deprecate imagen * remove the imagen utils file --- .../firebase_ai/example/lib/main.dart | 42 +- .../example/lib/pages/imagen_page.dart | 544 ------------------ .../lib/pages/server_template_page.dart | 67 --- .../example/lib/utils/image_utils.dart | 150 ----- .../lib/src/imagen/imagen_api.dart | 30 + .../lib/src/imagen/imagen_content.dart | 5 + .../lib/src/imagen/imagen_edit.dart | 55 ++ .../lib/src/imagen/imagen_model.dart | 5 + .../lib/src/imagen/imagen_reference.dart | 50 ++ .../template_imagen_model.dart | 5 + 10 files changed, 155 insertions(+), 798 deletions(-) delete mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/imagen_page.dart delete mode 100644 packages/firebase_ai/firebase_ai/example/lib/utils/image_utils.dart diff --git a/packages/firebase_ai/firebase_ai/example/lib/main.dart b/packages/firebase_ai/firebase_ai/example/lib/main.dart index 133f2c6ec257..69f37490f6ba 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/main.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/main.dart @@ -26,7 +26,6 @@ import 'pages/chat_page.dart'; import 'pages/document.dart'; import 'pages/function_calling_page.dart'; import 'pages/image_prompt_page.dart'; -import 'pages/imagen_page.dart'; import 'pages/json_schema_page.dart'; import 'pages/schema_page.dart'; import 'pages/token_count_page.dart'; @@ -53,7 +52,6 @@ class GenerativeAISample extends StatefulWidget { class _GenerativeAISampleState extends State { bool _useVertexBackend = false; late GenerativeModel _currentModel; - late ImagenModel _currentImagenModel; static final ThemeData _darkTheme = ThemeData( colorScheme: ColorScheme.fromSeed( @@ -74,30 +72,12 @@ class _GenerativeAISampleState extends State { if (useVertexBackend) { final vertexInstance = FirebaseAI.vertexAI(auth: FirebaseAuth.instance); _currentModel = vertexInstance.generativeModel(model: 'gemini-2.5-flash'); - _currentImagenModel = _initializeImagenModel(vertexInstance); } else { final googleAI = FirebaseAI.googleAI(auth: FirebaseAuth.instance); _currentModel = googleAI.generativeModel(model: 'gemini-2.5-flash'); - _currentImagenModel = _initializeImagenModel(googleAI); } } - ImagenModel _initializeImagenModel(FirebaseAI instance) { - var generationConfig = ImagenGenerationConfig( - numberOfImages: 1, - aspectRatio: ImagenAspectRatio.square1x1, - imageFormat: ImagenFormat.jpeg(compressionQuality: 75), - ); - return instance.imagenModel( - model: 'imagen-3.0-capability-001', - generationConfig: generationConfig, - safetySettings: ImagenSafetySettings( - ImagenSafetyFilterLevel.blockLowAndAbove, - ImagenPersonFilterLevel.allowAdult, - ), - ); - } - void _toggleBackend(bool value) { setState(() { _useVertexBackend = value; @@ -117,7 +97,6 @@ class _GenerativeAISampleState extends State { '${_useVertexBackend}_${_currentModel.hashCode}', ), model: _currentModel, - imagenModel: _currentImagenModel, useVertexBackend: _useVertexBackend, onBackendChanged: _toggleBackend, ), @@ -127,14 +106,12 @@ class _GenerativeAISampleState extends State { class HomeScreen extends StatefulWidget { final GenerativeModel model; - final ImagenModel imagenModel; final bool useVertexBackend; final ValueChanged onBackendChanged; const HomeScreen({ super.key, required this.model, - required this.imagenModel, required this.useVertexBackend, required this.onBackendChanged, }); @@ -156,7 +133,6 @@ class _HomeScreenState extends State { Widget _buildSelectedPage( int index, GenerativeModel currentModel, - ImagenModel currentImagenModel, bool useVertexBackend, ) { switch (index) { @@ -178,22 +154,20 @@ class _HomeScreenState extends State { case 4: return ImagePromptPage(title: 'Image Prompt', model: currentModel); case 5: - return ImagenPage(title: 'Imagen Model', model: currentImagenModel); - case 6: return SchemaPromptPage(title: 'Schema Prompt', model: currentModel); - case 7: + case 6: return JsonSchemaPage(title: 'JSON Schema', model: currentModel); - case 8: + case 7: return DocumentPage(title: 'Document Prompt', model: currentModel); - case 9: + case 8: return VideoPage(title: 'Video Prompt', model: currentModel); - case 10: + case 9: return BidiPage( title: 'Live Stream', model: currentModel, useVertexBackend: useVertexBackend, ); - case 11: + case 10: return ServerTemplatePage( title: 'Server Template', useVertexBackend: useVertexBackend, @@ -259,7 +233,6 @@ class _HomeScreenState extends State { child: _buildSelectedPage( _selectedIndex, widget.model, - widget.imagenModel, widget.useVertexBackend, ), ), @@ -297,11 +270,6 @@ class _HomeScreenState extends State { label: 'Image', tooltip: 'Image Prompt', ), - BottomNavigationBarItem( - icon: Icon(Icons.image_search), - label: 'Imagen', - tooltip: 'Imagen Model', - ), BottomNavigationBarItem( icon: Icon(Icons.schema), label: 'Schema', diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/imagen_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/imagen_page.dart deleted file mode 100644 index 390279c1ffd2..000000000000 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/imagen_page.dart +++ /dev/null @@ -1,544 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:typed_data'; - -import 'package:image_picker/image_picker.dart'; -import 'package:firebase_ai/firebase_ai.dart'; - -import 'package:flutter/material.dart'; -//import 'package:firebase_storage/firebase_storage.dart'; -import '../widgets/message_widget.dart'; -import '../utils/image_utils.dart'; - -class ImagenPage extends StatefulWidget { - const ImagenPage({ - super.key, - required this.title, - required this.model, - }); - - final String title; - final ImagenModel model; - - @override - State createState() => _ImagenPageState(); -} - -class _ImagenPageState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textController = TextEditingController(); - final FocusNode _textFieldFocus = FocusNode(); - final List _generatedContent = []; - bool _loading = false; - - // For image picking - ImagenInlineImage? _sourceImage; - ImagenInlineImage? _maskImageForEditing; - - void _scrollDown() { - WidgetsBinding.instance.addPostFrameCallback( - (_) => _scrollController.animateTo( - _scrollController.position.maxScrollExtent, - duration: const Duration( - milliseconds: 750, - ), - curve: Curves.easeOutCirc, - ), - ); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _generatedContent[idx].text, - image: Image.memory( - _generatedContent[idx].imageBytes!, - cacheWidth: 400, - cacheHeight: 400, - ), - isFromUser: _generatedContent[idx].fromUser ?? false, - ); - }, - itemCount: _generatedContent.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Column( - children: [ - // Generate Image Row - Row( - children: [ - Expanded( - child: TextField( - autofocus: true, - focusNode: _textFieldFocus, - decoration: const InputDecoration( - hintText: 'Enter a prompt...', - ), - controller: _textController, - ), - ), - const SizedBox.square(dimension: 15), - IconButton( - onPressed: () async { - await _pickSourceImage(); - }, - icon: Icon( - Icons.add_a_photo, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Pick Source Image', - ), - IconButton( - onPressed: () async { - await _pickMaskImage(); - }, - icon: Icon( - Icons.add_to_photos, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Pick mask', - ), - IconButton( - onPressed: () async { - await _editWithMask(); - }, - icon: Icon( - Icons.brush, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Edit with Mask', - ), - IconButton( - onPressed: () async { - await _editWithStyle(); - }, - icon: Icon( - Icons.edit, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Edit with Style', - ), - IconButton( - onPressed: () async { - await _outpaintImage(); - }, - icon: Icon( - Icons.masks, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Outpaint', - ), - IconButton( - onPressed: () async { - await _inpaintImageHappyPath(); - }, - icon: Icon( - Icons.plus_one, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Inpaint', - ), - if (!_loading) - IconButton( - onPressed: () async { - await _generateImageFromPrompt( - _textController.text, - ); - }, - icon: Icon( - Icons.image_search, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Generate Image', - ) - else - const CircularProgressIndicator(), - ], - ), - ], - ), - ), - ], - ), - ), - ); - } - - Future _pickImage() async { - final ImagePicker picker = ImagePicker(); - try { - final XFile? imageFile = - await picker.pickImage(source: ImageSource.gallery); - if (imageFile != null) { - // Attempt to get mimeType, default if null. - // Note: imageFile.mimeType might be null on some platforms or for some files. - final String mimeType = imageFile.mimeType ?? 'image/jpeg'; - final Uint8List imageBytes = await imageFile.readAsBytes(); - return ImagenInlineImage( - bytesBase64Encoded: imageBytes, - mimeType: mimeType, - ); - } - } catch (e) { - _showError('Error picking image: $e'); - } - return null; - } - - Future _pickSourceImage() async { - final pickedImage = await _pickImage(); - if (pickedImage != null) { - setState(() { - _sourceImage = pickedImage; - }); - } - } - - Future _pickMaskImage() async { - final pickedImage = await _pickImage(); - if (pickedImage != null) { - setState(() { - _maskImageForEditing = pickedImage; - }); - } - } - - Future _inpaintImageHappyPath() async { - if (_sourceImage == null) { - _showError('Please pick a source image for inpaint insertion.'); - return; - } - setState(() { - _loading = true; - }); - - final String prompt = _textController.text; - final promptMessage = MessageData( - imageBytes: _sourceImage!.bytesBase64Encoded, - text: 'Try to inpaint image with prompt: $prompt', - fromUser: true, - ); - - MessageData? resultMessage; - - try { - // ignore: experimental_member_use - final response = await widget.model.inpaintImage( - _sourceImage!, - prompt, - // ignore: experimental_member_use - ImagenBackgroundMask(), - // ignore: experimental_member_use - config: ImagenEditingConfig(editMode: ImagenEditMode.inpaintInsertion), - ); - if (response.images.isNotEmpty) { - final inpaintImage = response.images[0]; - resultMessage = MessageData( - imageBytes: inpaintImage.bytesBase64Encoded, - text: 'Inpaint image result with prompt: $prompt', - fromUser: false, - ); - } else { - _showError('No image was returned from inpaint.'); - } - } catch (e) { - _showError('Error inpaint image: $e'); - } - - setState(() { - _generatedContent.add(promptMessage); - if (resultMessage != null) { - _generatedContent.add(resultMessage); - } - _loading = false; - _scrollDown(); - }); - } - - Future _editWithMask() async { - if (_sourceImage == null) { - _showError('Please pick a source image for editing.'); - return; - } - if (_maskImageForEditing == null) { - _showError('Please pick a mask image for editing.'); - return; - } - - setState(() { - _loading = true; - }); - - final String prompt = _textController.text; - // Create a message to show what we are doing - final promptMessage = MessageData( - imageBytes: _sourceImage!.bytesBase64Encoded, - text: 'Editing image with mask and prompt: $prompt', - fromUser: true, - ); - - MessageData? resultMessage; - - try { - // ignore: experimental_member_use - final response = await widget.model.editImage( - [ - // ignore: experimental_member_use - ImagenRawImage(image: _sourceImage!), - // ignore: experimental_member_use - ImagenRawMask(mask: _maskImageForEditing!), - ], - prompt, - ); - - if (response.images.isNotEmpty) { - final editedImage = response.images[0]; - resultMessage = MessageData( - imageBytes: editedImage.bytesBase64Encoded, - text: 'Edited image result with prompt: $prompt', - fromUser: false, - ); - } else { - _showError('No image was returned from editing with mask.'); - } - } catch (e) { - _showError('Error editing image with mask: $e'); - } - - setState(() { - _generatedContent.add(promptMessage); - if (resultMessage != null) { - _generatedContent.add(resultMessage); - } - _loading = false; - _scrollDown(); - }); - } - - Future _outpaintImage() async { - if (_sourceImage == null) { - _showError('Please pick a source image for outpainting.'); - return; - } - setState(() { - _loading = true; - }); - - final promptMessage = MessageData( - imageBytes: _sourceImage!.bytesBase64Encoded, - text: 'Outpaint the picture to 1400*1400', - fromUser: true, - ); - - MessageData? resultMessage; - try { - final referenceImages = await generateMaskAndPadForOutpainting( - image: _sourceImage!, - // ignore: experimental_member_use - newDimensions: ImagenDimensions(width: 1400, height: 1400), - ); - // ignore: experimental_member_use - final response = await widget.model.editImage( - referenceImages, - '', - // ignore: experimental_member_use - config: ImagenEditingConfig(editMode: ImagenEditMode.outpaint), - ); - if (response.images.isNotEmpty) { - final editedImage = response.images[0]; - resultMessage = MessageData( - imageBytes: editedImage.bytesBase64Encoded, - text: 'Edited image Outpaint 1400*1400', - fromUser: false, - ); - } else { - _showError('No image was returned from editing.'); - } - } catch (e) { - _showError('Error editing image: $e'); - } - - setState(() { - _generatedContent.add(promptMessage); - if (resultMessage != null) { - _generatedContent.add(resultMessage); - } - _loading = false; - _scrollDown(); - }); - } - - Future _editWithStyle() async { - if (_sourceImage == null) { - _showError('Please pick a source image for style editing.'); - return; - } - setState(() { - _loading = true; - }); - - final String prompt = _textController.text; - final promptMessage = MessageData( - imageBytes: _sourceImage!.bytesBase64Encoded, - text: prompt, - fromUser: true, - ); - MessageData? resultMessage; - try { - // ignore: experimental_member_use - final response = await widget.model.editImage( - [ - // ignore: experimental_member_use - ImagenStyleReference( - image: _sourceImage!, - description: 'van goh style', - referenceId: 1, - ), - ], - prompt, - // ignore: experimental_member_use - config: ImagenEditingConfig(editSteps: 50), - ); - if (response.images.isNotEmpty) { - final editedImage = response.images[0]; - - resultMessage = MessageData( - imageBytes: editedImage.bytesBase64Encoded, - text: 'Edited image with style: $prompt', - fromUser: false, - ); - } else { - _showError('No image was returned from style editing.'); - } - } catch (e) { - _showError('Error performing style edit: $e'); - } - - setState(() { - _generatedContent.add(promptMessage); - if (resultMessage != null) { - _generatedContent.add(resultMessage); - } - - _loading = false; - _scrollDown(); - }); - } - - Future _generateImageFromPrompt(String prompt) async { - setState(() { - _loading = true; - }); - MessageData? resultMessage; - try { - var response = await widget.model.generateImages(prompt); - - if (response.images.isNotEmpty) { - var imagenImage = response.images[0]; - - resultMessage = MessageData( - imageBytes: imagenImage.bytesBase64Encoded, - text: prompt, - fromUser: false, - ); - } else { - // Handle the case where no images were generated - _showError('Error: No images were generated.'); - } - } catch (e) { - _showError(e.toString()); - } - - setState(() { - if (resultMessage != null) { - _generatedContent.add(resultMessage); - } - - _loading = false; - _scrollDown(); - }); - } - // NOTE: Keep this API private until future release. - // Future _testImagenGCS(String prompt) async { - // setState(() { - // _loading = true; - // }); - // var gcsUrl = 'gs://vertex-ai-example-ef5a2.appspot.com/imagen'; - - // var response = await widget.model.generateImagesGCS(prompt, gcsUrl); - - // if (response.images.isNotEmpty) { - // var imagenImage = response.images[0]; - // final returnImageUri = imagenImage.gcsUri; - // final reference = FirebaseStorage.instance.refFromURL(returnImageUri); - // final downloadUrl = await reference.getDownloadURL(); - // // Process the image - // _generatedContent.add( - // MessageData( - // image: Image(image: NetworkImage(downloadUrl)), - // text: prompt, - // fromUser: false, - // ), - // ); - // } else { - // // Handle the case where no images were generated - // _showError('Error: No images were generated.'); - // } - // setState(() { - // _loading = false; - // }); - // } - - void _showError(String message) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), - actions: [ - TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: const Text('OK'), - ), - ], - ); - }, - ); - } -} diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart index 1be4e6d11ffe..10386f3e4d7b 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart @@ -40,8 +40,6 @@ class _ServerTemplatePageState extends State { // ignore: experimental_member_use TemplateGenerativeModel? _templateGenerativeModel; - // ignore: experimental_member_use - TemplateImagenModel? _templateImagenModel; @override void initState() { @@ -54,16 +52,10 @@ class _ServerTemplatePageState extends State { _templateGenerativeModel = // ignore: experimental_member_use FirebaseAI.vertexAI(location: 'global').templateGenerativeModel(); - _templateImagenModel = - // ignore: experimental_member_use - FirebaseAI.vertexAI(location: 'global').templateImagenModel(); } else { _templateGenerativeModel = // ignore: experimental_member_use FirebaseAI.googleAI().templateGenerativeModel(); - _templateImagenModel = - // ignore: experimental_member_use - FirebaseAI.googleAI().templateImagenModel(); } } @@ -130,16 +122,6 @@ class _ServerTemplatePageState extends State { dimension: 15, ), if (!_loading) ...[ - IconButton( - onPressed: () async { - await _serverTemplateImagen(_textController.text); - }, - icon: Icon( - Icons.image_search, - color: Theme.of(context).colorScheme.primary, - ), - tooltip: 'Imagen', - ), IconButton( onPressed: () async { await _serverTemplateImageInput(_textController.text); @@ -254,55 +236,6 @@ class _ServerTemplatePageState extends State { } } - Future _serverTemplateImagen(String message) async { - setState(() { - _loading = true; - }); - MessageData? resultMessage; - try { - _messages.add(MessageData(text: message, fromUser: true)); - // ignore: experimental_member_use - var response = await _templateImagenModel?.generateImages( - 'portrait-googleai', - inputs: { - 'animal': message, - }, - ); - - if (response!.images.isNotEmpty) { - var imagenImage = response.images[0]; - - resultMessage = MessageData( - imageBytes: imagenImage.bytesBase64Encoded, - text: message, - fromUser: false, - ); - } else { - // Handle the case where no images were generated - _showError('Error: No images were generated.'); - } - - setState(() { - if (resultMessage != null) { - _messages.add(resultMessage); - } - _loading = false; - _scrollDown(); - }); - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } - } - Future _serverTemplateImageInput(String message) async { setState(() { _loading = true; diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/image_utils.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/image_utils.dart deleted file mode 100644 index f297c9b25e66..000000000000 --- a/packages/firebase_ai/firebase_ai/example/lib/utils/image_utils.dart +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -import 'package:firebase_ai/firebase_ai.dart'; -import 'package:image/image.dart' as img; -import 'package:flutter/foundation.dart'; - -/// The parameters passed to the isolate -class _IsolateParams { - final Uint8List imageBytes; - // ignore: experimental_member_use - final ImagenDimensions newDimensions; - // ignore: experimental_member_use - final ImagenImagePlacement newPosition; - - _IsolateParams({ - required Uint8List imageBytes, - required this.newDimensions, - required this.newPosition, - }) : imageBytes = Uint8List.fromList(imageBytes); -} - -/// The results returned from the isolate -class _IsolateResult { - final Uint8List paddedImageBytes; - final Uint8List maskBytes; - - _IsolateResult({ - required this.paddedImageBytes, - required this.maskBytes, - }); -} - -/// Processes the image request. -/// -/// This is the top-level function that will run in the background isolate. -/// It uses the 'image' package for all manipulations. -Future<_IsolateResult> _generateMaskAndPadInIsolate( - _IsolateParams params, -) async { - // 1. Decode the original image - final originalImage = img.decodeImage(params.imageBytes); - if (originalImage == null) { - throw StateError('Failed to decode image in isolate.'); - } - // Validate dimensions - if (originalImage.width >= params.newDimensions.width || - originalImage.height >= params.newDimensions.height) { - throw ArgumentError( - 'New Dimensions must be strictly larger than original image dimensions.', - ); - } - // 2. Calculate the position - // ignore: experimental_member_use - final originalDimensions = ImagenDimensions( - width: originalImage.width, - height: originalImage.height, - ); - final normalizedPosition = params.newPosition.normalizeToDimensions( - originalDimensions, - params.newDimensions, - ); - final x = normalizedPosition.x ?? 0; - final y = normalizedPosition.y ?? 0; - // 3. Create the mask image - final mask = img.Image( - width: params.newDimensions.width, - height: params.newDimensions.height, - ); - // Fill with white and draw a black rectangle for the original image area - img.fill(mask, color: img.ColorRgb8(255, 255, 255)); - img.fillRect( - mask, - x1: x, - y1: y, - x2: x + originalImage.width, - y2: y + originalImage.height, - color: img.ColorRgb8(0, 0, 0), - ); - // 4. Create the padded image - final paddedImage = img.Image( - width: params.newDimensions.width, - height: params.newDimensions.height, - ); - // Fill with black and draw the original image on top - img.fill(paddedImage, color: img.ColorRgb8(0, 0, 0)); - img.compositeImage( - paddedImage, - originalImage, - dstX: x, - dstY: y, - ); - // 5. Encode both images to PNG format (which is lossless) - final maskBytes = img.encodePng(mask); - final paddedBytes = img.encodePng(paddedImage); - return _IsolateResult( - paddedImageBytes: Uint8List.fromList(paddedBytes), - maskBytes: Uint8List.fromList(maskBytes), - ); -} - -/// Generates a mask and pads the image for outpainting. -// ignore: experimental_member_use -Future> generateMaskAndPadForOutpainting({ - required ImagenInlineImage image, - // ignore: experimental_member_use - required ImagenDimensions newDimensions, - // ignore: experimental_member_use - ImagenImagePlacement newPosition = ImagenImagePlacement.center, -}) async { - // Prepare the parameters for the isolate - // Note: We are assuming `image` has a way to get its raw bytes, - // which seems to be the case from `bytesBase64Encoded` in your example. - // If not, you'd need to convert the `ui.Image` to bytes here first. - final params = _IsolateParams( - imageBytes: image.bytesBase64Encoded, // Assuming this is Uint8List - newDimensions: newDimensions, - newPosition: newPosition, - ); - // Execute the image processing in a separate isolate and wait for the result - final result = await compute(_generateMaskAndPadInIsolate, params); - - // Use the resulting bytes to create your final objects - return [ - // ignore: experimental_member_use - ImagenRawImage( - image: ImagenInlineImage( - bytesBase64Encoded: result.paddedImageBytes, - mimeType: 'image/png', // The isolate always returns PNG - ), - ), - // ignore: experimental_member_use - ImagenRawMask( - mask: ImagenInlineImage( - bytesBase64Encoded: result.maskBytes, - mimeType: 'image/png', // The isolate always returns PNG - ), - ), - ]; -} diff --git a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_api.dart b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_api.dart index 20810f86690e..8bf9ef018b9a 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_api.dart @@ -16,6 +16,11 @@ import 'dart:developer'; /// Specifies the level of safety filtering for image generation. /// /// If not specified, default will be "block_medium_and_above". +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) enum ImagenSafetyFilterLevel { /// Strongest filtering level, most strict blocking. blockLowAndAbove('block_low_and_above'), @@ -57,6 +62,11 @@ enum ImagenSafetyFilterLevel { /// Allow generation of people by the model. /// /// If not specified, the default value is "allow_adult". +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) enum ImagenPersonFilterLevel { /// Disallow the inclusion of people or faces in images. blockAll('dont_allow'), @@ -92,6 +102,11 @@ enum ImagenPersonFilterLevel { /// A class representing safety settings for image generation. /// /// It includes a safety filter level and a person filter level. +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenSafetySettings { // ignore: public_member_api_docs ImagenSafetySettings(this.safetyFilterLevel, this.personFilterLevel); @@ -114,6 +129,11 @@ final class ImagenSafetySettings { /// The aspect ratio for the image. /// /// The default value is "1:1". +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) enum ImagenAspectRatio { /// Square (1:1). square1x1('1:1'), @@ -155,6 +175,11 @@ enum ImagenAspectRatio { } /// Configuration options for image generation. +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenGenerationConfig { // ignore: public_member_api_docs ImagenGenerationConfig( @@ -195,6 +220,11 @@ final class ImagenGenerationConfig { } /// Represents the image format and compression quality. +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenFormat { // ignore: public_member_api_docs ImagenFormat(this.mimeType, this.compressionQuality); diff --git a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_content.dart b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_content.dart index ef8be1bb31f6..01af99045211 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_content.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_content.dart @@ -28,6 +28,11 @@ sealed class ImagenImage { } /// Represents an image stored as a base64-encoded string. +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenInlineImage implements ImagenImage { // ignore: public_member_api_docs ImagenInlineImage({ diff --git a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_edit.dart b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_edit.dart index 5cff20d08bdb..99c8c1064c6a 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_edit.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_edit.dart @@ -18,6 +18,11 @@ import 'package:meta/meta.dart'; /// The desired outcome of the image editing. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) enum ImagenEditMode { /// The result of the editing will be an insertion of the prompt in the masked /// region. @@ -37,6 +42,11 @@ enum ImagenEditMode { /// The type of the subject in the image. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) enum ImagenSubjectReferenceType { /// The subject is a person. person('SUBJECT_TYPE_PERSON'), @@ -56,6 +66,11 @@ enum ImagenSubjectReferenceType { /// The type of control image. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) enum ImagenControlType { /// Use edge detection to ensure the new image follow the same outlines. canny('CONTROL_TYPE_CANNY'), @@ -81,6 +96,11 @@ enum ImagenControlType { /// The mode of the mask. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) enum ImagenMaskMode { /// The mask is user provided. userProvided('MASK_MODE_USER_PROVIDED'), @@ -108,6 +128,11 @@ sealed class ImagenReferenceConfig { /// The configuration for the mask. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenMaskConfig extends ImagenReferenceConfig { // ignore: public_member_api_docs ImagenMaskConfig({ @@ -137,6 +162,11 @@ final class ImagenMaskConfig extends ImagenReferenceConfig { /// The configuration for the subject. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenSubjectConfig extends ImagenReferenceConfig { // ignore: public_member_api_docs ImagenSubjectConfig({ @@ -161,6 +191,11 @@ final class ImagenSubjectConfig extends ImagenReferenceConfig { /// The configuration for the style. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenStyleConfig extends ImagenReferenceConfig { // ignore: public_member_api_docs ImagenStyleConfig({ @@ -179,6 +214,11 @@ final class ImagenStyleConfig extends ImagenReferenceConfig { /// The configuration for the control. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenControlConfig extends ImagenReferenceConfig { // ignore: public_member_api_docs ImagenControlConfig({ @@ -214,6 +254,11 @@ final class ImagenControlConfig extends ImagenReferenceConfig { /// The configuration for image editing. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenEditingConfig { // ignore: public_member_api_docs ImagenEditingConfig({ @@ -230,6 +275,11 @@ final class ImagenEditingConfig { /// The dimensions of an image. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenDimensions { // ignore: public_member_api_docs ImagenDimensions({ @@ -246,6 +296,11 @@ final class ImagenDimensions { /// The placement of an image. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenImagePlacement { const ImagenImagePlacement._(this.x, this.y); diff --git a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_model.dart b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_model.dart index 54789dcfadcc..197ed5714866 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_model.dart @@ -24,6 +24,11 @@ part of '../base_model.dart'; /// > Warning: For Vertex AI in Firebase, image generation using Imagen 3 models /// is in Public Preview, which means that the feature is not subject to any SLA /// or deprecation policy and could change in backwards-incompatible ways. +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenModel extends BaseApiClientModel { ImagenModel._( {required FirebaseApp app, diff --git a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_reference.dart b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_reference.dart index c05785168424..f8cb307bb456 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_reference.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/imagen/imagen_reference.dart @@ -30,6 +30,11 @@ enum _ReferenceType { /// A reference image for image editing. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) sealed class ImagenReferenceImage { ImagenReferenceImage._({ this.referenceConfig, @@ -72,6 +77,11 @@ sealed class ImagenReferenceImage { /// A reference image that is a mask. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) sealed class ImagenMaskReference extends ImagenReferenceImage { // ignore: public_member_api_docs ImagenMaskReference({ @@ -86,6 +96,11 @@ sealed class ImagenMaskReference extends ImagenReferenceImage { /// A raw image. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenRawImage extends ImagenReferenceImage { // ignore: public_member_api_docs ImagenRawImage({ @@ -96,6 +111,11 @@ final class ImagenRawImage extends ImagenReferenceImage { /// A raw mask. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenRawMask extends ImagenMaskReference { // ignore: public_member_api_docs ImagenRawMask({ @@ -113,6 +133,11 @@ final class ImagenRawMask extends ImagenMaskReference { /// A semantic mask. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenSemanticMask extends ImagenMaskReference { // ignore: public_member_api_docs ImagenSemanticMask({ @@ -130,6 +155,11 @@ final class ImagenSemanticMask extends ImagenMaskReference { /// A background mask. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenBackgroundMask extends ImagenMaskReference { // ignore: public_member_api_docs ImagenBackgroundMask({ @@ -145,6 +175,11 @@ final class ImagenBackgroundMask extends ImagenMaskReference { /// A foreground mask. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenForegroundMask extends ImagenMaskReference { // ignore: public_member_api_docs ImagenForegroundMask({ @@ -160,6 +195,11 @@ final class ImagenForegroundMask extends ImagenMaskReference { /// A subject reference. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenSubjectReference extends ImagenReferenceImage { // ignore: public_member_api_docs ImagenSubjectReference({ @@ -179,6 +219,11 @@ final class ImagenSubjectReference extends ImagenReferenceImage { /// A style reference. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenStyleReference extends ImagenReferenceImage { // ignore: public_member_api_docs ImagenStyleReference({ @@ -196,6 +241,11 @@ final class ImagenStyleReference extends ImagenReferenceImage { /// A control reference. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class ImagenControlReference extends ImagenReferenceImage { // ignore: public_member_api_docs ImagenControlReference({ diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart index e27dd5eaaa9d..0bfe90caebdc 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart @@ -16,6 +16,11 @@ part of '../base_model.dart'; /// An image model that connects to a remote server template. @experimental +@Deprecated( + 'All Imagen models are deprecated and will shut down as early as June 2026. ' + 'As a replacement, you can migrate your apps to use Gemini Image models (the ' + '"Nano Banana" models)(https://firebase.google.com/docs/ai-logic/imagen-models-migration).', +) final class TemplateImagenModel extends BaseTemplateApiClientModel { TemplateImagenModel._testModel( {required FirebaseApp app, From ac207eb33dda4e9c3db919ec55dba26ae2488414 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Mon, 30 Mar 2026 00:45:57 -0700 Subject: [PATCH 002/137] chore(ci): Add flutter&Dart AI rules for Gemini Review bot, Gemini CLI and Antigravity (#18152) --- .agent/rules/flutter.md | 173 ++++++++++++++++++++++++++++++++++++++++ .gemini/styleguide.md | 80 +++++++++++++++++++ GEMINI.md | 173 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 426 insertions(+) create mode 100644 .agent/rules/flutter.md create mode 100644 .gemini/styleguide.md create mode 100644 GEMINI.md diff --git a/.agent/rules/flutter.md b/.agent/rules/flutter.md new file mode 100644 index 000000000000..2f36c8befc58 --- /dev/null +++ b/.agent/rules/flutter.md @@ -0,0 +1,173 @@ +# AI Rules for Flutter + +You are an expert Flutter and Dart developer. Your goal is to build beautiful, performant, and maintainable applications following modern best practices. + +## Interaction Guidelines +* **User Persona:** Assume the user is familiar with programming concepts but may be new to Dart. +* **Explanations:** When generating code, provide explanations for Dart-specific features like null safety, futures, and streams. +* **Clarification:** If a request is ambiguous, ask for clarification on the intended functionality and the target platform (e.g., command-line, web, server). +* **Dependencies:** When suggesting new dependencies from `pub.dev`, explain their benefits. Use `pub_dev_search` if available. +* **Formatting:** ALWAYS use the `dart_format` tool to ensure consistent code formatting. +* **Fixes:** Use the `dart_fix` tool to automatically fix many common errors. +* **Linting:** Use the Dart linter with `flutter_lints` to catch common issues. + +## Flutter Style Guide +* **SOLID Principles:** Apply SOLID principles throughout the codebase. +* **Concise and Declarative:** Write concise, modern, technical Dart code. Prefer functional and declarative patterns. +* **Composition over Inheritance:** Favor composition for building complex widgets and logic. +* **Immutability:** Prefer immutable data structures. Widgets (especially `StatelessWidget`) should be immutable. +* **State Management:** Separate ephemeral state and app state. Use a state management solution for app state. +* **Widgets are for UI:** Everything in Flutter's UI is a widget. Compose complex UIs from smaller, reusable widgets. + +## Package Management +* **Pub Tool:** Use `pub` or `flutter pub add`. +* **Dev Dependencies:** Use `flutter pub add dev:`. +* **Overrides:** Use `flutter pub add override::`. +* **Removal:** `dart pub remove `. + +## Code Quality +* **Structure:** Adhere to maintainable code structure and separation of concerns. +* **Naming:** Avoid abbreviations. Use `PascalCase` (classes), `camelCase` (members), `snake_case` (files). +* **Conciseness:** Functions should be short (<20 lines) and single-purpose. +* **Error Handling:** Anticipate and handle potential errors. Don't let code fail silently. +* **Logging:** Use `dart:developer` `log` instead of `print`. + +## Dart Best Practices +* **Effective Dart:** Follow official guidelines. +* **Async/Await:** Use `Future`, `async`, `await` for operations. Use `Stream` for events. +* **Null Safety:** Write sound null-safe code. Avoid `!` operator unless guaranteed. +* **Pattern Matching:** Use switch expressions and pattern matching. +* **Records:** Use records for multiple return values. +* **Exception Handling:** Use custom exceptions for specific situations. +* **Arrow Functions:** Use `=>` for one-line functions. + +## Flutter Best Practices +* **Immutability:** Widgets are immutable. Rebuild, don't mutate. +* **Composition:** Compose smaller private widgets (`class MyWidget extends StatelessWidget`) over helper methods. +* **Lists:** Use `ListView.builder` or `SliverList` for performance. +* **Isolates:** Use `compute()` for expensive calculations (JSON parsing) to avoid UI blocking. +* **Const:** Use `const` constructors everywhere possible to reduce rebuilds. +* **Build Methods:** Avoid expensive ops (network) in `build()`. + +## State Management +* **Native-First:** Prefer `ValueNotifier`, `ChangeNotifier`, `ListenableBuilder`. +* **Restrictions:** Do NOT use Riverpod, Bloc, or GetX unless explicitly requested. +* **ChangeNotifier:** For state that is more complex or shared across multiple widgets, use `ChangeNotifier`. +* **MVVM:** When a more robust solution is needed, structure the app using the Model-View-ViewModel (MVVM) pattern. +* **Dependency Injection:** Use simple manual constructor dependency injection to make a class's dependencies explicit in its API, and to manage dependencies between different layers of the application. + +```dart +// Simple Local State +final ValueNotifier _counter = ValueNotifier(0); +ValueListenableBuilder( + valueListenable: _counter, + builder: (context, value, child) => Text('Count: $value'), +); +``` + +## Routing (GoRouter) +Use `go_router` for all navigation needs (deep linking, web). Ensure users are redirected to login when unauthorized. + +```dart +final GoRouter _router = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (context, state) => const HomeScreen(), + routes: [ + GoRoute( + path: 'details/:id', + builder: (context, state) { + final String id = state.pathParameters['id']!; + return DetailScreen(id: id); + }, + ), + ], + ), + ], +); +MaterialApp.router(routerConfig: _router); +``` + +## Data Handling & Serialization +* **JSON:** Use `json_serializable` and `json_annotation`. +* **Naming:** Use `fieldRename: FieldRename.snake` for consistency. + +```dart +@JsonSerializable(fieldRename: FieldRename.snake) +class User { + final String firstName; + final String lastName; + User({required this.firstName, required this.lastName}); + factory User.fromJson(Map json) => _$UserFromJson(json); +} +``` + +## Visual Design & Theming (Material 3) +* **Visual Design:** Build beautiful and intuitive user interfaces that follow modern design guidelines. +* **Typography:** Stress and emphasize font sizes to ease understanding, e.g., hero text, section headlines. +* **Background:** Apply subtle noise texture to the main background to add a premium, tactile feel. +* **Shadows:** Multi-layered drop shadows create a strong sense of depth; cards have a soft, deep shadow to look "lifted." +* **Icons:** Incorporate icons to enhance the user’s understanding and the logical navigation of the app. +* **Interactive Elements:** Buttons, checkboxes, sliders, lists, charts, graphs, and other interactive elements have a shadow with elegant use of color to create a "glow" effect. +* **Centralized Theme:** Define a centralized `ThemeData` object to ensure a consistent application-wide style. +* **Light and Dark Themes:** Implement support for both light and dark themes using `theme` and `darkTheme`. +* **Color Scheme Generation:** Generate harmonious color palettes from a single color using `ColorScheme.fromSeed`. + +```dart +final ThemeData lightTheme = ThemeData( + colorScheme: ColorScheme.fromSeed( + seedColor: Colors.deepPurple, + brightness: Brightness.light, + ), + textTheme: GoogleFonts.outfitTextTheme(), +); +``` + +## Layout Best Practices +* **Expanded:** Use to make a child widget fill the remaining available space along the main axis. +* **Flexible:** Use when you want a widget to shrink to fit, but not necessarily grow. Don't combine `Flexible` and `Expanded` in the same `Row` or `Column`. +* **Wrap:** Use when you have a series of widgets that would overflow a `Row` or `Column`, and you want them to move to the next line. +* **SingleChildScrollView:** Use when your content is intrinsically larger than the viewport, but is a fixed size. +* **ListView / GridView:** For long lists or grids of content, always use a builder constructor (`.builder`). +* **FittedBox:** Use to scale or fit a single child widget within its parent. +* **LayoutBuilder:** Use for complex, responsive layouts to make decisions based on the available space. +* **Positioned:** Use to precisely place a child within a `Stack` by anchoring it to the edges. +* **OverlayPortal:** Use to show UI elements (like custom dropdowns or tooltips) "on top" of everything else. + +```dart +// Network Image with Error Handler +Image.network( + 'https://example.com/img.png', + errorBuilder: (ctx, err, stack) => const Icon(Icons.error), + loadingBuilder: (ctx, child, prog) => prog == null ? child : const CircularProgressIndicator(), +); +``` + +## Documentation Philosophy +* **Comment wisely:** Use comments to explain why the code is written a certain way, not what the code does. The code itself should be self-explanatory. +* **Document for the user:** Write documentation with the reader in mind. If you had a question and found the answer, add it to the documentation where you first looked. +* **No useless documentation:** If the documentation only restates the obvious from the code's name, it's not helpful. +* **Consistency is key:** Use consistent terminology throughout your documentation. +* **Use `///` for doc comments:** This allows documentation generation tools to pick them up. +* **Start with a single-sentence summary:** The first sentence should be a concise, user-centric summary ending with a period. +* **Avoid redundancy:** Don't repeat information that's obvious from the code's context, like the class name or signature. +* **Public APIs are a priority:** Always document public APIs. + +## Accessibility +* **Contrast:** Ensure text has a contrast ratio of at least **4.5:1** against its background. +* **Dynamic Text Scaling:** Test your UI to ensure it remains usable when users increase the system font size. +* **Semantic Labels:** Use the `Semantics` widget to provide clear, descriptive labels for UI elements. +* **Screen Reader Testing:** Regularly test your app with TalkBack (Android) and VoiceOver (iOS). + +## Analysis Options +Strictly follow `flutter_lints`. + +```yaml +include: package:flutter_lints/flutter.yaml +linter: + rules: + avoid_print: true + prefer_single_quotes: true + always_use_package_imports: true +``` diff --git a/.gemini/styleguide.md b/.gemini/styleguide.md new file mode 100644 index 000000000000..fda88ab0528b --- /dev/null +++ b/.gemini/styleguide.md @@ -0,0 +1,80 @@ +# AI Rules for Flutter + +## Persona & Tools +* **Role:** Expert Flutter Developer. Focus: Beautiful, performant, maintainable code. +* **Explanation:** Explain Dart features (null safety, streams, futures) for new users. +* **Tools:** ALWAYS run `dart_format`. Use `dart_fix` for cleanups. Use `analyze_files` with `flutter_lints` to catch errors early. +* **Dependencies:** Add with `flutter pub add`. Use `pub_dev_search` for discovery. Explain why a package is needed. + +## Architecture & Structure +* **Entry:** Standard `lib/main.dart`. +* **Layers:** Presentation (Widgets), Domain (Logic), Data (Repo/API). +* **Features:** Group by feature (e.g., `lib/features/login/`) for scalable apps. +* **SOLID:** Strictly enforced. +* **State Management:** + * **Pattern:** Separate UI state (ephemeral) from App state. + * **Native First:** Use `ValueNotifier`, `ChangeNotifier`. + * **Prohibited:** NO Riverpod, Bloc, GetX unless explicitly requested. + * **DI:** Manual constructor injection or `provider` package if requested. + +## Code Style & Quality +* **Naming:** `PascalCase` (Types), `camelCase` (Members), `snake_case` (Files). +* **Conciseness:** Functions <20 lines. Avoid verbosity. +* **Null Safety:** NO `!` operator. Use `?` and flow analysis (e.g. `if (x != null)`). +* **Async:** Use `async/await` for Futures. Catch all errors with `try-catch`. +* **Logging:** Use `dart:developer` `log()` locally. NEVER use `print`. + +## Flutter Best Practices +* **Build Methods:** Keep pure and fast. No side effects. No network calls. +* **Isolates:** Use `compute()` for heavy tasks like JSON parsing. +* **Lists:** `ListView.builder` or `SliverList` for performance. +* **Immutability:** `const` constructors everywhere validation. `StatelessWidget` preference. +* **Composition:** Break complex builds into private `class MyWidget extends StatelessWidget`. + +## Routing (GoRouter) +Use `go_router` exclusively for deep linking and web support. + +```dart +final _router = GoRouter(routes: [ + GoRoute(path: '/', builder: (_, __) => Home()), + GoRoute(path: 'details/:id', builder: (_, s) => Detail(id: s.pathParameters['id']!)), +]); +MaterialApp.router(routerConfig: _router); +``` + +## Data (JSON) +Use `json_serializable` with `fieldRename: FieldRename.snake`. + +```dart +@JsonSerializable(fieldRename: FieldRename.snake) +class User { + final String name; + User({required this.name}); + factory User.fromJson(Map json) => _$UserFromJson(json); +} +``` + +## Visual Design (Material 3) +* **Aesthetics:** Premium, custom look. "Wow" the user. Avoid default blue. +* **Theme:** Use `ThemeData` with `ColorScheme.fromSeed`. +* **Modes:** Support Light & Dark modes (`ThemeMode.system`). +* **Typography:** `google_fonts`. Define a consistent Type Scale. +* **Layout:** `LayoutBuilder` for responsiveness. `OverlayPortal` for popups. +* **Components:** Use `ThemeExtension` for custom tokens (colors/sizes). + +## Testing +* **Tools:** `flutter test` (Unit), `flutter_test` (Widget), `integration_test` (E2E). +* **Mocks:** Prefer Fakes. Use `mockito` sparingly. +* **Pattern:** Arrange-Act-Assert. +* **Assertions:** Use `package:checks`. + +## Accessibility (A11Y) +* **Contrast:** 4.5:1 minimum for text. +* **Semantics:** Label all interactive elements specifically. +* **Scale:** Test dynamic font sizes (up to 200%). +* **Screen Readers:** Verify with TalkBack/VoiceOver. + +## Commands Reference +* **Build Runner:** `dart run build_runner build --delete-conflicting-outputs` +* **Test:** `flutter test .` +* **Analyze:** `flutter analyze .` diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 000000000000..2f36c8befc58 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,173 @@ +# AI Rules for Flutter + +You are an expert Flutter and Dart developer. Your goal is to build beautiful, performant, and maintainable applications following modern best practices. + +## Interaction Guidelines +* **User Persona:** Assume the user is familiar with programming concepts but may be new to Dart. +* **Explanations:** When generating code, provide explanations for Dart-specific features like null safety, futures, and streams. +* **Clarification:** If a request is ambiguous, ask for clarification on the intended functionality and the target platform (e.g., command-line, web, server). +* **Dependencies:** When suggesting new dependencies from `pub.dev`, explain their benefits. Use `pub_dev_search` if available. +* **Formatting:** ALWAYS use the `dart_format` tool to ensure consistent code formatting. +* **Fixes:** Use the `dart_fix` tool to automatically fix many common errors. +* **Linting:** Use the Dart linter with `flutter_lints` to catch common issues. + +## Flutter Style Guide +* **SOLID Principles:** Apply SOLID principles throughout the codebase. +* **Concise and Declarative:** Write concise, modern, technical Dart code. Prefer functional and declarative patterns. +* **Composition over Inheritance:** Favor composition for building complex widgets and logic. +* **Immutability:** Prefer immutable data structures. Widgets (especially `StatelessWidget`) should be immutable. +* **State Management:** Separate ephemeral state and app state. Use a state management solution for app state. +* **Widgets are for UI:** Everything in Flutter's UI is a widget. Compose complex UIs from smaller, reusable widgets. + +## Package Management +* **Pub Tool:** Use `pub` or `flutter pub add`. +* **Dev Dependencies:** Use `flutter pub add dev:`. +* **Overrides:** Use `flutter pub add override::`. +* **Removal:** `dart pub remove `. + +## Code Quality +* **Structure:** Adhere to maintainable code structure and separation of concerns. +* **Naming:** Avoid abbreviations. Use `PascalCase` (classes), `camelCase` (members), `snake_case` (files). +* **Conciseness:** Functions should be short (<20 lines) and single-purpose. +* **Error Handling:** Anticipate and handle potential errors. Don't let code fail silently. +* **Logging:** Use `dart:developer` `log` instead of `print`. + +## Dart Best Practices +* **Effective Dart:** Follow official guidelines. +* **Async/Await:** Use `Future`, `async`, `await` for operations. Use `Stream` for events. +* **Null Safety:** Write sound null-safe code. Avoid `!` operator unless guaranteed. +* **Pattern Matching:** Use switch expressions and pattern matching. +* **Records:** Use records for multiple return values. +* **Exception Handling:** Use custom exceptions for specific situations. +* **Arrow Functions:** Use `=>` for one-line functions. + +## Flutter Best Practices +* **Immutability:** Widgets are immutable. Rebuild, don't mutate. +* **Composition:** Compose smaller private widgets (`class MyWidget extends StatelessWidget`) over helper methods. +* **Lists:** Use `ListView.builder` or `SliverList` for performance. +* **Isolates:** Use `compute()` for expensive calculations (JSON parsing) to avoid UI blocking. +* **Const:** Use `const` constructors everywhere possible to reduce rebuilds. +* **Build Methods:** Avoid expensive ops (network) in `build()`. + +## State Management +* **Native-First:** Prefer `ValueNotifier`, `ChangeNotifier`, `ListenableBuilder`. +* **Restrictions:** Do NOT use Riverpod, Bloc, or GetX unless explicitly requested. +* **ChangeNotifier:** For state that is more complex or shared across multiple widgets, use `ChangeNotifier`. +* **MVVM:** When a more robust solution is needed, structure the app using the Model-View-ViewModel (MVVM) pattern. +* **Dependency Injection:** Use simple manual constructor dependency injection to make a class's dependencies explicit in its API, and to manage dependencies between different layers of the application. + +```dart +// Simple Local State +final ValueNotifier _counter = ValueNotifier(0); +ValueListenableBuilder( + valueListenable: _counter, + builder: (context, value, child) => Text('Count: $value'), +); +``` + +## Routing (GoRouter) +Use `go_router` for all navigation needs (deep linking, web). Ensure users are redirected to login when unauthorized. + +```dart +final GoRouter _router = GoRouter( + routes: [ + GoRoute( + path: '/', + builder: (context, state) => const HomeScreen(), + routes: [ + GoRoute( + path: 'details/:id', + builder: (context, state) { + final String id = state.pathParameters['id']!; + return DetailScreen(id: id); + }, + ), + ], + ), + ], +); +MaterialApp.router(routerConfig: _router); +``` + +## Data Handling & Serialization +* **JSON:** Use `json_serializable` and `json_annotation`. +* **Naming:** Use `fieldRename: FieldRename.snake` for consistency. + +```dart +@JsonSerializable(fieldRename: FieldRename.snake) +class User { + final String firstName; + final String lastName; + User({required this.firstName, required this.lastName}); + factory User.fromJson(Map json) => _$UserFromJson(json); +} +``` + +## Visual Design & Theming (Material 3) +* **Visual Design:** Build beautiful and intuitive user interfaces that follow modern design guidelines. +* **Typography:** Stress and emphasize font sizes to ease understanding, e.g., hero text, section headlines. +* **Background:** Apply subtle noise texture to the main background to add a premium, tactile feel. +* **Shadows:** Multi-layered drop shadows create a strong sense of depth; cards have a soft, deep shadow to look "lifted." +* **Icons:** Incorporate icons to enhance the user’s understanding and the logical navigation of the app. +* **Interactive Elements:** Buttons, checkboxes, sliders, lists, charts, graphs, and other interactive elements have a shadow with elegant use of color to create a "glow" effect. +* **Centralized Theme:** Define a centralized `ThemeData` object to ensure a consistent application-wide style. +* **Light and Dark Themes:** Implement support for both light and dark themes using `theme` and `darkTheme`. +* **Color Scheme Generation:** Generate harmonious color palettes from a single color using `ColorScheme.fromSeed`. + +```dart +final ThemeData lightTheme = ThemeData( + colorScheme: ColorScheme.fromSeed( + seedColor: Colors.deepPurple, + brightness: Brightness.light, + ), + textTheme: GoogleFonts.outfitTextTheme(), +); +``` + +## Layout Best Practices +* **Expanded:** Use to make a child widget fill the remaining available space along the main axis. +* **Flexible:** Use when you want a widget to shrink to fit, but not necessarily grow. Don't combine `Flexible` and `Expanded` in the same `Row` or `Column`. +* **Wrap:** Use when you have a series of widgets that would overflow a `Row` or `Column`, and you want them to move to the next line. +* **SingleChildScrollView:** Use when your content is intrinsically larger than the viewport, but is a fixed size. +* **ListView / GridView:** For long lists or grids of content, always use a builder constructor (`.builder`). +* **FittedBox:** Use to scale or fit a single child widget within its parent. +* **LayoutBuilder:** Use for complex, responsive layouts to make decisions based on the available space. +* **Positioned:** Use to precisely place a child within a `Stack` by anchoring it to the edges. +* **OverlayPortal:** Use to show UI elements (like custom dropdowns or tooltips) "on top" of everything else. + +```dart +// Network Image with Error Handler +Image.network( + 'https://example.com/img.png', + errorBuilder: (ctx, err, stack) => const Icon(Icons.error), + loadingBuilder: (ctx, child, prog) => prog == null ? child : const CircularProgressIndicator(), +); +``` + +## Documentation Philosophy +* **Comment wisely:** Use comments to explain why the code is written a certain way, not what the code does. The code itself should be self-explanatory. +* **Document for the user:** Write documentation with the reader in mind. If you had a question and found the answer, add it to the documentation where you first looked. +* **No useless documentation:** If the documentation only restates the obvious from the code's name, it's not helpful. +* **Consistency is key:** Use consistent terminology throughout your documentation. +* **Use `///` for doc comments:** This allows documentation generation tools to pick them up. +* **Start with a single-sentence summary:** The first sentence should be a concise, user-centric summary ending with a period. +* **Avoid redundancy:** Don't repeat information that's obvious from the code's context, like the class name or signature. +* **Public APIs are a priority:** Always document public APIs. + +## Accessibility +* **Contrast:** Ensure text has a contrast ratio of at least **4.5:1** against its background. +* **Dynamic Text Scaling:** Test your UI to ensure it remains usable when users increase the system font size. +* **Semantic Labels:** Use the `Semantics` widget to provide clear, descriptive labels for UI elements. +* **Screen Reader Testing:** Regularly test your app with TalkBack (Android) and VoiceOver (iOS). + +## Analysis Options +Strictly follow `flutter_lints`. + +```yaml +include: package:flutter_lints/flutter.yaml +linter: + rules: + avoid_print: true + prefer_single_quotes: true + always_use_package_imports: true +``` From b03782beb81dcde1e8bbd3ff2afdc4cab185dd80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:46:20 +0200 Subject: [PATCH 003/137] chore(deps): bump node-forge in /.github/workflows/scripts/functions (#18154) Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.3.3 to 1.4.0. - [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md) - [Commits](https://github.com/digitalbazaar/forge/compare/v1.3.3...v1.4.0) --- updated-dependencies: - dependency-name: node-forge dependency-version: 1.4.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../workflows/scripts/functions/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index a8c5655fd5c3..97614fe2cddc 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -1728,9 +1728,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", - "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", "engines": { "node": ">= 6.13.0" } @@ -3778,9 +3778,9 @@ } }, "node-forge": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", - "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==" }, "object-assign": { "version": "4.1.1", From f503961ee86a0e2a7318ea816e1f86ec78fb607e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:53:58 +0200 Subject: [PATCH 004/137] chore(deps): bump path-to-regexp in /.github/workflows/scripts/functions (#18155) Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) from 0.1.12 to 0.1.13. - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/v.0.1.13/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.12...v.0.1.13) --- updated-dependencies: - dependency-name: path-to-regexp dependency-version: 0.1.13 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../workflows/scripts/functions/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index 97614fe2cddc..77dc0313db80 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -1822,9 +1822,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==" }, "node_modules/proto3-json-serializer": { "version": "2.0.2", @@ -3836,9 +3836,9 @@ "optional": true }, "path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==" }, "proto3-json-serializer": { "version": "2.0.2", From 81f30325fc926fe94b630e49f56b795c781a4cbe Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 30 Mar 2026 16:25:47 +0200 Subject: [PATCH 005/137] feat(app_check, windows): add support for AppCheck for Windows (#18140) * feat(app_check, windows): add support for AppCheck for Windows * format * fixes * fixes * fix * format * clean * clean * adding * windows example * format * fix * fix --- melos.yaml | 4 +- .../firebase_app_check/android/build.gradle | 23 +- .../FlutterFirebaseAppCheckPlugin.java | 280 ---------------- .../appcheck/FlutterFirebaseAppRegistrar.java | 42 --- .../appcheck/TokenChannelStreamHandler.java | 43 --- .../appcheck/FirebaseAppCheckPlugin.kt | 173 ++++++++++ .../appcheck/FlutterFirebaseAppRegistrar.kt | 38 +++ .../GeneratedAndroidFirebaseAppCheck.g.kt | 185 +++++++++++ .../appcheck/TokenChannelStreamHandler.kt | 30 ++ .../firebase_app_check/example/.metadata | 12 +- .../example/android/app/build.gradle | 2 +- .../ios/Flutter/AppFrameworkInfo.plist | 2 - .../firebase_app_check/example/ios/Podfile | 50 --- .../ios/Runner.xcodeproj/project.pbxproj | 2 + .../xcshareddata/xcschemes/Runner.xcscheme | 3 + .../example/lib/firebase_options.dart | 5 +- .../firebase_app_check/example/lib/main.dart | 160 +++++++-- .../firebase_app_check/example/macos/Podfile | 40 --- .../macos/Runner.xcodeproj/project.pbxproj | 41 --- .../example/windows/.gitignore | 17 + .../example/windows/CMakeLists.txt | 108 ++++++ .../example/windows/flutter/CMakeLists.txt | 109 +++++++ .../example/windows/runner/CMakeLists.txt | 40 +++ .../example/windows/runner/Runner.rc | 121 +++++++ .../example/windows/runner/flutter_window.cpp | 73 +++++ .../example/windows/runner/flutter_window.h | 37 +++ .../example/windows/runner/main.cpp | 46 +++ .../example/windows/runner/resource.h | 20 ++ .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../windows/runner/runner.exe.manifest | 14 + .../example/windows/runner/utils.cpp | 69 ++++ .../example/windows/runner/utils.h | 23 ++ .../example/windows/runner/win32_window.cpp | 284 ++++++++++++++++ .../example/windows/runner/win32_window.h | 104 ++++++ .../ios/firebase_app_check.podspec | 3 +- .../ios/firebase_app_check/Package.swift | 6 - .../firebase_app_check/Constants.swift | 6 + .../firebase_app_check/FLTAppCheckProvider.m | 60 ---- .../FLTAppCheckProviderFactory.m | 49 --- .../FLTFirebaseAppCheckPlugin.m | 217 ------------- .../FLTTokenRefreshStreamHandler.m | 35 -- .../FirebaseAppCheckMessages.g.swift | 233 +++++++++++++ .../FirebaseAppCheckPlugin.swift | 300 +++++++++++++++++ .../include/FLTAppCheckProvider.h | 19 -- .../include/FLTAppCheckProviderFactory.h | 14 - .../include/FLTFirebaseAppCheckPlugin.h | 21 -- .../include/FLTTokenRefreshStreamHandler.h | 20 -- .../lib/firebase_app_check.dart | 4 +- .../lib/src/firebase_app_check.dart | 9 + .../macos/firebase_app_check.podspec | 3 +- .../macos/firebase_app_check/Package.swift | 6 - .../firebase_app_check/Constants.swift | 1 + .../firebase_app_check/FLTAppCheckProvider.m | 1 - .../FLTAppCheckProviderFactory.m | 1 - .../FLTFirebaseAppCheckPlugin.m | 1 - .../FLTTokenRefreshStreamHandler.m | 1 - .../FirebaseAppCheckMessages.g.swift | 1 + .../FirebaseAppCheckPlugin.swift | 1 + .../include/FLTAppCheckProvider.h | 1 - .../include/FLTAppCheckProviderFactory.h | 1 - .../include/FLTFirebaseAppCheckPlugin.h | 1 - .../include/FLTTokenRefreshStreamHandler.h | 1 - .../firebase_app_check/pubspec.yaml | 8 +- .../test/firebase_app_check_test.dart | 85 ----- .../firebase_app_check/test/mock.dart | 18 - .../firebase_app_check/windows/CMakeLists.txt | 81 +++++ .../windows/firebase_app_check_plugin.cpp | 249 ++++++++++++++ .../windows/firebase_app_check_plugin.h | 72 ++++ .../firebase_app_check_plugin_c_api.cpp | 16 + .../firebase_app_check_plugin_c_api.h | 29 ++ .../firebase_app_check/windows/messages.g.cpp | 307 ++++++++++++++++++ .../firebase_app_check/windows/messages.g.h | 118 +++++++ .../windows/plugin_version.h.in | 13 + ...firebase_app_check_platform_interface.dart | 1 + .../method_channel_firebase_app_check.dart | 95 +++--- .../lib/src/pigeon/messages.pigeon.dart | 198 +++++++++++ ...platform_interface_firebase_app_check.dart | 8 + .../lib/src/windows_providers.dart | 44 +++ .../pigeons/copyright.txt | 3 + .../pigeons/messages.dart | 48 +++ .../pubspec.yaml | 1 + ...ethod_channel_firebase_app_check_test.dart | 114 +------ .../test/mock.dart | 19 -- .../lib/firebase_app_check_web.dart | 1 + .../firebase_app_check_web_test.mocks.dart | 2 + .../firebase_core/windows/CMakeLists.txt | 2 +- .../network/rest_transport_test.mocks.dart | 3 + scripts/generate_versions_spm.dart | 9 +- tests/integration_test/e2e_test.dart | 1 + .../flutter/generated_plugin_registrant.cc | 3 + tests/windows/flutter/generated_plugins.cmake | 1 + 91 files changed, 3464 insertions(+), 1301 deletions(-) delete mode 100644 packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java delete mode 100644 packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java delete mode 100644 packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.java create mode 100644 packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt create mode 100644 packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt create mode 100644 packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt create mode 100644 packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt delete mode 100644 packages/firebase_app_check/firebase_app_check/example/ios/Podfile delete mode 100644 packages/firebase_app_check/firebase_app_check/example/macos/Podfile create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/.gitignore create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/CMakeLists.txt create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/flutter/CMakeLists.txt create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/CMakeLists.txt create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/Runner.rc create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.cpp create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.h create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/main.cpp create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/resource.h create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/resources/app_icon.ico create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/runner.exe.manifest create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.cpp create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.h create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.cpp create mode 100644 packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.h create mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m create mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift create mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h delete mode 100644 packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h create mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Constants.swift delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m create mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift create mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h delete mode 120000 packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h create mode 100644 packages/firebase_app_check/firebase_app_check/windows/CMakeLists.txt create mode 100644 packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.cpp create mode 100644 packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.h create mode 100644 packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin_c_api.cpp create mode 100644 packages/firebase_app_check/firebase_app_check/windows/include/firebase_app_check/firebase_app_check_plugin_c_api.h create mode 100644 packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp create mode 100644 packages/firebase_app_check/firebase_app_check/windows/messages.g.h create mode 100644 packages/firebase_app_check/firebase_app_check/windows/plugin_version.h.in create mode 100644 packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart create mode 100644 packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/windows_providers.dart create mode 100644 packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/copyright.txt create mode 100644 packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart diff --git a/melos.yaml b/melos.yaml index 38eab295bfa1..2f403ee4d305 100644 --- a/melos.yaml +++ b/melos.yaml @@ -21,7 +21,9 @@ command: dart run scripts/generate_dataconnect_version.dart && \ dart run scripts/generate_versions_web.dart && \ dart run scripts/generate_versions_spm.dart && \ - git add packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart && git add packages/*/*_web/lib/src/*_version.dart && git add packages/*/*/ios/*/Package.swift packages/*/*/macos/*/Package.swift + git add packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart && git add packages/*/*_web/lib/src/*_version.dart && git add packages/*/*/ios/*/Package.swift packages/*/*/macos/*/Package.swift && git add packages/*/*/ios/*/Sources/*/Constants.swift + post: | + dart run scripts/generate_tag_spm_firebase_core.dart bootstrap: # It seems so that running "pub get" in parallel has some issues (like diff --git a/packages/firebase_app_check/firebase_app_check/android/build.gradle b/packages/firebase_app_check/firebase_app_check/android/build.gradle index 099e28aab3c1..45c2fa4d6345 100644 --- a/packages/firebase_app_check/firebase_app_check/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/android/build.gradle @@ -5,14 +5,11 @@ apply plugin: 'com.android.library' apply from: file("local-config.gradle") buildscript { + ext.kotlin_version = "1.8.22" repositories { google() mavenCentral() } - - dependencies { - classpath 'com.android.tools.build:gradle:8.3.0' - } } rootProject.allprojects { @@ -22,6 +19,12 @@ rootProject.allprojects { } } +// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int +if (agpMajor < 9) { + apply plugin: 'kotlin-android' +} + def firebaseCoreProject = findProject(':firebase_core') if (firebaseCoreProject == null) { throw new GradleException('Could not find the firebase_core FlutterFire plugin, have you added it as a dependency in your pubspec?') @@ -48,11 +51,22 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + if (agpMajor < 9) { + kotlinOptions { + jvmTarget = project.ext.javaVersion + } + } + compileOptions { sourceCompatibility project.ext.javaVersion targetCompatibility project.ext.javaVersion } + sourceSets { + main.java.srcDirs += "src/main/kotlin" + test.java.srcDirs += "src/test/kotlin" + } + buildFeatures { buildConfig true } @@ -67,7 +81,6 @@ android { implementation 'com.google.firebase:firebase-appcheck-debug' implementation 'com.google.firebase:firebase-appcheck-playintegrity' implementation 'androidx.annotation:annotation:1.7.0' - } } diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java b/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java deleted file mode 100644 index a41d916f2db8..000000000000 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppCheckPlugin.java +++ /dev/null @@ -1,280 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.plugins.firebase.appcheck; - -import static io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry.registerPlugin; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import com.google.android.gms.tasks.Task; -import com.google.android.gms.tasks.TaskCompletionSource; -import com.google.android.gms.tasks.Tasks; -import com.google.firebase.FirebaseApp; -import com.google.firebase.appcheck.AppCheckToken; -import com.google.firebase.appcheck.FirebaseAppCheck; -import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory; -import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory; -import io.flutter.embedding.engine.plugins.FlutterPlugin; -import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.EventChannel; -import io.flutter.plugin.common.MethodCall; -import io.flutter.plugin.common.MethodChannel; -import io.flutter.plugin.common.MethodChannel.MethodCallHandler; -import io.flutter.plugin.common.MethodChannel.Result; -import io.flutter.plugins.firebase.core.FlutterFirebasePlugin; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -public class FlutterFirebaseAppCheckPlugin - implements FlutterFirebasePlugin, FlutterPlugin, MethodCallHandler { - - private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_app_check"; - private final Map streamHandlers = new HashMap<>(); - - private final String debugProvider = "debug"; - private final String playIntegrity = "playIntegrity"; - - @Nullable private BinaryMessenger messenger; - - private MethodChannel channel; - - private void initInstance(BinaryMessenger messenger) { - registerPlugin(METHOD_CHANNEL_NAME, this); - channel = new MethodChannel(messenger, METHOD_CHANNEL_NAME); - channel.setMethodCallHandler(this); - - this.messenger = messenger; - } - - @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - initInstance(binding.getBinaryMessenger()); - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - channel.setMethodCallHandler(null); - channel = null; - messenger = null; - - removeEventListeners(); - } - - private FirebaseAppCheck getAppCheck(Map arguments) { - String appName = (String) Objects.requireNonNull(arguments.get("appName")); - FirebaseApp app = FirebaseApp.getInstance(appName); - return FirebaseAppCheck.getInstance(app); - } - - private Task getLimitedUseAppCheckToken(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - AppCheckToken tokenResult = Tasks.await(firebaseAppCheck.getLimitedUseAppCheckToken()); - taskCompletionSource.setResult(tokenResult.getToken()); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task activate(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - String provider = (String) Objects.requireNonNull(arguments.get("androidProvider")); - - switch (provider) { - case debugProvider: - { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - FlutterFirebaseAppRegistrar.debugToken = - (String) arguments.get("androidDebugToken"); - firebaseAppCheck.installAppCheckProviderFactory( - DebugAppCheckProviderFactory.getInstance()); - break; - } - case playIntegrity: - { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - firebaseAppCheck.installAppCheckProviderFactory( - PlayIntegrityAppCheckProviderFactory.getInstance()); - break; - } - } - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task getToken(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - Boolean forceRefresh = (Boolean) Objects.requireNonNull(arguments.get("forceRefresh")); - AppCheckToken tokenResult = - Tasks.await(firebaseAppCheck.getAppCheckToken(forceRefresh)); - - taskCompletionSource.setResult(tokenResult.getToken()); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task setTokenAutoRefreshEnabled(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - Boolean isTokenAutoRefreshEnabled = - (Boolean) Objects.requireNonNull(arguments.get("isTokenAutoRefreshEnabled")); - firebaseAppCheck.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); - - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private Task registerTokenListener(Map arguments) { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - String appName = (String) Objects.requireNonNull(arguments.get("appName")); - FirebaseAppCheck firebaseAppCheck = getAppCheck(arguments); - - final TokenChannelStreamHandler handler = - new TokenChannelStreamHandler(firebaseAppCheck); - final String name = METHOD_CHANNEL_NAME + "/token/" + appName; - final EventChannel channel = new EventChannel(messenger, name); - channel.setStreamHandler(handler); - streamHandlers.put(channel, handler); - - taskCompletionSource.setResult(name); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - @Override - public void onMethodCall(MethodCall call, @NonNull final Result result) { - Task methodCallTask; - - switch (call.method) { - case "FirebaseAppCheck#activate": - methodCallTask = activate(call.arguments()); - break; - case "FirebaseAppCheck#getToken": - methodCallTask = getToken(call.arguments()); - break; - case "FirebaseAppCheck#setTokenAutoRefreshEnabled": - methodCallTask = setTokenAutoRefreshEnabled(call.arguments()); - break; - case "FirebaseAppCheck#registerTokenListener": - methodCallTask = registerTokenListener(call.arguments()); - break; - case "FirebaseAppCheck#getLimitedUseAppCheckToken": - methodCallTask = getLimitedUseAppCheckToken(call.arguments()); - break; - default: - result.notImplemented(); - return; - } - - methodCallTask.addOnCompleteListener( - task -> { - if (task.isSuccessful()) { - result.success(task.getResult()); - } else { - Exception exception = task.getException(); - result.error( - "firebase_app_check", - exception != null ? exception.getMessage() : null, - getExceptionDetails(exception)); - } - }); - } - - private Map getExceptionDetails(@Nullable Exception exception) { - Map details = new HashMap<>(); - details.put("code", "unknown"); - if (exception != null) { - details.put("message", exception.getMessage()); - } else { - details.put("message", "An unknown error has occurred."); - } - return details; - } - - @Override - public Task> getPluginConstantsForFirebaseApp(FirebaseApp firebaseApp) { - TaskCompletionSource> taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - @Override - public Task didReinitializeFirebaseCore() { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource<>(); - - cachedThreadPool.execute( - () -> { - try { - taskCompletionSource.setResult(null); - } catch (Exception e) { - taskCompletionSource.setException(e); - } - }); - - return taskCompletionSource.getTask(); - } - - private void removeEventListeners() { - for (EventChannel eventChannel : streamHandlers.keySet()) { - EventChannel.StreamHandler streamHandler = streamHandlers.get(eventChannel); - assert streamHandler != null; - streamHandler.onCancel(null); - eventChannel.setStreamHandler(null); - } - streamHandlers.clear(); - } -} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java b/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java deleted file mode 100644 index 2355ec819c0c..000000000000 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.java +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package io.flutter.plugins.firebase.appcheck; - -import androidx.annotation.Keep; -import androidx.annotation.Nullable; -import com.google.firebase.appcheck.debug.InternalDebugSecretProvider; -import com.google.firebase.components.Component; -import com.google.firebase.components.ComponentRegistrar; -import com.google.firebase.platforminfo.LibraryVersionComponent; -import java.util.Arrays; -import java.util.List; - -@Keep -public class FlutterFirebaseAppRegistrar - implements ComponentRegistrar, InternalDebugSecretProvider { - - private static final String DEBUG_SECRET_NAME = "fire-app-check-debug-secret"; - public static String debugToken; - - @Override - public List> getComponents() { - Component library = - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION); - - Component debugSecretProvider = - Component.builder(InternalDebugSecretProvider.class) - .name(DEBUG_SECRET_NAME) - .factory(container -> this) - .build(); - - return Arrays.asList(library, debugSecretProvider); - } - - @Nullable - @Override - public String getDebugSecret() { - return debugToken; - } -} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.java b/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.java deleted file mode 100644 index 3f1367002c70..000000000000 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/java/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2022, the Chromium project authors. Please see the AUTHORS file - * for details. All rights reserved. Use of this source code is governed by a - * BSD-style license that can be found in the LICENSE file. - */ - -package io.flutter.plugins.firebase.appcheck; - -import com.google.firebase.appcheck.FirebaseAppCheck; -import io.flutter.plugin.common.EventChannel; -import java.util.HashMap; -import java.util.Map; - -public class TokenChannelStreamHandler implements EventChannel.StreamHandler { - - private final FirebaseAppCheck firebaseAppCheck; - private FirebaseAppCheck.AppCheckListener listener; - - public TokenChannelStreamHandler(FirebaseAppCheck firebaseAppCheck) { - this.firebaseAppCheck = firebaseAppCheck; - } - - @Override - public void onListen(Object arguments, EventChannel.EventSink events) { - - listener = - result -> { - Map event = new HashMap<>(); - event.put("token", result.getToken()); - events.success(event); - }; - - firebaseAppCheck.addAppCheckListener(listener); - } - - @Override - public void onCancel(Object arguments) { - if (listener != null) { - firebaseAppCheck.removeAppCheckListener(listener); - listener = null; - } - } -} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt new file mode 100644 index 000000000000..0dc0ce26dc7e --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt @@ -0,0 +1,173 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package io.flutter.plugins.firebase.appcheck + +import android.os.Handler +import android.os.Looper +import com.google.firebase.FirebaseApp +import com.google.firebase.appcheck.FirebaseAppCheck +import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory +import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.EventChannel.EventSink +import io.flutter.plugins.firebase.core.FlutterFirebasePlugin +import io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry +import com.google.android.gms.tasks.Task +import com.google.android.gms.tasks.TaskCompletionSource +import com.google.android.gms.tasks.Tasks + +class FirebaseAppCheckPlugin : + FlutterFirebasePlugin, FlutterPlugin, FirebaseAppCheckHostApi { + + private val streamHandlers: MutableMap = HashMap() + private val eventChannels: MutableMap = HashMap() + private val mainThreadHandler = Handler(Looper.getMainLooper()) + private var messenger: BinaryMessenger? = null + + companion object { + const val METHOD_CHANNEL = "plugins.flutter.io/firebase_app_check" + const val EVENT_CHANNEL_PREFIX = "plugins.flutter.io/firebase_app_check/token/" + } + + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + messenger = binding.binaryMessenger + FirebaseAppCheckHostApi.setUp(binding.binaryMessenger, this) + FlutterFirebasePluginRegistry.registerPlugin(METHOD_CHANNEL, this) + } + + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + FirebaseAppCheckHostApi.setUp(binding.binaryMessenger, null) + messenger = null + removeEventListeners() + } + + private fun getAppCheck(appName: String): FirebaseAppCheck { + val app = FirebaseApp.getInstance(appName) + return FirebaseAppCheck.getInstance(app) + } + + override fun activate( + appName: String, + androidProvider: String?, + appleProvider: String?, + debugToken: String?, + callback: (Result) -> Unit + ) { + try { + val firebaseAppCheck = getAppCheck(appName) + when (androidProvider) { + "debug" -> { + FlutterFirebaseAppRegistrar.debugToken = debugToken + firebaseAppCheck.installAppCheckProviderFactory( + DebugAppCheckProviderFactory.getInstance() + ) + } + else -> { + firebaseAppCheck.installAppCheckProviderFactory( + PlayIntegrityAppCheckProviderFactory.getInstance() + ) + } + } + callback(Result.success(Unit)) + } catch (e: Exception) { + callback(Result.failure(FlutterError("unknown", e.message, null))) + } + } + + override fun getToken( + appName: String, + forceRefresh: Boolean, + callback: (Result) -> Unit + ) { + val firebaseAppCheck = getAppCheck(appName) + firebaseAppCheck.getAppCheckToken(forceRefresh).addOnCompleteListener { task -> + if (task.isSuccessful) { + callback(Result.success(task.result?.token)) + } else { + callback(Result.failure( + FlutterError("firebase_app_check", task.exception?.message, null) + )) + } + } + } + + override fun setTokenAutoRefreshEnabled( + appName: String, + isTokenAutoRefreshEnabled: Boolean, + callback: (Result) -> Unit + ) { + try { + val firebaseAppCheck = getAppCheck(appName) + firebaseAppCheck.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled) + callback(Result.success(Unit)) + } catch (e: Exception) { + callback(Result.failure(FlutterError("unknown", e.message, null))) + } + } + + override fun registerTokenListener( + appName: String, + callback: (Result) -> Unit + ) { + try { + val firebaseAppCheck = getAppCheck(appName) + val name = EVENT_CHANNEL_PREFIX + appName + + val handler = TokenChannelStreamHandler(firebaseAppCheck) + val channel = EventChannel(messenger, name) + channel.setStreamHandler(handler) + eventChannels[name] = channel + streamHandlers[name] = handler + + callback(Result.success(name)) + } catch (e: Exception) { + callback(Result.failure(FlutterError("unknown", e.message, null))) + } + } + + override fun getLimitedUseAppCheckToken( + appName: String, + callback: (Result) -> Unit + ) { + val firebaseAppCheck = getAppCheck(appName) + firebaseAppCheck.limitedUseAppCheckToken.addOnCompleteListener { task -> + if (task.isSuccessful) { + callback(Result.success(task.result?.token ?: "")) + } else { + callback(Result.failure( + FlutterError("firebase_app_check", task.exception?.message, null) + )) + } + } + } + + override fun getPluginConstantsForFirebaseApp( + firebaseApp: FirebaseApp + ): Task> { + val taskCompletionSource = TaskCompletionSource>() + taskCompletionSource.setResult(HashMap()) + return taskCompletionSource.task + } + + override fun didReinitializeFirebaseCore(): Task { + val taskCompletionSource = TaskCompletionSource() + removeEventListeners() + taskCompletionSource.setResult(null) + return taskCompletionSource.task + } + + private fun removeEventListeners() { + for ((name, channel) in eventChannels) { + channel.setStreamHandler(null) + } + for ((name, handler) in streamHandlers) { + handler.onCancel(null) + } + eventChannels.clear() + streamHandlers.clear() + } +} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt new file mode 100644 index 000000000000..d7146eba3a7f --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt @@ -0,0 +1,38 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package io.flutter.plugins.firebase.appcheck + +import androidx.annotation.Keep +import com.google.firebase.appcheck.debug.InternalDebugSecretProvider +import com.google.firebase.components.Component +import com.google.firebase.components.ComponentRegistrar +import com.google.firebase.platforminfo.LibraryVersionComponent + +@Keep +class FlutterFirebaseAppRegistrar : ComponentRegistrar, InternalDebugSecretProvider { + + companion object { + private const val DEBUG_SECRET_NAME = "fire-app-check-debug-secret" + + @JvmStatic + var debugToken: String? = null + } + + override fun getComponents(): List> { + val library = LibraryVersionComponent.create( + BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION + ) + + val debugSecretProvider = Component.builder(InternalDebugSecretProvider::class.java) + .name(DEBUG_SECRET_NAME) + .factory { this } + .build() + + return listOf(library, debugSecretProvider) + } + + override fun getDebugSecret(): String? { + return debugToken + } +} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt new file mode 100644 index 000000000000..0a046dd5aa47 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt @@ -0,0 +1,185 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +package io.flutter.plugins.firebase.appcheck + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer +private object GeneratedAndroidFirebaseAppCheckPigeonUtils { + + fun wrapResult(result: Any?): List { + return listOf(result) + } + + fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() +private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return super.readValueOfType(type, buffer) + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + super.writeValue(stream, value) + } +} + + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface FirebaseAppCheckHostApi { + fun activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, callback: (Result) -> Unit) + fun getToken(appName: String, forceRefresh: Boolean, callback: (Result) -> Unit) + fun setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Boolean, callback: (Result) -> Unit) + fun registerTokenListener(appName: String, callback: (Result) -> Unit) + fun getLimitedUseAppCheckToken(appName: String, callback: (Result) -> Unit) + + companion object { + /** The codec used by FirebaseAppCheckHostApi. */ + val codec: MessageCodec by lazy { + GeneratedAndroidFirebaseAppCheckPigeonCodec() + } + /** Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binaryMessenger`. */ + @JvmOverloads + fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseAppCheckHostApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val appNameArg = args[0] as String + val androidProviderArg = args[1] as String? + val appleProviderArg = args[2] as String? + val debugTokenArg = args[3] as String? + api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val appNameArg = args[0] as String + val forceRefreshArg = args[1] as Boolean + api.getToken(appNameArg, forceRefreshArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val appNameArg = args[0] as String + val isTokenAutoRefreshEnabledArg = args[1] as Boolean + api.setTokenAutoRefreshEnabled(appNameArg, isTokenAutoRefreshEnabledArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val appNameArg = args[0] as String + api.registerTokenListener(appNameArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val appNameArg = args[0] as String + api.getLimitedUseAppCheckToken(appNameArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt new file mode 100644 index 000000000000..2062821507c8 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt @@ -0,0 +1,30 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package io.flutter.plugins.firebase.appcheck + +import com.google.firebase.appcheck.FirebaseAppCheck +import io.flutter.plugin.common.EventChannel + +class TokenChannelStreamHandler( + private val firebaseAppCheck: FirebaseAppCheck +) : EventChannel.StreamHandler { + + private var listener: FirebaseAppCheck.AppCheckListener? = null + + override fun onListen(arguments: Any?, events: EventChannel.EventSink) { + listener = FirebaseAppCheck.AppCheckListener { result -> + val event = HashMap() + event["token"] = result.token + events.success(event) + } + firebaseAppCheck.addAppCheckListener(listener!!) + } + + override fun onCancel(arguments: Any?) { + listener?.let { + firebaseAppCheck.removeAppCheckListener(it) + listener = null + } + } +} diff --git a/packages/firebase_app_check/firebase_app_check/example/.metadata b/packages/firebase_app_check/firebase_app_check/example/.metadata index 784ce1298249..827d9a16d24a 100644 --- a/packages/firebase_app_check/firebase_app_check/example/.metadata +++ b/packages/firebase_app_check/firebase_app_check/example/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: "a14f74ff3a1cbd521163c5f03d68113d50af93d3" + revision: "90673a4eef275d1a6692c26ac80d6d746d41a73a" channel: "stable" project_type: app @@ -13,11 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 - base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 - - platform: web - create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 - base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3 + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + - platform: windows + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a # User provided section diff --git a/packages/firebase_app_check/firebase_app_check/example/android/app/build.gradle b/packages/firebase_app_check/firebase_app_check/example/android/app/build.gradle index ef73138ff489..92298e7270e5 100644 --- a/packages/firebase_app_check/firebase_app_check/example/android/app/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/example/android/app/build.gradle @@ -45,7 +45,7 @@ android { applicationId = "io.flutter.plugins.firebase.appcheck.example" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdk = 23 + minSdkVersion = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutterVersionCode.toInteger() versionName = flutterVersionName diff --git a/packages/firebase_app_check/firebase_app_check/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_app_check/firebase_app_check/example/ios/Flutter/AppFrameworkInfo.plist index 7c5696400627..391a902b2beb 100644 --- a/packages/firebase_app_check/firebase_app_check/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/firebase_app_check/firebase_app_check/example/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 12.0 diff --git a/packages/firebase_app_check/firebase_app_check/example/ios/Podfile b/packages/firebase_app_check/firebase_app_check/example/ios/Podfile deleted file mode 100644 index bc779113f7ca..000000000000 --- a/packages/firebase_app_check/firebase_app_check/example/ios/Podfile +++ /dev/null @@ -1,50 +0,0 @@ -# Uncomment this line to define a global platform for your project -platform :ios, '15.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -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 - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end - - installer.generated_projects.each do |project| - project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' - end - end - end -end - diff --git a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj index 7d86b897a846..1ef35c770b2f 100644 --- a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/project.pbxproj @@ -37,6 +37,7 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 4632D5BC275CD47A0059DC83 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; 46A64A032996811C003FC4F3 /* RunnerRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerRelease.entitlements; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -66,6 +67,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, diff --git a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 6f83bdc750b0..8a6c683e3d89 100644 --- a/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_app_check/firebase_app_check/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -44,6 +44,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> diff --git a/packages/firebase_app_check/firebase_app_check/example/lib/firebase_options.dart b/packages/firebase_app_check/firebase_app_check/example/lib/firebase_options.dart index 2a78f25ed1b0..8bbd98affc15 100644 --- a/packages/firebase_app_check/firebase_app_check/example/lib/firebase_options.dart +++ b/packages/firebase_app_check/firebase_app_check/example/lib/firebase_options.dart @@ -31,10 +31,7 @@ class DefaultFirebaseOptions { case TargetPlatform.macOS: return macos; case TargetPlatform.windows: - throw UnsupportedError( - 'DefaultFirebaseOptions have not been configured for windows - ' - 'you can reconfigure this by running the FlutterFire CLI again.', - ); + return web; case TargetPlatform.linux: throw UnsupportedError( 'DefaultFirebaseOptions have not been configured for linux - ' diff --git a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart index 7a1e778d35a0..8f26c6439a83 100644 --- a/packages/firebase_app_check/firebase_app_check/example/lib/main.dart +++ b/packages/firebase_app_check/firebase_app_check/example/lib/main.dart @@ -2,6 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// ignore_for_file: do_not_use_environment + import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -12,6 +14,15 @@ import 'firebase_options.dart'; const kWebRecaptchaSiteKey = '6Lemcn0dAAAAABLkf6aiiHvpGD6x-zF3nOSDU2M8'; +// Windows: create a debug token in the Firebase Console +// (App Check > Apps > Manage debug tokens), then paste it here +// or set the APP_CHECK_DEBUG_TOKEN environment variable. +const kWindowsDebugToken = String.fromEnvironment( + 'APP_CHECK_DEBUG_TOKEN', + // ignore: avoid_redundant_argument_values + defaultValue: '', +); + Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp( @@ -20,14 +31,21 @@ Future main() async { // Activate app check after initialization, but before // usage of any Firebase services. - await FirebaseAppCheck.instance - // Your personal reCaptcha public key goes here: - .activate( + await FirebaseAppCheck.instance.activate( providerWeb: kDebugMode ? WebDebugProvider() : ReCaptchaV3Provider(kWebRecaptchaSiteKey), providerAndroid: const AndroidDebugProvider(), providerApple: const AppleDebugProvider(), + // On Windows, only the debug provider is available. + // You must supply a debug token — the desktop C++ SDK does not + // auto-generate one. Create one in the Firebase Console under + // App Check > Apps > Manage debug tokens, then either: + // - pass it via --dart-define=APP_CHECK_DEBUG_TOKEN= + // - or set the APP_CHECK_DEBUG_TOKEN environment variable + providerWindows: WindowsDebugProvider( + debugToken: kWindowsDebugToken.isNotEmpty ? kWindowsDebugToken : null, + ), ); runApp(MyApp()); @@ -36,7 +54,6 @@ Future main() async { class MyApp extends StatelessWidget { final String title = 'Firebase App Check'; - // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( @@ -81,65 +98,136 @@ class _FirebaseAppCheck extends State { }); } + Future _activate({ + AndroidAppCheckProvider? android, + AppleAppCheckProvider? apple, + WindowsAppCheckProvider? windows, + }) async { + try { + await appCheck.activate( + providerAndroid: android ?? const AndroidPlayIntegrityProvider(), + providerApple: apple ?? const AppleDeviceCheckProvider(), + providerWeb: ReCaptchaV3Provider(kWebRecaptchaSiteKey), + providerWindows: windows ?? const WindowsDebugProvider(), + ); + final providerName = windows?.runtimeType.toString() ?? + apple?.runtimeType.toString() ?? + android?.runtimeType.toString() ?? + 'default'; + setMessage('Activated with $providerName'); + } catch (e) { + setMessage('activate error: $e'); + } + } + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), - body: Center( + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + const Text( + 'Providers', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), + ElevatedButton( + onPressed: () => _activate( + android: const AndroidDebugProvider(), + apple: const AppleDebugProvider(), + windows: WindowsDebugProvider( + debugToken: + kWindowsDebugToken.isNotEmpty ? kWindowsDebugToken : null, + ), + ), + child: const Text('activate(Debug)'), + ), + ElevatedButton( + onPressed: () => _activate( + android: const AndroidPlayIntegrityProvider(), + apple: const AppleDeviceCheckProvider(), + ), + child: const Text('activate(PlayIntegrity / DeviceCheck)'), + ), + if (!kIsWeb) + ElevatedButton( + onPressed: () => _activate( + apple: const AppleAppAttestProvider(), + ), + child: const Text('activate(AppAttest)'), + ), + if (!kIsWeb) + ElevatedButton( + onPressed: () => _activate( + apple: const AppleAppAttestWithDeviceCheckFallbackProvider(), + ), + child: const Text( + 'activate(AppAttest + DeviceCheck fallback)', + ), + ), + const SizedBox(height: 16), + const Text( + 'Actions', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 8), ElevatedButton( onPressed: () async { - // Use this button to check whether the request was validated on the Firebase console - // Gets first document in collection - final result = await FirebaseFirestore.instance - .collection('flutter-tests') - .limit(1) - .get(); - - if (result.docs.isNotEmpty) { - setMessage('Document found'); - } else { - setMessage( - 'Document not found, please add a document to the collection', - ); + try { + final token = await appCheck.getToken(true); + setMessage('Token: ${token?.substring(0, 20)}...'); + } catch (e) { + setMessage('getToken error: $e'); } }, - child: const Text('Test App Check validates requests'), + child: const Text('getToken(forceRefresh: true)'), ), ElevatedButton( onPressed: () async { - if (kIsWeb) { - print( - 'Pass in your "webRecaptchaSiteKey" key found on you Firebase Console to activate if using on the web platform.', + try { + final token = await appCheck.getLimitedUseToken(); + setMessage( + 'Limited use token: ${token.substring(0, 20)}...', ); + } catch (e) { + setMessage('getLimitedUseToken error: $e'); } - await appCheck.activate( - providerWeb: ReCaptchaV3Provider(kWebRecaptchaSiteKey), - ); - setMessage('activated!!'); }, - child: const Text('activate()'), + child: const Text('getLimitedUseToken()'), ), ElevatedButton( onPressed: () async { - // Token will be passed to `onTokenChange()` event handler - await appCheck.getToken(true); + await appCheck.setTokenAutoRefreshEnabled(true); + setMessage('Token auto-refresh enabled'); }, - child: const Text('getToken()'), + child: const Text('setTokenAutoRefreshEnabled(true)'), ), ElevatedButton( onPressed: () async { - await appCheck.setTokenAutoRefreshEnabled(true); - setMessage('successfully set auto token refresh!!'); + try { + final result = await FirebaseFirestore.instance + .collection('flutter-tests') + .limit(1) + .get(); + setMessage( + result.docs.isNotEmpty + ? 'Firestore: Document found' + : 'Firestore: No documents', + ); + } catch (e) { + setMessage('Firestore error: $e'); + } }, - child: const Text('setTokenAutoRefreshEnabled()'), + child: const Text('Test Firestore with App Check'), ), const SizedBox(height: 20), Text( - _message, //#007bff + _message, style: const TextStyle( color: Color.fromRGBO(47, 79, 79, 1), fontSize: 16, @@ -147,10 +235,10 @@ class _FirebaseAppCheck extends State { ), const SizedBox(height: 20), Text( - 'Token received from tokenChanges() API: $_eventToken', //#007bff + 'Token from onTokenChange: $_eventToken', style: const TextStyle( color: Color.fromRGBO(128, 0, 128, 1), - fontSize: 16, + fontSize: 14, ), ), ], diff --git a/packages/firebase_app_check/firebase_app_check/example/macos/Podfile b/packages/firebase_app_check/firebase_app_check/example/macos/Podfile deleted file mode 100644 index 9ec46f8cd53c..000000000000 --- a/packages/firebase_app_check/firebase_app_check/example/macos/Podfile +++ /dev/null @@ -1,40 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', '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 - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj index 7c41affca666..c0dc38604806 100644 --- a/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_app_check/firebase_app_check/example/macos/Runner.xcodeproj/project.pbxproj @@ -28,7 +28,6 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - BB0DE7CB0DF8ACBEFD8915B8 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 292B95E8595C74EC66477907 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -56,10 +55,7 @@ /* Begin PBXFileReference section */ 0DC934EE60634F0D37DD0EC3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; - 24274BFFB66F90649AACE273 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 25624AEB275E1E7900B1E491 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - 292B95E8595C74EC66477907 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3206A1D9CA5124387AA36F3A /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* firebase_app_check_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = firebase_app_check_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -76,7 +72,6 @@ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - B06DD14F985336F6BE0D10BF /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,7 +80,6 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, - BB0DE7CB0DF8ACBEFD8915B8 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -109,7 +103,6 @@ 33FAB671232836740065AC1E /* Runner */, 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, 74CB5F55BD11E25520F6FF45 /* Pods */, 0DC934EE60634F0D37DD0EC3 /* GoogleService-Info.plist */, ); @@ -162,21 +155,10 @@ 74CB5F55BD11E25520F6FF45 /* Pods */ = { isa = PBXGroup; children = ( - 24274BFFB66F90649AACE273 /* Pods-Runner.debug.xcconfig */, - 3206A1D9CA5124387AA36F3A /* Pods-Runner.release.xcconfig */, - B06DD14F985336F6BE0D10BF /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 292B95E8595C74EC66477907 /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -184,7 +166,6 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 8FAF6BECF1FF5E1A559C7452 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, @@ -304,28 +285,6 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - 8FAF6BECF1FF5E1A559C7452 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/.gitignore b/packages/firebase_app_check/firebase_app_check/example/windows/.gitignore new file mode 100644 index 000000000000..d492d0d98c8f --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/CMakeLists.txt b/packages/firebase_app_check/firebase_app_check/example/windows/CMakeLists.txt new file mode 100644 index 000000000000..ffc5f0c5bd79 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(firebase_app_check_example LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "firebase_app_check_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/flutter/CMakeLists.txt b/packages/firebase_app_check/firebase_app_check/example/windows/flutter/CMakeLists.txt new file mode 100644 index 000000000000..903f4899d6fc --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/CMakeLists.txt b/packages/firebase_app_check/firebase_app_check/example/windows/runner/CMakeLists.txt new file mode 100644 index 000000000000..394917c053a0 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/Runner.rc b/packages/firebase_app_check/firebase_app_check/example/windows/runner/Runner.rc new file mode 100644 index 000000000000..26d198ffd138 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.flutter.plugins.firebase.appcheck" "\0" + VALUE "FileDescription", "firebase_app_check_example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "firebase_app_check_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 io.flutter.plugins.firebase.appcheck. All rights reserved." "\0" + VALUE "OriginalFilename", "firebase_app_check_example.exe" "\0" + VALUE "ProductName", "firebase_app_check_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.cpp b/packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.cpp new file mode 100644 index 000000000000..d1bd86f4967a --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.cpp @@ -0,0 +1,73 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { this->Show(); }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.h b/packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.h new file mode 100644 index 000000000000..243c83529a77 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/flutter_window.h @@ -0,0 +1,37 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/main.cpp b/packages/firebase_app_check/firebase_app_check/example/windows/runner/main.cpp new file mode 100644 index 000000000000..129ed2c35f81 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/main.cpp @@ -0,0 +1,46 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t* command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"firebase_app_check_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/resource.h b/packages/firebase_app_check/firebase_app_check/example/windows/runner/resource.h new file mode 100644 index 000000000000..91d70fa37f5d --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/resource.h @@ -0,0 +1,20 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/resources/app_icon.ico b/packages/firebase_app_check/firebase_app_check/example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 zcmeHQc|26z|35SKE&G-*mXah&B~fFkXr)DEO&hIfqby^T&>|8^_Ub8Vp#`BLl3lbZ zvPO!8k!2X>cg~Elr=IVxo~J*a`+9wR=A83c-k-DFd(XM&UI1VKCqM@V;DDtJ09WB} zRaHKiW(GT00brH|0EeTeKVbpbGZg?nK6-j827q-+NFM34gXjqWxJ*a#{b_apGN<-L_m3#8Z26atkEn& ze87Bvv^6vVmM+p+cQ~{u%=NJF>#(d;8{7Q{^rWKWNtf14H}>#&y7$lqmY6xmZryI& z($uy?c5-+cPnt2%)R&(KIWEXww>Cnz{OUpT>W$CbO$h1= z#4BPMkFG1Y)x}Ui+WXr?Z!w!t_hjRq8qTaWpu}FH{MsHlU{>;08goVLm{V<&`itk~ zE_Ys=D(hjiy+5=?=$HGii=Y5)jMe9|wWoD_K07(}edAxh`~LBorOJ!Cf@f{_gNCC| z%{*04ViE!#>@hc1t5bb+NO>ncf@@Dv01K!NxH$3Eg1%)|wLyMDF8^d44lV!_Sr}iEWefOaL z8f?ud3Q%Sen39u|%00W<#!E=-RpGa+H8}{ulxVl4mwpjaU+%2pzmi{3HM)%8vb*~-M9rPUAfGCSos8GUXp02|o~0BTV2l#`>>aFV&_P$ejS;nGwSVP8 zMbOaG7<7eKD>c12VdGH;?2@q7535sa7MN*L@&!m?L`ASG%boY7(&L5imY#EQ$KrBB z4@_tfP5m50(T--qv1BJcD&aiH#b-QC>8#7Fx@3yXlonJI#aEIi=8&ChiVpc#N=5le zM*?rDIdcpawoc5kizv$GEjnveyrp3sY>+5_R5;>`>erS%JolimF=A^EIsAK zsPoVyyUHCgf0aYr&alx`<)eb6Be$m&`JYSuBu=p8j%QlNNp$-5C{b4#RubPb|CAIS zGE=9OFLP7?Hgc{?k45)84biT0k&-C6C%Q}aI~q<(7BL`C#<6HyxaR%!dFx7*o^laG z=!GBF^cwK$IA(sn9y6>60Rw{mYRYkp%$jH z*xQM~+bp)G$_RhtFPYx2HTsWk80+p(uqv9@I9)y{b$7NK53rYL$ezbmRjdXS?V}fj zWxX_feWoLFNm3MG7pMUuFPs$qrQWO9!l2B(SIuy2}S|lHNbHzoE+M2|Zxhjq9+Ws8c{*}x^VAib7SbxJ*Q3EnY5lgI9 z=U^f3IW6T=TWaVj+2N%K3<%Un;CF(wUp`TC&Y|ZjyFu6co^uqDDB#EP?DV5v_dw~E zIRK*BoY9y-G_ToU2V_XCX4nJ32~`czdjT!zwme zGgJ0nOk3U4@IE5JwtM}pwimLjk{ln^*4HMU%Fl4~n(cnsLB}Ja-jUM>xIB%aY;Nq8 z)Fp8dv1tkqKanv<68o@cN|%thj$+f;zGSO7H#b+eMAV8xH$hLggtt?O?;oYEgbq@= zV(u9bbd12^%;?nyk6&$GPI%|+<_mEpJGNfl*`!KV;VfmZWw{n{rnZ51?}FDh8we_L z8OI9nE31skDqJ5Oa_ybn7|5@ui>aC`s34p4ZEu6-s!%{uU45$Zd1=p$^^dZBh zu<*pDDPLW+c>iWO$&Z_*{VSQKg7=YEpS3PssPn1U!lSm6eZIho*{@&20e4Y_lRklKDTUCKI%o4Pc<|G^Xgu$J^Q|B87U;`c1zGwf^-zH*VQ^x+i^OUWE0yd z;{FJq)2w!%`x7yg@>uGFFf-XJl4H`YtUG%0slGKOlXV`q?RP>AEWg#x!b{0RicxGhS!3$p7 zij;{gm!_u@D4$Ox%>>bPtLJ> zwKtYz?T_DR1jN>DkkfGU^<#6sGz|~p*I{y`aZ>^Di#TC|Z!7j_O1=Wo8thuit?WxR zh9_S>kw^{V^|g}HRUF=dcq>?q(pHxw!8rx4dC6vbQVmIhmICF#zU!HkHpQ>9S%Uo( zMw{eC+`&pb=GZRou|3;Po1}m46H6NGd$t<2mQh}kaK-WFfmj_66_17BX0|j-E2fe3Jat}ijpc53 zJV$$;PC<5aW`{*^Z6e5##^`Ed#a0nwJDT#Qq~^e8^JTA=z^Kl>La|(UQ!bI@#ge{Dzz@61p-I)kc2?ZxFt^QQ}f%ldLjO*GPj(5)V9IyuUakJX=~GnTgZ4$5!3E=V#t`yOG4U z(gphZB6u2zsj=qNFLYShhg$}lNpO`P9xOSnO*$@@UdMYES*{jJVj|9z-}F^riksLK zbsU+4-{281P9e2UjY6tse^&a)WM1MFw;p#_dHhWI7p&U*9TR0zKdVuQed%6{otTsq z$f~S!;wg#Bd9kez=Br{m|66Wv z#g1xMup<0)H;c2ZO6su_ii&m8j&+jJz4iKnGZ&wxoQX|5a>v&_e#6WA!MB_4asTxLRGQCC5cI(em z%$ZfeqP>!*q5kU>a+BO&ln=4Jm>Ef(QE8o&RgLkk%2}4Tf}U%IFP&uS7}&|Q-)`5< z+e>;s#4cJ-z%&-^&!xsYx777Wt(wZY9(3(avmr|gRe4cD+a8&!LY`1^T?7x{E<=kdY9NYw>A;FtTvQ=Y&1M%lyZPl$ss1oY^Sl8we}n}Aob#6 zl4jERwnt9BlSoWb@3HxYgga(752Vu6Y)k4yk9u~Kw>cA5&LHcrvn1Y-HoIuFWg~}4 zEw4bR`mXZQIyOAzo)FYqg?$5W<;^+XX%Uz61{-L6@eP|lLH%|w?g=rFc;OvEW;^qh z&iYXGhVt(G-q<+_j}CTbPS_=K>RKN0&;dubh0NxJyDOHFF;<1k!{k#7b{|Qok9hac z;gHz}6>H6C6RnB`Tt#oaSrX0p-j-oRJ;_WvS-qS--P*8}V943RT6kou-G=A+7QPGQ z!ze^UGxtW3FC0$|(lY9^L!Lx^?Q8cny(rR`es5U;-xBhphF%_WNu|aO<+e9%6LuZq zt(0PoagJG<%hyuf;te}n+qIl_Ej;czWdc{LX^pS>77s9t*2b4s5dvP_!L^3cwlc)E!(!kGrg~FescVT zZCLeua3f4;d;Tk4iXzt}g}O@nlK3?_o91_~@UMIl?@77Qc$IAlLE95#Z=TES>2E%z zxUKpK{_HvGF;5%Q7n&vA?`{%8ohlYT_?(3A$cZSi)MvIJygXD}TS-3UwyUxGLGiJP znblO~G|*uA^|ac8E-w#}uBtg|s_~s&t>-g0X%zIZ@;o_wNMr_;{KDg^O=rg`fhDZu zFp(VKd1Edj%F zWHPl+)FGj%J1BO3bOHVfH^3d1F{)*PL&sRX`~(-Zy3&9UQX)Z;c51tvaI2E*E7!)q zcz|{vpK7bjxix(k&6=OEIBJC!9lTkUbgg?4-yE{9+pFS)$Ar@vrIf`D0Bnsed(Cf? zObt2CJ>BKOl>q8PyFO6w)+6Iz`LW%T5^R`U_NIW0r1dWv6OY=TVF?N=EfA(k(~7VBW(S;Tu5m4Lg8emDG-(mOSSs=M9Q&N8jc^Y4&9RqIsk(yO_P(mcCr}rCs%1MW1VBrn=0-oQN(Xj!k%iKV zb%ricBF3G4S1;+8lzg5PbZ|$Se$)I=PwiK=cDpHYdov2QO1_a-*dL4KUi|g&oh>(* zq$<`dQ^fat`+VW?m)?_KLn&mp^-@d=&7yGDt<=XwZZC=1scwxO2^RRI7n@g-1o8ps z)&+et_~)vr8aIF1VY1Qrq~Xe``KJrQSnAZ{CSq3yP;V*JC;mmCT6oRLSs7=GA?@6g zUooM}@tKtx(^|aKK8vbaHlUQqwE0}>j&~YlN3H#vKGm@u)xxS?n9XrOWUfCRa< z`20Fld2f&;gg7zpo{Adh+mqNntMc-D$N^yWZAZRI+u1T1zWHPxk{+?vcS1D>08>@6 zLhE@`gt1Y9mAK6Z4p|u(5I%EkfU7rKFSM=E4?VG9tI;a*@?6!ey{lzN5=Y-!$WFSe z&2dtO>^0@V4WRc#L&P%R(?@KfSblMS+N+?xUN$u3K4Ys%OmEh+tq}fnU}i>6YHM?< zlnL2gl~sF!j!Y4E;j3eIU-lfa`RsOL*Tt<%EFC0gPzoHfNWAfKFIKZN8}w~(Yi~=q z>=VNLO2|CjkxP}RkutxjV#4fWYR1KNrPYq5ha9Wl+u>ipsk*I(HS@iLnmGH9MFlTU zaFZ*KSR0px>o+pL7BbhB2EC1%PJ{67_ z#kY&#O4@P=OV#-79y_W>Gv2dxL*@G7%LksNSqgId9v;2xJ zrh8uR!F-eU$NMx@S*+sk=C~Dxr9Qn7TfWnTupuHKuQ$;gGiBcU>GF5sWx(~4IP3`f zWE;YFO*?jGwYh%C3X<>RKHC-DZ!*r;cIr}GLOno^3U4tFSSoJp%oHPiSa%nh=Zgn% z14+8v@ygy0>UgEN1bczD6wK45%M>psM)y^)IfG*>3ItX|TzV*0i%@>L(VN!zdKb8S?Qf7BhjNpziA zR}?={-eu>9JDcl*R=OP9B8N$IcCETXah9SUDhr{yrld{G;PnCWRsPD7!eOOFBTWUQ=LrA_~)mFf&!zJX!Oc-_=kT<}m|K52 z)M=G#;p;Rdb@~h5D{q^K;^fX-m5V}L%!wVC2iZ1uu401Ll}#rocTeK|7FAeBRhNdQ zCc2d^aQnQp=MpOmak60N$OgS}a;p(l9CL`o4r(e-nN}mQ?M&isv-P&d$!8|1D1I(3-z!wi zTgoo)*Mv`gC?~bm?S|@}I|m-E2yqPEvYybiD5azInexpK8?9q*$9Yy9-t%5jU8~ym zgZDx>!@ujQ=|HJnwp^wv-FdD{RtzO9SnyfB{mH_(c!jHL*$>0o-(h(eqe*ZwF6Lvu z{7rkk%PEqaA>o+f{H02tzZ@TWy&su?VNw43! z-X+rN`6llvpUms3ZiSt)JMeztB~>9{J8SPmYs&qohxdYFi!ra8KR$35Zp9oR)eFC4 zE;P31#3V)n`w$fZ|4X-|%MX`xZDM~gJyl2W;O$H25*=+1S#%|53>|LyH za@yh+;325%Gq3;J&a)?%7X%t@WXcWL*BaaR*7UEZad4I8iDt7^R_Fd`XeUo256;sAo2F!HcIQKk;h})QxEsPE5BcKc7WyerTchgKmrfRX z!x#H_%cL#B9TWAqkA4I$R^8{%do3Y*&(;WFmJ zU7Dih{t1<{($VtJRl9|&EB?|cJ)xse!;}>6mSO$o5XIx@V|AA8ZcoD88ZM?C*;{|f zZVmf94_l1OmaICt`2sTyG!$^UeTHx9YuUP!omj(r|7zpm5475|yXI=rR>>fteLI+| z)MoiGho0oEt=*J(;?VY0QzwCqw@cVm?d7Y!z0A@u#H?sCJ*ecvyhj& z-F77lO;SH^dmf?L>3i>?Z*U}Em4ZYV_CjgfvzYsRZ+1B!Uo6H6mbS<-FFL`ytqvb& zE7+)2ahv-~dz(Hs+f})z{*4|{)b=2!RZK;PWwOnO=hG7xG`JU5>bAvUbdYd_CjvtHBHgtGdlO+s^9ca^Bv3`t@VRX2_AD$Ckg36OcQRF zXD6QtGfHdw*hx~V(MV-;;ZZF#dJ-piEF+s27z4X1qi5$!o~xBnvf=uopcn7ftfsZc zy@(PuOk`4GL_n(H9(E2)VUjqRCk9kR?w)v@xO6Jm_Mx})&WGEl=GS0#)0FAq^J*o! zAClhvoTsNP*-b~rN{8Yym3g{01}Ep^^Omf=SKqvN?{Q*C4HNNAcrowIa^mf+3PRy! z*_G-|3i8a;+q;iP@~Of_$(vtFkB8yOyWt2*K)vAn9El>=D;A$CEx6b*XF@4y_6M+2 zpeW`RHoI_p(B{%(&jTHI->hmNmZjHUj<@;7w0mx3&koy!2$@cfX{sN19Y}euYJFn& z1?)+?HCkD0MRI$~uB2UWri})0bru_B;klFdwsLc!ne4YUE;t41JqfG# zZJq6%vbsdx!wYeE<~?>o4V`A3?lN%MnKQ`z=uUivQN^vzJ|C;sdQ37Qn?;lpzg})y z)_2~rUdH}zNwX;Tp0tJ78+&I=IwOQ-fl30R79O8@?Ub8IIA(6I`yHn%lARVL`%b8+ z4$8D-|MZZWxc_)vu6@VZN!HsI$*2NOV&uMxBNzIbRgy%ob_ zhwEH{J9r$!dEix9XM7n&c{S(h>nGm?el;gaX0@|QnzFD@bne`el^CO$yXC?BDJ|Qg z+y$GRoR`?ST1z^e*>;!IS@5Ovb7*RlN>BV_UC!7E_F;N#ky%1J{+iixp(dUJj93aK zzHNN>R-oN7>kykHClPnoPTIj7zc6KM(Pnlb(|s??)SMb)4!sMHU^-ntJwY5Big7xv zb1Ew`Xj;|D2kzGja*C$eS44(d&RMU~c_Y14V9_TLTz0J#uHlsx`S6{nhsA0dWZ#cG zJ?`fO50E>*X4TQLv#nl%3GOk*UkAgt=IY+u0LNXqeln3Z zv$~&Li`ZJOKkFuS)dJRA>)b_Da%Q~axwA_8zNK{BH{#}#m}zGcuckz}riDE-z_Ms> zR8-EqAMcfyGJCtvTpaUVQtajhUS%c@Yj}&6Zz;-M7MZzqv3kA7{SuW$oW#=0az2wQ zg-WG@Vb4|D`pl~Il54N7Hmsauc_ne-a!o5#j3WaBBh@Wuefb!QJIOn5;d)%A#s+5% zuD$H=VNux9bE-}1&bcYGZ+>1Fo;3Z@e&zX^n!?JK*adSbONm$XW9z;Q^L>9U!}Toj2WdafJ%oL#h|yWWwyAGxzfrAWdDTtaKl zK4`5tDpPg5>z$MNv=X0LZ0d6l%D{(D8oT@+w0?ce$DZ6pv>{1&Ok67Ix1 zH}3=IEhPJEhItCC8E=`T`N5(k?G=B4+xzZ?<4!~ ze~z6Wk9!CHTI(0rLJ4{JU?E-puc;xusR?>G?;4vt;q~iI9=kDL=z0Rr%O$vU`30X$ zDZRFyZ`(omOy@u|i6h;wtJlP;+}$|Ak|k2dea7n?U1*$T!sXqqOjq^NxLPMmk~&qI zYg0W?yK8T(6+Ea+$YyspKK?kP$+B`~t3^Pib_`!6xCs32!i@pqXfFV6PmBIR<-QW= zN8L{pt0Vap0x`Gzn#E@zh@H)0FfVfA_Iu4fjYZ+umO1LXIbVc$pY+E234u)ttcrl$ z>s92z4vT%n6cMb>=XT6;l0+9e(|CZG)$@C7t7Z7Ez@a)h)!hyuV&B5K%%)P5?Lk|C zZZSVzdXp{@OXSP0hoU-gF8s8Um(#xzjP2Vem zec#-^JqTa&Y#QJ>-FBxd7tf`XB6e^JPUgagB8iBSEps;92KG`!#mvVcPQ5yNC-GEG zTiHEDYfH+0O15}r^+ z#jxj=@x8iNHWALe!P3R67TwmhItn**0JwnzSV2O&KE8KcT+0hWH^OPD1pwiuyx=b@ zNf5Jh0{9X)8;~Es)$t@%(3!OnbY+`@?i{mGX7Yy}8T_*0a6g;kaFPq;*=px5EhO{Cp%1kI<0?*|h8v!6WnO3cCJRF2-CRrU3JiLJnj@6;L)!0kWYAc_}F{2P))3HmCrz zQ&N&gE70;`!6*eJ4^1IR{f6j4(-l&X!tjHxkbHA^Zhrnhr9g{exN|xrS`5Pq=#Xf& zG%P=#ra-TyVFfgW%cZo5OSIwFL9WtXAlFOa+ubmI5t*3=g#Y zF%;70p5;{ZeFL}&}yOY1N1*Q;*<(kTB!7vM$QokF)yr2FlIU@$Ph58$Bz z0J?xQG=MlS4L6jA22eS42g|9*9pX@$#*sUeM(z+t?hr@r5J&D1rx}2pW&m*_`VDCW zUYY@v-;bAO0HqoAgbbiGGC<=ryf96}3pouhy3XJrX+!!u*O_>Si38V{uJmQ&USptX zKp#l(?>%^7;2%h(q@YWS#9;a!JhKlkR#Vd)ERILlgu!Hr@jA@V;sk4BJ-H#p*4EqC zDGjC*tl=@3Oi6)Bn^QwFpul18fpkbpg0+peH$xyPBqb%`$OUhPKyWb32o7clB*9Z< zN=i~NLjavrLtwgJ01bufP+>p-jR2I95|TpmKpQL2!oV>g(4RvS2pK4*ou%m(h6r3A zX#s&`9LU1ZG&;{CkOK!4fLDTnBys`M!vuz>Q&9OZ0hGQl!~!jSDg|~s*w52opC{sB ze|Cf2luD(*G13LcOAGA!s2FjSK8&IE5#W%J25w!vM0^VyQM!t)inj&RTiJ!wXzFgz z3^IqzB7I0L$llljsGq})thBy9UOyjtFO_*hYM_sgcMk>44jeH0V1FDyELc{S1F-;A zS;T^k^~4biG&V*Irq}O;e}j$$+E_#G?HKIn05iP3j|87TkGK~SqG!-KBg5+mN(aLm z8ybhIM`%C19UX$H$KY6JgXbY$0AT%rEpHC;u`rQ$Y=rxUdsc5*Kvc8jaYaO$^)cI6){P6K0r)I6DY4Wr4&B zLQUBraey#0HV|&c4v7PVo3n$zHj99(TZO^3?Ly%C4nYvJTL9eLBLHsM3WKKD>5!B` zQ=BsR3aR6PD(Fa>327E2HAu5TM~Wusc!)>~(gM)+3~m;92Jd;FnSib=M5d6;;5{%R zb4V7DEJ0V!CP-F*oU?gkc>ksUtAYP&V4ND5J>J2^jt*vcFflQWCrB&fLdT%O59PVJ zhid#toR=FNgD!q3&r8#wEBr`!wzvQu5zX?Q>nlSJ4i@WC*CN*-xU66F^V5crWevQ9gsq$I@z1o(a=k7LL~ z7m_~`o;_Ozha1$8Q}{WBehvAlO4EL60y5}8GDrZ< zXh&F}71JbW2A~8KfEWj&UWV#4+Z4p`b{uAj4&WC zha`}X@3~+Iz^WRlOHU&KngK>#j}+_o@LdBC1H-`gT+krWX3-;!)6?{FBp~%20a}FL zFP9%Emqcwa#(`=G>BBZ0qZDQhmZKJg_g8<=bBFKWr!dyg(YkpE+|R*SGpDVU!+VlU zFC54^DLv}`qa%49T>nNiA9Q7Ips#!Xx90tCU2gvK`(F+GPcL=J^>No{)~we#o@&mUb6c$ zCc*<|NJBk-#+{j9xkQ&ujB zI~`#kN~7W!f*-}wkG~Ld!JqZ@tK}eeSnsS5J1fMFXm|`LJx&}5`@dK3W^7#Wnm+_P zBZkp&j1fa2Y=eIjJ0}gh85jt43kaIXXv?xmo@eHrka!Z|vQv12HN#+!I5E z`(fbuW>gFiJL|uXJ!vKt#z3e3HlVdboH7;e#i3(2<)Fg-I@BR!qY#eof3MFZ&*Y@l zI|KJf&ge@p2Dq09Vu$$Qxb7!}{m-iRk@!)%KL)txi3;~Z4Pb}u@GsW;ELiWeG9V51 znX#}B&4Y2E7-H=OpNE@q{%hFLxwIpBF2t{vPREa8_{linXT;#1vMRWjOzLOP$-hf( z>=?$0;~~PnkqY;~K{EM6Vo-T(0K{A0}VUGmu*hR z{tw3hvBN%N3G3Yw`X5Te+F{J`(3w1s3-+1EbnFQKcrgrX1Jqvs@ADGe%M0s$EbK$$ zK)=y=upBc6SjGYAACCcI=Y*6Fi8_jgwZlLxD26fnQfJmb8^gHRN5(TemhX@0e=vr> zg`W}6U>x6VhoA3DqsGGD9uL1DhB3!OXO=k}59TqD@(0Nb{)Ut_luTioK_>7wjc!5C zIr@w}b`Fez3)0wQfKl&bae7;PcTA7%?f2xucM0G)wt_KO!Ewx>F~;=BI0j=Fb4>pp zv}0R^xM4eti~+^+gE$6b81p(kwzuDti(-K9bc|?+pJEl@H+jSYuxZQV8rl8 zjp@M{#%qItIUFN~KcO9Hed*`$5A-2~pAo~K&<-Q+`9`$CK>rzqAI4w~$F%vs9s{~x zg4BP%Gy*@m?;D6=SRX?888Q6peF@_4Z->8wAH~Cn!R$|Hhq2cIzFYqT_+cDourHbY z0qroxJnrZ4Gh+Ay+F`_c%+KRT>y3qw{)89?=hJ@=KO=@ep)aBJ$c!JHfBMJpsP*3G za7|)VJJ8B;4?n{~ldJF7%jmb`-ftIvNd~ekoufG(`K(3=LNc;HBY& z(lp#q8XAD#cIf}k49zX_i`*fO+#!zKA&%T3j@%)R+#yag067CU%yUEe47>wzGU8^` z1EXFT^@I!{J!F8!X?S6ph8J=gUi5tl93*W>7}_uR<2N2~e}FaG?}KPyugQ=-OGEZs z!GBoyYY+H*ANn4?Z)X4l+7H%`17i5~zRlRIX?t)6_eu=g2Q`3WBhxSUeea+M-S?RL zX9oBGKn%a!H+*hx4d2(I!gsi+@SQK%<{X22M~2tMulJoa)0*+z9=-YO+;DFEm5eE1U9b^B(Z}2^9!Qk`!A$wUE z7$Ar5?NRg2&G!AZqnmE64eh^Anss3i!{}%6@Et+4rr!=}!SBF8eZ2*J3ujCWbl;3; z48H~goPSv(8X61fKKdpP!Z7$88NL^Z?j`!^*I?-P4X^pMxyWz~@$(UeAcTSDd(`vO z{~rc;9|GfMJcApU3k}22a!&)k4{CU!e_ny^Y3cO;tOvOMKEyWz!vG(Kp*;hB?d|R3`2X~=5a6#^o5@qn?J-bI8Ppip{-yG z!k|VcGsq!jF~}7DMr49Wap-s&>o=U^T0!Lcy}!(bhtYsPQy z4|EJe{12QL#=c(suQ89Mhw9<`bui%nx7Nep`C&*M3~vMEACmcRYYRGtANq$F%zh&V zc)cEVeHz*Z1N)L7k-(k3np#{GcDh2Q@ya0YHl*n7fl*ZPAsbU-a94MYYtA#&!c`xGIaV;yzsmrjfieTEtqB_WgZp2*NplHx=$O{M~2#i_vJ{ps-NgK zQsxKK_CBM2PP_je+Xft`(vYfXXgIUr{=PA=7a8`2EHk)Ym2QKIforz# tySWtj{oF3N9@_;i*Fv5S)9x^z=nlWP>jpp-9)52ZmLVA=i*%6g{{fxOO~wEK literal 0 HcmV?d00001 diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/runner.exe.manifest b/packages/firebase_app_check/firebase_app_check/example/windows/runner/runner.exe.manifest new file mode 100644 index 000000000000..153653e8d67f --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.cpp b/packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.cpp new file mode 100644 index 000000000000..3b1344754669 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.cpp @@ -0,0 +1,69 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE* unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr) - + 1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, input_length, + utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.h b/packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.h new file mode 100644 index 000000000000..8ec0c44d5bfe --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/utils.h @@ -0,0 +1,23 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.cpp b/packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.cpp new file mode 100644 index 000000000000..82754b04cd09 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.cpp @@ -0,0 +1,284 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: +/// https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = + L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { return ShowWindow(window_handle_, SW_SHOWNORMAL); } + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = + RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, nullptr, + &light_mode, &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.h b/packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.h new file mode 100644 index 000000000000..dd2425483126 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/windows/runner/win32_window.h @@ -0,0 +1,104 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec index a1a5161f0e7f..b4d81500ec2a 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check.podspec @@ -24,8 +24,7 @@ Pod::Spec.new do |s| s.license = { :file => '../LICENSE' } s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.{h,m}' - s.public_header_files = 'firebase_app_check/Sources/firebase_app_check/include/*.h' + s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.swift' s.ios.deployment_target = '15.0' # Flutter dependencies diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index 55b8a05577b1..59c19bba50af 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -7,7 +7,6 @@ import PackageDescription -let library_version = "0.4.1-5" let firebase_sdk_version: Version = "12.9.0" let package = Package( @@ -31,11 +30,6 @@ let package = Package( ], resources: [ .process("Resources"), - ], - cSettings: [ - .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), - .define("LIBRARY_NAME", to: "\"flutter-fire-appcheck\""), ] ), ] diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift new file mode 100644 index 000000000000..7dbfc84ba33b --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift @@ -0,0 +1,6 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Auto-generated file. Do not edit. +public let versionNumber = "0.4.2" diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m deleted file mode 100644 index aacddaf48f2f..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FLTAppCheckProvider.h" - -@implementation FLTAppCheckProvider - -- (id)initWithApp:app { - self = [super init]; - if (self) { - self.app = app; - } - return self; -} - -- (void)configure:(FIRApp *)app - providerName:(NSString *)providerName - debugToken:(NSString *)debugToken { - if ([providerName isEqualToString:@"debug"]) { - if (debugToken != nil) { - // We have a debug token, so just need to stuff it in the environment and it will hook up - char *key = "FIRAAppCheckDebugToken", *value = (char *)[debugToken UTF8String]; - int overwrite = 1; - setenv(key, value, overwrite); - } - FIRAppCheckDebugProvider *provider = [[FIRAppCheckDebugProvider alloc] initWithApp:app]; - if (debugToken == nil) NSLog(@"Firebase App Check Debug Token: %@", [provider localDebugToken]); - self.delegateProvider = provider; - } - - if ([providerName isEqualToString:@"deviceCheck"]) { - self.delegateProvider = [[FIRDeviceCheckProvider alloc] initWithApp:app]; - } - - if ([providerName isEqualToString:@"appAttest"]) { - if (@available(iOS 14.0, macCatalyst 14.0, tvOS 15.0, watchOS 9.0, *)) { - self.delegateProvider = [[FIRAppAttestProvider alloc] initWithApp:app]; - } else { - // This is not a valid environment, setup debug provider. - self.delegateProvider = [[FIRAppCheckDebugProvider alloc] initWithApp:app]; - } - } - - if ([providerName isEqualToString:@"appAttestWithDeviceCheckFallback"]) { - if (@available(iOS 14.0, *)) { - self.delegateProvider = [[FIRAppAttestProvider alloc] initWithApp:app]; - } else { - self.delegateProvider = [[FIRDeviceCheckProvider alloc] initWithApp:app]; - } - } -} - -- (void)getTokenWithCompletion:(nonnull void (^)(FIRAppCheckToken *_Nullable, - NSError *_Nullable))handler { - // Proxying to delegateProvider - [self.delegateProvider getTokenWithCompletion:handler]; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m deleted file mode 100644 index 3eee91a08fc8..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import - -@import FirebaseAppCheck; -@import FirebaseCore; - -#import "FLTAppCheckProviderFactory.h" - -#import "FLTAppCheckProvider.h" - -@implementation FLTAppCheckProviderFactory - -- (nullable id)createProviderWithApp:(FIRApp *)app { - // The SDK may try to call this before we have been configured, - // so we will configure ourselves and set the provider up as a default to start - // pre-configure - if (self.providers == nil) { - self.providers = [NSMutableDictionary new]; - } - - if (self.providers[app.name] == nil) { - self.providers[app.name] = [FLTAppCheckProvider new]; - FLTAppCheckProvider *provider = self.providers[app.name]; - // We set "deviceCheck" as this is currently what is default. Backward compatible. - [provider configure:app providerName:@"deviceCheck" debugToken:nil]; - } - - return self.providers[app.name]; -} - -- (void)configure:(FIRApp *)app - providerName:(NSString *)providerName - debugToken:(NSString *)debugToken { - if (self.providers == nil) { - self.providers = [NSMutableDictionary new]; - } - - if (self.providers[app.name] == nil) { - self.providers[app.name] = [FLTAppCheckProvider new]; - } - - FLTAppCheckProvider *provider = self.providers[app.name]; - [provider configure:app providerName:providerName debugToken:debugToken]; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m deleted file mode 100644 index 7c47283e60b9..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FLTFirebaseAppCheckPlugin.h" -#import "FLTTokenRefreshStreamHandler.h" - -@import FirebaseAppCheck; - -#if __has_include() -#import -#else -#import -#endif - -#import "FLTAppCheckProviderFactory.h" - -NSString *const kFLTFirebaseAppCheckChannelName = @"plugins.flutter.io/firebase_app_check"; - -@interface FLTFirebaseAppCheckPlugin () -@end - -@implementation FLTFirebaseAppCheckPlugin { - NSMutableDictionary *_eventChannels; - NSMutableDictionary *> *_streamHandlers; - NSObject *_binaryMessenger; - FLTAppCheckProviderFactory *_Nullable providerFactory; -} - -#pragma mark - FlutterPlugin - -- (instancetype)init:(NSObject *)messenger { - self = [super init]; - if (self) { - self->providerFactory = [[FLTAppCheckProviderFactory alloc] init]; - [FIRAppCheck setAppCheckProviderFactory:self->providerFactory]; - - [[FLTFirebasePluginRegistry sharedInstance] registerFirebasePlugin:self]; - _binaryMessenger = messenger; - _eventChannels = [NSMutableDictionary dictionary]; - _streamHandlers = [NSMutableDictionary dictionary]; - } - return self; -} - -+ (void)registerWithRegistrar:(NSObject *)registrar { - FlutterMethodChannel *channel = - [FlutterMethodChannel methodChannelWithName:kFLTFirebaseAppCheckChannelName - binaryMessenger:[registrar messenger]]; - FLTFirebaseAppCheckPlugin *instance = - [[FLTFirebaseAppCheckPlugin alloc] init:registrar.messenger]; - [registrar addMethodCallDelegate:instance channel:channel]; -} - -- (void)cleanupWithCompletion:(void (^)(void))completion { - for (FlutterEventChannel *channel in self->_eventChannels.allValues) { - [channel setStreamHandler:nil]; - } - [self->_eventChannels removeAllObjects]; - for (NSObject *handler in self->_streamHandlers.allValues) { - [handler onCancelWithArguments:nil]; - } - [self->_streamHandlers removeAllObjects]; - - if (completion != nil) completion(); -} - -- (void)detachFromEngineForRegistrar:(NSObject *)registrar { - [self cleanupWithCompletion:nil]; -} - -- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)flutterResult { - FLTFirebaseMethodCallErrorBlock errorBlock = ^( - NSString *_Nullable code, NSString *_Nullable message, NSDictionary *_Nullable details, - NSError *_Nullable error) { - NSMutableDictionary *errorDetails = [NSMutableDictionary dictionary]; - NSString *errorCode; - - switch (error.code) { - case FIRAppCheckErrorCodeServerUnreachable: - errorCode = @"server-unreachable"; - break; - case FIRAppCheckErrorCodeInvalidConfiguration: - errorCode = @"invalid-configuration"; - break; - case FIRAppCheckErrorCodeKeychain: - errorCode = @"code-keychain"; - break; - case FIRAppCheckErrorCodeUnsupported: - errorCode = @"code-unsupported"; - break; - case FIRAppCheckErrorCodeUnknown: - default: - errorCode = @"unknown"; - } - - NSString *errorMessage = error.localizedDescription; - errorDetails[@"code"] = errorCode; - errorDetails[@"message"] = errorMessage; - flutterResult([FlutterError errorWithCode:errorCode message:errorMessage details:errorDetails]); - }; - - FLTFirebaseMethodCallResult *methodCallResult = - [FLTFirebaseMethodCallResult createWithSuccess:flutterResult andErrorBlock:errorBlock]; - - if ([@"FirebaseAppCheck#activate" isEqualToString:call.method]) { - [self activate:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#getToken" isEqualToString:call.method]) { - [self getToken:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#setTokenAutoRefreshEnabled" isEqualToString:call.method]) { - [self setTokenAutoRefreshEnabled:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#registerTokenListener" isEqualToString:call.method]) { - [self registerTokenListener:call.arguments withMethodCallResult:methodCallResult]; - } else if ([@"FirebaseAppCheck#getLimitedUseAppCheckToken" isEqualToString:call.method]) { - [self getLimitedUseAppCheckToken:call.arguments withMethodCallResult:methodCallResult]; - } else { - flutterResult(FlutterMethodNotImplemented); - } -} - -#pragma mark - Firebase App Check API - -- (void)activate:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - NSString *appNameDart = arguments[@"appName"]; - NSString *providerName = arguments[@"appleProvider"]; - NSString *debugToken = arguments[@"appleDebugToken"]; - - FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:appNameDart]; - [self->providerFactory configure:app providerName:providerName debugToken:debugToken]; - result.success(nil); -} - -- (void)registerTokenListener:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - NSString *appName = arguments[@"appName"]; - NSString *name = - [NSString stringWithFormat:@"%@/token/%@", kFLTFirebaseAppCheckChannelName, appName]; - - FlutterEventChannel *channel = [FlutterEventChannel eventChannelWithName:name - binaryMessenger:_binaryMessenger]; - - FLTTokenRefreshStreamHandler *handler = [[FLTTokenRefreshStreamHandler alloc] init]; - [channel setStreamHandler:handler]; - - [_eventChannels setObject:channel forKey:name]; - [_streamHandlers setObject:handler forKey:name]; - result.success(name); -} - -- (void)getToken:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAppCheck *appCheck = [self getFIRAppCheckFromArguments:arguments]; - bool forceRefresh = [arguments[@"forceRefresh"] boolValue]; - - [appCheck tokenForcingRefresh:forceRefresh - completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(token.token); - } - }]; -} - -- (void)getLimitedUseAppCheckToken:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAppCheck *appCheck = [self getFIRAppCheckFromArguments:arguments]; - [appCheck - limitedUseTokenWithCompletion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) { - if (error != nil) { - result.error(nil, nil, nil, error); - } else { - result.success(token.token); - } - }]; -} - -- (void)setTokenAutoRefreshEnabled:(id)arguments - withMethodCallResult:(FLTFirebaseMethodCallResult *)result { - FIRAppCheck *appCheck = [self getFIRAppCheckFromArguments:arguments]; - bool isTokenAutoRefreshEnabled = arguments[@"isTokenAutoRefreshEnabled"]; - appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled; - result.success(nil); -} - -#pragma mark - FLTFirebasePlugin - -- (void)didReinitializeFirebaseCore:(void (^)(void))completion { - [self cleanupWithCompletion:completion]; -} - -- (NSDictionary *_Nonnull)pluginConstantsForFIRApp:(FIRApp *)firebase_app { - return @{}; -} - -- (NSString *_Nonnull)firebaseLibraryName { - return @LIBRARY_NAME; -} - -- (NSString *_Nonnull)firebaseLibraryVersion { - return @LIBRARY_VERSION; -} - -- (NSString *_Nonnull)flutterChannelName { - return kFLTFirebaseAppCheckChannelName; -} - -#pragma mark - Utilities - -- (FIRAppCheck *_Nullable)getFIRAppCheckFromArguments:(NSDictionary *)arguments { - NSString *appNameDart = arguments[@"appName"]; - FIRApp *app = [FLTFirebasePlugin firebaseAppNamed:appNameDart]; - FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:app]; - - return appCheck; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m deleted file mode 100644 index 4b411926d616..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FLTTokenRefreshStreamHandler.h" -#import "FLTFirebaseAppCheckPlugin.h" - -const NSNotificationName kNotififactionEvent = @"FIRAppCheckAppCheckTokenDidChangeNotification"; - -NSString *const kTokenKey = @"FIRAppCheckTokenNotificationKey"; - -@implementation FLTTokenRefreshStreamHandler { - id _observer; -} - -- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events { - _observer = - [NSNotificationCenter.defaultCenter addObserverForName:kNotififactionEvent - object:nil - queue:nil - usingBlock:^(NSNotification *_Nonnull note) { - NSString *token = note.userInfo[kTokenKey]; - - events(@{@"token" : token}); - }]; - - return nil; -} - -- (FlutterError *)onCancelWithArguments:(id)arguments { - [NSNotificationCenter.defaultCenter removeObserver:_observer]; - return nil; -} - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift new file mode 100644 index 000000000000..1842cfe9c240 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -0,0 +1,233 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func isNullish(_ value: Any?) -> Bool { + value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader {} + +private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter {} + +private class FirebaseAppCheckMessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + FirebaseAppCheckMessagesPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + FirebaseAppCheckMessagesPigeonCodecWriter(data: data) + } +} + +class FirebaseAppCheckMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = + FirebaseAppCheckMessagesPigeonCodec( + readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter() + ) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol FirebaseAppCheckHostApi { + func activate(appName: String, androidProvider: String?, appleProvider: String?, + debugToken: String?, completion: @escaping (Result) -> Void) + func getToken(appName: String, forceRefresh: Bool, + completion: @escaping (Result) -> Void) + func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, + completion: @escaping (Result) -> Void) + func registerTokenListener(appName: String, completion: @escaping (Result) -> Void) + func getLimitedUseAppCheckToken(appName: String, + completion: @escaping (Result) -> Void) +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class FirebaseAppCheckHostApiSetup { + static var codec: FlutterStandardMessageCodec { + FirebaseAppCheckMessagesPigeonCodec.shared + } + + /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the + /// `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppCheckHostApi?, + messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + let activateChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + activateChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appNameArg = args[0] as! String + let androidProviderArg: String? = nilOrValue(args[1]) + let appleProviderArg: String? = nilOrValue(args[2]) + let debugTokenArg: String? = nilOrValue(args[3]) + api.activate( + appName: appNameArg, + androidProvider: androidProviderArg, + appleProvider: appleProviderArg, + debugToken: debugTokenArg + ) { result in + switch result { + case .success: + reply(wrapResult(nil)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + activateChannel.setMessageHandler(nil) + } + let getTokenChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getTokenChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appNameArg = args[0] as! String + let forceRefreshArg = args[1] as! Bool + api.getToken(appName: appNameArg, forceRefresh: forceRefreshArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + getTokenChannel.setMessageHandler(nil) + } + let setTokenAutoRefreshEnabledChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + setTokenAutoRefreshEnabledChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appNameArg = args[0] as! String + let isTokenAutoRefreshEnabledArg = args[1] as! Bool + api.setTokenAutoRefreshEnabled( + appName: appNameArg, + isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabledArg + ) { result in + switch result { + case .success: + reply(wrapResult(nil)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + setTokenAutoRefreshEnabledChannel.setMessageHandler(nil) + } + let registerTokenListenerChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + registerTokenListenerChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appNameArg = args[0] as! String + api.registerTokenListener(appName: appNameArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + registerTokenListenerChannel.setMessageHandler(nil) + } + let getLimitedUseAppCheckTokenChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken\(channelSuffix)", + binaryMessenger: binaryMessenger, + codec: codec + ) + if let api { + getLimitedUseAppCheckTokenChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let appNameArg = args[0] as! String + api.getLimitedUseAppCheckToken(appName: appNameArg) { result in + switch result { + case let .success(res): + reply(wrapResult(res)) + case let .failure(error): + reply(wrapError(error)) + } + } + } + } else { + getLimitedUseAppCheckTokenChannel.setMessageHandler(nil) + } + } +} diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift new file mode 100644 index 000000000000..5aec32b1ad2c --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift @@ -0,0 +1,300 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#if canImport(FlutterMacOS) + import FlutterMacOS +#else + import Flutter +#endif + +#if canImport(firebase_core) + import firebase_core +#else + import firebase_core_shared +#endif +import FirebaseAppCheck +import FirebaseCore + +let kFirebaseAppCheckChannelName = "plugins.flutter.io/firebase_app_check" +let kFirebaseAppCheckTokenChannelPrefix = "plugins.flutter.io/firebase_app_check/token/" + +extension FlutterError: @retroactive Error {} + +public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, + FLTFirebasePluginProtocol, FirebaseAppCheckHostApi { + private var eventChannels: [String: FlutterEventChannel] = [:] + private var streamHandlers: [String: AppCheckTokenStreamHandler] = [:] + private var providerFactory: FlutterAppCheckProviderFactory? + + static let shared: FirebaseAppCheckPlugin = { + let instance = FirebaseAppCheckPlugin() + instance.providerFactory = FlutterAppCheckProviderFactory() + AppCheck.setAppCheckProviderFactory(instance.providerFactory) + FLTFirebasePluginRegistry.sharedInstance().register(instance) + return instance + }() + + public static func register(with registrar: FlutterPluginRegistrar) { + let binaryMessenger: FlutterBinaryMessenger + + #if os(macOS) + binaryMessenger = registrar.messenger + #elseif os(iOS) + binaryMessenger = registrar.messenger() + #endif + + let instance = shared + instance.binaryMessenger = binaryMessenger + FirebaseAppCheckHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: instance) + + if FirebaseApp.responds(to: NSSelectorFromString("registerLibrary:withVersion:")) { + FirebaseApp.perform( + NSSelectorFromString("registerLibrary:withVersion:"), + with: instance.firebaseLibraryName(), + with: instance.firebaseLibraryVersion() + ) + } + } + + private var binaryMessenger: FlutterBinaryMessenger? + + func activate(appName: String, androidProvider: String?, appleProvider: String?, + debugToken: String?, + completion: @escaping (Result) -> Void) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { + completion(.failure(FlutterError( + code: "unknown", message: "Firebase app not found: \(appName)", details: nil + ))) + return + } + let provider = appleProvider ?? "deviceCheck" + + providerFactory?.configure(app: app, providerName: provider, debugToken: debugToken) + + completion(.success(())) + } + + func getToken(appName: String, forceRefresh: Bool, + completion: @escaping (Result) -> Void) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName), + let appCheck = AppCheck.appCheck(app: app) + else { + completion(.failure(FlutterError( + code: "unknown", message: "App Check not available for app: \(appName)", details: nil + ))) + return + } + + appCheck.token(forcingRefresh: forceRefresh) { token, error in + if let error { + completion(.failure(self.createFlutterError(error))) + } else { + completion(.success(token?.token)) + } + } + } + + func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, + completion: @escaping (Result) -> Void) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName), + let appCheck = AppCheck.appCheck(app: app) + else { + completion(.failure(FlutterError( + code: "unknown", message: "App Check not available for app: \(appName)", details: nil + ))) + return + } + appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled + completion(.success(())) + } + + func registerTokenListener(appName: String, + completion: @escaping (Result) -> Void) { + let name = kFirebaseAppCheckTokenChannelPrefix + appName + + guard let messenger = binaryMessenger else { + completion(.failure(FlutterError( + code: "no-messenger", + message: "Binary messenger not available", + details: nil + ))) + return + } + + let channel = FlutterEventChannel(name: name, binaryMessenger: messenger) + let handler = AppCheckTokenStreamHandler() + channel.setStreamHandler(handler) + + eventChannels[name] = channel + streamHandlers[name] = handler + + completion(.success(name)) + } + + func getLimitedUseAppCheckToken(appName: String, + completion: @escaping (Result) -> Void) { + guard let app = FLTFirebasePlugin.firebaseAppNamed(appName), + let appCheck = AppCheck.appCheck(app: app) + else { + completion(.failure(FlutterError( + code: "unknown", message: "App Check not available for app: \(appName)", details: nil + ))) + return + } + + appCheck.limitedUseToken { token, error in + if let error { + completion(.failure(self.createFlutterError(error))) + } else { + completion(.success(token?.token ?? "")) + } + } + } + + // MARK: - FLTFirebasePluginProtocol + + public func didReinitializeFirebaseCore(_ completion: @escaping () -> Void) { + for (_, channel) in eventChannels { + channel.setStreamHandler(nil) + } + for (_, handler) in streamHandlers { + handler.onCancel(withArguments: nil) + } + eventChannels.removeAll() + streamHandlers.removeAll() + completion() + } + + public func pluginConstants(for firebaseApp: FirebaseApp) -> [AnyHashable: Any] { + [:] + } + + public func firebaseLibraryName() -> String { + "flutter-fire-appcheck" + } + + public func firebaseLibraryVersion() -> String { + versionNumber + } + + public func flutterChannelName() -> String { + kFirebaseAppCheckChannelName + } + + private func createFlutterError(_ error: Error) -> FlutterError { + let nsError = error as NSError + var code = "unknown" + switch nsError.code { + case 0: // FIRAppCheckErrorCodeServerUnreachable + code = "server-unreachable" + case 1: // FIRAppCheckErrorCodeInvalidConfiguration + code = "invalid-configuration" + case 2: // FIRAppCheckErrorCodeKeychain + code = "code-keychain" + case 3: // FIRAppCheckErrorCodeUnsupported + code = "code-unsupported" + default: + code = "unknown" + } + return FlutterError( + code: code, + message: nsError.localizedDescription, + details: nil + ) + } +} + +// MARK: - Token Stream Handler + +class AppCheckTokenStreamHandler: NSObject, FlutterStreamHandler { + private var observer: NSObjectProtocol? + + func onListen(withArguments arguments: Any?, + eventSink events: @escaping FlutterEventSink) -> FlutterError? { + observer = NotificationCenter.default.addObserver( + forName: NSNotification.Name("FIRAppCheckAppCheckTokenDidChangeNotification"), + object: nil, + queue: nil + ) { notification in + if let token = notification.userInfo?["FIRAppCheckTokenNotificationKey"] as? String { + events(["token": token]) + } + } + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + if let observer { + NotificationCenter.default.removeObserver(observer) + self.observer = nil + } + return nil + } +} + +// MARK: - App Check Provider Factory + +class FlutterAppCheckProviderFactory: NSObject, AppCheckProviderFactory { + private var providers: [String: AppCheckProviderWrapper] = [:] + + func createProvider(with app: FirebaseApp) -> (any AppCheckProvider)? { + if providers[app.name] == nil { + let wrapper = AppCheckProviderWrapper() + // Default to deviceCheck. activate() will reconfigure with the correct provider. + wrapper.configure(app: app, providerName: "deviceCheck", debugToken: nil) + providers[app.name] = wrapper + } + return providers[app.name] + } + + func configure(app: FirebaseApp, providerName: String, debugToken: String?) { + if providers[app.name] == nil { + providers[app.name] = AppCheckProviderWrapper() + } + providers[app.name]?.configure(app: app, providerName: providerName, debugToken: debugToken) + } +} + +class AppCheckProviderWrapper: NSObject, AppCheckProvider { + private var delegateProvider: (any AppCheckProvider)? + + func configure(app: FirebaseApp, providerName: String, debugToken: String?) { + switch providerName { + case "debug": + if let debugToken { + setenv("FIRAAppCheckDebugToken", debugToken, 1) + } + delegateProvider = AppCheckDebugProvider(app: app) + if debugToken == nil, let debugProvider = delegateProvider as? AppCheckDebugProvider { + print("Firebase App Check Debug Token: \(debugProvider.localDebugToken())") + } + case "appAttest": + if #available(iOS 14.0, macOS 14.0, macCatalyst 14.0, tvOS 15.0, watchOS 9.0, *) { + delegateProvider = AppAttestProvider(app: app) + } else { + delegateProvider = AppCheckDebugProvider(app: app) + } + case "appAttestWithDeviceCheckFallback": + if #available(iOS 14.0, macOS 14.0, *) { + delegateProvider = AppAttestProvider(app: app) + } else { + delegateProvider = DeviceCheckProvider(app: app) + } + default: + // deviceCheck + delegateProvider = DeviceCheckProvider(app: app) + } + } + + func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) { + guard let delegateProvider else { + handler(nil, NSError( + domain: "firebase_app_check", code: -1, + userInfo: [NSLocalizedDescriptionKey: "Provider not configured"] + )) + return + } + delegateProvider.getToken(completion: handler) + } +} diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h deleted file mode 100644 index da9efde18370..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import FirebaseAppCheck; - -@interface FLTAppCheckProvider : NSObject - -@property FIRApp *app; - -@property id delegateProvider; - -- (void)configure:(FIRApp *)app - providerName:(NSString *)providerName - debugToken:(NSString *)debugToken; - -- (id)initWithApp:(FIRApp *)app; - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h deleted file mode 100644 index 8e5511ebea94..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#import - -@interface FLTAppCheckProviderFactory : NSObject - -@property NSMutableDictionary *_Nullable providers; - -- (void)configure:(FIRApp *_Nonnull)app - providerName:(NSString *_Nonnull)providerName - debugToken:(NSString *_Nullable)debugToken; - -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h deleted file mode 100644 index 9d07d0ebc671..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#import - -#if TARGET_OS_OSX -#import -#else -#import -#endif - -#import -#if __has_include() -#import -#else -#import -#endif -#import "FLTAppCheckProviderFactory.h" - -@interface FLTFirebaseAppCheckPlugin : FLTFirebasePlugin -@end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h deleted file mode 100644 index acd570bc3b75..000000000000 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import - -#if TARGET_OS_OSX -#import -#else -#import -#endif - -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface FLTTokenRefreshStreamHandler : NSObject -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart index c5f5ae1ad633..cd569468c12c 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart @@ -21,7 +21,9 @@ export 'package:firebase_app_check_platform_interface/firebase_app_check_platfor AppleAppAttestWithDeviceCheckFallbackProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, - WebDebugProvider; + WebDebugProvider, + WindowsAppCheckProvider, + WindowsDebugProvider; export 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' show FirebaseException; diff --git a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart index d605174a3366..25a1845449e8 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart @@ -61,6 +61,13 @@ class FirebaseAppCheck extends FirebasePluginPlatform { /// "app attest with fallback to device check" via `AppleAppCheckProvider`. /// Note: App Attest is only available on iOS 14.0+ and macOS 14.0+. /// + /// **Windows**: Only the debug provider is supported. You **must** supply a + /// debug token — the desktop C++ SDK does not auto-generate one. Either pass + /// it via `providerWindows: WindowsDebugProvider(debugToken: 'your-token')` + /// or set the `APP_CHECK_DEBUG_TOKEN` environment variable. The token must + /// first be registered in the Firebase Console under + /// *App Check → Apps → Manage debug tokens*. + /// /// ## Migration Notice /// /// The `androidProvider` and `appleProvider` parameters will be deprecated @@ -89,6 +96,7 @@ class FirebaseAppCheck extends FirebasePluginPlatform { AndroidAppCheckProvider providerAndroid = const AndroidPlayIntegrityProvider(), AppleAppCheckProvider providerApple = const AppleDeviceCheckProvider(), + WindowsAppCheckProvider providerWindows = const WindowsDebugProvider(), }) { return _delegate.activate( webProvider: providerWeb ?? webProvider, @@ -98,6 +106,7 @@ class FirebaseAppCheck extends FirebasePluginPlatform { appleProvider: appleProvider, providerAndroid: providerAndroid, providerApple: providerApple, + providerWindows: providerWindows, ); } diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec index d1b3b7eb6fe8..497fbc642162 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check.podspec @@ -43,8 +43,7 @@ Pod::Spec.new do |s| s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.{h,m}' - s.public_header_files = 'firebase_app_check/Sources/firebase_app_check/include/*.h' + s.source_files = 'firebase_app_check/Sources/firebase_app_check/**/*.swift' s.platform = :osx, '10.13' diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift index 092bbc07f8ed..b78be7a14dba 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift @@ -7,7 +7,6 @@ import PackageDescription -let library_version = "0.4.1-5" let firebase_sdk_version: Version = "12.9.0" let package = Package( @@ -31,11 +30,6 @@ let package = Package( ], resources: [ .process("Resources"), - ], - cSettings: [ - .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), - .define("LIBRARY_NAME", to: "\"flutter-fire-appcheck\""), ] ), ] diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Constants.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Constants.swift new file mode 120000 index 000000000000..4a4a4bdd92d1 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/Constants.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/Constants.swift \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m deleted file mode 120000 index 57fc55914ef1..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProvider.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m deleted file mode 120000 index 90899e731380..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTAppCheckProviderFactory.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m deleted file mode 120000 index 3bef267bc202..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTFirebaseAppCheckPlugin.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m deleted file mode 120000 index 93cf7946f352..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m +++ /dev/null @@ -1 +0,0 @@ -../../../../ios/firebase_app_check/Sources/firebase_app_check/FLTTokenRefreshStreamHandler.m \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift new file mode 120000 index 000000000000..3593b6772bba --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift new file mode 120000 index 000000000000..37995e4b53db --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift @@ -0,0 +1 @@ +../../../../ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h deleted file mode 120000 index 62bc70731543..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProvider.h \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h deleted file mode 120000 index 5638882c87c2..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTAppCheckProviderFactory.h \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h deleted file mode 120000 index e64b79a492b6..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTFirebaseAppCheckPlugin.h \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h deleted file mode 120000 index f4b967d7d5b3..000000000000 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h +++ /dev/null @@ -1 +0,0 @@ -../../../../../ios/firebase_app_check/Sources/firebase_app_check/include/FLTTokenRefreshStreamHandler.h \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/pubspec.yaml index ae655d160abc..48ed3305f04e 100644 --- a/packages/firebase_app_check/firebase_app_check/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/pubspec.yaml @@ -36,10 +36,12 @@ flutter: platforms: android: package: io.flutter.plugins.firebase.appcheck - pluginClass: FlutterFirebaseAppCheckPlugin + pluginClass: FirebaseAppCheckPlugin ios: - pluginClass: FLTFirebaseAppCheckPlugin + pluginClass: FirebaseAppCheckPlugin macos: - pluginClass: FLTFirebaseAppCheckPlugin + pluginClass: FirebaseAppCheckPlugin web: default_package: firebase_app_check_web + windows: + pluginClass: FirebaseAppCheckPluginCApi diff --git a/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart index 98aca115dc08..3c07056759cf 100755 --- a/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -13,7 +11,6 @@ import './mock.dart'; void main() { setupFirebaseAppCheckMocks(); late FirebaseApp secondaryApp; - late FirebaseAppCheck appCheck; group('$FirebaseAppCheck', () { setUpAll(() async { @@ -27,15 +24,8 @@ void main() { messagingSenderId: '1234567890', ), ); - appCheck = FirebaseAppCheck.instance; - }); - - setUp(() async { - methodCallLog.clear(); }); - tearDown(methodCallLog.clear); - group('instance', () { test('successful call', () async { final appCheck = FirebaseAppCheck.instance; @@ -53,80 +43,5 @@ void main() { expect(appCheck.app.name, 'secondaryApp'); }); }); - - group('activate', () { - test('successful call', () async { - await appCheck.activate( - providerWeb: ReCaptchaV3Provider('key'), - providerAndroid: const AndroidDebugProvider( - debugToken: 'androidDebug', - ), - providerApple: const AppleDebugProvider( - debugToken: 'appleDebug', - ), - ); - - expect( - methodCallLog, - [ - isMethodCall( - 'FirebaseAppCheck#activate', - arguments: { - 'appName': defaultFirebaseAppName, - 'androidProvider': 'debug', - 'appleProvider': 'debug', - 'androidDebugToken': 'androidDebug', - 'appleDebugToken': 'appleDebug', - }, - ), - ], - ); - }); - }); - group('getToken', () { - test('successful call', () async { - await appCheck.getToken(true); - - expect( - methodCallLog, - [ - isMethodCall( - 'FirebaseAppCheck#getToken', - arguments: { - 'appName': defaultFirebaseAppName, - 'forceRefresh': true, - }, - ), - ], - ); - }); - }); - - group('setTokenAutoRefreshEnabled', () { - test('successful call', () async { - await appCheck.setTokenAutoRefreshEnabled(false); - - expect( - methodCallLog, - [ - isMethodCall( - 'FirebaseAppCheck#setTokenAutoRefreshEnabled', - arguments: { - 'appName': defaultFirebaseAppName, - 'isTokenAutoRefreshEnabled': false, - }, - ), - ], - ); - }); - }); - - group('tokenChanges', () { - test('successful call', () async { - final stream = appCheck.onTokenChange; - - expect(stream, isA>()); - }); - }); }); } diff --git a/packages/firebase_app_check/firebase_app_check/test/mock.dart b/packages/firebase_app_check/firebase_app_check/test/mock.dart index 2da26a89c239..1f151cf1cac2 100644 --- a/packages/firebase_app_check/firebase_app_check/test/mock.dart +++ b/packages/firebase_app_check/firebase_app_check/test/mock.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:firebase_app_check_platform_interface/firebase_app_check_platform_interface.dart'; import 'package:firebase_core_platform_interface/test.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -15,21 +14,4 @@ void setupFirebaseAppCheckMocks([Callback? customHandlers]) { TestWidgetsFlutterBinding.ensureInitialized(); setupFirebaseCoreMocks(); - - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(MethodChannelFirebaseAppCheck.channel, - (MethodCall methodCall) async { - if (methodCall.method != 'FirebaseAppCheck#registerTokenListener') { - methodCallLog.add(methodCall); - } - - switch (methodCall.method) { - case 'FirebaseAppCheck#registerTokenListener': - return 'channelName'; - case 'FirebaseAppCheck#getToken': - return 'test-token'; - default: - return false; - } - }); } diff --git a/packages/firebase_app_check/firebase_app_check/windows/CMakeLists.txt b/packages/firebase_app_check/firebase_app_check/windows/CMakeLists.txt new file mode 100644 index 000000000000..7c40c200c5e9 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/CMakeLists.txt @@ -0,0 +1,81 @@ +# The Flutter tooling requires that developers have a version of Visual Studio +# installed that includes CMake 3.14 or later. You should not increase this +# version, as doing so will cause the plugin to fail to compile for some +# customers of the plugin. +cmake_minimum_required(VERSION 3.14) + +# Project-level configuration. +set(PROJECT_NAME "firebase_app_check") +project(${PROJECT_NAME} LANGUAGES CXX) + +# This value is used when generating builds using this plugin, so it must +# not be changed +set(PLUGIN_NAME "firebase_app_check_plugin") + +# Any new source files that you add to the plugin should be added here. +list(APPEND PLUGIN_SOURCES + "firebase_app_check_plugin.cpp" + "firebase_app_check_plugin.h" + "messages.g.cpp" + "messages.g.h" +) + +# Read version from pubspec.yaml +file(STRINGS "../pubspec.yaml" pubspec_content) +foreach(line ${pubspec_content}) + string(FIND ${line} "version: " has_version) + + if("${has_version}" STREQUAL "0") + string(FIND ${line} ": " version_start_pos) + math(EXPR version_start_pos "${version_start_pos} + 2") + string(LENGTH ${line} version_end_pos) + math(EXPR len "${version_end_pos} - ${version_start_pos}") + string(SUBSTRING ${line} ${version_start_pos} ${len} PLUGIN_VERSION) + break() + endif() +endforeach(line) + +configure_file(plugin_version.h.in ${CMAKE_BINARY_DIR}/generated/firebase_app_check/plugin_version.h) +include_directories(${CMAKE_BINARY_DIR}/generated/) + +# Define the plugin library target. Its name must not be changed (see comment +# on PLUGIN_NAME above). +add_library(${PLUGIN_NAME} STATIC + "include/firebase_app_check/firebase_app_check_plugin_c_api.h" + "firebase_app_check_plugin_c_api.cpp" + ${PLUGIN_SOURCES} + ${CMAKE_BINARY_DIR}/generated/firebase_app_check/plugin_version.h +) + +# Apply a standard set of build settings that are configured in the +# application-level CMakeLists.txt. This can be removed for plugins that want +# full control over build settings. +apply_standard_settings(${PLUGIN_NAME}) + +# Symbols are hidden by default to reduce the chance of accidental conflicts +# between plugins. This should not be removed; any symbols that should be +# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PUBLIC FLUTTER_PLUGIN_IMPL) + +# Enable firebase-cpp-sdk's platform logging api. +target_compile_definitions(${PLUGIN_NAME} PRIVATE -DINTERNAL_EXPERIMENTAL=1) + +# Source include directories and library dependencies. Add any plugin-specific +# dependencies here. +set(MSVC_RUNTIME_MODE MD) +set(firebase_libs firebase_core_plugin firebase_app_check) +target_link_libraries(${PLUGIN_NAME} PRIVATE "${firebase_libs}") + +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PUBLIC flutter flutter_wrapper_plugin) + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(firebase_app_check_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.cpp b/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.cpp new file mode 100644 index 000000000000..d9a0a72d7014 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.cpp @@ -0,0 +1,249 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "firebase_app_check_plugin.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "firebase/app.h" +#include "firebase/app_check.h" +#include "firebase/app_check/debug_provider.h" +#include "firebase/future.h" +#include "firebase_app_check/plugin_version.h" +#include "firebase_core/firebase_core_plugin_c_api.h" +#include "messages.g.h" + +using ::firebase::App; +using ::firebase::Future; +using ::firebase::app_check::AppCheck; +using ::firebase::app_check::AppCheckListener; +using ::firebase::app_check::AppCheckToken; +using ::firebase::app_check::DebugAppCheckProviderFactory; + +namespace firebase_app_check_windows { + +static const std::string kLibraryName = "flutter-fire-app-check"; +static const std::string kEventChannelNamePrefix = + "plugins.flutter.io/firebase_app_check/token/"; + +flutter::BinaryMessenger* FirebaseAppCheckPlugin::binaryMessenger = nullptr; +std::map>> + FirebaseAppCheckPlugin::event_channels_; +std::map + FirebaseAppCheckPlugin::listeners_map_; + +// AppCheckListener implementation that forwards token changes to an EventSink. +class FlutterAppCheckListener : public AppCheckListener { + public: + void SetEventSink( + std::unique_ptr> event_sink) { + event_sink_ = std::move(event_sink); + } + + void OnAppCheckTokenChanged(const AppCheckToken& token) override { + if (event_sink_) { + flutter::EncodableMap event; + event[flutter::EncodableValue("token")] = + flutter::EncodableValue(token.token); + event_sink_->Success(flutter::EncodableValue(event)); + } + } + + private: + std::unique_ptr> event_sink_; +}; + +// StreamHandler for token change events. +class TokenStreamHandler + : public flutter::StreamHandler { + public: + TokenStreamHandler(AppCheck* app_check, const std::string& app_name) + : app_check_(app_check), app_name_(app_name) {} + + std::unique_ptr> + OnListenInternal( + const flutter::EncodableValue* arguments, + std::unique_ptr>&& events) + override { + listener_ = std::make_unique(); + listener_->SetEventSink(std::move(events)); + app_check_->AddAppCheckListener(listener_.get()); + FirebaseAppCheckPlugin::listeners_map_[app_name_] = listener_.get(); + return nullptr; + } + + std::unique_ptr> + OnCancelInternal(const flutter::EncodableValue* arguments) override { + if (listener_) { + app_check_->RemoveAppCheckListener(listener_.get()); + FirebaseAppCheckPlugin::listeners_map_.erase(app_name_); + listener_.reset(); + } + return nullptr; + } + + private: + AppCheck* app_check_; + std::string app_name_; + std::unique_ptr listener_; +}; + +static AppCheck* GetAppCheckFromPigeon(const std::string& app_name) { + App* app = App::GetInstance(app_name.c_str()); + return AppCheck::GetInstance(app); +} + +static FlutterError ParseError(const firebase::FutureBase& completed_future) { + std::string error_code = "unknown"; + int error = completed_future.error(); + switch (error) { + case firebase::app_check::kAppCheckErrorServerUnreachable: + error_code = "server-unreachable"; + break; + case firebase::app_check::kAppCheckErrorInvalidConfiguration: + error_code = "invalid-configuration"; + break; + case firebase::app_check::kAppCheckErrorSystemKeychain: + error_code = "system-keychain"; + break; + case firebase::app_check::kAppCheckErrorUnsupportedProvider: + error_code = "unsupported-provider"; + break; + default: + error_code = "unknown"; + break; + } + + std::string error_message = completed_future.error_message() + ? completed_future.error_message() + : "An unknown error occurred"; + + return FlutterError(error_code, error_message); +} + +// static +void FirebaseAppCheckPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows* registrar) { + auto plugin = std::make_unique(); + + FirebaseAppCheckHostApi::SetUp(registrar->messenger(), plugin.get()); + + registrar->AddPlugin(std::move(plugin)); + + binaryMessenger = registrar->messenger(); + + // Register for platform logging + App::RegisterLibrary(kLibraryName.c_str(), getPluginVersion().c_str(), + nullptr); +} + +FirebaseAppCheckPlugin::FirebaseAppCheckPlugin() {} + +FirebaseAppCheckPlugin::~FirebaseAppCheckPlugin() { + for (auto& [app_name, listener] : listeners_map_) { + App* app = App::GetInstance(app_name.c_str()); + if (app) { + AppCheck* app_check = AppCheck::GetInstance(app); + if (app_check) { + app_check->RemoveAppCheckListener(listener); + } + } + } + listeners_map_.clear(); + event_channels_.clear(); +} + +void FirebaseAppCheckPlugin::Activate( + const std::string& app_name, const std::string* android_provider, + const std::string* apple_provider, const std::string* debug_token, + std::function reply)> result) { + // On Windows/desktop, only the Debug provider is available. + DebugAppCheckProviderFactory* factory = + DebugAppCheckProviderFactory::GetInstance(); + + if (debug_token != nullptr && !debug_token->empty()) { + factory->SetDebugToken(*debug_token); + } + + AppCheck::SetAppCheckProviderFactory(factory); + + result(std::nullopt); +} + +void FirebaseAppCheckPlugin::GetToken( + const std::string& app_name, bool force_refresh, + std::function> reply)> result) { + AppCheck* app_check = GetAppCheckFromPigeon(app_name); + + Future future = app_check->GetAppCheckToken(force_refresh); + future.OnCompletion([result](const Future& completed_future) { + if (completed_future.error() != 0) { + result(ParseError(completed_future)); + } else { + const AppCheckToken* token = completed_future.result(); + if (token) { + result(std::optional(token->token)); + } else { + result(std::optional(std::nullopt)); + } + } + }); +} + +void FirebaseAppCheckPlugin::SetTokenAutoRefreshEnabled( + const std::string& app_name, bool is_token_auto_refresh_enabled, + std::function reply)> result) { + AppCheck* app_check = GetAppCheckFromPigeon(app_name); + app_check->SetTokenAutoRefreshEnabled(is_token_auto_refresh_enabled); + result(std::nullopt); +} + +void FirebaseAppCheckPlugin::RegisterTokenListener( + const std::string& app_name, + std::function reply)> result) { + AppCheck* app_check = GetAppCheckFromPigeon(app_name); + + const std::string name = kEventChannelNamePrefix + app_name; + + auto event_channel = + std::make_unique>( + binaryMessenger, name, &flutter::StandardMethodCodec::GetInstance()); + event_channel->SetStreamHandler( + std::make_unique(app_check, app_name)); + + event_channels_[app_name] = std::move(event_channel); + + result(name); +} + +void FirebaseAppCheckPlugin::GetLimitedUseAppCheckToken( + const std::string& app_name, + std::function reply)> result) { + AppCheck* app_check = GetAppCheckFromPigeon(app_name); + + Future future = app_check->GetLimitedUseAppCheckToken(); + future.OnCompletion([result](const Future& completed_future) { + if (completed_future.error() != 0) { + result(ParseError(completed_future)); + } else { + const AppCheckToken* token = completed_future.result(); + if (token) { + result(token->token); + } else { + result(FlutterError("unknown", "Failed to get limited use token")); + } + } + }); +} + +} // namespace firebase_app_check_windows diff --git a/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.h b/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.h new file mode 100644 index 000000000000..baabf2bd5931 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin.h @@ -0,0 +1,72 @@ +/* + * Copyright 2025, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef FLUTTER_PLUGIN_FIREBASE_APP_CHECK_PLUGIN_H_ +#define FLUTTER_PLUGIN_FIREBASE_APP_CHECK_PLUGIN_H_ + +#include +#include +#include + +#include +#include +#include + +#include "firebase/app.h" +#include "firebase/app_check.h" +#include "firebase/future.h" +#include "messages.g.h" + +namespace firebase_app_check_windows { + +class TokenStreamHandler; + +class FirebaseAppCheckPlugin : public flutter::Plugin, + public FirebaseAppCheckHostApi { + friend class TokenStreamHandler; + + public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar); + + FirebaseAppCheckPlugin(); + + virtual ~FirebaseAppCheckPlugin(); + + // Disallow copy and assign. + FirebaseAppCheckPlugin(const FirebaseAppCheckPlugin&) = delete; + FirebaseAppCheckPlugin& operator=(const FirebaseAppCheckPlugin&) = delete; + + // FirebaseAppCheckHostApi methods. + void Activate( + const std::string& app_name, const std::string* android_provider, + const std::string* apple_provider, const std::string* debug_token, + std::function reply)> result) override; + void GetToken(const std::string& app_name, bool force_refresh, + std::function> reply)> + result) override; + void SetTokenAutoRefreshEnabled( + const std::string& app_name, bool is_token_auto_refresh_enabled, + std::function reply)> result) override; + void RegisterTokenListener( + const std::string& app_name, + std::function reply)> result) override; + void GetLimitedUseAppCheckToken( + const std::string& app_name, + std::function reply)> result) override; + + private: + static flutter::BinaryMessenger* binaryMessenger; + static std::map< + std::string, + std::unique_ptr>> + event_channels_; + static std::map + listeners_map_; +}; + +} // namespace firebase_app_check_windows + +#endif // FLUTTER_PLUGIN_FIREBASE_APP_CHECK_PLUGIN_H_ diff --git a/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin_c_api.cpp b/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin_c_api.cpp new file mode 100644 index 000000000000..f0ace78f6241 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/firebase_app_check_plugin_c_api.cpp @@ -0,0 +1,16 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "include/firebase_app_check/firebase_app_check_plugin_c_api.h" + +#include + +#include "firebase_app_check_plugin.h" + +void FirebaseAppCheckPluginCApiRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + firebase_app_check_windows::FirebaseAppCheckPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/packages/firebase_app_check/firebase_app_check/windows/include/firebase_app_check/firebase_app_check_plugin_c_api.h b/packages/firebase_app_check/firebase_app_check/windows/include/firebase_app_check/firebase_app_check_plugin_c_api.h new file mode 100644 index 000000000000..ab2d9e9464ee --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/include/firebase_app_check/firebase_app_check_plugin_c_api.h @@ -0,0 +1,29 @@ +/* + * Copyright 2025, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#ifndef FLUTTER_PLUGIN_FIREBASE_APP_CHECK_PLUGIN_C_API_H_ +#define FLUTTER_PLUGIN_FIREBASE_APP_CHECK_PLUGIN_C_API_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void FirebaseAppCheckPluginCApiRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_PLUGIN_FIREBASE_APP_CHECK_PLUGIN_C_API_H_ diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp new file mode 100644 index 000000000000..0343b73ea815 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp @@ -0,0 +1,307 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#undef _HAS_EXCEPTIONS + +#include "messages.g.h" + +#include +#include +#include +#include + +#include +#include +#include + +namespace firebase_app_check_windows { +using flutter::BasicMessageChannel; +using flutter::CustomEncodableValue; +using flutter::EncodableList; +using flutter::EncodableMap; +using flutter::EncodableValue; + +FlutterError CreateConnectionError(const std::string channel_name) { + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); +} + +PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} + +EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const { + return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); +} + +void PigeonInternalCodecSerializer::WriteValue( + const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + flutter::StandardCodecSerializer::WriteValue(value, stream); +} + +/// The codec used by FirebaseAppCheckHostApi. +const flutter::StandardMessageCodec& FirebaseAppCheckHostApi::GetCodec() { + return flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); +} + +// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through +// the `binary_messenger`. +void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api) { + FirebaseAppCheckHostApi::SetUp(binary_messenger, api, ""); +} + +void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = + message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : ""; + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.activate" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + const auto& encodable_android_provider_arg = args.at(1); + const auto* android_provider_arg = + std::get_if(&encodable_android_provider_arg); + const auto& encodable_apple_provider_arg = args.at(2); + const auto* apple_provider_arg = + std::get_if(&encodable_apple_provider_arg); + const auto& encodable_debug_token_arg = args.at(3); + const auto* debug_token_arg = + std::get_if(&encodable_debug_token_arg); + api->Activate(app_name_arg, android_provider_arg, + apple_provider_arg, debug_token_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.getToken" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + const auto& encodable_force_refresh_arg = args.at(1); + if (encodable_force_refresh_arg.IsNull()) { + reply(WrapError("force_refresh_arg unexpectedly null.")); + return; + } + const auto& force_refresh_arg = + std::get(encodable_force_refresh_arg); + api->GetToken( + app_name_arg, force_refresh_arg, + [reply](ErrorOr>&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + auto output_optional = std::move(output).TakeValue(); + if (output_optional) { + wrapped.push_back( + EncodableValue(std::move(output_optional).value())); + } else { + wrapped.push_back(EncodableValue()); + } + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + const auto& encodable_is_token_auto_refresh_enabled_arg = + args.at(1); + if (encodable_is_token_auto_refresh_enabled_arg.IsNull()) { + reply(WrapError( + "is_token_auto_refresh_enabled_arg unexpectedly null.")); + return; + } + const auto& is_token_auto_refresh_enabled_arg = + std::get(encodable_is_token_auto_refresh_enabled_arg); + api->SetTokenAutoRefreshEnabled( + app_name_arg, is_token_auto_refresh_enabled_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.registerTokenListener" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + api->RegisterTokenListener( + app_name_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface." + "FirebaseAppCheckHostApi.getLimitedUseAppCheckToken" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_name_arg = args.at(0); + if (encodable_app_name_arg.IsNull()) { + reply(WrapError("app_name_arg unexpectedly null.")); + return; + } + const auto& app_name_arg = + std::get(encodable_app_name_arg); + api->GetLimitedUseAppCheckToken( + app_name_arg, [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } +} + +EncodableValue FirebaseAppCheckHostApi::WrapError( + std::string_view error_message) { + return EncodableValue( + EncodableList{EncodableValue(std::string(error_message)), + EncodableValue("Error"), EncodableValue()}); +} + +EncodableValue FirebaseAppCheckHostApi::WrapError(const FlutterError& error) { + return EncodableValue(EncodableList{EncodableValue(error.code()), + EncodableValue(error.message()), + error.details()}); +} + +} // namespace firebase_app_check_windows diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.h b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h new file mode 100644 index 000000000000..c56d71862604 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h @@ -0,0 +1,118 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#ifndef PIGEON_MESSAGES_G_H_ +#define PIGEON_MESSAGES_G_H_ +#include +#include +#include +#include + +#include +#include +#include + +namespace firebase_app_check_windows { + +// Generated class from Pigeon. + +class FlutterError { + public: + explicit FlutterError(const std::string& code) : code_(code) {} + explicit FlutterError(const std::string& code, const std::string& message) + : code_(code), message_(message) {} + explicit FlutterError(const std::string& code, const std::string& message, + const flutter::EncodableValue& details) + : code_(code), message_(message), details_(details) {} + + const std::string& code() const { return code_; } + const std::string& message() const { return message_; } + const flutter::EncodableValue& details() const { return details_; } + + private: + std::string code_; + std::string message_; + flutter::EncodableValue details_; +}; + +template +class ErrorOr { + public: + ErrorOr(const T& rhs) : v_(rhs) {} + ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} + ErrorOr(const FlutterError& rhs) : v_(rhs) {} + ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {} + + bool has_error() const { return std::holds_alternative(v_); } + const T& value() const { return std::get(v_); }; + const FlutterError& error() const { return std::get(v_); }; + + private: + friend class FirebaseAppCheckHostApi; + ErrorOr() = default; + T TakeValue() && { return std::get(std::move(v_)); } + + std::variant v_; +}; + +class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { + public: + PigeonInternalCodecSerializer(); + inline static PigeonInternalCodecSerializer& GetInstance() { + static PigeonInternalCodecSerializer sInstance; + return sInstance; + } + + void WriteValue(const flutter::EncodableValue& value, + flutter::ByteStreamWriter* stream) const override; + + protected: + flutter::EncodableValue ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const override; +}; + +// Generated interface from Pigeon that represents a handler of messages from +// Flutter. +class FirebaseAppCheckHostApi { + public: + FirebaseAppCheckHostApi(const FirebaseAppCheckHostApi&) = delete; + FirebaseAppCheckHostApi& operator=(const FirebaseAppCheckHostApi&) = delete; + virtual ~FirebaseAppCheckHostApi() {} + virtual void Activate( + const std::string& app_name, const std::string* android_provider, + const std::string* apple_provider, const std::string* debug_token, + std::function reply)> result) = 0; + virtual void GetToken( + const std::string& app_name, bool force_refresh, + std::function> reply)> + result) = 0; + virtual void SetTokenAutoRefreshEnabled( + const std::string& app_name, bool is_token_auto_refresh_enabled, + std::function reply)> result) = 0; + virtual void RegisterTokenListener( + const std::string& app_name, + std::function reply)> result) = 0; + virtual void GetLimitedUseAppCheckToken( + const std::string& app_name, + std::function reply)> result) = 0; + + // The codec used by FirebaseAppCheckHostApi. + static const flutter::StandardMessageCodec& GetCodec(); + // Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through + // the `binary_messenger`. + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api); + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api, + const std::string& message_channel_suffix); + static flutter::EncodableValue WrapError(std::string_view error_message); + static flutter::EncodableValue WrapError(const FlutterError& error); + + protected: + FirebaseAppCheckHostApi() = default; +}; +} // namespace firebase_app_check_windows +#endif // PIGEON_MESSAGES_G_H_ diff --git a/packages/firebase_app_check/firebase_app_check/windows/plugin_version.h.in b/packages/firebase_app_check/firebase_app_check/windows/plugin_version.h.in new file mode 100644 index 000000000000..0a52f845105a --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/windows/plugin_version.h.in @@ -0,0 +1,13 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef PLUGIN_VERSION_CONFIG_H +#define PLUGIN_VERSION_CONFIG_H + +namespace firebase_app_check_windows { + +std::string getPluginVersion() { return "@PLUGIN_VERSION@"; } +} // namespace firebase_app_check_windows + +#endif // PLUGIN_VERSION_CONFIG_H diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/firebase_app_check_platform_interface.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/firebase_app_check_platform_interface.dart index c8292c8b7eaf..53a285e48729 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/firebase_app_check_platform_interface.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/firebase_app_check_platform_interface.dart @@ -10,3 +10,4 @@ export 'src/apple_providers.dart'; export 'src/method_channel/method_channel_firebase_app_check.dart'; export 'src/platform_interface/platform_interface_firebase_app_check.dart'; export 'src/web_providers.dart'; +export 'src/windows_providers.dart'; diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart index 59f05fa8b527..96afb6f2c999 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart @@ -10,6 +10,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import '../../firebase_app_check_platform_interface.dart'; +import '../pigeon/messages.pigeon.dart'; import 'utils/exception.dart'; import 'utils/provider_to_string.dart'; @@ -19,10 +20,8 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { : super(appInstance: app) { _tokenChangesListeners[app.name] = StreamController.broadcast(); - channel.invokeMethod('FirebaseAppCheck#registerTokenListener', { - 'appName': app.name, - }).then((channelName) { - final events = EventChannel(channelName!, channel.codec); + _pigeonApi.registerTokenListener(app.name).then((channelName) { + final events = EventChannel(channelName); events .receiveGuardedBroadcastStream(onError: convertPlatformException) .listen( @@ -34,6 +33,10 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { controller.add(result['token'] as String?); }, ); + // ignore: avoid_catches_without_on_clauses + }).catchError((_) { + // Silently ignore errors during token listener registration. + // This can happen in test environments where the host API is not set up. }); } @@ -44,10 +47,8 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { _methodChannelFirebaseAppCheckInstances = {}; - /// The [MethodChannel] used to communicate with the native plugin - static MethodChannel channel = const MethodChannel( - 'plugins.flutter.io/firebase_app_check', - ); + /// The Pigeon API used for platform communication. + final FirebaseAppCheckHostApi _pigeonApi = FirebaseAppCheckHostApi(); /// Returns a stub instance to allow the platform interface to access /// the class instance statically. @@ -88,30 +89,39 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { AppleProvider? appleProvider, AndroidAppCheckProvider? providerAndroid, AppleAppCheckProvider? providerApple, + WindowsAppCheckProvider? providerWindows, }) async { try { - await channel.invokeMethod('FirebaseAppCheck#activate', { - 'appName': app.name, - // Allow value to pass for debug mode for unit testing - if (defaultTargetPlatform == TargetPlatform.android || kDebugMode) - 'androidProvider': getAndroidProviderString( - legacyProvider: androidProvider, - newProvider: providerAndroid, - ), - if (providerAndroid is AndroidDebugProvider && - providerAndroid.debugToken != null) - 'androidDebugToken': providerAndroid.debugToken, - if (defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.macOS || - kDebugMode) - 'appleProvider': getAppleProviderString( - legacyProvider: appleProvider, - newProvider: providerApple, - ), - if (providerApple is AppleDebugProvider && - providerApple.debugToken != null) - 'appleDebugToken': providerApple.debugToken, - }); + String? debugToken; + if (providerAndroid is AndroidDebugProvider && + providerAndroid.debugToken != null) { + debugToken = providerAndroid.debugToken; + } else if (providerApple is AppleDebugProvider && + providerApple.debugToken != null) { + debugToken = providerApple.debugToken; + } else if (providerWindows is WindowsDebugProvider && + providerWindows.debugToken != null) { + debugToken = providerWindows.debugToken; + } + + await _pigeonApi.activate( + app.name, + defaultTargetPlatform == TargetPlatform.android || kDebugMode + ? getAndroidProviderString( + legacyProvider: androidProvider, + newProvider: providerAndroid, + ) + : null, + defaultTargetPlatform == TargetPlatform.iOS || + defaultTargetPlatform == TargetPlatform.macOS || + kDebugMode + ? getAppleProviderString( + legacyProvider: appleProvider, + newProvider: providerApple, + ) + : null, + debugToken, + ); } on PlatformException catch (e, s) { convertPlatformException(e, s); } @@ -120,12 +130,7 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { @override Future getToken(bool forceRefresh) async { try { - final result = await channel.invokeMethod( - 'FirebaseAppCheck#getToken', - {'appName': app.name, 'forceRefresh': forceRefresh}, - ); - - return result; + return await _pigeonApi.getToken(app.name, forceRefresh); } on PlatformException catch (e, s) { convertPlatformException(e, s); } @@ -136,12 +141,9 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { bool isTokenAutoRefreshEnabled, ) async { try { - await channel.invokeMethod( - 'FirebaseAppCheck#setTokenAutoRefreshEnabled', - { - 'appName': app.name, - 'isTokenAutoRefreshEnabled': isTokenAutoRefreshEnabled, - }, + await _pigeonApi.setTokenAutoRefreshEnabled( + app.name, + isTokenAutoRefreshEnabled, ); } on PlatformException catch (e, s) { convertPlatformException(e, s); @@ -156,14 +158,7 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { @override Future getLimitedUseToken() async { try { - final result = await channel.invokeMethod( - 'FirebaseAppCheck#getLimitedUseAppCheckToken', - { - 'appName': app.name, - }, - ); - - return result; + return await _pigeonApi.getLimitedUseAppCheckToken(app.name); } on PlatformException catch (e, s) { convertPlatformException(e, s); } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart new file mode 100644 index 000000000000..fab0d53008a2 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -0,0 +1,198 @@ +// Copyright 2025, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers, require_trailing_commas + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} + +class FirebaseAppCheckHostApi { + /// Constructor for [FirebaseAppCheckHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + FirebaseAppCheckHostApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future activate(String appName, String? androidProvider, + String? appleProvider, String? debugToken) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([appName, androidProvider, appleProvider, debugToken]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + Future getToken(String appName, bool forceRefresh) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName, forceRefresh]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as String?); + } + } + + Future setTokenAutoRefreshEnabled( + String appName, bool isTokenAutoRefreshEnabled) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName, isTokenAutoRefreshEnabled]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + Future registerTokenListener(String appName) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as String?)!; + } + } + + Future getLimitedUseAppCheckToken(String appName) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([appName]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as String?)!; + } + } +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart index 988d7e0b8e1f..346c745a5652 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart @@ -67,6 +67,13 @@ abstract class FirebaseAppCheckPlatform extends PlatformInterface { /// "app attest with fallback to device check" via `AppleAppCheckProvider`. /// Note: App Attest is only available on iOS 14.0+ and macOS 14.0+. /// + /// **Windows**: Only the debug provider is supported. You **must** supply a + /// debug token — the desktop C++ SDK does not auto-generate one. Either pass + /// it via `providerWindows: WindowsDebugProvider(debugToken: 'your-token')` + /// or set the `APP_CHECK_DEBUG_TOKEN` environment variable. The token must + /// first be registered in the Firebase Console under + /// *App Check → Apps → Manage debug tokens*. + /// /// ## Migration Notice /// /// The `androidProvider` and `appleProvider` parameters will be deprecated @@ -89,6 +96,7 @@ abstract class FirebaseAppCheckPlatform extends PlatformInterface { AppleProvider? appleProvider, AndroidAppCheckProvider? providerAndroid, AppleAppCheckProvider? providerApple, + WindowsAppCheckProvider? providerWindows, }) { throw UnimplementedError('activate() is not implemented'); } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/windows_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/windows_providers.dart new file mode 100644 index 000000000000..b6b09e55b20b --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/windows_providers.dart @@ -0,0 +1,44 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Base class for Windows App Check providers. +/// +/// On Windows, only the [WindowsDebugProvider] is supported. The Firebase C++ +/// SDK does not support platform attestation providers (such as Play Integrity +/// or DeviceCheck) on desktop platforms. +abstract class WindowsAppCheckProvider { + final String type; + const WindowsAppCheckProvider(this.type); +} + +/// Debug provider for Windows. +/// +/// This is the **only** provider available on Windows. Unlike mobile platforms, +/// the desktop C++ SDK does **not** auto-generate a debug token. You must +/// supply one explicitly. +/// +/// ## Setup +/// +/// 1. Generate a debug token (a UUID v4) — for example using an online +/// generator or a CLI tool. +/// 2. Register it in the **Firebase Console** under +/// *App Check → Apps → Manage debug tokens*. +/// 3. Pass it here via [debugToken], **or** set the `APP_CHECK_DEBUG_TOKEN` +/// environment variable before launching your app. +/// +/// If neither a [debugToken] nor the environment variable is provided, +/// `getToken()` will fail with an `invalid-configuration` error. +/// +/// **Do not ship the debug provider or debug tokens in production builds.** +class WindowsDebugProvider extends WindowsAppCheckProvider { + /// Creates a Windows debug provider. + /// + /// [debugToken] is the debug token registered in the Firebase Console. + /// If omitted, the C++ SDK falls back to the `APP_CHECK_DEBUG_TOKEN` + /// environment variable. + const WindowsDebugProvider({this.debugToken}) : super('debug'); + + /// The debug token for this provider. + final String? debugToken; +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/copyright.txt b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/copyright.txt new file mode 100644 index 000000000000..4e197781c6db --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2025, the Chromium project authors. Please see the AUTHORS file +for details. All rights reserved. Use of this source code is governed by a +BSD-style license that can be found in the LICENSE file. \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart new file mode 100644 index 000000000000..e84ff78ab5f4 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pigeons/messages.dart @@ -0,0 +1,48 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/pigeon/messages.pigeon.dart', + dartPackageName: 'firebase_app_check_platform_interface', + kotlinOut: + '../firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt', + kotlinOptions: KotlinOptions( + package: 'io.flutter.plugins.firebase.appcheck', + ), + swiftOut: + '../firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift', + cppHeaderOut: '../firebase_app_check/windows/messages.g.h', + cppSourceOut: '../firebase_app_check/windows/messages.g.cpp', + cppOptions: CppOptions(namespace: 'firebase_app_check_windows'), + copyrightHeader: 'pigeons/copyright.txt', + ), +) +@HostApi(dartHostTestHandler: 'TestFirebaseAppCheckHostApi') +abstract class FirebaseAppCheckHostApi { + @async + void activate( + String appName, + String? androidProvider, + String? appleProvider, + String? debugToken, + ); + + @async + String? getToken(String appName, bool forceRefresh); + + @async + void setTokenAutoRefreshEnabled( + String appName, + bool isTokenAutoRefreshEnabled, + ); + + @async + String registerTokenListener(String appName); + + @async + String getLimitedUseAppCheckToken(String appName); +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 98f24a09895a..7fd0731274db 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -20,3 +20,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 + pigeon: 25.3.2 diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart index 721dc2de0b7c..5f215cec19fc 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart @@ -2,24 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - import 'package:firebase_app_check_platform_interface/firebase_app_check_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter/services.dart'; import '../mock.dart'; void main() { setupFirebaseAppCheckMocks(); - late FirebaseAppCheckPlatform appCheck; late FirebaseApp secondaryApp; - final List methodCallLogger = []; group('$MethodChannelFirebaseAppCheck', () { setUpAll(() async { - FirebaseApp app = await Firebase.initializeApp(); + await Firebase.initializeApp(); secondaryApp = await Firebase.initializeApp( name: 'secondaryApp', options: const FirebaseOptions( @@ -29,28 +24,11 @@ void main() { messagingSenderId: '1234567890', ), ); - handleMethodCall((call) async { - methodCallLogger.add(call); - - switch (call.method) { - case 'FirebaseAppCheck#registerTokenListener': - return 'channelName'; - case 'FirebaseAppCheck#getToken': - return 'test-token'; - default: - return true; - } - }); - - appCheck = MethodChannelFirebaseAppCheck(app: app); - }); - - setUp(() async { - methodCallLogger.clear(); }); group('delegateFor()', () { test('returns a [FirebaseAppCheckPlatform]', () { + final appCheck = FirebaseAppCheckPlatform.instance; expect( // ignore: invalid_use_of_protected_member appCheck.delegateFor(app: secondaryApp), @@ -61,96 +39,10 @@ void main() { group('setInitialValues()', () { test('returns a [MethodChannelFirebaseAppCheck]', () { + final appCheck = MethodChannelFirebaseAppCheck.instance; // ignore: invalid_use_of_protected_member expect(appCheck.setInitialValues(), appCheck); }); }); - - test('activate', () async { - await appCheck.activate( - webProvider: ReCaptchaV3Provider('test-key'), - providerAndroid: const AndroidPlayIntegrityProvider(), - providerApple: const AppleDeviceCheckProvider(), - ); - expect( - methodCallLogger, - [ - isMethodCall( - 'FirebaseAppCheck#activate', - arguments: { - 'appName': defaultFirebaseAppName, - 'androidProvider': 'playIntegrity', - 'appleProvider': 'deviceCheck', - }, - ), - ], - ); - }); - - test('activate with debug providers', () async { - await appCheck.activate( - webProvider: ReCaptchaV3Provider('test-key'), - providerAndroid: const AndroidDebugProvider(debugToken: 'androidDebug'), - providerApple: const AppleDebugProvider(debugToken: 'appleDebug'), - ); - expect( - methodCallLogger, - [ - isMethodCall( - 'FirebaseAppCheck#activate', - arguments: { - 'appName': defaultFirebaseAppName, - 'androidProvider': 'debug', - 'appleProvider': 'debug', - 'androidDebugToken': 'androidDebug', - 'appleDebugToken': 'appleDebug', - }, - ), - ], - ); - }); - - test('getToken', () async { - final tokenResult = await appCheck.getToken(true); - expect( - methodCallLogger, - [ - isMethodCall( - 'FirebaseAppCheck#getToken', - arguments: { - 'appName': defaultFirebaseAppName, - 'forceRefresh': true, - }, - ), - ], - ); - - expect(tokenResult, isA()); - }); - - test('setTokenAutoRefreshEnabled', () async { - await appCheck.setTokenAutoRefreshEnabled(false); - expect( - methodCallLogger, - [ - isMethodCall( - 'FirebaseAppCheck#setTokenAutoRefreshEnabled', - arguments: { - 'appName': defaultFirebaseAppName, - 'isTokenAutoRefreshEnabled': false, - }, - ), - ], - ); - }); - - test('tokenChanges', () async { - final stream = appCheck.onTokenChange; - expect(stream, isA>()); - }); }); } - -class TestMethodChannelFirebaseAppCheck extends MethodChannelFirebaseAppCheck { - TestMethodChannelFirebaseAppCheck(FirebaseApp app) : super(app: app); -} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/test/mock.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/test/mock.dart index 9cefc319fe4c..454b7253292b 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/test/mock.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/test/mock.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:firebase_app_check_platform_interface/firebase_app_check_platform_interface.dart'; -import 'package:firebase_app_check_platform_interface/src/method_channel/method_channel_firebase_app_check.dart'; import 'package:firebase_core_platform_interface/test.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -17,21 +15,4 @@ void setupFirebaseAppCheckMocks([Callback? customHandlers]) { TestWidgetsFlutterBinding.ensureInitialized(); setupFirebaseCoreMocks(); - - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(MethodChannelFirebaseAppCheck.channel, - (MethodCall methodCall) async { - methodCallLog.add(methodCall); - switch (methodCall.method) { - default: - return false; - } - }); } - -void handleMethodCall(MethodCallCallback methodCallCallback) => - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(MethodChannelFirebaseAppCheck.channel, - (call) async { - return await methodCallCallback(call); - }); diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart b/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart index 8524c3a1352c..cfb4a24e9ce0 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart @@ -132,6 +132,7 @@ class FirebaseAppCheckWeb extends FirebaseAppCheckPlatform { AppleProvider? appleProvider, AndroidAppCheckProvider? providerAndroid, AppleAppCheckProvider? providerApple, + WindowsAppCheckProvider? providerWindows, }) async { // save the recaptcha type and site key for future startups if (webProvider != null) { diff --git a/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.mocks.dart b/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.mocks.dart index 122699cb4b89..357b30beeca5 100644 --- a/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.mocks.dart +++ b/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.mocks.dart @@ -141,6 +141,7 @@ class MockFirebaseAppCheckWeb extends _i1.Mock _i3.AppleProvider? appleProvider, _i3.AndroidAppCheckProvider? providerAndroid, _i3.AppleAppCheckProvider? providerApple, + _i3.WindowsAppCheckProvider? providerWindows, }) => (super.noSuchMethod( Invocation.method( @@ -152,6 +153,7 @@ class MockFirebaseAppCheckWeb extends _i1.Mock #appleProvider: appleProvider, #providerAndroid: providerAndroid, #providerApple: providerApple, + #providerWindows: providerWindows, }, ), returnValue: _i5.Future.value(), diff --git a/packages/firebase_core/firebase_core/windows/CMakeLists.txt b/packages/firebase_core/firebase_core/windows/CMakeLists.txt index d944944c8c8a..277ea0e10c24 100644 --- a/packages/firebase_core/firebase_core/windows/CMakeLists.txt +++ b/packages/firebase_core/firebase_core/windows/CMakeLists.txt @@ -122,7 +122,7 @@ add_subdirectory(${FIREBASE_CPP_SDK_DIR} bin/ EXCLUDE_FROM_ALL) target_include_directories(${PLUGIN_NAME} INTERFACE "${FIREBASE_CPP_SDK_DIR}/include") -set(FIREBASE_RELEASE_PATH_LIBS firebase_app firebase_auth firebase_remote_config firebase_storage firebase_firestore firebase_database) +set(FIREBASE_RELEASE_PATH_LIBS firebase_app firebase_auth firebase_remote_config firebase_storage firebase_firestore firebase_database firebase_app_check) foreach(firebase_lib IN ITEMS ${FIREBASE_RELEASE_PATH_LIBS}) get_target_property(firebase_lib_path ${firebase_lib} IMPORTED_LOCATION) string(REPLACE "Debug" "Release" firebase_lib_release_path ${firebase_lib_path}) diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.mocks.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.mocks.dart index 625e092f5989..828b48d4f7e7 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.mocks.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.mocks.dart @@ -778,6 +778,8 @@ class MockFirebaseAppCheck extends _i1.Mock implements _i10.FirebaseAppCheck { const _i11.AndroidPlayIntegrityProvider(), _i11.AppleAppCheckProvider? providerApple = const _i11.AppleDeviceCheckProvider(), + _i11.WindowsAppCheckProvider? providerWindows = + const _i11.WindowsDebugProvider(), }) => (super.noSuchMethod( Invocation.method( @@ -790,6 +792,7 @@ class MockFirebaseAppCheck extends _i1.Mock implements _i10.FirebaseAppCheck { #appleProvider: appleProvider, #providerAndroid: providerAndroid, #providerApple: providerApple, + #providerWindows: providerWindows, }, ), returnValue: _i6.Future.value(), diff --git a/scripts/generate_versions_spm.dart b/scripts/generate_versions_spm.dart index 8bc30470bd46..27485fd76e32 100644 --- a/scripts/generate_versions_spm.dart +++ b/scripts/generate_versions_spm.dart @@ -25,9 +25,10 @@ void main(List args) async { final firebaseiOSVersion = getFirebaseiOSVersion(firebaseCoreIosVersionFile); // Update hard-coded versions in all plugin Package.swift files - final firebaseCoreVersion = - loadYaml(File('${firebaseCorePackage.path}/pubspec.yaml').readAsStringSync())['version'] - .toString(); + final firebaseCoreVersion = loadYaml( + File('${firebaseCorePackage.path}/pubspec.yaml') + .readAsStringSync())['version'] + .toString(); updatePluginPackageSwiftVersions( workspace, firebaseiOSVersion, @@ -128,6 +129,8 @@ void updateLibraryVersionPureSwiftPlugins() { 'firebase_ml_model_downloader', 'firebase_app_installations', 'cloud_functions', + 'firebase_remote_config', + 'firebase_app_check', ]; for (final package in packages) { diff --git a/tests/integration_test/e2e_test.dart b/tests/integration_test/e2e_test.dart index 75818dc8f3a0..12511585363c 100644 --- a/tests/integration_test/e2e_test.dart +++ b/tests/integration_test/e2e_test.dart @@ -78,6 +78,7 @@ void main() { firebase_auth.main(); firebase_remote_config.main(); firebase_storage.main(); + firebase_app_check.main(); break; default: throw UnsupportedError( diff --git a/tests/windows/flutter/generated_plugin_registrant.cc b/tests/windows/flutter/generated_plugin_registrant.cc index 9a180bb54481..b6d55c18d245 100644 --- a/tests/windows/flutter/generated_plugin_registrant.cc +++ b/tests/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,7 @@ #include "generated_plugin_registrant.h" +#include #include #include #include @@ -13,6 +14,8 @@ #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FirebaseAppCheckPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseAppCheckPluginCApi")); FirebaseAuthPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); FirebaseCorePluginCApiRegisterWithRegistrar( diff --git a/tests/windows/flutter/generated_plugins.cmake b/tests/windows/flutter/generated_plugins.cmake index 1a9da22be867..89f9a20f171a 100644 --- a/tests/windows/flutter/generated_plugins.cmake +++ b/tests/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + firebase_app_check firebase_auth firebase_core firebase_database From b3ab00036c70debca59414ea236c5012fb841a63 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 2 Apr 2026 09:07:21 +0200 Subject: [PATCH 006/137] feat: bump JS SDK to version 12.11.0 (#18160) --- .../firebase_core_web/lib/src/firebase_sdk_version.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart index 3e04c6928134..8de3584a7165 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart @@ -6,4 +6,4 @@ part of '../firebase_core_web.dart'; /// The currently supported Firebase JS SDK version. -const String supportedFirebaseJsSdkVersion = '12.9.0'; +const String supportedFirebaseJsSdkVersion = '12.11.0'; From 2664b2c2dab4d0147461ce4d3f7862267e880542 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 2 Apr 2026 09:07:46 +0200 Subject: [PATCH 007/137] feat: bump iOS SDK to version 12.11.0 (#18161) --- .../firebase_core/firebase_core/ios/firebase_sdk_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb index accce4bb66a3..f36a836d1580 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb +++ b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb @@ -1,4 +1,4 @@ # https://firebase.google.com/support/release-notes/ios def firebase_sdk_version!() - '12.9.0' + '12.11.0' end From 7d32374045e21ca1d9e360b580edda1ccb41949c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:12:14 +0200 Subject: [PATCH 008/137] chore(deps): bump dart-lang/setup-dart from 1.7.1 to 1.7.2 (#18162) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.7.1 to 1.7.2. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c...65eb853c7ba17dde3be364c3d2858773e7144260) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-version: 1.7.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/all_plugins.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index ac5acce22e61..1b62f4c6281d 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -193,7 +193,7 @@ jobs: # check-license-header) - run: go install github.com/google/addlicense@latest - name: Install Dart - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c + uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260 - name: Install Melos uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa with: From f701b1ac8488d33d8de5578fe247c07a35fa2c7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:12:26 +0200 Subject: [PATCH 009/137] chore(deps): bump ossf/scorecard-action from 2.4.0 to 2.4.3 (#18163) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.0 to 2.4.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/62b2cac7ed8198b15735ed49ab1e5cf35480ba46...4eaacf0543bb3f2c246792bd56e8cdeffafb205a) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ossf-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 95e86678e12e..6ae3d045155f 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif From 3f06afbaab605f0b7ebad402ab5438eed3580f0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:12:40 +0200 Subject: [PATCH 010/137] chore(deps): bump bluefireteam/melos-action (#18164) Bumps [bluefireteam/melos-action](https://github.com/bluefireteam/melos-action) from c7dcb921b23cc520cace360b95d02b37bf09cdaa to 705015c3d2bc4ab94201ac24accb2bbe070cf533. - [Release notes](https://github.com/bluefireteam/melos-action/releases) - [Commits](https://github.com/bluefireteam/melos-action/compare/c7dcb921b23cc520cace360b95d02b37bf09cdaa...705015c3d2bc4ab94201ac24accb2bbe070cf533) --- updated-dependencies: - dependency-name: bluefireteam/melos-action dependency-version: 705015c3d2bc4ab94201ac24accb2bbe070cf533 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/all_plugins.yaml | 16 ++++++++-------- .github/workflows/android.yaml | 2 +- .github/workflows/e2e_tests_fdc.yaml | 8 ++++---- .github/workflows/ios.yaml | 2 +- .github/workflows/macos.yaml | 2 +- .github/workflows/web.yaml | 6 +++--- .github/workflows/windows.yaml | 4 ++-- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 1b62f4c6281d..8a85f7f9bf8b 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -30,7 +30,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: melos-version: '5.3.0' - name: 'Run Analyze' @@ -50,7 +50,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: melos-version: '5.3.0' - name: 'Pub Check' @@ -69,7 +69,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: melos-version: '5.3.0' - name: 'Flutter Pub Get' @@ -89,7 +89,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: melos-version: '5.3.0' - uses: Homebrew/actions/setup-homebrew@master @@ -125,7 +125,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: melos-version: '5.3.0' - name: 'Build Examples' @@ -154,7 +154,7 @@ jobs: cd packages/firebase_core/firebase_core/example flutter pub add $FLUTTER_DEPENDENCIES cd ../../../.. - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: melos-version: '5.3.0' - name: 'Swift Integration Setup' @@ -173,7 +173,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: melos-version: '5.3.0' - name: 'Flutter Test' @@ -195,7 +195,7 @@ jobs: - name: Install Dart uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260 - name: Install Melos - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: # Running `melos bootstrap` is not needed because we use Melos just # for the `check-license-header` script. diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 54bb34693732..6505223c5b5c 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -68,7 +68,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 998ae091362d..b5d8ad3f956c 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -67,7 +67,7 @@ jobs: pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - name: Setup PostgreSQL for Linux/macOS/Windows uses: ikalnytskyi/action-setup-postgres@v7 - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' @@ -192,7 +192,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' @@ -281,7 +281,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' @@ -360,7 +360,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 494ca9adc250..5118008dc7c6 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -81,7 +81,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index b92acb0687ea..eba5c18208b2 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -79,7 +79,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index 7ebde01e698b..da55914fffeb 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -49,7 +49,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' @@ -119,7 +119,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' @@ -199,7 +199,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '5.3.0' diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 1783aa967913..2a56eee0ef39 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -44,7 +44,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '3.0.0' @@ -78,7 +78,7 @@ jobs: cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false melos-version: '3.0.0' From 502dd0ec2ed57d5d9efd5c117ccd1d7d1cd53fca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:12:53 +0200 Subject: [PATCH 011/137] chore(deps): bump actions/setup-go from 5.3.0 to 6.4.0 (#18165) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.3.0 to 6.4.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/f111f3307d8850f501ac008e886eec1fd1932a34...4a3601121dd01d1626a1e23e37211e3254c1c06c) --- updated-dependencies: - dependency-name: actions/setup-go dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/all_plugins.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 8a85f7f9bf8b..f6cb84512f8c 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -186,7 +186,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c with: go-version: '^1.13.1' # Go is used by addlicense command (addlicense is used in melos run From e9c99ef6a9421430258db16cefca2f0eb5f3c4cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:13:06 +0200 Subject: [PATCH 012/137] chore(deps): bump actions/cache from 4.2.0 to 5.0.4 (#18166) Bumps [actions/cache](https://github.com/actions/cache) from 4.2.0 to 5.0.4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/1bd1e32a3bdc45362d1e726936510720a7c30a57...668228422ae6a00e4ad889ee87cd7109ec5666a7) --- updated-dependencies: - dependency-name: actions/cache dependency-version: 5.0.4 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/android.yaml | 8 ++++---- .github/workflows/e2e_tests_fdc.yaml | 24 ++++++++++++------------ .github/workflows/ios.yaml | 8 ++++---- .github/workflows/macos.yaml | 8 ++++---- .github/workflows/web.yaml | 12 ++++++------ 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 6505223c5b5c..bcd3a290d84e 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -53,7 +53,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -92,7 +92,7 @@ jobs: remove-docker-images: true remove-large-packages: true - name: AVD cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true id: avd-cache with: @@ -119,7 +119,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 with: # The firebase emulators are pure javascript and java, OS-independent enableCrossOsArchive: true @@ -129,7 +129,7 @@ jobs: - name: Save Android Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 with: key: ${{ steps.avd-cache.outputs.cache-primary-key }} # Must match the restore path exactly diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index b5d8ad3f956c..09c75e073f17 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -50,7 +50,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -95,7 +95,7 @@ jobs: remove-docker-images: true remove-large-packages: true - name: AVD cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 id: avd-cache continue-on-error: true with: @@ -117,7 +117,7 @@ jobs: - name: Save Android Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: key: ${{ steps.avd-cache.outputs.cache-primary-key }} @@ -128,7 +128,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -162,7 +162,7 @@ jobs: key: xcode-cache-${{ runner.os }} save: "${{ github.ref == 'refs/heads/main' }}" max-size: 700M - - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true name: Pods Cache id: pods-cache @@ -177,7 +177,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -240,7 +240,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -251,7 +251,7 @@ jobs: - name: Save Pods Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: key: ${{ steps.pods-cache.outputs.cache-primary-key }} @@ -293,7 +293,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -328,7 +328,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -372,7 +372,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -407,7 +407,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 5118008dc7c6..5e8df18080a0 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -51,7 +51,7 @@ jobs: key: xcode-cache-${{ runner.os }} save: "${{ github.ref == 'refs/heads/main' }}" max-size: 700M - - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true name: Pods Cache id: pods-cache @@ -66,7 +66,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -139,7 +139,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -150,7 +150,7 @@ jobs: - name: Save Pods Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: key: ${{ steps.pods-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index eba5c18208b2..d9c41a6376c9 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -51,7 +51,7 @@ jobs: max-size: 700M - name: Pods Cache continue-on-error: true - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 id: pods-cache with: # Must match the save path exactly @@ -64,7 +64,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -126,7 +126,7 @@ jobs: continue-on-error: true # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 with: # The firebase emulators are pure javascript and java, OS-independent enableCrossOsArchive: true @@ -137,7 +137,7 @@ jobs: continue-on-error: true # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 with: key: ${{ steps.pods-cache.outputs.cache-primary-key }} # Must match the restore paths exactly diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index da55914fffeb..30472fb9d097 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -61,7 +61,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -92,7 +92,7 @@ jobs: # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' continue-on-error: true - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 with: # The firebase emulators are pure javascript and java, OS-independent enableCrossOsArchive: true @@ -131,7 +131,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -166,7 +166,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -211,7 +211,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -242,7 +242,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent From bb1e04f8cd0f29cad3913af7bcf40744ffb2515a Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Thu, 2 Apr 2026 11:11:35 -0700 Subject: [PATCH 013/137] feat(firebaseai): add spm support for firebase_ai, and update example to running with spm (#18159) * add spm support for firebase_ai, and update example to running with spm * remove unnecessary test file * delete one more non-necessary test file * try to fix review comments * delete * this package doesn't need cSettings * fix formatter * add firebase_ai to the github swift integration workflow --- .github/workflows/all_plugins.yaml | 2 +- .../firebase_ai/firebase_ai/example/.metadata | 18 +++-- .../ios/Flutter/AppFrameworkInfo.plist | 2 +- .../firebase_ai/example/ios/Podfile | 1 - .../ios/Runner.xcodeproj/project.pbxproj | 70 ++++++++++--------- .../firebase_ai/example/macos/Podfile | 1 - .../macos/Runner.xcodeproj/project.pbxproj | 70 +++++++++++++------ .../contents.xcworkspacedata | 7 ++ .../xcshareddata/xcschemes/Runner.xcscheme | 18 +++++ .../firebase_ai/example/pubspec.yaml | 2 +- .../firebase_ai/ios/firebase_ai/Package.swift | 28 ++++++++ .../macos/firebase_ai/Package.swift | 28 ++++++++ 12 files changed, 183 insertions(+), 64 deletions(-) create mode 100644 packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/firebase_ai/firebase_ai/ios/firebase_ai/Package.swift create mode 100644 packages/firebase_ai/firebase_ai/macos/firebase_ai/Package.swift diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index f6cb84512f8c..d2d71d5a0fde 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -136,7 +136,7 @@ jobs: runs-on: macos-15 timeout-minutes: 45 env: - FLUTTER_DEPENDENCIES: "cloud_firestore firebase_remote_config cloud_functions firebase_database firebase_auth firebase_storage firebase_analytics firebase_messaging firebase_app_check firebase_in_app_messaging firebase_performance firebase_crashlytics firebase_ml_model_downloader firebase_app_installations" + FLUTTER_DEPENDENCIES: "cloud_firestore firebase_remote_config cloud_functions firebase_database firebase_auth firebase_storage firebase_analytics firebase_messaging firebase_app_check firebase_in_app_messaging firebase_performance firebase_crashlytics firebase_ml_model_downloader firebase_app_installations firebase_ai" PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 diff --git a/packages/firebase_ai/firebase_ai/example/.metadata b/packages/firebase_ai/firebase_ai/example/.metadata index b6128fc4f019..9ab588718994 100644 --- a/packages/firebase_ai/firebase_ai/example/.metadata +++ b/packages/firebase_ai/firebase_ai/example/.metadata @@ -4,8 +4,8 @@ # This file should be version controlled and should not be manually edited. version: - revision: "2615ab6c1932e44e6802aaba8dc715b387ff155f" - channel: "main" + revision: "aa1d2edd012bbf31e58827bf3ac7010c10991e20" + channel: "beta" project_type: app @@ -13,11 +13,17 @@ project_type: app migration: platforms: - platform: root - create_revision: 2615ab6c1932e44e6802aaba8dc715b387ff155f - base_revision: 2615ab6c1932e44e6802aaba8dc715b387ff155f + create_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 + base_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 + - platform: ios + create_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 + base_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 + - platform: macos + create_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 + base_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 - platform: android - create_revision: 2615ab6c1932e44e6802aaba8dc715b387ff155f - base_revision: 2615ab6c1932e44e6802aaba8dc715b387ff155f + create_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 + base_revision: aa1d2edd012bbf31e58827bf3ac7010c10991e20 # User provided section diff --git a/packages/firebase_ai/firebase_ai/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_ai/firebase_ai/example/ios/Flutter/AppFrameworkInfo.plist index 7c5696400627..0d14080090af 100644 --- a/packages/firebase_ai/firebase_ai/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/firebase_ai/firebase_ai/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 12.0 + 15.0 diff --git a/packages/firebase_ai/firebase_ai/example/ios/Podfile b/packages/firebase_ai/firebase_ai/example/ios/Podfile index a419e4239013..9d7ef08d52b2 100644 --- a/packages/firebase_ai/firebase_ai/example/ios/Podfile +++ b/packages/firebase_ai/firebase_ai/example/ios/Podfile @@ -29,7 +29,6 @@ flutter_ios_podfile_setup target 'Runner' do use_frameworks! - use_modular_headers! flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do diff --git a/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj index 40278fc43dec..2552246e5d98 100644 --- a/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj @@ -55,6 +55,9 @@ 5F1FA05866A2D0FCA3287B20 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = Flutter/ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* firebase_ai */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = firebase_ai; path = ../../ios/firebase_ai; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 8ACDC47C7E9AF1A1B9595598 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 94CE5BFCDF90764354BB6740 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -115,6 +118,9 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78DABEA22ED26510000E7860 /* firebase_ai */, + 784666492D4C4C64000A1A5F /* FlutterFramework */, + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -195,14 +201,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - F51794D56D63ACA383D5C2E4 /* [CP] Check Pods Manifest.lock */, + 65E1413F3D5F0EF9AF4CD1AB /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 34F21DFC67109DEAFD936E80 /* [CP] Embed Pods Frameworks */, + 7C03669E7720256A458F4A2F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -281,23 +287,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 34F21DFC67109DEAFD936E80 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -314,42 +303,59 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 65E1413F3D5F0EF9AF4CD1AB /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Run Script"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - F51794D56D63ACA383D5C2E4 /* [CP] Check Pods Manifest.lock */ = { + 7C03669E7720256A458F4A2F /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( ); + inputPaths = ( + ); + name = "Run Script"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; F5C7CFE0E232B64D613F0623 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; diff --git a/packages/firebase_ai/firebase_ai/example/macos/Podfile b/packages/firebase_ai/firebase_ai/example/macos/Podfile index b52666a10389..ff5ddb3b8bdc 100644 --- a/packages/firebase_ai/firebase_ai/example/macos/Podfile +++ b/packages/firebase_ai/firebase_ai/example/macos/Podfile @@ -28,7 +28,6 @@ flutter_macos_podfile_setup target 'Runner' do use_frameworks! - use_modular_headers! flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do diff --git a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj index 4bc66a519ca5..9a68c0a44f3c 100644 --- a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 3D1CF19370CB8E26E5C667A5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -85,11 +86,14 @@ 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 766A2E414AFDFA56243527A6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 816B0EE72BF94FC5261D04E6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; A2911B8EF91B3925874FDE6A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* firebase_ai */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = firebase_ai; path = ../../macos/firebase_ai; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -105,6 +109,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, 3D1CF19370CB8E26E5C667A5 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -167,6 +172,9 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78DABEA22ED26510000E7860 /* firebase_ai */, + 784666492D4C4C64000A1A5F /* FlutterFramework */, + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -198,7 +206,6 @@ 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */, 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -237,13 +244,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - E10F886575A4AF9F1D3D5C5B /* [CP] Check Pods Manifest.lock */, + 606AE4A9031C7C91EFF70994 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - 1D3525FBE401B81EB0265948 /* [CP] Embed Pods Frameworks */, + 7035891EAAFF34285DDE160B /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -251,6 +258,9 @@ 33CC11202044C79F0003C045 /* PBXTargetDependency */, ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 33CC10ED2044A3C60003C045 /* example.app */; productType = "com.apple.product-type.application"; @@ -295,6 +305,9 @@ Base, ); mainGroup = 33CC10E42044A3C60003C045; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -327,23 +340,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 1D3525FBE401B81EB0265948 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -404,7 +400,7 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - E10F886575A4AF9F1D3D5C5B /* [CP] Check Pods Manifest.lock */ = { + 606AE4A9031C7C91EFF70994 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -426,6 +422,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 7035891EAAFF34285DDE160B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -800,6 +813,21 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + package = 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..919434a6254f --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index b0a82f087ad1..49eac59ad872 100644 --- a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + Date: Thu, 2 Apr 2026 17:29:02 -0700 Subject: [PATCH 014/137] feat(firebaseai): server prompt chat and function calling (#17972) * add chat and function back to server prompt template * auto function calling for server prompt template * update with api decision * add tool structure * kts support * fix compile error for server template page * Add auto function calling to chat stream, and add test cases * add tools and toolConfig into template request * fix the template function name and update the schema override sample * add too config * some fix for e2e test * fix analyzer * tiny year change * bot review comment * fix analyzer and formatter * remove unrelated files from PR * fix formatter --- .../lib/pages/function_calling_page.dart | 37 +- .../lib/pages/server_template_page.dart | 324 ++++++++++++++---- .../lib/utils/function_call_utils.dart | 47 +++ .../firebase_ai/lib/firebase_ai.dart | 9 +- .../firebase_ai/lib/src/base_model.dart | 17 + .../src/server_template/template_chat.dart | 249 ++++++++++++++ .../template_generative_model.dart | 49 ++- .../template_imagen_model.dart | 4 +- .../src/server_template/template_tool.dart | 105 ++++++ 9 files changed, 728 insertions(+), 113 deletions(-) create mode 100644 packages/firebase_ai/firebase_ai/example/lib/utils/function_call_utils.dart create mode 100644 packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart create mode 100644 packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart index 633106664ba1..ccd09c3e1b34 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart @@ -15,6 +15,7 @@ import 'package:flutter/material.dart'; import 'package:firebase_ai/firebase_ai.dart'; import 'package:firebase_auth/firebase_auth.dart'; +import '../utils/function_call_utils.dart'; import '../widgets/message_widget.dart'; class FunctionCallingPage extends StatefulWidget { @@ -31,13 +32,6 @@ class FunctionCallingPage extends StatefulWidget { State createState() => _FunctionCallingPageState(); } -class Location { - final String city; - final String state; - - Location(this.city, this.state); -} - class _FunctionCallingPageState extends State { late GenerativeModel _functionCallModel; late GenerativeModel _autoFunctionCallModel; @@ -80,7 +74,7 @@ class _FunctionCallingPageState extends State { 'The date for which to get the weather. Date must be in the format: YYYY-MM-DD.', ), }, - callable: _fetchWeatherCallable, + callable: fetchWeatherCallable, ); _autoFindRestaurantsTool = AutoFunctionDeclaration( name: 'findRestaurants', @@ -231,16 +225,6 @@ class _FunctionCallingPageState extends State { }; } - Future> _fetchWeatherCallable( - Map args, - ) async { - final locationData = args['location']! as Map; - final city = locationData['city']! as String; - final state = locationData['state']! as String; - final date = args['date']! as String; - return fetchWeather(Location(city, state), date); - } - void _initializeModel() { final generationConfig = GenerationConfig( thinkingConfig: _enableThinking @@ -301,23 +285,6 @@ class _FunctionCallingPageState extends State { ); } - // This is a hypothetical API to return a fake weather data collection for - // certain location - Future> fetchWeather( - Location location, - String date, - ) async { - // TODO(developer): Call a real weather API. - // Mock response from the API. In developer live code this would call the - // external API and return what that API returns. - final apiResponse = { - 'temperature': 38, - 'chancePrecipitation': '56%', - 'cloudConditions': 'partly-cloudy', - }; - return apiResponse; - } - /// Actual function to demonstrate the function calling feature. final fetchWeatherTool = FunctionDeclaration( 'fetchWeather', diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart index 10386f3e4d7b..c10c6e243323 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart @@ -14,6 +14,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import '../utils/function_call_utils.dart'; import '../widgets/message_widget.dart'; import 'package:firebase_ai/firebase_ai.dart'; @@ -41,6 +42,11 @@ class _ServerTemplatePageState extends State { // ignore: experimental_member_use TemplateGenerativeModel? _templateGenerativeModel; + TemplateChatSession? _chatSession; + TemplateChatSession? _chatFunctionOverrideSession; + TemplateChatSession? _chatAutoFunctionSession; + TemplateChatSession? _chatStreamFunctionSession; + @override void initState() { super.initState(); @@ -57,15 +63,84 @@ class _ServerTemplatePageState extends State { // ignore: experimental_member_use FirebaseAI.googleAI().templateGenerativeModel(); } + + // Inputs are now provided ONCE here when creating the session + _chatSession = _templateGenerativeModel?.startChat( + 'chat_history.prompt', + inputs: {}, + ); + _chatFunctionOverrideSession = _templateGenerativeModel?.startChat( + 'cj-function-calling-weather-override', + inputs: {}, + tools: [ + TemplateTool.functionDeclarations([ + TemplateFunctionDeclaration( + 'fetchWeather', + parameters: { + 'location': JSONSchema.object( + description: + 'The name of the city and its state for which to get ' + 'the weather. Only cities in the USA are supported.', + properties: { + 'city': JSONSchema.string( + description: 'The city of the location.', + ), + 'state': JSONSchema.string( + description: 'The state of the location.', + ), + 'zipCode': JSONSchema.integer( + description: 'Optional zip code of the location.', + nullable: true, + ), + }, + optionalProperties: ['zipCode'], + ), + 'date': JSONSchema.string( + description: 'The date for which to get the weather. ' + 'Date must be in the format: YYYY-MM-DD.', + ), + 'unit': JSONSchema.enumString( + enumValues: ['CELSIUS', 'FAHRENHEIT'], + description: 'The temperature unit.', + nullable: true, + ), + }, + optionalParameters: ['unit'], + ), + ]), + ], + ); + _chatAutoFunctionSession = _templateGenerativeModel?.startChat( + 'cj-function-calling-weather', + inputs: {}, + tools: [ + TemplateTool.functionDeclarations([ + TemplateAutoFunctionDeclaration( + name: 'fetchWeather', + callable: fetchWeatherCallable, + ), + ]), + ], + ); + _chatStreamFunctionSession = _templateGenerativeModel?.startChat( + 'cj-function-calling-weather-stream', + inputs: {}, + tools: [ + TemplateTool.functionDeclarations([ + TemplateAutoFunctionDeclaration( + name: 'fetchWeather', + callable: fetchWeatherCallable, + ), + ]), + ], + ); } void _scrollDown() { WidgetsBinding.instance.addPostFrameCallback( (_) => _scrollController.animateTo( _scrollController.position.maxScrollExtent, - duration: const Duration( - milliseconds: 750, - ), + duration: const Duration(milliseconds: 750), curve: Curves.easeOutCirc, ), ); @@ -74,9 +149,7 @@ class _ServerTemplatePageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), + appBar: AppBar(title: Text(widget.title)), body: Padding( padding: const EdgeInsets.all(8), child: Column( @@ -104,10 +177,7 @@ class _ServerTemplatePageState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), + padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 15), child: Row( children: [ Expanded( @@ -118,10 +188,58 @@ class _ServerTemplatePageState extends State { onSubmitted: _sendServerTemplateMessage, ), ), - const SizedBox.square( - dimension: 15, - ), + const SizedBox.square(dimension: 15), if (!_loading) ...[ + if (!_loading) + IconButton( + onPressed: () async { + await _serverTemplateAutoFunctionCall( + _textController.text, + ); + }, + icon: Icon( + Icons.auto_mode, + color: Theme.of(context).colorScheme.primary, + ), + tooltip: 'Auto Function Calling', + ), + if (!_loading) + IconButton( + onPressed: () async { + await _serverTemplateFunctionCall( + _textController.text, + ); + }, + icon: Icon( + Icons.functions, + color: Theme.of(context).colorScheme.primary, + ), + tooltip: 'Function Calling (client override)', + ), + if (!_loading) + IconButton( + onPressed: () async { + await _serverTemplateAutoStreamFunctionCall( + _textController.text, + ); + }, + icon: Icon( + Icons.smart_toy, + color: Theme.of(context).colorScheme.primary, + ), + tooltip: 'Auto Stream Function Calling', + ), + if (!_loading) + IconButton( + onPressed: () async { + await _serverTemplateChat(_textController.text); + }, + icon: Icon( + Icons.chat, + color: Theme.of(context).colorScheme.primary, + ), + tooltip: 'Chat', + ), IconButton( onPressed: () async { await _serverTemplateImageInput(_textController.text); @@ -171,13 +289,31 @@ class _ServerTemplatePageState extends State { ); } - Future _serverTemplateUrlContext(String message) async { + Future _handleServerTemplateMessage( + String message, + Future Function(String) generateContent, + ) async { setState(() { _loading = true; }); try { _messages.add(MessageData(text: message, fromUser: true)); + await generateContent(message); + } catch (e) { + _showError(e.toString()); + } finally { + _textController.clear(); + setState(() { + _loading = false; + }); + _textFieldFocus.requestFocus(); + _scrollDown(); + } + } + + Future _serverTemplateUrlContext(String message) async { + await _handleServerTemplateMessage(message, (message) async { var response = await _templateGenerativeModel // ignore: experimental_member_use ?.generateContent('cj-urlcontext', inputs: {'url': message}); @@ -217,44 +353,113 @@ class _ServerTemplatePageState extends State { } _messages.add(MessageData(text: buffer.toString(), fromUser: false)); } + }); + } - setState(() { - _loading = false; - _scrollDown(); - }); - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } + Future _serverTemplateAutoFunctionCall(String message) async { + await _handleServerTemplateMessage(message, (message) async { + // Inputs are no longer passed during sendMessage + var response = await _chatAutoFunctionSession?.sendMessage( + Content.text(message), + ); + + _messages.add(MessageData(text: response?.text, fromUser: false)); + }); } - Future _serverTemplateImageInput(String message) async { - setState(() { - _loading = true; + Future _serverTemplateFunctionCall(String message) async { + await _handleServerTemplateMessage(message, (message) async { + // Inputs are no longer passed during sendMessage + var response = await _chatFunctionOverrideSession?.sendMessage( + Content.text(message), + ); + + _messages.add(MessageData(text: response?.text, fromUser: false)); + final functionCalls = response?.functionCalls.toList(); + if (functionCalls!.isNotEmpty) { + final functionCall = functionCalls.first; + if (functionCall.name == 'fetchWeather') { + final location = + functionCall.args['location']! as Map; + final date = functionCall.args['date']! as String; + final city = location['city'] as String; + final state = location['state'] as String; + final functionResult = await fetchWeather( + Location(city, state), + date, + ); + + // Respond to the function call + var functionResponse = + await _chatFunctionOverrideSession?.sendMessage( + Content.functionResponse(functionCall.name, functionResult), + ); + _messages.add( + MessageData(text: functionResponse?.text, fromUser: false), + ); + } + } }); + } - try { + Future _serverTemplateAutoStreamFunctionCall(String message) async { + await _handleServerTemplateMessage(message, (message) async { + var responseStream = _chatStreamFunctionSession?.sendMessageStream( + Content.text(message), + ); + + var accumulatedText = ''; + MessageData? modelMessage; + + if (responseStream != null) { + await for (final response in responseStream) { + if (response.text case final text?) { + accumulatedText += text; + if (modelMessage == null) { + modelMessage = MessageData( + text: accumulatedText, + fromUser: false, + ); + _messages.add(modelMessage); + } else { + modelMessage = modelMessage.copyWith(text: accumulatedText); + _messages.last = modelMessage; + } + setState(() {}); + } + } + } + + if (accumulatedText.isEmpty) { + _messages.add( + MessageData(text: 'No text response from model.', fromUser: false), + ); + } + }); + } + + Future _serverTemplateChat(String message) async { + await _handleServerTemplateMessage(message, (message) async { + // Inputs are no longer passed during sendMessage + var response = await _chatSession?.sendMessage(Content.text(message)); + + var text = response?.text; + + _messages.add(MessageData(text: text, fromUser: false)); + }); + } + + Future _serverTemplateImageInput(String message) async { + await _handleServerTemplateMessage(message, (message) async { ByteData catBytes = await rootBundle.load('assets/images/cat.jpg'); var imageBytes = catBytes.buffer.asUint8List(); _messages.add( - MessageData( - text: message, - imageBytes: imageBytes, - fromUser: true, - ), + MessageData(text: message, imageBytes: imageBytes, fromUser: true), ); // ignore: experimental_member_use var response = await _templateGenerativeModel?.generateContent( - 'media.prompt', + 'media', inputs: { 'imageData': { 'isInline': true, @@ -264,23 +469,7 @@ class _ServerTemplatePageState extends State { }, ); _messages.add(MessageData(text: response?.text, fromUser: false)); - - setState(() { - _loading = false; - _scrollDown(); - }); - } catch (e) { - _showError(e.toString()); - setState(() { - _loading = false; - }); - } finally { - _textController.clear(); - setState(() { - _loading = false; - }); - _textFieldFocus.requestFocus(); - } + }); } Future _sendServerTemplateMessage(String message) async { @@ -295,11 +484,6 @@ class _ServerTemplatePageState extends State { ?.generateContent('new-greeting', inputs: {}); _messages.add(MessageData(text: response?.text, fromUser: false)); - - setState(() { - _loading = false; - _scrollDown(); - }); } catch (e) { _showError(e.toString()); setState(() { @@ -320,8 +504,9 @@ class _ServerTemplatePageState extends State { }); try { - _messages - .add(MessageData(text: 'Testing code execution', fromUser: true)); + _messages.add( + MessageData(text: 'Testing code execution', fromUser: true), + ); final response = await _templateGenerativeModel // ignore: experimental_member_use ?.generateContent('cj-code-execution', inputs: {}); @@ -344,12 +529,7 @@ class _ServerTemplatePageState extends State { } if (buffer.isNotEmpty) { - _messages.add( - MessageData( - text: buffer.toString(), - fromUser: false, - ), - ); + _messages.add(MessageData(text: buffer.toString(), fromUser: false)); } setState(() { @@ -376,9 +556,7 @@ class _ServerTemplatePageState extends State { builder: (context) { return AlertDialog( title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), + content: SingleChildScrollView(child: SelectableText(message)), actions: [ TextButton( onPressed: () { diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/function_call_utils.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/function_call_utils.dart new file mode 100644 index 000000000000..fcbd01151063 --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/lib/utils/function_call_utils.dart @@ -0,0 +1,47 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +class Location { + final String city; + final String state; + + Location(this.city, this.state); +} + +// This is a hypothetical API to return a fake weather data collection for +// certain location +Future> fetchWeather( + Location location, + String date, +) async { + // TODO(developer): Call a real weather API. + // Mock response from the API. In developer live code this would call the + // external API and return what that API returns. + final apiResponse = { + 'temperature': 38, + 'chancePrecipitation': '56%', + 'cloudConditions': 'partly-cloudy', + }; + return apiResponse; +} + +Future> fetchWeatherCallable( + Map args, +) async { + final locationData = args['location']! as Map; + final city = locationData['city']! as String; + final state = locationData['state']! as String; + final date = args['date']! as String; + return fetchWeather(Location(city, state), date); +} diff --git a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart index 6f90f6a6d977..730c8516c045 100644 --- a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart @@ -111,7 +111,14 @@ export 'src/live_api.dart' Transcription; export 'src/live_session.dart' show LiveSession; export 'src/schema.dart' show JSONSchema, Schema, SchemaType; - +export 'src/server_template/template_chat.dart' + show TemplateChatSession, StartTemplateChatExtension; +export 'src/server_template/template_tool.dart' + show + TemplateAutoFunctionDeclaration, + TemplateFunctionDeclaration, + TemplateTool, + TemplateToolConfig; export 'src/tool.dart' show AutoFunctionDeclaration, diff --git a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart index cf1f98db8b1a..edd5a9a7c7b2 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart @@ -37,6 +37,7 @@ import 'imagen/imagen_reference.dart'; import 'live_api.dart'; import 'live_session.dart'; import 'platform_header_helper.dart'; +import 'server_template/template_tool.dart'; import 'tool.dart'; part 'generative_model.dart'; @@ -369,6 +370,8 @@ abstract class BaseTemplateApiClientModel extends BaseApiClientModel { String templateId, Map? inputs, Iterable? history, + List? tools, + TemplateToolConfig? toolConfig, T Function(Map) parse) { Map body = {}; if (inputs != null) { @@ -377,6 +380,12 @@ abstract class BaseTemplateApiClientModel extends BaseApiClientModel { if (history != null) { body['history'] = history.map((c) => c.toJson()).toList(); } + if (tools != null) { + body['tools'] = tools.map((t) => t.toJson()).toList(); + } + if (toolConfig != null) { + body['toolConfig'] = toolConfig.toJson(); + } return _client .makeRequest(templateTaskUri(task, templateId), body) .then(parse); @@ -391,6 +400,8 @@ abstract class BaseTemplateApiClientModel extends BaseApiClientModel { String templateId, Map? inputs, Iterable? history, + List? tools, + TemplateToolConfig? toolConfig, T Function(Map) parse) { Map body = {}; if (inputs != null) { @@ -399,6 +410,12 @@ abstract class BaseTemplateApiClientModel extends BaseApiClientModel { if (history != null) { body['history'] = history.map((c) => c.toJson()).toList(); } + if (tools != null) { + body['tools'] = tools.map((t) => t.toJson()).toList(); + } + if (toolConfig != null) { + body['toolConfig'] = toolConfig.toJson(); + } final response = _client.streamRequest(templateTaskUri(task, templateId), body); return response.map(parse); diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart new file mode 100644 index 000000000000..26fb90dabc7d --- /dev/null +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart @@ -0,0 +1,249 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import 'dart:async'; + +import '../api.dart'; +import '../base_model.dart'; +import '../content.dart'; +import '../utils/chat_utils.dart'; +import '../utils/mutex.dart'; +import 'template_tool.dart'; + +/// A back-and-forth chat with a server template. +/// +/// Records messages sent and received in [history]. The history will always +/// record the content from the first candidate in the +/// [GenerateContentResponse], other candidates may be available on the returned +/// response. The history reflects the most current state of the chat session. +final class TemplateChatSession { + TemplateChatSession._( + this._templateHistoryGenerateContent, + this._templateHistoryGenerateContentStream, + this._templateId, + this._inputs, + this._history, + this._tools, + this._toolConfig, + this._maxTurns, + ) : _autoFunctions = _tools + ?.expand((tool) => tool.templateAutoFunctionDeclarations) + .fold({}, (map, function) { + map?[function.name] = function; + return map; + }); + + final Future Function( + Iterable content, String templateId, + {required Map inputs, + List? tools, + TemplateToolConfig? templateToolConfig}) _templateHistoryGenerateContent; + + final Stream Function( + Iterable content, String templateId, + {required Map inputs, + List? tools, + TemplateToolConfig? templateToolConfig}) + _templateHistoryGenerateContentStream; + + final String _templateId; + final Map _inputs; + final List _history; + final List? _tools; + final TemplateToolConfig? _toolConfig; + final Map? _autoFunctions; + final int _maxTurns; + + final _mutex = Mutex(); + + /// The content that has been successfully sent to, or received from, the + /// generative model. + /// + /// If there are outstanding requests from calls to [sendMessage], + /// these will not be reflected in the history. + /// Messages without a candidate in the response are not recorded in history, + /// including the message sent to the model. + Iterable get history => _history.skip(0); + + /// Sends [message] to the server template as a continuation of the chat [history]. + /// + /// Prepends the history to the request and uses the provided model to + /// generate new content, providing the session's initialized inputs. + /// + /// When there are no candidates in the response, the [message] and response + /// are ignored and will not be recorded in the [history]. + Future sendMessage(Content message) async { + final lock = await _mutex.acquire(); + try { + final requestHistory = [message]; + var turn = 0; + while (turn < _maxTurns) { + final response = await _templateHistoryGenerateContent( + _history.followedBy(requestHistory), + _templateId, + inputs: _inputs, + tools: _tools, + templateToolConfig: _toolConfig, + ); + + final functionCalls = response.functionCalls; + final shouldAutoExecute = _autoFunctions != null && + _autoFunctions.isNotEmpty && + functionCalls.isNotEmpty && + functionCalls.every((c) => _autoFunctions.containsKey(c.name)); + + if (!shouldAutoExecute) { + // Standard handling: Update history and return the response to the user. + if (response.candidates case [final candidate, ...]) { + _history.add(message); + final normalizedContent = candidate.content.role == null + ? Content('model', candidate.content.parts) + : candidate.content; + _history.add(normalizedContent); + } + return response; + } + + // Auto function execution + requestHistory.add(response.candidates.first.content); + final functionResponses = []; + for (final functionCall in functionCalls) { + final function = _autoFunctions[functionCall.name]; + + Object? result; + try { + result = await function!.callable(functionCall.args); + } catch (e) { + result = e.toString(); + } + functionResponses + .add(FunctionResponse(functionCall.name, {'result': result})); + } + requestHistory.add(Content('function', functionResponses)); + turn++; + } + throw Exception('Max turns of $_maxTurns reached.'); + } finally { + lock.release(); + } + } + + /// Sends [message] to the server template as a continuation of the chat + /// [history]. + /// + /// Returns a stream of responses, which may be chunks of a single aggregate + /// response. + /// + /// Prepends the history to the request and uses the provided model to + /// generate new content, providing the session's initialized inputs. + /// + /// When there are no candidates in the response, the [message] and response + /// are ignored and will not be recorded in the [history]. + Stream sendMessageStream(Content message) { + final controller = StreamController(); + _mutex.acquire().then((lock) async { + try { + final requestHistory = [message]; + var turn = 0; + while (turn < _maxTurns) { + final responses = _templateHistoryGenerateContentStream( + _history.followedBy(requestHistory), + _templateId, + inputs: _inputs, + tools: _tools, + templateToolConfig: _toolConfig, + ); + + final turnChunks = []; + await for (final response in responses) { + turnChunks.add(response); + controller.add(response); + } + if (turnChunks.isEmpty) break; + final aggregatedContent = historyAggregate(turnChunks.map((r) { + final content = r.candidates.firstOrNull?.content; + if (content == null) { + throw Exception('No content in response candidate'); + } + return content; + }).toList()); + + final functionCalls = + aggregatedContent.parts.whereType().toList(); + + final shouldAutoExecute = _autoFunctions != null && + _autoFunctions.isNotEmpty && + functionCalls.isNotEmpty && + functionCalls.every((c) => _autoFunctions.containsKey(c.name)); + + if (!shouldAutoExecute) { + _history.addAll(requestHistory); + _history.add(aggregatedContent); + return; + } + + requestHistory.add(aggregatedContent); + final functionResponseFutures = + functionCalls.map((functionCall) async { + final function = _autoFunctions[functionCall.name]; + + Object? result; + try { + result = await function!.callable(functionCall.args); + } catch (e) { + result = e.toString(); + } + return FunctionResponse(functionCall.name, {'result': result}); + }); + final functionResponseParts = + await Future.wait(functionResponseFutures); + requestHistory.add(Content.functionResponses(functionResponseParts)); + turn++; + } + throw Exception('Max turns of $_maxTurns reached.'); + } catch (e, s) { + controller.addError(e, s); + } finally { + lock.release(); + unawaited(controller.close()); + } + }); + return controller.stream; + } +} + +/// An extension on [TemplateGenerativeModel] that provides a `startChat` method. +extension StartTemplateChatExtension on TemplateGenerativeModel { + /// Starts a [TemplateChatSession] that will use this model to respond to messages. + /// + /// ```dart + /// final chat = model.startChat('my_template', inputs: {'language': 'en'}); + /// final response = await chat.sendMessage(Content.text('Hello there.')); + /// print(response.text); + /// ``` + TemplateChatSession startChat(String templateId, + {required Map inputs, + List? history, + List? tools, + TemplateToolConfig? toolConfig, + int? maxTurns}) => + TemplateChatSession._( + templateGenerateContentWithHistory, + templateGenerateContentWithHistoryStream, + templateId, + inputs, + history ?? [], + tools ?? [], + toolConfig, + maxTurns ?? 5); +} diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart index 75e9029f44b4..41efccb4f460 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart @@ -70,8 +70,14 @@ final class TemplateGenerativeModel extends BaseTemplateApiClientModel { @experimental Future generateContent(String templateId, {required Map inputs}) => - makeTemplateRequest(TemplateTask.templateGenerateContent, templateId, - inputs, null, _serializationStrategy.parseGenerateContentResponse); + makeTemplateRequest( + TemplateTask.templateGenerateContent, + templateId, + inputs, + null, // history + null, // tools + null, // toolConfig + _serializationStrategy.parseGenerateContentResponse); /// Generates a stream of content responding to [templateId] and [inputs]. /// @@ -84,7 +90,44 @@ final class TemplateGenerativeModel extends BaseTemplateApiClientModel { TemplateTask.templateStreamGenerateContent, templateId, inputs, - null, + null, // history + null, // tools + null, // toolConfig + _serializationStrategy.parseGenerateContentResponse); + } + + /// Generates content from a template with the given [templateId], [inputs] and + /// [history]. + @experimental + Future templateGenerateContentWithHistory( + Iterable history, String templateId, + {required Map inputs, + List? tools, + TemplateToolConfig? templateToolConfig}) => + makeTemplateRequest( + TemplateTask.templateGenerateContent, + templateId, + inputs, + history, + tools, + templateToolConfig, + _serializationStrategy.parseGenerateContentResponse); + + /// Generates a stream of content from a template with the given [templateId], + /// [inputs] and [history]. + @experimental + Stream templateGenerateContentWithHistoryStream( + Iterable history, String templateId, + {required Map inputs, + List? tools, + TemplateToolConfig? templateToolConfig}) { + return streamTemplateRequest( + TemplateTask.templateStreamGenerateContent, + templateId, + inputs, + history, + tools, + templateToolConfig, _serializationStrategy.parseGenerateContentResponse); } } diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart index 0bfe90caebdc..14437e5f2ec3 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_imagen_model.dart @@ -73,7 +73,9 @@ final class TemplateImagenModel extends BaseTemplateApiClientModel { TemplateTask.templatePredict, templateId, inputs, - null, + null, // history + null, // tools + null, // toolConfig (jsonObject) => parseImagenGenerationResponse(jsonObject), ); diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart new file mode 100644 index 000000000000..31c60af4b82f --- /dev/null +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart @@ -0,0 +1,105 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +import 'dart:async'; + +import '../schema.dart'; + +/// A collection of template tools. +final class TemplateTool { + // ignore: public_member_api_docs + TemplateTool._(this._functionDeclarations); + + /// Returns a [TemplateTool] instance with list of [TemplateFunctionDeclaration]. + static TemplateTool functionDeclarations( + List functionDeclarations) { + return TemplateTool._(functionDeclarations); + } + + /// Returns a list of all [TemplateAutoFunctionDeclaration] objects + /// found within the [_functionDeclarations] list. + List get templateAutoFunctionDeclarations { + return _functionDeclarations + ?.whereType() + .toList() ?? + []; + } + + final List? _functionDeclarations; + + /// Convert to json object. + Map toJson() => { + if (_functionDeclarations case final functionDeclarations? + when functionDeclarations.isNotEmpty) + 'templateFunctions': functionDeclarations + .map((f) => f.hasSchema ? f.toJson() : null) + .where((f) => f != null) + .toList(), + }; +} + +/// A function declaration for a template tool. +class TemplateFunctionDeclaration { + // ignore: public_member_api_docs + TemplateFunctionDeclaration(this.name, + {Map? parameters, + List optionalParameters = const []}) + : _schemaObject = parameters != null + ? JSONSchema.object( + properties: parameters, optionalProperties: optionalParameters) + : null; + + /// The name of the function. + /// + /// Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum + /// length of 63. + final String name; + + final Schema? _schemaObject; + + /// Whether the function declaration has a schema override. + bool get hasSchema => _schemaObject != null; + + /// Convert to json object. + Map toJson() => { + 'name': name, + if (_schemaObject case final schemaObject?) + 'inputSchema': schemaObject.toJson(), + }; +} + +/// A function declaration for a template tool that can be called by the model. +final class TemplateAutoFunctionDeclaration + extends TemplateFunctionDeclaration { + // ignore: public_member_api_docs + TemplateAutoFunctionDeclaration( + {required String name, + required this.callable, + Map? parameters, + List optionalParameters = const []}) + : super(name, + parameters: parameters, optionalParameters: optionalParameters); + + /// The callable function that this declaration represents. + final FutureOr> Function(Map args) + callable; +} + +/// Config for template tools to use with server prompts. +final class TemplateToolConfig { + // ignore: public_member_api_docs + TemplateToolConfig(); + + /// Convert to json object. + Map toJson() => {}; +} From 501168ad41f2dac7009bb08d8c540269e696d597 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 10:37:09 +0200 Subject: [PATCH 015/137] chore(deps): bump lodash in /.github/workflows/scripts/functions (#18168) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.23 to 4.18.1. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.23...4.18.1) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.18.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../workflows/scripts/functions/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index 77dc0313db80..8e9a4027cadb 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -1592,9 +1592,9 @@ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==" }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -3683,9 +3683,9 @@ "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" }, "lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==" }, "lodash.camelcase": { "version": "4.3.0", From 752cbcaa57f887a8fea3bda728bb8482290fa049 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:58:11 +0000 Subject: [PATCH 016/137] fix(auth, ios): serialize Sign in with Apple to prevent crash on overlapping requests (#18172) --- .../firebase_auth/FLTFirebaseAuthPlugin.m | 82 ++++++++++++++----- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m index 7edbadb78910..8247abf829da 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m @@ -97,6 +97,8 @@ @interface FLTFirebaseAuthPlugin () @property(strong, nonatomic) void (^appleCompletion) (PigeonUserCredential *_Nullable, FlutterError *_Nullable); @property(strong, nonatomic) AuthPigeonFirebaseApp *appleArguments; +/// YES while an `ASAuthorizationController` Sign in with Apple flow is active. +@property(nonatomic, assign) BOOL appleSignInRequestInFlight; @end @@ -380,16 +382,25 @@ static void handleSignInWithApple(FLTFirebaseAuthPlugin *object, FIRAuthDataResu NSString *authorizationCode, NSError *error) { void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = object.appleCompletion; - if (completion == nil) return; + if (completion == nil) { + object.appleSignInRequestInFlight = NO; + return; + } if (error != nil) { if (error.code == FIRAuthErrorCodeSecondFactorRequired) { + object.appleCompletion = nil; + object.appleSignInRequestInFlight = NO; [object handleMultiFactorError:object.appleArguments completion:completion withError:error]; } else { + object.appleCompletion = nil; + object.appleSignInRequestInFlight = NO; completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); } return; } + object.appleCompletion = nil; + object.appleSignInRequestInFlight = NO; completion([PigeonParser getPigeonUserCredentialFromAuthResult:authResult authorizationCode:authorizationCode], nil); @@ -406,6 +417,15 @@ - (void)authorizationController:(ASAuthorizationController *)controller if (appleIDCredential.identityToken == nil) { NSLog(@"Unable to fetch identity token."); + void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + self.appleCompletion; + self.appleCompletion = nil; + self.appleSignInRequestInFlight = NO; + if (completion != nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeInvalidCredential + message:kErrMsgInvalidCredential + details:nil]); + } return; } @@ -459,47 +479,62 @@ - (void)authorizationController:(ASAuthorizationController *)controller handleSignInWithApple(self, authResult, authorizationCode, error); }]; } + } else { + void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + self.appleCompletion; + self.appleCompletion = nil; + self.appleSignInRequestInFlight = NO; + if (completion != nil) { + completion(nil, [FlutterError errorWithCode:kErrCodeInvalidCredential + message:kErrMsgInvalidCredential + details:nil]); + } } } - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(macos(10.15), ios(13.0)) { + void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + self.appleCompletion; + self.appleCompletion = nil; + self.appleSignInRequestInFlight = NO; + NSLog(@"Sign in with Apple errored: %@", error); + if (completion == nil) { + return; + } + switch (error.code) { case ASAuthorizationErrorCanceled: - self.appleCompletion( - nil, [FlutterError errorWithCode:@"canceled" - message:@"The user canceled the authorization attempt." - details:nil]); + completion(nil, [FlutterError errorWithCode:@"canceled" + message:@"The user canceled the authorization attempt." + details:nil]); break; case ASAuthorizationErrorInvalidResponse: - self.appleCompletion( - nil, - [FlutterError errorWithCode:@"invalid-response" - message:@"The authorization request received an invalid response." - details:nil]); + completion(nil, [FlutterError + errorWithCode:@"invalid-response" + message:@"The authorization request received an invalid response." + details:nil]); break; case ASAuthorizationErrorNotHandled: - self.appleCompletion(nil, - [FlutterError errorWithCode:@"not-handled" - message:@"The authorization request wasn’t handled." - details:nil]); + completion(nil, [FlutterError errorWithCode:@"not-handled" + message:@"The authorization request wasn’t handled." + details:nil]); break; case ASAuthorizationErrorFailed: - self.appleCompletion(nil, [FlutterError errorWithCode:@"failed" - message:@"The authorization attempt failed." - details:nil]); + completion(nil, [FlutterError errorWithCode:@"failed" + message:@"The authorization attempt failed." + details:nil]); break; case ASAuthorizationErrorUnknown: default: - self.appleCompletion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); + completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); break; } - self.appleCompletion = nil; } - (void)handleInternalError:(nonnull void (^)(PigeonUserCredential *_Nullable, @@ -570,10 +605,19 @@ static void launchAppleSignInRequest(FLTFirebaseAuthPlugin *object, AuthPigeonFi void (^_Nonnull completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable)) { if (@available(iOS 13.0, macOS 10.15, *)) { + if (object.appleSignInRequestInFlight) { + completion(nil, + [FlutterError errorWithCode:@"operation-not-allowed" + message:@"A Sign in with Apple request is already in progress." + details:nil]); + return; + } + NSString *nonce = [object randomNonce:32]; object.currentNonce = nonce; object.appleCompletion = completion; object.appleArguments = app; + object.appleSignInRequestInFlight = YES; ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init]; From a63bd2a521e4556707e4673cc7f4b6b9a82f61fe Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Wed, 8 Apr 2026 10:18:33 +0000 Subject: [PATCH 017/137] docs(auth): enhance iOS phone authentication error handling and setup instructions (#18175) --- docs/auth/errors.md | 8 +++++++ docs/auth/phone-auth.md | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/docs/auth/errors.md b/docs/auth/errors.md index 422acdfead97..0f4154ada219 100644 --- a/docs/auth/errors.md +++ b/docs/auth/errors.md @@ -97,3 +97,11 @@ try { } } ``` + +## `recaptcha-sdk-not-linked` (iOS phone auth) + +If `e.code` is **`recaptcha-sdk-not-linked`** during **`verifyPhoneNumber`** on **iOS**, the native layer expects **reCAPTCHA Enterprise** +to be linked or your **Identity Platform** project configuration must be adjusted. This is not fixed from Dart alone. + +See [Phone Authentication — iOS: reCAPTCHA SDK and Identity Platform](/docs/auth/phone-auth#ios-recaptcha-sdk-and-identity-platform) for +recommended setup, the Safari flow, and a documented **GCP / Identity Toolkit** workaround with trade-offs. diff --git a/docs/auth/phone-auth.md b/docs/auth/phone-auth.md index 55adadd06c95..e28a02103a64 100644 --- a/docs/auth/phone-auth.md +++ b/docs/auth/phone-auth.md @@ -26,12 +26,64 @@ Before starting with Phone Authentication, ensure you have followed these steps: your APNs authentication key is [configured with Firebase Cloud Messaging (FCM)](/docs/cloud-messaging/ios/certs). Additionally, you must [enable background modes](https://help.apple.com/xcode/mac/current/#/deve49d0ba96) for remote notifications. To view an in-depth explanation of this step, view the [Firebase iOS Phone Auth](/docs/auth/ios/phone-auth) documentation. + If verification fails with **`recaptcha-sdk-not-linked`** (*The reCAPTCHA SDK is not linked to your app*), see + [iOS: reCAPTCHA SDK and Identity Platform](#ios-recaptcha-sdk-and-identity-platform). 4. **Web**: Ensure that you have added your applications domain on the [Firebase console](https://console.firebase.google.com/), under **OAuth redirect domains**. **Note**; Phone number sign-in is only available for use on real devices and the web. To test your authentication flow on device emulators, please see [Testing](#testing). +## iOS: reCAPTCHA SDK and Identity Platform + +On **iOS**, phone sign-in can fail with `FirebaseAuthException` code **`recaptcha-sdk-not-linked`** (for example: *The reCAPTCHA SDK is not linked to your app*). +That error is raised by the **native Firebase iOS Auth** SDK when your Firebase / **Identity Platform** configuration expects **reCAPTCHA Enterprise** +for SMS-related verification, but the **reCAPTCHA Enterprise iOS SDK** is not linked in your Xcode project. + +The `firebase_auth` plugin does not inject a reCAPTCHA client from Dart—you must fix this in **native iOS** setup or in **Google Cloud / Firebase** configuration. + +### Recommended: Link reCAPTCHA Enterprise on iOS + +Add the **reCAPTCHA Enterprise** client to your app using Google’s guide: +[Instrument your iOS app with reCAPTCHA Enterprise](https://cloud.google.com/recaptcha-enterprise/docs/instrument-ios-apps) +(CocoaPods or Swift Package Manager), so Firebase Auth can satisfy the Enterprise requirement. + +### Safari-hosted challenge (`SFSafariViewController`) + +If the SDK uses a **Safari view controller**-hosted challenge instead of the Enterprise SDK, your app must handle the **return URL** +(for example with **`uni_links`** / **`app_links`**, or **`onOpenUrl`** / **`application:openURL:`** in the iOS runner), following standard +Flutter + Firebase iOS setup for OAuth-style callbacks. + +### When you don’t need reCAPTCHA Enterprise for phone auth + +[Google’s guide to reCAPTCHA SMS defense](https://cloud.google.com/identity-platform/docs/recaptcha-tfp) describes an **optional** Identity Platform +feature that depends on the **reCAPTCHA Enterprise API** and (on iOS) linking the [reCAPTCHA Enterprise client](https://cloud.google.com/recaptcha-enterprise/docs/instrument-ios-apps). +Standard Firebase phone authentication often **does not** require that flow—turning **reCAPTCHA Enterprise** on in Firebase / Google Cloud without also +shipping the native SDK can surface **`recaptcha-sdk-not-linked`**. + +### Disable reCAPTCHA SMS defense (Google-documented REST update) + +To **disable** reCAPTCHA SMS defense (for example when you cannot or won’t link the Enterprise SDK), Google documents a **`projects.updateConfig`** call +on **`projects/{project_id}/config`** with **`updateMask=recaptchaConfig`** and: + +- `recaptchaConfig.phoneEnforcementState`: **`OFF`** +- `recaptchaConfig.useSmsTollFraudProtection`: **`false`** + +Use Google’s **official steps** (including the **APIs Explorer** URL with `PROJECT_ID` replaced by your project ID): + +- [Disable reCAPTCHA SMS defense](https://cloud.google.com/identity-platform/docs/recaptcha-tfp#disable_recaptcha_sms_defense) +- REST reference: [`projects.updateConfig`](https://cloud.google.com/identity-platform/docs/reference/rest/v2/projects/updateConfig) + +Some developers report that **enabling then disabling** *Manage reCAPTCHA* / **reCAPTCHA Enterprise API** in the Firebase or Google Cloud UI can leave +**`recaptchaConfig`** expecting Enterprise until the **`OFF` / `false`** update is applied; see +[flutterfire#18171 (comment)](https://github.com/firebase/flutterfire/issues/18171#issuecomment-4195461765). + +**Caution:** Disabling SMS defense **reduces fraud protection**. Prefer keeping defense **on** and [linking reCAPTCHA Enterprise on iOS](#recommended-link-recaptcha-enterprise-on-ios) when your product allows. + +More context: [flutterfire#18171](https://github.com/firebase/flutterfire/issues/18171), +[flutterfire#17557](https://github.com/firebase/flutterfire/issues/17557), +[firebase-ios-sdk#15345](https://github.com/firebase/firebase-ios-sdk/issues/15345). + ## Usage The Firebase Authentication SDK for Flutter provides two individual ways to sign a user in with their phone number. Native (e.g. Android & iOS) platforms provide From 3c29048a859b62f3f224b1fa3c8db61f78f63374 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 9 Apr 2026 14:01:46 +0000 Subject: [PATCH 018/137] fix: improve error handling in _firebaseExceptionFromCoreFirebaseError (#18177) --- .../lib/_flutterfire_internals.dart | 8 +++++--- .../_flutterfire_internals/test/guard_test.dart | 13 +++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/_flutterfire_internals/lib/_flutterfire_internals.dart b/packages/_flutterfire_internals/lib/_flutterfire_internals.dart index 649dabb767a2..b4c6b6c905fd 100644 --- a/packages/_flutterfire_internals/lib/_flutterfire_internals.dart +++ b/packages/_flutterfire_internals/lib/_flutterfire_internals.dart @@ -91,12 +91,14 @@ FirebaseException _firebaseExceptionFromCoreFirebaseError( /// /// See also https://github.com/dart-lang/sdk/issues/30741 bool _testException(Object? objectException) { - final exception = objectException! as core_interop.JSError; + if (objectException is! core_interop.JSError) { + return false; + } - final message = _safeConvertFromPossibleJSObject(exception.message); + final message = _safeConvertFromPossibleJSObject(objectException.message); // Firestore web does not contain `Firebase` in the message so we check the exception itself. return message.contains('Firebase') || - exception.toString().contains('FirebaseError'); + objectException.toString().contains('FirebaseError'); } /// Transforms internal errors in something more readable for end-users. diff --git a/packages/_flutterfire_internals/test/guard_test.dart b/packages/_flutterfire_internals/test/guard_test.dart index 40df9658bf6e..7e8332d6e74f 100644 --- a/packages/_flutterfire_internals/test/guard_test.dart +++ b/packages/_flutterfire_internals/test/guard_test.dart @@ -52,6 +52,19 @@ void main() { expect(stack, current); } }); + + test( + 'propagates plain Dart errors from Futures (e.g. ArgumentError on web)', + () async { + await expectLater( + guardWebExceptions( + () => Future.error(ArgumentError('test')), + plugin: 'test', + codeParser: (c) => c, + ), + throwsA(isA()), + ); + }); }); } From 1a20154f4fce298c04a3ff6a255a98481d7b8b6b Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Thu, 9 Apr 2026 09:00:17 -0700 Subject: [PATCH 019/137] chore(firebaseai): update example to merge multimodel and add nano banana page (#18179) * update example to merge multimodel and add nano banana page * fix the new file year header * fix analyzer * fix the format --- .../firebase_ai/example/lib/main.dart | 45 ++- .../example/lib/pages/audio_page.dart | 185 ---------- .../example/lib/pages/document.dart | 117 ------- .../lib/pages/image_generation_page.dart | 198 +++++++++++ .../example/lib/pages/multimodal_page.dart | 317 ++++++++++++++++++ .../example/lib/pages/video_page.dart | 114 ------- 6 files changed, 535 insertions(+), 441 deletions(-) delete mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/audio_page.dart delete mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/document.dart create mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart create mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/multimodal_page.dart delete mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/video_page.dart diff --git a/packages/firebase_ai/firebase_ai/example/lib/main.dart b/packages/firebase_ai/firebase_ai/example/lib/main.dart index 69f37490f6ba..c978b210a066 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/main.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/main.dart @@ -18,19 +18,18 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; // Import after file is generated through flutterfire_cli. -//import 'package:firebase_ai_example/firebase_options.dart'; +// import 'package:firebase_ai_example/firebase_options.dart'; -import 'pages/audio_page.dart'; import 'pages/bidi_page.dart'; import 'pages/chat_page.dart'; -import 'pages/document.dart'; import 'pages/function_calling_page.dart'; +import 'pages/image_generation_page.dart'; import 'pages/image_prompt_page.dart'; import 'pages/json_schema_page.dart'; +import 'pages/multimodal_page.dart'; import 'pages/schema_page.dart'; -import 'pages/token_count_page.dart'; -import 'pages/video_page.dart'; import 'pages/server_template_page.dart'; +import 'pages/token_count_page.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -142,7 +141,7 @@ class _HomeScreenState extends State { useVertexBackend: useVertexBackend, ); case 1: - return AudioPage(title: 'Audio', model: currentModel); + return MultimodalPage(title: 'Multimodal', model: currentModel); case 2: return TokenCountPage(title: 'Token Count', model: currentModel); case 3: @@ -154,20 +153,21 @@ class _HomeScreenState extends State { case 4: return ImagePromptPage(title: 'Image Prompt', model: currentModel); case 5: - return SchemaPromptPage(title: 'Schema Prompt', model: currentModel); + return ImageGenerationPage( + title: 'Image Gen', + useVertexBackend: useVertexBackend, + ); case 6: - return JsonSchemaPage(title: 'JSON Schema', model: currentModel); + return SchemaPromptPage(title: 'Schema Prompt', model: currentModel); case 7: - return DocumentPage(title: 'Document Prompt', model: currentModel); + return JsonSchemaPage(title: 'JSON Schema', model: currentModel); case 8: - return VideoPage(title: 'Video Prompt', model: currentModel); - case 9: return BidiPage( title: 'Live Stream', model: currentModel, useVertexBackend: useVertexBackend, ); - case 10: + case 9: return ServerTemplatePage( title: 'Server Template', useVertexBackend: useVertexBackend, @@ -251,9 +251,9 @@ class _HomeScreenState extends State { tooltip: 'Chat', ), BottomNavigationBarItem( - icon: Icon(Icons.mic), - label: 'Audio', - tooltip: 'Audio Prompt', + icon: Icon(Icons.perm_media), + label: 'Multimodal', + tooltip: 'Multimodal Prompt', ), BottomNavigationBarItem( icon: Icon(Icons.numbers), @@ -270,6 +270,11 @@ class _HomeScreenState extends State { label: 'Image', tooltip: 'Image Prompt', ), + BottomNavigationBarItem( + icon: Icon(Icons.brush), + label: 'NanoBanana', + tooltip: 'Image Generation', + ), BottomNavigationBarItem( icon: Icon(Icons.schema), label: 'Schema', @@ -280,16 +285,6 @@ class _HomeScreenState extends State { label: 'JSON', tooltip: 'JSON Schema', ), - BottomNavigationBarItem( - icon: Icon(Icons.edit_document), - label: 'Document', - tooltip: 'Document Prompt', - ), - BottomNavigationBarItem( - icon: Icon(Icons.video_collection), - label: 'Video', - tooltip: 'Video Prompt', - ), BottomNavigationBarItem( icon: Icon( Icons.stream, diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/audio_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/audio_page.dart deleted file mode 100644 index 4af259693bac..000000000000 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/audio_page.dart +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:firebase_ai/firebase_ai.dart'; -import '../widgets/message_widget.dart'; -import 'package:record/record.dart'; -import 'package:path_provider/path_provider.dart'; - -final record = AudioRecorder(); - -class AudioPage extends StatefulWidget { - const AudioPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _AudioPageState(); -} - -class _AudioPageState extends State { - ChatSession? chat; - final ScrollController _scrollController = ScrollController(); - final List _messages = []; - bool _recording = false; - - @override - void initState() { - super.initState(); - chat = widget.model.startChat(); - } - - Future recordAudio() async { - if (!await record.hasPermission()) { - print('Audio recording permission denied'); - return; - } - - final dir = Directory( - '${(await getApplicationDocumentsDirectory()).path}/libs/recordings', - ); - - // ignore: avoid_slow_async_io - if (!await dir.exists()) { - await dir.create(recursive: true); - } - - String filePath = - '${dir.path}/recording_${DateTime.now().millisecondsSinceEpoch}.wav'; - - await record.start( - const RecordConfig( - encoder: AudioEncoder.wav, - ), - path: filePath, - ); - } - - Future stopRecord() async { - var path = await record.stop(); - - if (path == null) { - print('Failed to stop recording'); - return; - } - - debugPrint('Recording saved to: $path'); - - try { - File file = File(path); - final audio = await file.readAsBytes(); - debugPrint('Audio file size: ${audio.length} bytes'); - - final audioPart = InlineDataPart('audio/wav', audio); - - await _submitAudioToModel(audioPart); - - await file.delete(); - debugPrint('Recording deleted successfully.'); - } catch (e) { - debugPrint('Error processing recording: $e'); - } - } - - Future _submitAudioToModel(audioPart) async { - try { - String textPrompt = 'What is in the audio recording?'; - const prompt = TextPart('What is in the audio recording?'); - - setState(() { - _messages.add(MessageData(text: textPrompt, fromUser: true)); - }); - - final response = await widget.model.generateContent([ - Content.multi([prompt, audioPart]), - ]); - - setState(() { - _messages.add(MessageData(text: response.text, fromUser: false)); - }); - - debugPrint(response.text); - } catch (e) { - debugPrint('Error sending audio to model: $e'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - IconButton( - onPressed: () async { - setState(() { - _recording = !_recording; - }); - if (_recording) { - await recordAudio(); - } else { - await stopRecord(); - } - }, - icon: Icon( - Icons.mic, - color: _recording - ? Colors.blueGrey - : Theme.of(context).colorScheme.primary, - ), - ), - const SizedBox.square( - dimension: 15, - ), - const Text( - 'Tap the mic to record, tap again to submit', - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/document.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/document.dart deleted file mode 100644 index db2715c402e0..000000000000 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/document.dart +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_ai/firebase_ai.dart'; -import 'package:flutter/services.dart'; -import '../widgets/message_widget.dart'; - -class DocumentPage extends StatefulWidget { - const DocumentPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _DocumentPageState(); -} - -class _DocumentPageState extends State { - ChatSession? chat; - late final GenerativeModel model; - final List _messages = []; - bool _loading = false; - - @override - void initState() { - super.initState(); - chat = widget.model.startChat(); - } - - Future _testDocumentReading(model) async { - try { - ByteData docBytes = - await rootBundle.load('assets/documents/gemini_summary.pdf'); - - const _prompt = - 'Write me a summary in one sentence what this document is about.'; - - const prompt = TextPart(_prompt); - - setState(() { - _messages.add(MessageData(text: _prompt, fromUser: true)); - }); - - final pdfPart = - InlineDataPart('application/pdf', docBytes.buffer.asUint8List()); - - final response = await widget.model.generateContent([ - Content.multi([prompt, pdfPart]), - ]); - - setState(() { - _messages.add(MessageData(text: response.text, fromUser: false)); - }); - } catch (e) { - print('Error sending document to model: $e'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Center( - child: SizedBox( - child: ElevatedButton( - onPressed: !_loading - ? () async { - await _testDocumentReading(widget.model); - } - : null, - child: const Text('Test Document Reading'), - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart new file mode 100644 index 000000000000..f4e2f527d3c4 --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart @@ -0,0 +1,198 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:typed_data'; +import 'package:flutter/material.dart'; +import 'package:firebase_ai/firebase_ai.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import '../widgets/message_widget.dart'; + +class ImageGenerationPage extends StatefulWidget { + const ImageGenerationPage({ + super.key, + required this.title, + required this.useVertexBackend, + }); + + final String title; + final bool useVertexBackend; + + @override + State createState() => _ImageGenerationPageState(); +} + +class _ImageGenerationPageState extends State { + late GenerativeModel _model; + final ScrollController _scrollController = ScrollController(); + final TextEditingController _textController = TextEditingController(); + final FocusNode _textFieldFocus = FocusNode(); + final List _messages = []; + bool _loading = false; + + @override + void initState() { + super.initState(); + _initializeModel(); + } + + void _initializeModel() { + final aiClient = widget.useVertexBackend + ? FirebaseAI.vertexAI(auth: FirebaseAuth.instance) + : FirebaseAI.googleAI(auth: FirebaseAuth.instance); + + _model = aiClient.generativeModel( + model: 'gemini-2.5-flash-image', + generationConfig: GenerationConfig( + responseModalities: [ResponseModalities.text, ResponseModalities.image], + ), + ); + } + + void _scrollDown() { + WidgetsBinding.instance.addPostFrameCallback( + (_) => _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 750), + curve: Curves.easeOutCirc, + ), + ); + } + + Future _generateImage(String prompt) async { + if (prompt.trim().isEmpty) return; + + setState(() { + _loading = true; + _messages.add(MessageData(text: prompt, fromUser: true)); + }); + _textController.clear(); + _scrollDown(); + + try { + final response = await _model.generateContent([Content.text(prompt)]); + + String? textResponse = response.text; + Uint8List? imageBytes; + + if (response.inlineDataParts.isNotEmpty) { + imageBytes = response.inlineDataParts.first.bytes; + } + + setState(() { + _messages.add( + MessageData( + text: (textResponse ?? '') + + (imageBytes != null + ? '\nGenerated Image:' + : 'No picture generated'), + imageBytes: imageBytes, + fromUser: false, + ), + ); + }); + } catch (e) { + _showError(e.toString()); + } finally { + setState(() { + _loading = false; + }); + _scrollDown(); + _textFieldFocus.requestFocus(); + } + } + + void _showError(String message) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('Something went wrong'), + content: SingleChildScrollView( + child: SelectableText(message), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('OK'), + ), + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + Expanded( + child: ListView.builder( + controller: _scrollController, + itemCount: _messages.length, + itemBuilder: (context, index) { + final message = _messages[index]; + return MessageWidget( + text: message.text, + image: message.imageBytes == null + ? null + : Image.memory( + message.imageBytes!, + fit: BoxFit.contain, + ), + isFromUser: message.fromUser ?? false, + ); + }, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 15), + child: Row( + children: [ + Expanded( + child: TextField( + autofocus: true, + focusNode: _textFieldFocus, + controller: _textController, + decoration: const InputDecoration( + hintText: 'Enter image prompt...', + ), + onSubmitted: _generateImage, + ), + ), + const SizedBox(width: 15), + if (!_loading) + IconButton( + onPressed: () => _generateImage(_textController.text), + icon: Icon( + Icons.send, + color: Theme.of(context).colorScheme.primary, + ), + ) + else + const CircularProgressIndicator(), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/multimodal_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/multimodal_page.dart new file mode 100644 index 000000000000..9c559abdaada --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/multimodal_page.dart @@ -0,0 +1,317 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:firebase_ai/firebase_ai.dart'; +import 'package:flutter/services.dart'; +import '../widgets/message_widget.dart'; +import 'package:record/record.dart'; +import 'package:path_provider/path_provider.dart'; + +final record = AudioRecorder(); + +class MultimodalPage extends StatefulWidget { + const MultimodalPage({super.key, required this.title, required this.model}); + + final String title; + final GenerativeModel model; + + @override + State createState() => _MultimodalPageState(); +} + +class _MultimodalPageState extends State { + final ScrollController _scrollController = ScrollController(); + final List _messages = []; + bool _recording = false; + bool _loading = false; + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + Future recordAudio() async { + if (!await record.hasPermission()) { + debugPrint('Audio recording permission denied'); + return; + } + + final dir = Directory( + '${(await getApplicationDocumentsDirectory()).path}/libs/recordings', + ); + + await dir.create(recursive: true); + + String filePath = + '${dir.path}/recording_${DateTime.now().millisecondsSinceEpoch}.wav'; + + await record.start( + const RecordConfig( + encoder: AudioEncoder.wav, + ), + path: filePath, + ); + } + + Future stopRecord() async { + var path = await record.stop(); + + if (path == null) { + debugPrint('Failed to stop recording'); + return; + } + + debugPrint('Recording saved to: $path'); + + try { + File file = File(path); + final audio = await file.readAsBytes(); + debugPrint('Audio file size: ${audio.length} bytes'); + + final audioPart = InlineDataPart('audio/wav', audio); + + await _submitAudioToModel(audioPart); + + await file.delete(); + debugPrint('Recording deleted successfully.'); + } catch (e) { + debugPrint('Error processing recording: $e'); + } + } + + Future _submitAudioToModel(InlineDataPart audioPart) async { + try { + String textPrompt = 'What is in the audio recording?'; + const prompt = TextPart('What is in the audio recording?'); + + setState(() { + _messages.add(MessageData(text: textPrompt, fromUser: true)); + _loading = true; + }); + + final response = await widget.model.generateContent([ + Content.multi([prompt, audioPart]), + ]); + + setState(() { + _messages.add(MessageData(text: response.text, fromUser: false)); + _loading = false; + }); + + _scrollToBottom(); + } catch (e) { + debugPrint('Error sending audio to model: $e'); + setState(() { + _loading = false; + }); + } + } + + Future _testVideo() async { + try { + setState(() { + _loading = true; + }); + + ByteData videoBytes = + await rootBundle.load('assets/videos/landscape.mp4'); + + const promptText = 'Can you tell me what is in the video?'; + + setState(() { + _messages.add(MessageData(text: promptText, fromUser: true)); + }); + + final videoPart = + InlineDataPart('video/mp4', videoBytes.buffer.asUint8List()); + + final response = await widget.model.generateContent([ + Content.multi([const TextPart(promptText), videoPart]), + ]); + + setState(() { + _messages.add(MessageData(text: response.text, fromUser: false)); + _loading = false; + }); + + _scrollToBottom(); + } catch (e) { + debugPrint('Error sending video to model: $e'); + setState(() { + _loading = false; + }); + } + } + + Future _testDocumentReading() async { + try { + setState(() { + _loading = true; + }); + + ByteData docBytes = + await rootBundle.load('assets/documents/gemini_summary.pdf'); + + const promptText = + 'Write me a summary in one sentence what this document is about.'; + + setState(() { + _messages.add(MessageData(text: promptText, fromUser: true)); + }); + + final pdfPart = + InlineDataPart('application/pdf', docBytes.buffer.asUint8List()); + + final response = await widget.model.generateContent([ + Content.multi([const TextPart(promptText), pdfPart]), + ]); + + setState(() { + _messages.add(MessageData(text: response.text, fromUser: false)); + _loading = false; + }); + + _scrollToBottom(); + } catch (e) { + debugPrint('Error sending document to model: $e'); + setState(() { + _loading = false; + }); + } + } + + void _scrollToBottom() { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_scrollController.hasClients) { + _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOut, + ); + } + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + Expanded( + child: ListView.builder( + controller: _scrollController, + itemBuilder: (context, idx) { + return MessageWidget( + text: _messages[idx].text, + isFromUser: _messages[idx].fromUser ?? false, + ); + }, + itemCount: _messages.length, + ), + ), + if (_loading) + const Padding( + padding: EdgeInsets.all(8), + child: CircularProgressIndicator(), + ), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 15, + horizontal: 10, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _loading + ? null + : () async { + setState(() { + _recording = !_recording; + }); + if (_recording) { + await recordAudio(); + } else { + await stopRecord(); + } + }, + icon: Icon( + Icons.mic, + color: _recording + ? Colors.red + : Theme.of(context).colorScheme.primary, + ), + iconSize: 32, + ), + Text( + _recording ? 'Stop' : 'Record', + style: const TextStyle(fontSize: 12), + ), + ], + ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _loading ? null : _testVideo, + icon: Icon( + Icons.video_collection, + color: Theme.of(context).colorScheme.primary, + ), + iconSize: 32, + ), + const Text( + 'Test Video', + style: TextStyle(fontSize: 12), + ), + ], + ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: _loading ? null : _testDocumentReading, + icon: Icon( + Icons.edit_document, + color: Theme.of(context).colorScheme.primary, + ), + iconSize: 32, + ), + const Text( + 'Test Doc', + style: TextStyle(fontSize: 12), + ), + ], + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/video_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/video_page.dart deleted file mode 100644 index 565555e19cd6..000000000000 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/video_page.dart +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2025 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'package:flutter/material.dart'; -import 'package:firebase_ai/firebase_ai.dart'; -import 'package:flutter/services.dart'; -import '../widgets/message_widget.dart'; - -class VideoPage extends StatefulWidget { - const VideoPage({super.key, required this.title, required this.model}); - - final String title; - final GenerativeModel model; - - @override - State createState() => _VideoPageState(); -} - -class _VideoPageState extends State { - ChatSession? chat; - late final GenerativeModel model; - final List _messages = []; - bool _loading = false; - - @override - void initState() { - super.initState(); - chat = widget.model.startChat(); - } - - Future _testVideo(model) async { - try { - ByteData videoBytes = - await rootBundle.load('assets/videos/landscape.mp4'); - - const _prompt = 'Can you tell me what is in the video?'; - - setState(() { - _messages.add(MessageData(text: _prompt, fromUser: true)); - }); - - final videoPart = - InlineDataPart('video/mp4', videoBytes.buffer.asUint8List()); - - final response = await widget.model.generateContent([ - Content.multi([const TextPart(_prompt), videoPart]), - ]); - - setState(() { - _messages.add(MessageData(text: response.text, fromUser: false)); - }); - } catch (e) { - print('Error sending video to model: $e'); - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: ListView.builder( - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - isFromUser: _messages[idx].fromUser ?? false, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Center( - child: SizedBox( - child: ElevatedButton( - onPressed: !_loading - ? () async { - await _testVideo(widget.model); - } - : null, - child: const Text('Test Video Prompt'), - ), - ), - ), - ), - ], - ), - ), - ); - } -} From 55a7f6ff17940487e29d8bc78779ca4cfce24b0c Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Fri, 10 Apr 2026 09:23:10 +0200 Subject: [PATCH 020/137] fix(crashlytics,android): fix an issue with deobfuscating flavored builds (#18085) * fix(crashlytics,android): fix an issue with deobfuscating flavored builds * format * improve ELFBuildIdReader so it handles AAB as well * format --- .../crashlytics/ElfBuildIdReader.java | 398 ++++++++++++++++++ .../FlutterFirebaseCrashlyticsPlugin.java | 19 +- 2 files changed, 414 insertions(+), 3 deletions(-) create mode 100644 packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/ElfBuildIdReader.java diff --git a/packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/ElfBuildIdReader.java b/packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/ElfBuildIdReader.java new file mode 100644 index 000000000000..0e6b9561168a --- /dev/null +++ b/packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/ElfBuildIdReader.java @@ -0,0 +1,398 @@ +// Copyright 2024 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.firebase.crashlytics; + +import android.content.Context; +import android.util.Log; +import java.io.File; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * Reads the ELF build ID from libapp.so at runtime. + * + *

The Firebase CLI's {@code crashlytics:symbols:upload} command uses the ELF build ID (from the + * {@code .note.gnu.build-id} section) when uploading symbols. To ensure Crashlytics can match crash + * reports to uploaded symbols, the plugin must report the same ELF build ID rather than the Dart + * VM's internal snapshot build ID (which may differ, especially for AAB + flavor builds). + */ +final class ElfBuildIdReader { + + private static final String TAG = "FLTFirebaseCrashlytics"; + + private static final byte[] ELF_MAGIC = {0x7f, 'E', 'L', 'F'}; + private static final int ELFCLASS64 = 2; + private static final int PT_NOTE = 4; + private static final int NT_GNU_BUILD_ID = 3; + private static final String GNU_NOTE_NAME = "GNU"; + + private ElfBuildIdReader() {} + + /** + * Reads the ELF build ID from libapp.so. + * + *

First checks the native library directory (for devices that extract native libs). If not + * found there, reads libapp.so from inside the APK (for devices with extractNativeLibs=false). + * + * @return the build ID as a lowercase hex string, or {@code null} if it cannot be read. + */ + static String readBuildId(Context context) { + try { + // Try extracted native library first. + String nativeLibDir = context.getApplicationInfo().nativeLibraryDir; + File libApp = new File(nativeLibDir, "libapp.so"); + if (libApp.exists()) { + return readBuildIdFromElf(libApp); + } + + // Fall back to reading from inside the APK (or split APKs for AAB installs). + return readBuildIdFromApk(context); + } catch (Exception e) { + Log.d(TAG, "Could not read ELF build ID from libapp.so", e); + return null; + } + } + + /** + * Reads the ELF build ID from libapp.so stored inside the APK. On newer Android versions, native + * libraries may not be extracted to the filesystem. + */ + private static String readBuildIdFromApk(Context context) throws Exception { + // Check the base APK first. + String result = readBuildIdFromZip(context.getApplicationInfo().sourceDir); + if (result != null) { + return result; + } + + // For AAB installs, libapp.so is in a split APK (e.g., split_config.arm64_v8a.apk). + String[] splitDirs = context.getApplicationInfo().splitSourceDirs; + if (splitDirs != null) { + for (String splitDir : splitDirs) { + result = readBuildIdFromZip(splitDir); + if (result != null) { + return result; + } + } + } + return null; + } + + private static String readBuildIdFromZip(String apkPath) throws Exception { + try (ZipFile zipFile = new ZipFile(apkPath)) { + Enumeration entries = zipFile.entries(); + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if (entry.getName().endsWith("/libapp.so")) { + try (InputStream is = zipFile.getInputStream(entry)) { + byte[] elfData = new byte[(int) entry.getSize()]; + int offset = 0; + while (offset < elfData.length) { + int read = is.read(elfData, offset, elfData.length - offset); + if (read < 0) break; + offset += read; + } + return readBuildIdFromBytes(elfData); + } + } + } + } + return null; + } + + private static String readBuildIdFromElf(File elfFile) throws Exception { + try (RandomAccessFile raf = new RandomAccessFile(elfFile, "r")) { + return readBuildIdFromRaf(raf); + } + } + + private static String readBuildIdFromBytes(byte[] data) { + try { + ByteBuffer buf = ByteBuffer.wrap(data); + + // Verify ELF magic bytes. + for (int i = 0; i < 4; i++) { + if (buf.get() != ELF_MAGIC[i]) { + return null; + } + } + + int elfClass = buf.get() & 0xFF; // 1 = 32-bit, 2 = 64-bit + boolean is64 = elfClass == ELFCLASS64; + + int dataEncoding = buf.get() & 0xFF; // 1 = little-endian, 2 = big-endian + ByteOrder order = dataEncoding == 1 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN; + buf.order(order); + + if (is64) { + return readBuildIdFromBuffer64(buf); + } else { + return readBuildIdFromBuffer32(buf); + } + } catch (Exception e) { + Log.d(TAG, "Could not parse ELF from APK", e); + return null; + } + } + + private static String readBuildIdFromBuffer64(ByteBuffer buf) { + // e_phoff is at offset 32 in the 64-bit ELF header. + buf.position(32); + long phoff = buf.getLong(); + + // e_phentsize is at offset 54, e_phnum at offset 56. + buf.position(54); + int phentsize = buf.getShort() & 0xFFFF; + int phnum = buf.getShort() & 0xFFFF; + + for (int i = 0; i < phnum; i++) { + int phdr = (int) (phoff + (long) i * phentsize); + buf.position(phdr); + int type = buf.getInt(); + if (type == PT_NOTE) { + // p_offset is at phdr + 8, p_filesz at phdr + 32 for 64-bit. + buf.position(phdr + 8); + long noteOffset = buf.getLong(); + buf.position(phdr + 32); + long noteSize = buf.getLong(); + + String buildId = findGnuBuildIdInBuffer(buf, noteOffset, noteSize); + if (buildId != null) { + return buildId; + } + } + } + return null; + } + + private static String readBuildIdFromBuffer32(ByteBuffer buf) { + // e_phoff is at offset 28 in the 32-bit ELF header. + buf.position(28); + long phoff = buf.getInt() & 0xFFFFFFFFL; + + // e_phentsize is at offset 42, e_phnum at offset 44. + buf.position(42); + int phentsize = buf.getShort() & 0xFFFF; + int phnum = buf.getShort() & 0xFFFF; + + for (int i = 0; i < phnum; i++) { + int phdr = (int) (phoff + (long) i * phentsize); + buf.position(phdr); + int type = buf.getInt(); + if (type == PT_NOTE) { + // p_offset is at phdr + 4, p_filesz at phdr + 16 for 32-bit. + buf.position(phdr + 4); + long noteOffset = buf.getInt() & 0xFFFFFFFFL; + buf.position(phdr + 16); + long noteSize = buf.getInt() & 0xFFFFFFFFL; + + String buildId = findGnuBuildIdInBuffer(buf, noteOffset, noteSize); + if (buildId != null) { + return buildId; + } + } + } + return null; + } + + private static String findGnuBuildIdInBuffer(ByteBuffer buf, long offset, long size) { + long end = offset + size; + long pos = offset; + + while (pos + 12 <= end) { + buf.position((int) pos); + int namesz = buf.getInt(); + int descsz = buf.getInt(); + int type = buf.getInt(); + + if (namesz < 0 || descsz < 0 || namesz > 256) { + break; + } + + int nameAligned = align4(namesz); + long descPos = pos + 12 + nameAligned; + + if (namesz > 0 && type == NT_GNU_BUILD_ID && descPos + descsz <= end) { + byte[] nameBytes = new byte[namesz]; + buf.get(nameBytes); + String name = + new String( + nameBytes, 0, Math.max(0, namesz - 1), java.nio.charset.StandardCharsets.US_ASCII); + + if (GNU_NOTE_NAME.equals(name) && descsz > 0) { + buf.position((int) descPos); + byte[] desc = new byte[descsz]; + buf.get(desc); + return bytesToHex(desc); + } + } + + pos = descPos + align4(descsz); + } + return null; + } + + private static String readBuildIdFromRaf(RandomAccessFile raf) throws Exception { + // Verify ELF magic bytes. + byte[] magic = new byte[4]; + raf.readFully(magic); + for (int i = 0; i < 4; i++) { + if (magic[i] != ELF_MAGIC[i]) { + return null; + } + } + + int elfClass = raf.read(); // 1 = 32-bit, 2 = 64-bit + boolean is64 = elfClass == ELFCLASS64; + + int dataEncoding = raf.read(); // 1 = little-endian, 2 = big-endian + ByteOrder order = dataEncoding == 1 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN; + + if (is64) { + return readBuildIdFromElf64(raf, order); + } else { + return readBuildIdFromElf32(raf, order); + } + } + + private static String readBuildIdFromElf64(RandomAccessFile raf, ByteOrder order) + throws Exception { + // e_phoff is at offset 32 in the 64-bit ELF header. + raf.seek(32); + long phoff = readLong(raf, order); + + // e_phentsize is at offset 54, e_phnum at offset 56. + raf.seek(54); + int phentsize = readUnsignedShort(raf, order); + int phnum = readUnsignedShort(raf, order); + + for (int i = 0; i < phnum; i++) { + long phdr = phoff + (long) i * phentsize; + raf.seek(phdr); + int type = readInt(raf, order); + if (type == PT_NOTE) { + // p_offset is at phdr + 8, p_filesz at phdr + 32 for 64-bit. + raf.seek(phdr + 8); + long noteOffset = readLong(raf, order); + raf.seek(phdr + 32); + long noteSize = readLong(raf, order); + + String buildId = findGnuBuildId(raf, noteOffset, noteSize, order); + if (buildId != null) { + return buildId; + } + } + } + return null; + } + + private static String readBuildIdFromElf32(RandomAccessFile raf, ByteOrder order) + throws Exception { + // e_phoff is at offset 28 in the 32-bit ELF header. + raf.seek(28); + long phoff = readInt(raf, order) & 0xFFFFFFFFL; + + // e_phentsize is at offset 42, e_phnum at offset 44. + raf.seek(42); + int phentsize = readUnsignedShort(raf, order); + int phnum = readUnsignedShort(raf, order); + + for (int i = 0; i < phnum; i++) { + long phdr = phoff + (long) i * phentsize; + raf.seek(phdr); + int type = readInt(raf, order); + if (type == PT_NOTE) { + // p_offset is at phdr + 4, p_filesz at phdr + 16 for 32-bit. + raf.seek(phdr + 4); + long noteOffset = readInt(raf, order) & 0xFFFFFFFFL; + raf.seek(phdr + 16); + long noteSize = readInt(raf, order) & 0xFFFFFFFFL; + + String buildId = findGnuBuildId(raf, noteOffset, noteSize, order); + if (buildId != null) { + return buildId; + } + } + } + return null; + } + + /** + * Searches a PT_NOTE segment for the GNU build ID note. + * + *

Note format: namesz (4) | descsz (4) | type (4) | name (aligned to 4) | desc (aligned to 4) + */ + private static String findGnuBuildId( + RandomAccessFile raf, long offset, long size, ByteOrder order) throws Exception { + long end = offset + size; + long pos = offset; + + while (pos + 12 <= end) { + raf.seek(pos); + int namesz = readInt(raf, order); + int descsz = readInt(raf, order); + int type = readInt(raf, order); + + if (namesz < 0 || descsz < 0 || namesz > 256) { + break; + } + + int nameAligned = align4(namesz); + long descPos = pos + 12 + nameAligned; + + if (namesz > 0 && type == NT_GNU_BUILD_ID && descPos + descsz <= end) { + byte[] nameBytes = new byte[namesz]; + raf.readFully(nameBytes); + // Name is null-terminated. + String name = + namesz > 0 ? new String(nameBytes, 0, Math.max(0, namesz - 1), "US-ASCII") : ""; + + if (GNU_NOTE_NAME.equals(name) && descsz > 0) { + raf.seek(descPos); + byte[] desc = new byte[descsz]; + raf.readFully(desc); + return bytesToHex(desc); + } + } + + pos = descPos + align4(descsz); + } + return null; + } + + private static int align4(int value) { + return (value + 3) & ~3; + } + + private static int readInt(RandomAccessFile raf, ByteOrder order) throws Exception { + byte[] buf = new byte[4]; + raf.readFully(buf); + return ByteBuffer.wrap(buf).order(order).getInt(); + } + + private static long readLong(RandomAccessFile raf, ByteOrder order) throws Exception { + byte[] buf = new byte[8]; + raf.readFully(buf); + return ByteBuffer.wrap(buf).order(order).getLong(); + } + + private static int readUnsignedShort(RandomAccessFile raf, ByteOrder order) throws Exception { + byte[] buf = new byte[2]; + raf.readFully(buf); + return ByteBuffer.wrap(buf).order(order).getShort() & 0xFFFF; + } + + private static String bytesToHex(byte[] bytes) { + StringBuilder sb = new StringBuilder(bytes.length * 2); + for (byte b : bytes) { + sb.append(String.format("%02x", b & 0xff)); + } + return sb.toString(); + } +} diff --git a/packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/FlutterFirebaseCrashlyticsPlugin.java b/packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/FlutterFirebaseCrashlyticsPlugin.java index 18a55bd9f530..0ad27c015091 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/FlutterFirebaseCrashlyticsPlugin.java +++ b/packages/firebase_crashlytics/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/FlutterFirebaseCrashlyticsPlugin.java @@ -40,6 +40,13 @@ public class FlutterFirebaseCrashlyticsPlugin private MethodChannel channel; private EventChannel testEventChannel; private EventChannel.EventSink testEventSink; + private Context applicationContext; + + // Cached ELF build ID read from libapp.so at startup. This is the build ID that the + // firebase-crashlytics-buildtools JAR extracts from .symbols files during upload, so using + // it ensures crash reports match uploaded symbols (even when the Dart VM's internal snapshot + // build ID differs, which happens with AAB + flavor + obfuscation builds). + private String elfBuildId; private static final String FIREBASE_CRASHLYTICS_COLLECTION_ENABLED = "firebase_crashlytics_collection_enabled"; @@ -56,6 +63,8 @@ private void initInstance(BinaryMessenger messenger) { @Override public void onAttachedToEngine(FlutterPluginBinding binding) { + applicationContext = binding.getApplicationContext(); + elfBuildId = ElfBuildIdReader.readBuildId(applicationContext); initInstance(binding.getBinaryMessenger()); } @@ -157,14 +166,18 @@ private Task recordError(final Map arguments) { final String information = (String) Objects.requireNonNull(arguments.get(Constants.INFORMATION)); final boolean fatal = (boolean) Objects.requireNonNull(arguments.get(Constants.FATAL)); - final String buildId = + final String dartBuildId = (String) Objects.requireNonNull(arguments.get(Constants.BUILD_ID)); @SuppressWarnings("unchecked") final List loadingUnits = (List) Objects.requireNonNull(arguments.get(Constants.LOADING_UNITS)); - if (buildId.length() > 0) { - FlutterFirebaseCrashlyticsInternal.setFlutterBuildId(buildId); + // Prefer the ELF build ID from libapp.so over the Dart VM's snapshot build ID. + // The firebase-crashlytics-buildtools JAR uses the ELF build ID when uploading + // symbols, so we must report the same ID for Crashlytics to match them. + String effectiveBuildId = elfBuildId != null ? elfBuildId : dartBuildId; + if (effectiveBuildId.length() > 0) { + FlutterFirebaseCrashlyticsInternal.setFlutterBuildId(effectiveBuildId); } FlutterFirebaseCrashlyticsInternal.setLoadingUnits(loadingUnits); From 6ce6f6b2369b9d43e69b24b284d8ef816c430e31 Mon Sep 17 00:00:00 2001 From: Aashish <112133849+aashishpatil-g@users.noreply.github.com> Date: Mon, 13 Apr 2026 02:19:25 -0700 Subject: [PATCH 021/137] feat(fdc): Streaming implementation for data connect (#18174) * feat(fdc): Happy Path Implementation (#18151) * Initial Commit * Fix formatting and analyzer warnings * Fix tests and licenses * Denver feedback: var initialization best practice * sorted keys for id generation * Fix analyze info messages * feat(fdc): Handle disconnects and reconnects (#18157) * Handle disconnects and reconnects * Address gemini review comments * Reconnection logic * Fixes to reconnect on startup * Fix to decode binary data from server * Handle gemini feedback * Update rest_transport mocks with new windows provider sig * feat(fdc): Hardening (#18173) * debug logging and hardering * Hardening: ensure only one multicast stream controller is created in a ref * Handle cancellations * Formatting fix * Cynthia feedback (final, ...) * Gemini feedback: checkTransport single instancing. * Gemini feedback: cancel and nullify authSubscription in disconnect * Reverting authSubscription nullifying This affects reconnects. Taking tech debt instead. * Handle low priority gemini feedback * Gemini feedback: optimized operation id creation initialized as a lazy var that is used everywhere instead of computing always * Remove _queryId and use the computed operationId * Cynthia feedback on sending empty message to server * Remove grpc transport since its no longer used. * Update tests to incorporate operationId * Remove authToken appCheckToken fields. * Remove metadata file --- .../analysis_options.yaml | 1 + .../lib/src/cache/cache.dart | 2 +- .../lib/src/cache/cache_data_types.dart | 12 +- .../lib/src/common/common_library.dart | 12 + .../lib/src/common/dataconnect_error.dart | 4 +- .../lib/src/core/ref.dart | 198 ++++-- .../lib/src/firebase_data_connect.dart | 143 +++- .../google/protobuf/duration.pb.dart | 1 + .../generated/google/protobuf/struct.pb.dart | 1 + .../lib/src/network/grpc_library.dart | 27 - .../lib/src/network/grpc_transport.dart | 242 ------- .../lib/src/network/rest_transport.dart | 16 + .../lib/src/network/stream_protocol.dart | 160 +++++ .../lib/src/network/transport_library.dart | 9 + .../lib/src/network/transport_stub.dart | 16 + .../lib/src/network/websocket_transport.dart | 646 ++++++++++++++++++ .../firebase_data_connect/pubspec.yaml | 1 + .../test/src/cache/cache_manager_test.dart | 2 +- .../test/src/common/common_library_test.dart | 32 +- .../src/common/dataconnect_error_test.dart | 6 +- .../test/src/core/ref_test.dart | 23 +- .../test/src/firebase_data_connect_test.dart | 11 +- .../test/src/network/rest_transport_test.dart | 20 +- .../test/src/network/transport_stub_test.dart | 2 + 24 files changed, 1209 insertions(+), 378 deletions(-) create mode 100644 packages/firebase_data_connect/firebase_data_connect/analysis_options.yaml delete mode 100644 packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_library.dart delete mode 100644 packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart create mode 100644 packages/firebase_data_connect/firebase_data_connect/lib/src/network/stream_protocol.dart create mode 100644 packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart diff --git a/packages/firebase_data_connect/firebase_data_connect/analysis_options.yaml b/packages/firebase_data_connect/firebase_data_connect/analysis_options.yaml new file mode 100644 index 000000000000..f9b303465f19 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/analysis_options.yaml @@ -0,0 +1 @@ +include: package:flutter_lints/flutter.yaml diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache.dart index 3983df6c5842..6b26001a8ac3 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache.dart @@ -51,7 +51,7 @@ class Cache { String _constructCacheIdentifier() { final rawPrefix = - '${_settings.storage}-${dataConnect.app.options.projectId}-${dataConnect.app.name}-${dataConnect.connectorConfig.serviceId}-${dataConnect.connectorConfig.connector}-${dataConnect.connectorConfig.location}-${dataConnect.transport.transportOptions.host}'; + '${_settings.storage}-${dataConnect.app.options.projectId}-${dataConnect.app.name}-${dataConnect.connectorConfig.serviceId}-${dataConnect.connectorConfig.connector}-${dataConnect.connectorConfig.location}-${dataConnect.transport?.transportOptions.host}'; final prefixSha = convertToSha256(rawPrefix); final rawSuffix = dataConnect.auth?.currentUser?.uid ?? 'anon'; final suffixSha = convertToSha256(rawSuffix); diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache_data_types.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache_data_types.dart index 0768da15232c..9b991a946a79 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache_data_types.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/cache/cache_data_types.dart @@ -332,11 +332,11 @@ class EntityNode { srcListMap.forEach((key, value) { List enodeList = []; List jsonList = value as List; - jsonList.forEach((jsonObj) { + for (var jsonObj in jsonList) { Map jmap = jsonObj as Map; EntityNode en = EntityNode.fromJson(jmap, cacheProvider); enodeList.add(en); - }); + } objLists?[key] = enodeList; }); } @@ -367,9 +367,9 @@ class EntityNode { if (nestedObjectLists != null) { nestedObjectLists!.forEach((key, edoList) { List> jsonList = []; - edoList.forEach((edo) { + for (var edo in edoList) { jsonList.add(edo.toJson(mode: mode)); - }); + } jsonData[key] = jsonList; }); } @@ -396,9 +396,9 @@ class EntityNode { Map nestedObjectListsJson = {}; nestedObjectLists!.forEach((key, edoList) { List> jsonList = []; - edoList.forEach((edo) { + for (var edo in edoList) { jsonList.add(edo.toJson(mode: mode)); - }); + } nestedObjectListsJson[key] = jsonList; }); jsonData[listsKey] = nestedObjectListsJson; diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/common/common_library.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/common/common_library.dart index 9247287f5adf..df7b405ab788 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/common/common_library.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/common/common_library.dart @@ -102,6 +102,7 @@ abstract class DataConnectTransport { /// Invokes corresponding query endpoint. Future invokeQuery( + String operationId, String queryName, Deserializer deserializer, Serializer serializer, @@ -111,6 +112,17 @@ abstract class DataConnectTransport { /// Invokes corresponding mutation endpoint. Future invokeMutation( + String operationId, + String queryName, + Deserializer deserializer, + Serializer serializer, + Variables? vars, + String? token, + ); + + /// Invokes corresponding stream query endpoint. + Stream invokeStreamQuery( + String operationId, String queryName, Deserializer deserializer, Serializer serializer, diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/common/dataconnect_error.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/common/dataconnect_error.dart index 43b7fd964418..32641baafa85 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/common/dataconnect_error.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/common/dataconnect_error.dart @@ -36,9 +36,7 @@ class DataConnectError extends FirebaseException { /// Error thrown when an operation is partially successful. class DataConnectOperationError extends DataConnectError { - DataConnectOperationError( - DataConnectErrorCode code, String message, this.response) - : super(code, message); + DataConnectOperationError(super.code, super.message, this.response); final DataConnectOperationFailureResponse response; } diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart index 5b359f6a15b3..44cbf9ca45c1 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart @@ -51,17 +51,51 @@ abstract class OperationRef { this.serializer, this.variables, ); - Variables? variables; - String operationName; - DataConnectTransport _transport; - Deserializer deserializer; - Serializer serializer; + final Variables? variables; + final String operationName; + final DataConnectTransport _transport; + final Deserializer deserializer; + final Serializer serializer; String? _lastToken; - FirebaseDataConnect dataConnect; + final FirebaseDataConnect dataConnect; + + late final String operationId = + createOperationId(operationName, variables, serializer); - Future> execute( - {QueryFetchPolicy fetchPolicy = QueryFetchPolicy.preferCache}); + static dynamic _sortKeys(dynamic value) { + if (value is Map) { + final sortedMap = {}; + final sortedKeys = value.keys.toList()..sort(); + for (final key in sortedKeys) { + sortedMap[key.toString()] = _sortKeys(value[key]); + } + return sortedMap; + } else if (value is List) { + return value.map(_sortKeys).toList(); + } + return value; + } + + static String createOperationId(String operationName, + Variables? vars, Serializer? serializer) { + if (vars != null && serializer != null) { + try { + final decoded = jsonDecode(serializer(vars)); + final sortedStr = jsonEncode(_sortKeys(decoded)); + final hashVars = convertToSha256(sortedStr); + return '$operationName::$hashVars'; + } catch (_) { + final rawVars = serializer(vars); + final hashVars = convertToSha256(rawVars); + return '$operationName::$hashVars'; + } + } else { + return operationName; + } + } + + Future> execute(); Future _shouldRetry() async { String? newToken; @@ -152,7 +186,7 @@ class QueryManager { try { await queryRef.execute(fetchPolicy: QueryFetchPolicy.cacheOnly); } catch (e) { - log('Error executing impacted query $e'); + log('Error executing impacted query $queryId $e'); } } } @@ -175,24 +209,20 @@ class QueryManager { StreamController> addQuery( QueryRef ref, ) { - final queryId = ref._queryId; + final queryId = ref.operationId; trackedQueries[queryId] = ref; final streamController = - StreamController>.broadcast(); + StreamController>.broadcast( + onCancel: () { + trackedQueries.remove(queryId); + ref._onAllSubscribersCancelled(); + }, + ); return streamController; } - static String createQueryId(String queryName, - QueryVariables? vars, Serializer varSerializer) { - if (vars != null) { - return '$queryName::${varSerializer(vars)}'; - } else { - return queryName; - } - } - void dispose() { _impactedQueriesSubscription?.cancel(); } @@ -216,7 +246,7 @@ class QueryRef extends OperationRef { variables, ); - QueryManager _queryManager; + final QueryManager _queryManager; @override Future> execute( @@ -239,9 +269,6 @@ class QueryRef extends OperationRef { } } - String get _queryId => - QueryManager.createQueryId(operationName, variables, serializer); - Future> _executeFromCache( QueryFetchPolicy fetchPolicy) async { if (dataConnect.cacheManager == null) { @@ -251,7 +278,7 @@ class QueryRef extends OperationRef { final cacheManager = dataConnect.cacheManager!; bool allowStale = fetchPolicy == QueryFetchPolicy.cacheOnly; //if its cache only, we always allow stale - final cachedData = await cacheManager.resultTree(_queryId, allowStale); + final cachedData = await cacheManager.resultTree(operationId, allowStale); if (cachedData != null) { try { @@ -280,6 +307,7 @@ class QueryRef extends OperationRef { try { ServerResponse serverResponse = await _transport.invokeQuery( + operationId, operationName, deserializer, serializer, @@ -288,7 +316,7 @@ class QueryRef extends OperationRef { ); if (dataConnect.cacheManager != null) { - await dataConnect.cacheManager!.update(_queryId, serverResponse); + await dataConnect.cacheManager!.update(operationId, serverResponse); } Data typedData = _convertBodyJsonToData(serverResponse.data); @@ -307,22 +335,109 @@ class QueryRef extends OperationRef { } StreamController>? _streamController; + Stream? _serverStream; + StreamSubscription? _serverStreamSubscription; + + void _onAllSubscribersCancelled() { + _serverStreamSubscription?.cancel(); + _serverStreamSubscription = null; + _serverStream = null; + log("QueryRef $operationId: All subscribers cancelled. Unsubscribed from server stream."); + } Stream> subscribe() { _streamController ??= _queryManager.addQuery(this); - execute(); + final stream = + _streamController!.stream.cast>(); + + // Return the stream to the caller, then execute fetches + Future.microtask(() async { + if (dataConnect.cacheManager != null) { + try { + await _executeFromCache(QueryFetchPolicy.cacheOnly); + } catch (err) { + log("Error fetching from cache during subscribe $err"); + // Ignore cache misses here, server stream will provide latest data + } + } + + // Initiate Web Socket stream only if not already streaming + if (_serverStream == null) { + _streamFromServer(); + } + }); + + return stream; + } + + void _streamFromServer() async { + bool shouldRetry = await _shouldRetry(); + log("QueryRef $operationId _streamFromServer loop started."); + try { + _serverStream = _transport.invokeStreamQuery( + operationId, + operationName, + deserializer, + serializer, + variables, + _lastToken, + ); - return _streamController!.stream.cast>(); + _serverStreamSubscription = _serverStream!.listen( + (serverResponse) async { + log("QueryRef $operationId _streamFromServer loop received snapshot."); + if (dataConnect.cacheManager != null) { + try { + await dataConnect.cacheManager! + .update(operationId, serverResponse); + } catch (e) { + log("QueryRef $operationId _streamFromServer loop cache update failed: $e"); + } + } + Data typedData = _convertBodyJsonToData(serverResponse.data); + + QueryResult res = + QueryResult(dataConnect, typedData, DataSource.server, this); + publishResultToStream(res); + }, + onError: (e) { + _serverStreamSubscription?.cancel(); + _serverStreamSubscription = null; + _serverStream = null; + + if (shouldRetry && + e is DataConnectError && + e.code == DataConnectErrorCode.unauthorized.toString()) { + _streamFromServer(); + } else { + publishErrorToStream(e); + } + }, + onDone: () { + _serverStreamSubscription?.cancel(); + _serverStreamSubscription = null; + _serverStream = null; + }, + ); + } catch (e) { + _serverStreamSubscription?.cancel(); + _serverStreamSubscription = null; + _serverStream = null; + log("QueryRef $operationId _streamFromServer loop Unknown loop failure: $e"); + publishErrorToStream(e); + } } void publishResultToStream(QueryResult result) { if (_streamController != null) { _streamController?.add(result); + } else { + log("QueryRef $operationId _streamFromServer loop _streamController is null"); } } - void publishErrorToStream(Error err) { + void publishErrorToStream(Object err) { if (_streamController != null) { _streamController?.addError(err); } @@ -331,24 +446,16 @@ class QueryRef extends OperationRef { class MutationRef extends OperationRef { MutationRef( - FirebaseDataConnect dataConnect, - String operationName, - DataConnectTransport transport, - Deserializer deserializer, - Serializer serializer, - Variables? variables, - ) : super( - dataConnect, - operationName, - transport, - deserializer, - serializer, - variables, - ); + super.dataConnect, + super.operationName, + super.transport, + super.deserializer, + super.serializer, + super.variables, + ); @override - Future> execute( - {QueryFetchPolicy fetchPolicy = QueryFetchPolicy.serverOnly}) async { + Future> execute() async { bool shouldRetry = await _shouldRetry(); try { // Logic below is duplicated due to the fact that `executeOperation` returns @@ -370,6 +477,7 @@ class MutationRef extends OperationRef { ) async { ServerResponse serverResponse = await _transport.invokeMutation( + operationId, operationName, deserializer, serializer, diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart index d5813f94dc89..ec731343a66c 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart @@ -20,10 +20,8 @@ import 'package:firebase_data_connect/src/common/common_library.dart'; import 'package:firebase_data_connect/src/core/ref.dart'; import 'package:flutter/foundation.dart'; -import './network/transport_library.dart' - if (dart.library.io) './network/grpc_library.dart' - if (dart.library.js_interop) './network/rest_library.dart' - if (dart.library.html) './network/rest_library.dart'; +import './network/rest_library.dart'; +import './network/transport_library.dart'; import 'cache/cache_data_types.dart'; import 'cache/cache.dart'; @@ -67,9 +65,9 @@ class FirebaseDataConnect extends FirebasePluginPlatform { /// FirebaseAppCheck FirebaseAppCheck? appCheck; - /// Due to compatibility issues with grpc-web, we swap out the transport based on what platform the user is using. - /// For web, we use RestTransport. For mobile, we use GRPCTransport. - late DataConnectTransport transport; + /// Transport for connecting to the Data Connect service. + /// Routes between RestTransport and WebSocketTransport based on subscription status + DataConnectTransport? transport; /// FirebaseAuth FirebaseAuth? auth; @@ -91,15 +89,27 @@ class FirebaseDataConnect extends FirebasePluginPlatform { /// Checks whether the transport has been properly initialized. @visibleForTesting void checkTransport() { + if (transport != null) { + return; + } transportOptions ??= TransportOptions('firebasedataconnect.googleapis.com', null, true); - transport = getTransport( + final rest = RestTransport( + transportOptions!, + options, + app.options.appId, + _sdkType, + appCheck, + ); + final ws = WebSocketTransport( transportOptions!, options, app.options.appId, _sdkType, appCheck, + auth, ); + transport = _RoutingTransport(rest, ws); } @visibleForTesting @@ -120,7 +130,7 @@ class FirebaseDataConnect extends FirebasePluginPlatform { checkTransport(); checkAndInitializeCache(); String queryId = - QueryManager.createQueryId(operationName, vars, varsSerializer); + OperationRef.createOperationId(operationName, vars, varsSerializer); QueryRef? ref = _queryManager.trackedQueries[queryId] as QueryRef?; @@ -130,7 +140,7 @@ class FirebaseDataConnect extends FirebasePluginPlatform { return QueryRef( this, operationName, - transport, + transport!, dataDeserializer, _queryManager, varsSerializer, @@ -147,10 +157,12 @@ class FirebaseDataConnect extends FirebasePluginPlatform { Variables? vars, ) { checkTransport(); + //initialize cache since mutations on a stream could result in subscribed query updates + checkAndInitializeCache(); return MutationRef( this, operationName, - transport, + transport!, dataDeserializer, varsSerializer, vars, @@ -167,11 +179,12 @@ class FirebaseDataConnect extends FirebasePluginPlatform { String mappedHost = automaticHostMapping ? getMappedHost(host) : host; transportOptions = TransportOptions(mappedHost, port, isSecure); - if (cacheManager != null) { - // dispose and clean this up. it will get reinitialized for newer QueryRefs that target the emulator. - cacheManager?.dispose(); - cacheManager = null; - } + // dispose and clean this up. it will get reinitialized for newer QueryRefs that target the emulator. + cacheManager?.dispose(); + cacheManager = null; + + // transport will get reinitialized for newer QueryRefs that target the emulator. + transport = null; } /// Currently cached DataConnect instances. Maps from app name to ConnectorConfigStr, DataConnect. @@ -199,16 +212,13 @@ class FirebaseDataConnect extends FirebasePluginPlatform { return cachedInstances[app.name]![connectorConfig.toJson()]!; } - //TODO remove after testing since CS should be null by default - final resolvedCacheSettings = cacheSettings ?? CacheSettings(); - FirebaseDataConnect newInstance = FirebaseDataConnect( app: app, auth: auth, appCheck: appCheck, connectorConfig: connectorConfig, sdkType: sdkType, - cacheSettings: resolvedCacheSettings, + cacheSettings: cacheSettings, ); if (cachedInstances[app.name] == null) { cachedInstances[app.name] = {}; @@ -218,3 +228,96 @@ class FirebaseDataConnect extends FirebasePluginPlatform { return newInstance; } } + +class _RoutingTransport implements DataConnectTransport { + _RoutingTransport(this.rest, this.websocket); + final RestTransport rest; + final WebSocketTransport websocket; + + @override + FirebaseAppCheck? get appCheck => rest.appCheck; + @override + set appCheck(FirebaseAppCheck? val) { + rest.appCheck = val; + websocket.appCheck = val; + } + + @override + CallerSDKType get sdkType => rest.sdkType; + @override + set sdkType(CallerSDKType val) { + rest.sdkType = val; + websocket.sdkType = val; + } + + @override + TransportOptions get transportOptions => rest.transportOptions; + @override + set transportOptions(TransportOptions val) { + rest.transportOptions = val; + websocket.transportOptions = val; + } + + @override + DataConnectOptions get options => rest.options; + @override + set options(DataConnectOptions val) { + rest.options = val; + websocket.options = val; + } + + @override + String get appId => rest.appId; + @override + set appId(String val) { + rest.appId = val; + websocket.appId = val; + } + + @override + Future invokeMutation( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? token, + ) { + if (websocket.isConnected) { + return websocket.invokeMutation( + operationId, queryName, deserializer, serializer, vars, token); + } + return rest.invokeMutation( + operationId, queryName, deserializer, serializer, vars, token); + } + + @override + Future invokeQuery( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serialize, + Variables? vars, + String? token, + ) { + if (websocket.isConnected) { + return websocket.invokeQuery( + operationId, queryName, deserializer, serialize, vars, token); + } + return rest.invokeQuery( + operationId, queryName, deserializer, serialize, vars, token); + } + + @override + Stream invokeStreamQuery( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? token, + ) { + return websocket.invokeStreamQuery( + operationId, queryName, deserializer, serializer, vars, token); + } +} diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/duration.pb.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/duration.pb.dart index 4bcbcd32a4c2..6c32fb50221c 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/duration.pb.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/duration.pb.dart @@ -1,3 +1,4 @@ +// ignore_for_file: implementation_imports // // Generated code. Do not modify. // source: google/protobuf/duration.proto diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/struct.pb.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/struct.pb.dart index 42d55e426602..42164fbc928f 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/struct.pb.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/generated/google/protobuf/struct.pb.dart @@ -1,3 +1,4 @@ +// ignore_for_file: implementation_imports // // Generated code. Do not modify. // source: google/protobuf/struct.proto diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_library.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_library.dart deleted file mode 100644 index d46b30815133..000000000000 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_library.dart +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import 'dart:convert'; -import 'dart:developer'; - -import 'package:firebase_app_check/firebase_app_check.dart'; -import 'package:firebase_data_connect/src/generated/graphql_error.pb.dart'; -import 'package:grpc/grpc.dart'; - -import '../common/common_library.dart'; -import '../dataconnect_version.dart'; -import '../generated/connector_service.pbgrpc.dart'; -import '../generated/google/protobuf/struct.pb.dart'; - -part 'grpc_transport.dart'; diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart deleted file mode 100644 index 180bb209168b..000000000000 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/grpc_transport.dart +++ /dev/null @@ -1,242 +0,0 @@ -// Copyright 2024 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -part of 'grpc_library.dart'; - -/// Transport used for Android/iOS. Uses a GRPC transport instead of REST. -class GRPCTransport implements DataConnectTransport { - /// GRPCTransport creates a new channel - GRPCTransport( - this.transportOptions, - this.options, - this.appId, - this.sdkType, - this.appCheck, - ) { - bool isSecure = transportOptions.isSecure ?? true; - channel = ClientChannel( - transportOptions.host, - port: transportOptions.port ?? 443, - options: ChannelOptions( - credentials: (isSecure - ? const ChannelCredentials.secure() - : const ChannelCredentials.insecure()), - ), - ); - stub = ConnectorServiceClient(channel); - name = - 'projects/${options.projectId}/locations/${options.location}/services/${options.serviceId}/connectors/${options.connector}'; - } - - /// FirebaseAppCheck - @override - FirebaseAppCheck? appCheck; - - @override - CallerSDKType sdkType; - - /// Name of the endpoint. - late String name; - - /// ConnectorServiceClient used to execute the query/mutation. - late ConnectorServiceClient stub; - - /// ClientChannel used to configure connection to the GRPC server. - late ClientChannel channel; - - /// Current host configuration. - @override - TransportOptions transportOptions; - - /// Data Connect backend configuration options. - @override - DataConnectOptions options; - - /// Application ID - @override - String appId; - - Future> getMetadata(String? authToken) async { - String? appCheckToken; - try { - appCheckToken = await appCheck?.getToken(); - } catch (e) { - log('Unable to get app check token: $e'); - } - Map metadata = { - 'x-goog-request-params': 'location=${options.location}&frontend=data', - 'x-goog-api-client': getGoogApiVal(sdkType, packageVersion), - 'x-firebase-client': getFirebaseClientVal(packageVersion) - }; - - if (authToken != null) { - metadata['x-firebase-auth-token'] = authToken; - } - if (appCheckToken != null) { - metadata['X-Firebase-AppCheck'] = appCheckToken; - } - metadata['x-firebase-gmpid'] = appId; - return metadata; - } - - /// Invokes GPRC query endpoint. - @override - Future invokeQuery( - String queryName, - Deserializer deserializer, - Serializer? serializer, - Variables? vars, - String? authToken, - ) async { - ExecuteQueryResponse response; - - ExecuteQueryRequest request = - ExecuteQueryRequest(name: name, operationName: queryName); - if (vars != null && serializer != null) { - request.variables = getStruct(vars, serializer); - } - try { - response = await stub.executeQuery( - request, - options: CallOptions(metadata: await getMetadata(authToken)), - ); - return handleResponse( - CommonResponse.fromExecuteQuery(deserializer, response)); - } on Exception catch (e) { - if (e.toString().contains('invalid Firebase Auth Credentials')) { - throw DataConnectError( - DataConnectErrorCode.unauthorized, - 'Failed to invoke operation: $e', - ); - } - rethrow; - } - } - - /// Converts the variables into a proto Struct. - Struct getStruct( - Variables vars, - Serializer serializer, - ) { - Struct struct = Struct.create(); - struct.mergeFromProto3Json(jsonDecode(serializer(vars))); - return struct; - } - - /// Invokes GPRC mutation endpoint. - @override - Future invokeMutation( - String queryName, - Deserializer deserializer, - Serializer? serializer, - Variables? vars, - String? authToken, - ) async { - ExecuteMutationResponse response; - ExecuteMutationRequest request = - ExecuteMutationRequest(name: name, operationName: queryName); - if (vars != null && serializer != null) { - request.variables = getStruct(vars, serializer); - } - - try { - response = await stub.executeMutation( - request, - options: CallOptions(metadata: await getMetadata(authToken)), - ); - return handleResponse( - CommonResponse.fromExecuteMutation(deserializer, response)); - } on Exception catch (e) { - if (e.toString().contains('invalid Firebase Auth Credentials')) { - throw DataConnectError( - DataConnectErrorCode.unauthorized, - 'Failed to invoke operation: $e', - ); - } - rethrow; - } - } -} - -ServerResponse handleResponse(CommonResponse commonResponse) { - Map? jsond = commonResponse.data as Map?; - String jsonEncoded = jsonEncode(commonResponse.data); - - Map? jsonExt = - commonResponse.extensions as Map?; - - if (commonResponse.errors.isNotEmpty) { - Map? data = - jsonDecode(jsonEncoded) as Map?; - Data? decodedData; - List errors = commonResponse - .errors - .map((e) => DataConnectOperationFailureResponseErrorInfo( - e.path.values - .map((val) => val.hasStringValue() - ? DataConnectFieldPathSegment(val.stringValue) - : DataConnectListIndexPathSegment(val.numberValue.toInt())) - .toList(), - e.message)) - .toList(); - if (data != null) { - try { - decodedData = commonResponse.deserializer(jsonEncoded); - } catch (e) { - // nothing required - } - } - final response = - DataConnectOperationFailureResponse(errors, data, decodedData); - throw DataConnectOperationError(DataConnectErrorCode.other, - 'failed to invoke operation: ${response.errors}', response); - } - - // no errors - return a standard response - if (jsond != null) { - return ServerResponse(jsond, extensions: jsonExt); - } else { - return ServerResponse({}); - } -} - -/// Initializes GRPC transport for Data Connect. -DataConnectTransport getTransport( - TransportOptions transportOptions, - DataConnectOptions options, - String appId, - CallerSDKType sdkType, - FirebaseAppCheck? appCheck, -) => - GRPCTransport(transportOptions, options, appId, sdkType, appCheck); - -class CommonResponse { - CommonResponse(this.deserializer, this.data, this.errors, this.extensions); - static CommonResponse fromExecuteMutation( - Deserializer deserializer, ExecuteMutationResponse response) { - return CommonResponse( - deserializer, response.data.toProto3Json(), response.errors, null); - } - - static CommonResponse fromExecuteQuery( - Deserializer deserializer, ExecuteQueryResponse response) { - return CommonResponse(deserializer, response.data.toProto3Json(), - response.errors, response.extensions.toProto3Json()); - } - - final Deserializer deserializer; - final Object? data; - final List errors; - final Object? extensions; -} diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart index 2680f692e350..4480096e49a3 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart @@ -150,6 +150,7 @@ class RestTransport implements DataConnectTransport { /// Invokes query REST endpoint. @override Future invokeQuery( + String operationId, String queryName, Deserializer deserializer, Serializer? serializer, @@ -169,6 +170,7 @@ class RestTransport implements DataConnectTransport { /// Invokes mutation REST endpoint. @override Future invokeMutation( + String operationId, String queryName, Deserializer deserializer, Serializer? serializer, @@ -184,6 +186,20 @@ class RestTransport implements DataConnectTransport { token, ); } + + /// WebSockets are now handled by WebSocketTransport in FirebaseDataConnect. + @override + Stream invokeStreamQuery( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? token, + ) { + throw UnsupportedError( + 'Streaming should be routed through WebSocketTransport'); + } } /// Initializes Rest transport for Data Connect. diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/stream_protocol.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/stream_protocol.dart new file mode 100644 index 000000000000..a0478e6e1e0c --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/stream_protocol.dart @@ -0,0 +1,160 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// The kind of streaming request. +enum RequestKind { + subscribe, + execute, + resume, + cancel, +} + +/// Request to execute or subscribe to a Data Connect query or mutation. +class ExecuteRequest { + ExecuteRequest(this.operationName, this.variables); + + final String operationName; + final Map? variables; + + Map toJson() { + final Map data = {}; + data['operationName'] = operationName; + if (variables != null) { + data['variables'] = variables; + } + return data; + } +} + +/// Request to resume a query. +class ResumeRequest { + ResumeRequest(); + + Map toJson() { + return {}; + } +} + +/// StreamRequest defines the request of Data Connect's bi-directional streaming API. +class StreamRequest { + StreamRequest({ + this.name, + this.headers, + this.requestId, + this.requestKind, + this.subscribe, + this.execute, + this.resume, + this.cancel, + this.dataEtag, + }); + + /// The resource name of the connector. + final String? name; + + /// Optional headers. + final Map? headers; + + /// The request id used to identify a request within the stream. + final String? requestId; + + /// Kind of the request. + final RequestKind? requestKind; + + /// Subscribe to a Data Connect query. + final ExecuteRequest? subscribe; + + /// Execute a Data Connect query or mutation. + final ExecuteRequest? execute; + + /// Resume a query. + final ResumeRequest? resume; + + /// Signal that the client is no longer interested. + final bool? cancel; + + /// Etag for caching. + final String? dataEtag; + + Map toJson() { + final Map data = {}; + if (name != null) { + data['name'] = name; + } + if (headers != null) { + data['headers'] = headers; + } + if (requestId != null) { + data['requestId'] = requestId; + } + if (dataEtag != null) { + data['dataEtag'] = dataEtag; + } + + if (subscribe != null) { + data['subscribe'] = subscribe!.toJson(); + } else if (execute != null) { + data['execute'] = execute!.toJson(); + } else if (resume != null) { + data['resume'] = resume!.toJson(); + } else if (cancel == true) { + data['cancel'] = {}; + } + + return data; + } +} + +/// StreamResponse defines the response of Data Connect's bi-directional streaming API. +class StreamResponse { + StreamResponse({ + this.requestId, + this.data, + this.dataEtag, + this.errors, + this.cancelled, + this.extensions, + }); + + factory StreamResponse.fromJson(Map json) { + if (json.containsKey('result')) { + json = json['result'] as Map; + } else if (json.containsKey('error')) { + final errObj = json['error'] as Map; + json = { + 'errors': [ + {'message': errObj['message']} + ] + }; + } + + List? errorsList = json['errors'] as List?; + + return StreamResponse( + requestId: json['requestId'] as String?, + data: json['data'] as Map?, + dataEtag: json['dataEtag'] as String?, + errors: errorsList, + cancelled: json['cancelled'] as bool?, + extensions: json['extensions'] as Map?, + ); + } + + final String? requestId; + final Map? data; + final String? dataEtag; + final List? errors; + final bool? cancelled; + final Map? extensions; +} diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_library.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_library.dart index 7da28d92b812..44e0391dd6c7 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_library.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_library.dart @@ -12,8 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +import 'dart:async'; +import 'dart:convert'; +import 'dart:developer' as developer; +import 'dart:math'; import 'package:firebase_app_check/firebase_app_check.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; import '../common/common_library.dart'; +import '../dataconnect_version.dart'; +import 'stream_protocol.dart'; part 'transport_stub.dart'; +part 'websocket_transport.dart'; diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_stub.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_stub.dart index e00c53b5bac1..87b8445f3abe 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_stub.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/transport_stub.dart @@ -50,6 +50,7 @@ class TransportStub implements DataConnectTransport { /// Stub for invoking a mutation. @override Future invokeMutation( + String operationId, String queryName, Deserializer deserializer, Serializer? serializer, @@ -60,9 +61,24 @@ class TransportStub implements DataConnectTransport { throw UnimplementedError(); } + /// Stub for subscribing to a query. + @override + Stream invokeStreamQuery( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? token, + ) { + // TODO: implement invokeStreamQuery + throw UnimplementedError(); + } + /// Stub for invoking a query. @override Future invokeQuery( + String operationId, String queryName, Deserializer deserializer, Serializer? serialize, diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart new file mode 100644 index 000000000000..0fb62e5fde33 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart @@ -0,0 +1,646 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +part of 'transport_library.dart'; + +/// WebSocketTransport makes requests out to the streaming endpoints of the configured backend, +/// multiplexing multiple subscriptions and unary operations over a single WebSocket connection. + +class _PendingUnary { + final Completer completer; + final String operationName; + final Map? variables; + final bool isMutation; + + _PendingUnary( + this.completer, this.operationName, this.variables, this.isMutation); +} + +class _PendingSubscription { + final String operationId; + final String queryName; + final Map? variables; + + _PendingSubscription(this.operationId, this.queryName, this.variables); +} + +class WebSocketTransport implements DataConnectTransport { + static const int _maxReconnectAttempts = 10; + static const int _maxReconnectDelayMs = 30000; + static const int _initialReconnectDelayMs = 1000; + + /// Initializes necessary protocol and port. + WebSocketTransport( + this.transportOptions, + this.options, + this.appId, + this.sdkType, + this.appCheck, [ + this.auth, + ]) { + final protocol = (transportOptions.isSecure ?? true) ? 'wss' : 'ws'; + final host = transportOptions.host; + final port = transportOptions.port ?? 443; + final location = options.location; + + _url = Uri( + scheme: protocol, + host: host, + port: port, + path: + '/ws/google.firebase.dataconnect.v1.ConnectorStreamService/Connect/locations/$location', + ).toString(); + + _currentUid = auth?.currentUser?.uid; + _authSubscription = auth?.idTokenChanges().listen((user) async { + final newUid = user?.uid; + // Disconnect and reconnect on any fundamental user change (login, logout, switch). + if (_currentUid != newUid) { + _disconnect(); + _scheduleReconnect(); + } else if (newUid != null && isConnected) { + // Token refreshed for the same user, push the new token natively down the socket. + try { + final token = await user?.getIdToken(); + final request = StreamRequest( + requestId: _generateRequestId('auth'), + headers: _buildHeaders(token, null), + ); + _send(request.toJson()); + } catch (_) { + // Ignored + } + } + _currentUid = newUid; + }); + } + + FirebaseAuth? auth; + String? _currentUid; + // ignore: unused_field + StreamSubscription? _authSubscription; //required to hold reference + + @override + FirebaseAppCheck? appCheck; + + @override + CallerSDKType sdkType; + + late String _url; + + @override + TransportOptions transportOptions; + + @override + DataConnectOptions options; + + @override + String appId; + + WebSocketChannel? _channel; + // ignore: unused_field + StreamSubscription? _channelSubscription; + + // Active listeners for stream subscriptions mapped by requestId. + final Map>> _streamListeners = + {}; + + // Pending information for subscriptions mapped by requestId. + final Map _pendingSubscriptions = {}; + + // Active completers for unary operations mapped by requestId. + final Map> _unaryListeners = {}; + + // Active subscriptions mapped by operationId => requestId. + final Map _activeSubscriptions = {}; + + bool _isReconnecting = false; + int _reconnectAttempts = 0; + bool _isExpectedDisconnect = false; + + void _checkIdleAndDisconnect() { + if (_streamListeners.isEmpty && _unaryListeners.isEmpty) { + _isExpectedDisconnect = true; + _disconnect(); + _clearState(); + } + } + + final Random _random = Random(); + static const String _chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; + + String _generateRequestId(String operationName) { + final randStr = String.fromCharCodes(Iterable.generate( + 15, (_) => _chars.codeUnitAt(_random.nextInt(_chars.length)))); + return '${operationName}_$randStr'; + } + + void _send(Map json) { + if (_channel == null) return; + final encoded = jsonEncode(json); + if (encoded.isNotEmpty) { + developer.log("Sending stream message \n $encoded"); + _channel!.sink.add(encoded); + } + } + + bool get isConnected => _channel != null; + + Map _buildHeaders(String? authToken, String? appCheckToken) { + Map headers = { + 'x-goog-api-client': getGoogApiVal(sdkType, packageVersion), + 'x-firebase-client': getFirebaseClientVal(packageVersion) + }; + if (authToken != null) { + headers['X-Firebase-Auth-Token'] = authToken; + } + if (appCheckToken != null) { + headers['X-Firebase-AppCheck'] = appCheckToken; + } + headers['x-firebase-gmpid'] = appId; + return headers; + } + + Future? _connectionFuture; + + Future _ensureConnected(String? authToken) { + if (_channel != null) return Future.value(); + if (_connectionFuture != null) return _connectionFuture!; + _connectionFuture = _doConnect(authToken).whenComplete(() { + _connectionFuture = null; + }); + return _connectionFuture!; + } + + Future _doConnect(String? authToken) async { + String? appCheckToken; + try { + appCheckToken = await appCheck?.getToken(); + } catch (_) { + // Ignored + } + + final headers = _buildHeaders(authToken, appCheckToken); + + _channel = WebSocketChannel.connect(Uri.parse(_url)); + _channelSubscription = _channel?.stream.listen( + _onMessage, + onError: _onError, + onDone: _onDone, + ); + + // reset this since an explicit connect was requested + _isExpectedDisconnect = false; + + try { + await _channel?.ready; + } catch (e) { + developer.log('WebSocket connection failed to become ready: $e'); + _channel = null; + throw DataConnectError( + DataConnectErrorCode.other, 'WebSocket connection failed: $e'); + } + + final initRequest = StreamRequest( + name: + 'projects/${options.projectId}/locations/${options.location}/services/${options.serviceId}/connectors/${options.connector}', + headers: headers, + ); + _send(initRequest.toJson()); + } + + // called when a message is received from the stream + void _onMessage(dynamic message) { + try { + var bodyString = ''; + if (message is List) { + bodyString = utf8.decode(message); + } else { + bodyString = message as String; + } + developer.log("Received stream response \n $bodyString"); + + final bodyJson = jsonDecode(bodyString) as Map; + final response = StreamResponse.fromJson(bodyJson); + + final requestId = response.requestId; + if (requestId == null) return; + + final serverResponse = ServerResponse( + response.data ?? {}, + extensions: response.extensions, + ); + + // Append errors if any exist on the stream payload + if (response.errors != null && response.errors!.isNotEmpty) { + // We simulate a DataConnectOperationError payload structure + // so that ref.dart can parse it correctly + serverResponse.data['errors'] = response.errors; + } + + if (_unaryListeners.containsKey(requestId)) { + final pendings = _unaryListeners.remove(requestId) ?? []; + for (final p in pendings) { + if (!p.completer.isCompleted) { + p.completer.complete(serverResponse); + } + } + _checkIdleAndDisconnect(); + } + + if (_streamListeners.containsKey(requestId)) { + final controllers = _streamListeners[requestId] ?? []; + if (response.cancelled == true) { + for (final controller in controllers) { + controller.close(); + } + _streamListeners.remove(requestId); + _activeSubscriptions.removeWhere((key, value) => value == requestId); + _pendingSubscriptions.remove(requestId); + _checkIdleAndDisconnect(); + } else { + for (final controller in controllers) { + controller.add(serverResponse); + } + } + } + } catch (e) { + // JSON decoding error or unknown format + developer.log('error decoding server response $e'); + } + } + + void _clearState([DataConnectError? error]) { + final e = error ?? + DataConnectError( + DataConnectErrorCode.other, 'WebSocket connection closed.'); + for (final pendings in _unaryListeners.values) { + for (final p in pendings) { + if (!p.completer.isCompleted) { + p.completer.completeError(e); + } + } + } + for (final controllers in _streamListeners.values) { + for (final controller in controllers) { + controller.addError(e); + controller.close(); + } + } + _unaryListeners.clear(); + _streamListeners.clear(); + _activeSubscriptions.clear(); + _pendingSubscriptions.clear(); + _isReconnecting = false; + _reconnectAttempts = 0; + } + + Timer? _reconnectTimer; + + void _scheduleReconnect() { + developer.log( + '${DateTime.now()} _scheduleReconnect $_reconnectAttempts $_isReconnecting $_isExpectedDisconnect'); + if (_isReconnecting || _isExpectedDisconnect) return; + _isReconnecting = true; + + if (_reconnectAttempts >= _maxReconnectAttempts) { + _clearState(DataConnectError(DataConnectErrorCode.other, + 'Network disconnected after max attempts.')); + return; + } + + final delay = min( + _initialReconnectDelayMs * pow(2, _reconnectAttempts).toInt(), + _maxReconnectDelayMs); + var startTime = DateTime.now(); + developer.log('$startTime scheduling _performReconnect in $delay ms'); + + _reconnectTimer?.cancel(); + _reconnectTimer = Timer(Duration(milliseconds: delay), () async { + developer.log( + '${DateTime.now()} calling delayed _performReconnect scheduled at $startTime'); + _performReconnect(); + }); + } + + Future _refreshAuthToken() async { + try { + return await auth?.currentUser?.getIdToken(); + } catch (_) { + // If fetching token fails, continue unauthenticated. + return null; + } + } + + Future _refreshAppCheckToken() async { + try { + if (appCheck != null) { + return await appCheck!.getToken(); + } + } catch (_) { + // Ignored: continue without AppCheck token if it fails. + } + return null; + } + + void _resubscribeActive(String? authToken, String? appCheckToken) { + for (final sub in _pendingSubscriptions.values) { + final reqId = _activeSubscriptions[sub.operationId]; + if (reqId == null) continue; + final headers = _buildHeaders(authToken, appCheckToken); + final request = StreamRequest( + requestId: reqId, + requestKind: RequestKind.subscribe, + subscribe: ExecuteRequest(sub.queryName, sub.variables), + headers: headers, + ); + _send(request.toJson()); + } + } + + void _replayQueriesAndFailMutations( + String? authToken, String? appCheckToken) { + final unariesToReplay = >{}; + for (final entry in _unaryListeners.entries) { + final reqId = entry.key; + final kept = <_PendingUnary>[]; + for (final p in entry.value) { + if (p.isMutation) { + p.completer.completeError(DataConnectError(DataConnectErrorCode.other, + 'Network reconnected; mutations cannot be safely retried.')); + } else { + kept.add(p); + final headers = _buildHeaders(authToken, appCheckToken); + final request = StreamRequest( + requestId: reqId, + requestKind: RequestKind.execute, + execute: ExecuteRequest(p.operationName, p.variables), + headers: headers, + ); + _send(request.toJson()); + } + } + if (kept.isNotEmpty) { + unariesToReplay[reqId] = kept; + } + } + _unaryListeners.clear(); + _unaryListeners.addAll(unariesToReplay); + } + + Future _performReconnect() async { + _channel?.sink.close(); + _channel = null; + _reconnectAttempts++; + + final authToken = await _refreshAuthToken(); + final appCheckToken = await _refreshAppCheckToken(); + + try { + await _ensureConnected(authToken); + + _reconnectAttempts = 0; + _isReconnecting = false; + + _resubscribeActive(authToken, appCheckToken); + _replayQueriesAndFailMutations(authToken, appCheckToken); + } catch (e) { + _isReconnecting = false; + _scheduleReconnect(); + } + } + + void _onError(dynamic error) { + if (_channel == null) return; + developer.log('WebSocket error: $error'); + _channel = null; + _isReconnecting = false; + _scheduleReconnect(); + } + + void _disconnect() { + _reconnectTimer?.cancel(); + _reconnectTimer = null; + _channel?.sink.close(); + _channel = null; + } + + void disconnect() { + _isExpectedDisconnect = true; + _disconnect(); + } + + void _onDone() { + if (_channel == null) return; + developer.log('WebSocket connection closed.'); + _channel = null; + _isReconnecting = false; + if (!_isExpectedDisconnect) { + _scheduleReconnect(); + } + } + + @override + Future invokeQuery( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? authToken, + ) async { + return _invokeUnary(operationId, queryName, deserializer, serializer, vars, + authToken, RequestKind.execute, false); + } + + @override + Future invokeMutation( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? authToken, + ) async { + return _invokeUnary(operationId, queryName, deserializer, serializer, vars, + authToken, RequestKind.execute, true); + } + + Future _invokeUnary( + String operationId, + String operationName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? authToken, + RequestKind requestKind, + bool isMutation, + ) async { + await _ensureConnected(authToken); + + final completer = Completer(); + + if (_activeSubscriptions.containsKey(operationId)) { + final existingRequestId = _activeSubscriptions[operationId]!; + Map? variablesMap; + if (vars != null && serializer != null) { + variablesMap = jsonDecode(serializer(vars)); + } + _unaryListeners.putIfAbsent(existingRequestId, () => []).add( + _PendingUnary(completer, operationName, variablesMap, isMutation)); + + String? appCheckToken; + try { + appCheckToken = await appCheck?.getToken(); + } catch (_) { + // Ignored + } + + final headers = _buildHeaders(authToken, appCheckToken); + + final request = StreamRequest( + requestId: existingRequestId, + requestKind: RequestKind.resume, + resume: ResumeRequest(), + headers: headers, + ); + _send(request.toJson()); + + return completer.future; + } + + final requestId = _generateRequestId(operationId); + + Map? variables; + if (vars != null && serializer != null) { + variables = jsonDecode(serializer(vars)); + } + _unaryListeners + .putIfAbsent(requestId, () => []) + .add(_PendingUnary(completer, operationName, variables, isMutation)); + + String? appCheckToken; + try { + appCheckToken = await appCheck?.getToken(); + } catch (_) { + // Ignored + } + + final headers = _buildHeaders(authToken, appCheckToken); + + final request = StreamRequest( + requestId: requestId, + requestKind: requestKind, + execute: ExecuteRequest(operationName, variables), + headers: headers, + ); + + _send(request.toJson()); + + return completer.future; + } + + @override + Stream invokeStreamQuery( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? authToken, + ) { + late StreamController controller; + + controller = StreamController( + onListen: () async { + try { + await _ensureConnected(authToken); + } catch (e) { + developer.log("Error subscribing - setting up stream $e"); + // Do NOT add error to sink here. The stream is designed to quietly + // add the query to `_pendingSubscriptions` below and silently + // retry when the network reconnects via `_scheduleReconnect`. + } + + if (_activeSubscriptions.containsKey(operationId)) { + final existingRequestId = _activeSubscriptions[operationId]!; + _streamListeners + .putIfAbsent(existingRequestId, () => []) + .add(controller); + return; + } + + final requestId = _generateRequestId(operationId); + _activeSubscriptions[operationId] = requestId; + _streamListeners.putIfAbsent(requestId, () => []).add(controller); + + Map? variables; + if (vars != null && serializer != null) { + variables = json.decode(serializer(vars)); + } + _pendingSubscriptions[requestId] = + _PendingSubscription(operationId, queryName, variables); + + if (!isConnected) { + // we are not connected - + // keep pending sub to use for retry + _scheduleReconnect(); + return; + } + + String? appCheckToken; + try { + appCheckToken = await appCheck?.getToken(); + } catch (_) { + // Ignored + } + + final headers = _buildHeaders(authToken, appCheckToken); + + final request = StreamRequest( + requestId: requestId, + requestKind: RequestKind.subscribe, + subscribe: ExecuteRequest(queryName, variables), + headers: headers, + ); + + _send(request.toJson()); + }, + onCancel: () { + if (!_activeSubscriptions.containsKey(operationId)) return; + final requestId = _activeSubscriptions[operationId]!; + + final listeners = _streamListeners[requestId]; + if (listeners != null) { + listeners.remove(controller); + if (listeners.isEmpty) { + _streamListeners.remove(requestId); + _activeSubscriptions.remove(operationId); + _pendingSubscriptions.remove(requestId); + + final cancelReq = StreamRequest( + requestId: requestId, + requestKind: RequestKind.cancel, + cancel: true, + ); + _send(cancelReq.toJson()); + _checkIdleAndDisconnect(); + } + } + }, + ); + + return controller.stream; + } +} diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index d0145d0290ac..3bd28b86b42c 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -27,6 +27,7 @@ dependencies: protobuf: ^3.1.0 sqlite3: ^2.9.0 sqlite3_flutter_libs: ^0.5.40 + web_socket_channel: ^3.0.1 dev_dependencies: build_runner: ^2.4.12 diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.dart index dec53744b7e3..6848824996c4 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.dart @@ -233,7 +233,7 @@ void main() { }); test('maxAge conformance', () async { - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; final mockResponseSuccess = http.Response('{"success": true}', 200); if (dataConnect.cacheManager == null) { diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/common/common_library_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/common/common_library_test.dart index 353f34aeec75..a3798daf98f7 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/common/common_library_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/common/common_library_test.dart @@ -103,8 +103,10 @@ void main() { test('should handle invokeQuery with proper deserializer', () async { const queryName = 'testQuery'; - final deserializer = (json) => json; + const queryId = 'testQueryId'; + deserializer(json) => json; final result = await transport.invokeQuery( + queryId, queryName, deserializer, emptySerializer, @@ -117,8 +119,10 @@ void main() { test('should handle invokeMutation with proper deserializer', () async { const queryName = 'testMutation'; - final deserializer = (json) => json; + const operationId = 'testMutationId'; + deserializer(json) => json; final result = await transport.invokeMutation( + operationId, queryName, deserializer, emptySerializer, @@ -134,17 +138,18 @@ void main() { // Test class extending DataConnectTransport for testing purposes class TestDataConnectTransport extends DataConnectTransport { TestDataConnectTransport( - TransportOptions transportOptions, - DataConnectOptions options, - String appId, - CallerSDKType sdkType, { + super.transportOptions, + super.options, + super.appId, + super.sdkType, { FirebaseAppCheck? appCheck, - }) : super(transportOptions, options, appId, sdkType) { + }) { this.appCheck = appCheck; } @override Future invokeQuery( + String operationId, String queryName, Deserializer deserializer, Serializer? serializer, @@ -157,6 +162,7 @@ class TestDataConnectTransport extends DataConnectTransport { @override Future invokeMutation( + String operationId, String queryName, Deserializer deserializer, Serializer? serializer, @@ -166,4 +172,16 @@ class TestDataConnectTransport extends DataConnectTransport { // Simulate mutation invocation logic here return ServerResponse({}); } + + @override + Stream invokeStreamQuery( + String operationId, + String queryName, + Deserializer deserializer, + Serializer? serializer, + Variables? vars, + String? authToken, + ) { + return Stream.value(ServerResponse({})); + } } diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/common/dataconnect_error_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/common/dataconnect_error_test.dart index 3cb6c9ce26c8..5735f324f3b4 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/common/dataconnect_error_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/common/dataconnect_error_test.dart @@ -79,8 +79,7 @@ void main() { group('Serializer and Deserializer', () { test('should serialize variables into string format', () { - Serializer> serializer = - (Map vars) => vars.toString(); + String serializer(Map vars) => vars.toString(); final inputVars = {'key1': 'value1', 'key2': 123}; final serializedString = serializer(inputVars); @@ -89,8 +88,7 @@ void main() { }); test('should deserialize string data into expected format', () { - Deserializer> deserializer = - (String data) => {'data': data}; + deserializer(String data) => {'data': data}; const inputData = '{"message": "Hello World"}'; final deserializedData = deserializer(inputData); diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/core/ref_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/core/ref_test.dart index 636cae0cde52..b057f4aeb71f 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/core/ref_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/core/ref_test.dart @@ -82,7 +82,7 @@ void main() { test( 'addQuery should create a new StreamController if query does not exist', () { - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; String varSerializer(Object? _) { return 'varsAsStr'; } @@ -98,8 +98,7 @@ void main() { ); final stream = queryManager.addQuery(ref); - //expect(queryManager.trackedQueries['testQuery'], isNotNull); - expect(queryManager.trackedQueries['testQuery::varsAsStr'], isNotNull); + expect(queryManager.trackedQueries.values.contains(ref), isTrue); expect(stream, isA()); }); }); @@ -149,7 +148,7 @@ void main() { mockDataConnect.transport = transport; }); test('executeQuery should gracefully handle getIdToken failures', () async { - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; final mockResponseSuccess = http.Response('{"success": true}', 200); when(mockUser.getIdToken()).thenThrow(Exception('Auth error')); QueryRef ref = QueryRef( @@ -175,7 +174,7 @@ void main() { () async { final mockResponse = http.Response('{"error": "Unauthorized"}', 401); final mockResponseSuccess = http.Response('{"success": true}', 200); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; int count = 0; int idTokenCount = 0; QueryRef ref = QueryRef( @@ -219,7 +218,7 @@ void main() { }); test('throw Error if server throws one', () { - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; final mockResponse = http.Response( ''' { @@ -285,10 +284,10 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) { + AbcHolder deserializer(String data) { Map decoded = jsonDecode(data) as Map; return AbcHolder(decoded['abc']!); - }; + } QueryRef ref = QueryRef( mockDataConnect, @@ -339,10 +338,10 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) { + AbcHolder deserializer(String data) { Map decoded = jsonDecode(data) as Map; return AbcHolder(decoded['abc']!); - }; + } QueryRef ref = QueryRef( mockDataConnect, @@ -390,10 +389,10 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) { + AbcHolder deserializer(String data) { Map decoded = jsonDecode(data) as Map; return AbcHolder(decoded['abc']!); - }; + } QueryRef ref = QueryRef( mockDataConnect, diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart index 2deb28f22749..b4edc25b2a81 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart @@ -25,7 +25,16 @@ import 'package:mockito/mockito.dart'; @GenerateNiceMocks([MockSpec(), MockSpec()]) import 'firebase_data_connect_test.mocks.dart'; -class MockFirebaseAuth extends Mock implements FirebaseAuth {} +class MockFirebaseAuth extends Mock implements FirebaseAuth { + @override + Stream idTokenChanges() { + return super.noSuchMethod( + Invocation.method(#idTokenChanges, []), + returnValue: const Stream.empty(), + returnValueForMissingStub: const Stream.empty(), + ) as Stream; + } +} class MockFirebaseAppCheck extends Mock implements FirebaseAppCheck {} diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart index bad97d364d32..d3dbc2902d12 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart @@ -98,7 +98,7 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; expect( () => transport.invokeOperation( @@ -124,7 +124,7 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; expect( () => transport.invokeOperation( @@ -150,9 +150,10 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; - await transport.invokeQuery('testQuery', deserializer, null, null, null); + await transport.invokeQuery( + 'testQueryId', 'testQuery', deserializer, null, null, null); verify( mockHttpClient.post( @@ -178,9 +179,10 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) => 'Deserialized Mutation Data'; + String deserializer(String data) => 'Deserialized Mutation Data'; await transport.invokeMutation( + 'testMutationId', 'testMutation', deserializer, null, @@ -215,7 +217,7 @@ void main() { when(mockUser.getIdToken()).thenAnswer((_) async => 'authToken123'); when(mockAppCheck.getToken()).thenAnswer((_) async => 'appCheckToken123'); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; await transport.invokeOperation( 'testQuery', @@ -250,7 +252,7 @@ void main() { when(mockUser.getIdToken()).thenAnswer((_) async => 'authToken123'); when(mockAppCheck.getToken()).thenAnswer((_) async => 'appCheckToken123'); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; await transport.invokeOperation( 'testQuery', @@ -297,7 +299,7 @@ void main() { ), ).thenAnswer((_) async => mockResponse); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; final result = await transport.invokeOperation( 'testQuery', @@ -327,7 +329,7 @@ void main() { when(mockUser.getIdToken()).thenThrow(Exception('Auth error')); when(mockAppCheck.getToken()).thenThrow(Exception('AppCheck error')); - final deserializer = (String data) => 'Deserialized Data'; + String deserializer(String data) => 'Deserialized Data'; await transport.invokeOperation( 'testQuery', diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/network/transport_stub_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/network/transport_stub_test.dart index d8c6a865d316..daeffedd48cc 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/network/transport_stub_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/network/transport_stub_test.dart @@ -65,6 +65,7 @@ void main() { expect( () async => transportStub.invokeMutation( + 'operationId', 'queryName', (json) => json, null, @@ -86,6 +87,7 @@ void main() { expect( () async => transportStub.invokeQuery( + 'operationId', 'queryName', (json) => json, null, From 3d943ed4154eb61617746825fc5c1c90f1e73d88 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:40:25 +0000 Subject: [PATCH 022/137] feat: bump JS SDK to version 12.12.0 (#18186) Made-with: Cursor --- .../firebase_core_web/lib/src/firebase_sdk_version.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart index 8de3584a7165..34c5c064adbb 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart @@ -6,4 +6,4 @@ part of '../firebase_core_web.dart'; /// The currently supported Firebase JS SDK version. -const String supportedFirebaseJsSdkVersion = '12.11.0'; +const String supportedFirebaseJsSdkVersion = '12.12.0'; From cc063bd9df1c59dd3bb8c25d067f8655bc268523 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:40:46 +0000 Subject: [PATCH 023/137] feat: bump Firebase iOS SDK to 12.12.0 (#18187) --- .../firebase_core/firebase_core/ios/firebase_sdk_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb index f36a836d1580..c354b3b9dd54 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb +++ b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb @@ -1,4 +1,4 @@ # https://firebase.google.com/support/release-notes/ios def firebase_sdk_version!() - '12.11.0' + '12.12.0' end From 346a048f098090e6848fdd0f61a8bf7d01394676 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:41:05 +0000 Subject: [PATCH 024/137] feat(core): bump Firebase Android SDK to 34.12.0 (#18185) --- packages/firebase_core/firebase_core/android/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/android/gradle.properties b/packages/firebase_core/firebase_core/android/gradle.properties index 12e57d452ef2..2c89565e4791 100644 --- a/packages/firebase_core/firebase_core/android/gradle.properties +++ b/packages/firebase_core/firebase_core/android/gradle.properties @@ -1,2 +1,2 @@ # https://firebase.google.com/support/release-notes/android -FirebaseSDKVersion=34.11.0 +FirebaseSDKVersion=34.12.0 From d734cf0885f6d9403c2fb3ac48d6c52e14199309 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 13 Apr 2026 11:09:04 +0000 Subject: [PATCH 025/137] feat: support for Firestore Pipelines (#18183) * feat(firestore): introduce pipeline functionality (Dart API) (#18096) * feat(firestore): introduce pipeline functionality (Dart API) * fix * fix: restore unrelated regressions in settings, changelog, pubspec and exports Made-with: Cursor * fix * chore: fix formatting * chore: add pipeline stages tests nd fix bugs * chore: remove unnecessary parentheses in pipeline stage tests * test: add aggregate stage serialization tests for pipeline stages * test: add unit tests for pipeline expressions, ordering, sampling, and snapshot handling * chore: improve formatting and readability in pipeline test files * chore: update docs for PipelineSnapshot and PipelineResult * chore: fix ci * test: add serialization tests for arrayContainsAll and related expressions in pipeline expressions * feat: add arrayContainsAll expressions for enhanced array handling in pipeline expressions * refactor: remove PipelineFilter * fix: update arrayConcat method to accept Object? and convert to Expression * chore: remove unsupported expressions * chore: add timestamp unit validation and enhance timestamp expression methods * refactor: rename replace methods to stringReplaceAll * refactor: update test for stringReplaceAll serialization * chore: fix ci * chore: fix ci * docs: add documentation with examples for pipeline functions * chore: add pipeline_example Flutter project and integration tests * refactor: improve code formatting and add new execute options tests * fix ci * chore: add pipeline e2e test workflow and script for cloud_firestore * refactor: remove commented-out button for stringReplaceAll in pipeline example * chore: update e2e tests pipeline to include additional branches for triggering * chore: add test comment in pipeline example for clarity * chore: rename e2e pipeline and add iOS testing steps with Firebase configuration * test ci * chore: add workflow_dispatch trigger to e2e tests pipeline * chore: remove Firebase options condition from e2e tests pipeline jobs * chore: update e2e tests pipeline to run on macOS and implement flutter drive for integration tests * chore: update cloud_firestore dependency to use local path in pipeline example * chore: add dependency overrides for local development in cloud_firestore pipeline example * chore: update analysis options and refactor integration tests * refactor: improve formatting * fix ci * chore: remove Linux pipeline example files and associated configurations * chore: refine e2e tests pipeline triggers and enhance iOS project setup for Swift Package Manager * chore: add branch trigger for firestore-pipelines-ios in e2e tests pipeline * chore: update minimum target version for iOS to 15 * chore: add iOS and macOS paths to e2e tests pipeline triggers * refactor: improve code formatting in pipeline integration tests * chore: add branch triggers for Android and Web in e2e tests pipeline * fix formatting * trigger CI * chore: add more expression tests * chore: add more tests * fix ci * chore: include web package in e2e tests pipeline * chore: remove support for mapFromPairs(not supported on sdks) * chore: remove support for arraySlice(not supported on SDKs) * chore: remove arraySlice and _ArraySliceExpression due to SDK incompatibility * feat(firestore, android): Android implementation for Pipeline APIs (#18098) * feat(firestore): Android implementation for Pipeline APIs * refactor: improve handling of timestamps and array expressions in pipeline * chore: add support for more Expression functions in Android * chore: remove unsupported 'replace' expression from Android Firestore pipeline API * chore: enhance PipelineParser to support execute options for Firestore pipelines * chore: remove commented-out button for stringReplaceAll in pipeline example * trigger CI * trigger CI * trigger CI * refactor: enhance expression parsing logic in ExpressionParsers * feat(firestore, web): Web implementation for Pipeline APIs (#18100) * feat(firestore): Web implementation for Pipeline APIs * chore: fix ci * chore: inject firestore pipelines script for web * chore: add comments for Firestore Pipelines script injection in web implementation * refactor: remove unecessary comment * chore: add support for missing Expressions and fix bugs * chore: fix ci * feat: enhance pipeline expression handling with new expressions and error handling * refactor: rename 'replace' case to 'string_replace_all' in pipeline expression parser * chore: update Pipeline execution to accept options for index mode * fix: resolve failing mapGet test on web * fix: correctly parse 'not' expression arguments * trigger CI * fix tests * fix tests * fix: update type casting for boolean expression in PipelineExpressionParserWeb * fix ci * feat(firestore, iOS): iOS implementation for Pipeline APIs (#18099) * feat(firestore): iOS implementation for Pipeline APIs * fix: conditionally import FIRPipelineBridge.h for iOS * chore: add macOS support for FLTPipelineParser by linking to iOS implementation * fix: conditionally include FIRPipelineBridge.h for macOS support in FLTPipelineParser * chore: add support for missing Expression function * refactor: clean up formatting in FLTPipelineParser.m for improved readability * chore: enhance FLTPipelineParser with support for array and map expressions, ensuring proper argument handling * chore: implement conditional expression and current timestamp handling in FLTPipelineParser * chore: add 'find_nearest' stage support in FLTPipelineParser with validation for vector_field, vector_value, and distance_measure * chore: introduce FLTFirebaseFirestoreErrorCodePipelineParse for improved error handling in pipeline parsing * trigger CI * fix: update header inclusion logic for FirebaseFirestore in FLTPipelineParser.m * trigger CI * chore: enhance FLTPipelineParser with new expression handling * chore: update e2e tests pipeline to ignore specific paths for pull requests and pushes * chore: add new aggregate functions and expression methods * fix: update end-to-end test to conditionally skip based on platform * chore: fix ci * chore: fix ci * feat: add new pipeline expressions for regex, string manipulation, and aggregation * fix ci * fix: add conditional import for FIRVectorValue to FLTPipelineParser.m * fix: update argument passing in PipelineExpressionParserWeb for type expression * refactor: update type handling in pipeline expressions to use enum Type for better clarity and consistency * fix ci * chore: remove unused branch triggers from e2e tests pipeline * chore: add permissions section to e2e tests pipeline for content access * chore: enhance FLTPipelineParser to support options in FIRFunctionExprBridge initializations * chore: update Firebase SDK version to 12.11.0 in cloud_firestore Package.swift * refactor: streamline FIRFunctionExprBridge initializations in FLTPipelineParser by removing unnecessary options parameter * refactor: unify FIRFunctionExprBridge initialization logic in FLTPipelineParser to enhance compatibility across Firebase SDK versions * chore: trigger CI --- .github/workflows/e2e_tests_pipeline.yaml | 214 + melos.yaml | 7 + .../FlutterFirebaseFirestorePlugin.java | 64 + .../GeneratedAndroidFirebaseFirestore.java | 254 +- .../firestore/utils/ExpressionHelpers.java | 159 + .../firestore/utils/ExpressionParsers.java | 683 ++++ .../firestore/utils/PipelineParser.java | 140 + .../utils/PipelineStageHandlers.java | 338 ++ .../ios/cloud_firestore/Package.swift | 2 +- .../FLTFirebaseFirestorePlugin.m | 77 + .../FLTFirebaseFirestoreUtils.m | 7 + .../cloud_firestore/FLTPipelineParser.m | 1339 ++++++ .../cloud_firestore/FirestoreMessages.g.m | 124 +- .../Private/FLTFirebaseFirestoreUtils.h | 4 + .../Private/FLTPipelineParser.h | 23 + .../Public/FirestoreMessages.g.h | 28 + .../cloud_firestore/lib/cloud_firestore.dart | 10 + .../cloud_firestore/lib/src/firestore.dart | 20 + .../cloud_firestore/lib/src/pipeline.dart | 827 ++++ .../lib/src/pipeline_aggregate.dart | 294 ++ .../lib/src/pipeline_distance.dart | 17 + .../lib/src/pipeline_execute_options.dart | 20 + .../lib/src/pipeline_expression.dart | 3589 +++++++++++++++++ .../lib/src/pipeline_ordering.dart | 30 + .../lib/src/pipeline_sample.dart | 43 + .../lib/src/pipeline_snapshot.dart | 41 + .../lib/src/pipeline_source.dart | 67 + .../lib/src/pipeline_stage.dart | 419 ++ .../cloud_firestore/FLTPipelineParser.m | 1 + .../Private/FLTPipelineParser.h | 1 + .../pipeline_example/.gitignore | 45 + .../pipeline_example/.metadata | 45 + .../pipeline_example/README.md | 16 + .../pipeline_example/analysis_options.yaml | 34 + .../pipeline_example/android/.gitignore | 14 + .../android/app/build.gradle.kts | 47 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 45 + .../example/pipeline_example/MainActivity.kt | 5 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + .../pipeline_example/android/build.gradle.kts | 24 + .../android/gradle.properties | 2 + .../gradle/wrapper/gradle-wrapper.properties | 5 + .../android/settings.gradle.kts | 29 + .../pipeline/pipeline_add_fields_e2e.dart | 42 + .../pipeline/pipeline_aggregate_e2e.dart | 109 + .../pipeline_execute_options_e2e.dart | 37 + .../pipeline/pipeline_expressions_e2e.dart | 1088 +++++ .../pipeline/pipeline_filter_sort_e2e.dart | 89 + .../pipeline/pipeline_find_nearest_e2e.dart | 45 + .../pipeline/pipeline_live_test.dart | 52 + .../pipeline/pipeline_remove_fields_e2e.dart | 44 + .../pipeline/pipeline_replace_with_e2e.dart | 53 + .../pipeline/pipeline_sample_e2e.dart | 47 + .../pipeline/pipeline_seed.dart | 183 + .../pipeline/pipeline_select_e2e.dart | 42 + .../pipeline/pipeline_test_helpers.dart | 50 + .../pipeline/pipeline_unnest_union_e2e.dart | 63 + .../pipeline_example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../ios/Flutter/Debug.xcconfig | 2 + .../ios/Flutter/Release.xcconfig | 2 + .../pipeline_example/ios/Podfile | 43 + .../ios/Runner.xcodeproj/project.pbxproj | 741 ++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 101 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 + .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../pipeline_example/ios/Runner/Info.plist | 72 + .../ios/Runner/Runner-Bridging-Header.h | 1 + .../ios/RunnerTests/RunnerTests.swift | 10 + .../pipeline_example/lib/main.dart | 1377 +++++++ .../pipeline_example/macos/.gitignore | 7 + .../macos/Flutter/Flutter-Debug.xcconfig | 2 + .../macos/Flutter/Flutter-Release.xcconfig | 2 + .../pipeline_example/macos/Podfile | 42 + .../macos/Runner.xcodeproj/project.pbxproj | 805 ++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 99 + .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../macos/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 68 + .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 102994 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 5680 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 520 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14142 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1066 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 36406 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 2218 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 ++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + .../pipeline_example/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../macos/Runner/Release.entitlements | 8 + .../macos/RunnerTests/RunnerTests.swift | 10 + .../pipeline_example/pubspec.yaml | 111 + .../pipeline_example/test/widget_test.dart | 34 + .../test_driver/integration_test.dart | 7 + .../pipeline_example/web/favicon.png | Bin 0 -> 917 bytes .../pipeline_example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes .../pipeline_example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes .../web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes .../pipeline_example/web/index.html | 38 + .../pipeline_example/web/manifest.json | 35 + .../pipeline_example/windows/.gitignore | 17 + .../pipeline_example/windows/CMakeLists.txt | 108 + .../windows/flutter/CMakeLists.txt | 109 + .../windows/runner/CMakeLists.txt | 40 + .../pipeline_example/windows/runner/Runner.rc | 121 + .../windows/runner/flutter_window.cpp | 73 + .../windows/runner/flutter_window.h | 37 + .../pipeline_example/windows/runner/main.cpp | 46 + .../windows/runner/resource.h | 20 + .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../windows/runner/runner.exe.manifest | 14 + .../pipeline_example/windows/runner/utils.cpp | 69 + .../pipeline_example/windows/runner/utils.h | 23 + .../windows/runner/win32_window.cpp | 284 ++ .../windows/runner/win32_window.h | 104 + .../test/pipeline_aggregate_test.dart | 201 + .../test/pipeline_distance_test.dart | 29 + .../test/pipeline_execute_options_test.dart | 21 + .../test/pipeline_expression_test.dart | 1027 +++++ .../test/pipeline_ordering_test.dart | 62 + .../test/pipeline_sample_test.dart | 56 + .../test/pipeline_snapshot_test.dart | 80 + .../test/pipeline_source_test.dart | 155 + .../test/pipeline_stage_test.dart | 457 +++ .../cloud_firestore_platform_interface.dart | 2 + .../method_channel_firestore.dart | 35 + .../method_channel_pipeline.dart | 51 + .../method_channel_pipeline_snapshot.dart | 83 + .../lib/src/pigeon/messages.pigeon.dart | 120 +- .../platform_interface_firestore.dart | 15 + .../platform_interface_pipeline.dart | 54 + .../platform_interface_pipeline_snapshot.dart | 44 + .../pigeons/generate_pigeon.sh | 4 +- .../pigeons/messages.dart | 32 + .../test/pigeon/test_api.dart | 112 +- .../lib/cloud_firestore_web.dart | 47 + .../lib/src/interop/firestore.dart | 119 + .../lib/src/interop/firestore_interop.dart | 335 +- .../lib/src/pipeline_builder_web.dart | 137 + .../src/pipeline_expression_parser_web.dart | 842 ++++ .../lib/src/pipeline_web.dart | 110 + .../lib/src/firebase_core_web.dart | 11 + 188 files changed, 20850 insertions(+), 51 deletions(-) create mode 100644 .github/workflows/e2e_tests_pipeline.yaml create mode 100644 packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionHelpers.java create mode 100644 packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java create mode 100644 packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineParser.java create mode 100644 packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java create mode 100644 packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m create mode 100644 packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_snapshot.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart create mode 120000 packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m create mode 120000 packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/.gitignore create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/.metadata create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/README.md create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/analysis_options.yaml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/.gitignore create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/build.gradle.kts create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/debug/AndroidManifest.xml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/kotlin/com/example/pipeline_example/MainActivity.kt create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values-night/styles.xml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values/styles.xml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/build.gradle.kts create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle.properties create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/android/settings.gradle.kts create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_add_fields_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_aggregate_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_execute_options_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_filter_sort_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_find_nearest_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_remove_fields_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_replace_with_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_sample_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_select_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_test_helpers.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_unnest_union_e2e.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/.gitignore create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Debug.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Release.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Podfile create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Info.plist create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/ios/RunnerTests/RunnerTests.swift create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/.gitignore create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Release.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Podfile create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.pbxproj create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/AppDelegate.swift create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Debug.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Release.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Warnings.xcconfig create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/DebugProfile.entitlements create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Info.plist create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/MainFlutterWindow.swift create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Release.entitlements create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/macos/RunnerTests/RunnerTests.swift create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/test/widget_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/test_driver/integration_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/web/favicon.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-192.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-512.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-maskable-192.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-maskable-512.png create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/web/index.html create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/web/manifest.json create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/.gitignore create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/CMakeLists.txt create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/flutter/CMakeLists.txt create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/CMakeLists.txt create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/Runner.rc create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.cpp create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.h create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/main.cpp create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/resource.h create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/resources/app_icon.ico create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/runner.exe.manifest create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.cpp create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.h create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.cpp create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.h create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_aggregate_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_distance_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_execute_options_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_ordering_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_sample_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_snapshot_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_source_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart create mode 100644 packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart create mode 100644 packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart create mode 100644 packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart create mode 100644 packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_web.dart diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml new file mode 100644 index 000000000000..f13f10f20af6 --- /dev/null +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -0,0 +1,214 @@ +name: e2e-pipeline + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + pull_request: + paths-ignore: + - 'docs/**' + - 'website/**' + - '**/example/**' + - '**.md' + push: + branches: + - main + paths-ignore: + - 'docs/**' + - 'website/**' + - '**/example/**' + - '**.md' + +permissions: + contents: read + +jobs: + pipeline-e2e-android: + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + AVD_ARCH: x86_64 + AVD_API_LEVEL: 34 + AVD_TARGET: google_apis + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a + name: Install Node.js 20 + with: + node-version: '20' + - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + with: + distribution: 'temurin' + java-version: '21' + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + cache: true + cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" + pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" + - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + with: + run-bootstrap: false + melos-version: '5.3.0' + - name: Inject Firebase config for pipeline E2E + env: + FIREBASE_OPTIONS_DART: ${{ secrets.PIPELINE_E2E_FIREBASE_OPTIONS_DART }} + GOOGLE_SERVICES_JSON: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICES_JSON }} + GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICE_INFO_PLIST }} + run: | + echo "$FIREBASE_OPTIONS_DART" > packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart + echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json + echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist + - name: Bootstrap package + run: melos bootstrap --scope "cloud_firestore*" + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - name: Gradle cache + uses: gradle/actions/setup-gradle@v4 + - name: Free Disk Space (Ubuntu) + uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 + with: + remove-dotnet: true + remove-haskell: true + remove-codeql: true + remove-docker-images: true + remove-large-packages: true + - name: AVD cache + uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + continue-on-error: true + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} + - name: Start AVD then run pipeline E2E tests + uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b + with: + api-level: ${{ env.AVD_API_LEVEL }} + target: ${{ env.AVD_TARGET }} + arch: ${{ env.AVD_ARCH }} + emulator-build: 14214601 + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + script: | + flutter test integration_test/pipeline/pipeline_live_test.dart --timeout 10x --dart-define=CI=true -d emulator-5554 + - name: Ensure Appium is shut down + run: | + pgrep -f appium && pkill -f appium || echo "No Appium process found" + - name: Save Android Emulator Cache + if: github.ref == 'refs/heads/main' + uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + continue-on-error: true + with: + key: ${{ steps.avd-cache.outputs.cache-primary-key }} + path: | + ~/.android/avd/* + ~/.android/adb* + + pipeline-e2e-web: + runs-on: macos-latest + timeout-minutes: 25 + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a + name: Install Node.js 20 + with: + node-version: '20' + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + cache: true + cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" + pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" + - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + with: + run-bootstrap: false + melos-version: '5.3.0' + - name: Inject Firebase config for pipeline E2E + env: + FIREBASE_OPTIONS_DART: ${{ secrets.PIPELINE_E2E_FIREBASE_OPTIONS_DART }} + GOOGLE_SERVICES_JSON: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICES_JSON }} + GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICE_INFO_PLIST }} + run: | + echo "$FIREBASE_OPTIONS_DART" > packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart + echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json + echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist + - name: Bootstrap package + run: melos bootstrap --scope "cloud_firestore*" + - name: Run pipeline E2E tests (Chrome) + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + # Web devices are not supported for the `flutter test` command yet. As a + # workaround we use the `flutter drive` command. Tracking issue: + # https://github.com/flutter/flutter/issues/66264 + run: | + chromedriver --port=4444 --trace-buffer-size=100000 & + flutter drive --target=./integration_test/pipeline/pipeline_live_test.dart --driver=./test_driver/integration_test.dart -d chrome --dart-define=CI=true | tee output.log + output=$( packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart + echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json + echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist + - name: Bootstrap package + run: melos bootstrap --scope "cloud_firestore*" + - name: Prepare iOS project for Swift Package Manager + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example/ios + run: | + if [ -f Podfile ]; then pod deintegrate; fi + rm -f Podfile Podfile.lock + rm -rf Pods + - uses: futureware-tech/simulator-action@e89aa8f93d3aec35083ff49d2854d07f7186f7f5 + id: simulator + with: + model: "iPhone 16" + - name: Build iOS (simulator) + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + run: | + flutter build ios --no-codesign --simulator --debug --target=./integration_test/pipeline/pipeline_live_test.dart --dart-define=CI=true + - name: Run pipeline E2E tests (iOS) + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + env: + SIMULATOR: ${{ steps.simulator.outputs.udid }} + run: | + flutter test integration_test/pipeline/pipeline_live_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true diff --git a/melos.yaml b/melos.yaml index 2f403ee4d305..e1154f148da3 100644 --- a/melos.yaml +++ b/melos.yaml @@ -172,6 +172,13 @@ scripts: description: | Run all e2e tests for cloud_firestore. + test:e2e:pipeline: + run: | + cd packages/cloud_firestore/cloud_firestore/pipeline_example + flutter test integration_test/pipeline/pipeline_live_test.dart + description: | + Run pipeline e2e tests. + test:e2e:firebase_performance: run: | cd packages/firebase_performance/firebase_performance/example diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java index fb420c95bee2..e7af885e3454 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java @@ -28,6 +28,8 @@ import com.google.firebase.firestore.MemoryCacheSettings; import com.google.firebase.firestore.PersistentCacheIndexManager; import com.google.firebase.firestore.PersistentCacheSettings; +import com.google.firebase.firestore.Pipeline; +import com.google.firebase.firestore.PipelineResult; import com.google.firebase.firestore.Query; import com.google.firebase.firestore.QuerySnapshot; import com.google.firebase.firestore.SetOptions; @@ -52,6 +54,7 @@ import io.flutter.plugins.firebase.firestore.streamhandler.TransactionStreamHandler; import io.flutter.plugins.firebase.firestore.utils.ExceptionConverter; import io.flutter.plugins.firebase.firestore.utils.PigeonParser; +import io.flutter.plugins.firebase.firestore.utils.PipelineParser; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -1007,4 +1010,65 @@ public void documentReferenceSnapshot( parameters.getServerTimestampBehavior()), PigeonParser.parseListenSource(source)))); } + + @Override + public void executePipeline( + @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, + @NonNull List> stages, + @Nullable Map options, + @NonNull + GeneratedAndroidFirebaseFirestore.Result< + GeneratedAndroidFirebaseFirestore.PigeonPipelineSnapshot> + result) { + cachedThreadPool.execute( + () -> { + try { + FirebaseFirestore firestore = getFirestoreFromPigeon(app); + + // Execute pipeline using Android Firestore SDK + Pipeline.Snapshot snapshot = PipelineParser.executePipeline(firestore, stages, options); + + // Convert Pipeline.Snapshot to PigeonPipelineSnapshot + List pipelineResults = + new ArrayList<>(); + + // Iterate through snapshot results + for (PipelineResult pipelineResult : snapshot.getResults()) { + GeneratedAndroidFirebaseFirestore.PigeonPipelineResult.Builder resultBuilder = + new GeneratedAndroidFirebaseFirestore.PigeonPipelineResult.Builder(); + if (pipelineResult.getRef() != null) { + resultBuilder.setDocumentPath(pipelineResult.getRef().getPath()); + } + + if (pipelineResult.getCreateTime() != null) { + resultBuilder.setCreateTime(pipelineResult.getCreateTime().toDate().getTime()); + } + if (pipelineResult.getUpdateTime() != null) { + resultBuilder.setUpdateTime(pipelineResult.getUpdateTime().toDate().getTime()); + } + + Map data = pipelineResult.getData(); + if (data != null) { + resultBuilder.setData(data); + } + + pipelineResults.add(resultBuilder.build()); + } + + // Build the snapshot + GeneratedAndroidFirebaseFirestore.PigeonPipelineSnapshot.Builder snapshotBuilder = + new GeneratedAndroidFirebaseFirestore.PigeonPipelineSnapshot.Builder(); + snapshotBuilder.setResults(pipelineResults); + + // Set execution time when available. Do not fabricate a value when null. + if (snapshot.getExecutionTime() != null) { + snapshotBuilder.setExecutionTime(snapshot.getExecutionTime().toDate().getTime()); + } + + result.success(snapshotBuilder.build()); + } catch (Exception e) { + ExceptionConverter.sendErrorToFlutter(result, e); + } + }); + } } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java index b67642961626..bf5bb3fff9ef 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java @@ -856,6 +856,197 @@ public ArrayList toList() { } } + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonPipelineResult { + private @Nullable String documentPath; + + public @Nullable String getDocumentPath() { + return documentPath; + } + + public void setDocumentPath(@Nullable String setterArg) { + this.documentPath = setterArg; + } + + private @Nullable Long createTime; + + public @Nullable Long getCreateTime() { + return createTime; + } + + public void setCreateTime(@Nullable Long setterArg) { + this.createTime = setterArg; + } + + private @Nullable Long updateTime; + + public @Nullable Long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(@Nullable Long setterArg) { + this.updateTime = setterArg; + } + + /** All fields in the result (from PipelineResult.data() on Android). */ + private @Nullable Map data; + + public @Nullable Map getData() { + return data; + } + + public void setData(@Nullable Map setterArg) { + this.data = setterArg; + } + + public static final class Builder { + + private @Nullable String documentPath; + + public @NonNull Builder setDocumentPath(@Nullable String setterArg) { + this.documentPath = setterArg; + return this; + } + + private @Nullable Long createTime; + + public @NonNull Builder setCreateTime(@Nullable Long setterArg) { + this.createTime = setterArg; + return this; + } + + private @Nullable Long updateTime; + + public @NonNull Builder setUpdateTime(@Nullable Long setterArg) { + this.updateTime = setterArg; + return this; + } + + private @Nullable Map data; + + public @NonNull Builder setData(@Nullable Map setterArg) { + this.data = setterArg; + return this; + } + + public @NonNull PigeonPipelineResult build() { + PigeonPipelineResult pigeonReturn = new PigeonPipelineResult(); + pigeonReturn.setDocumentPath(documentPath); + pigeonReturn.setCreateTime(createTime); + pigeonReturn.setUpdateTime(updateTime); + pigeonReturn.setData(data); + return pigeonReturn; + } + } + + @NonNull + public ArrayList toList() { + ArrayList toListResult = new ArrayList(4); + toListResult.add(documentPath); + toListResult.add(createTime); + toListResult.add(updateTime); + toListResult.add(data); + return toListResult; + } + + static @NonNull PigeonPipelineResult fromList(@NonNull ArrayList list) { + PigeonPipelineResult pigeonResult = new PigeonPipelineResult(); + Object documentPath = list.get(0); + pigeonResult.setDocumentPath((String) documentPath); + Object createTime = list.get(1); + pigeonResult.setCreateTime( + (createTime == null) + ? null + : ((createTime instanceof Integer) ? (Integer) createTime : (Long) createTime)); + Object updateTime = list.get(2); + pigeonResult.setUpdateTime( + (updateTime == null) + ? null + : ((updateTime instanceof Integer) ? (Integer) updateTime : (Long) updateTime)); + Object data = list.get(3); + pigeonResult.setData((Map) data); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class PigeonPipelineSnapshot { + private @NonNull List results; + + public @NonNull List getResults() { + return results; + } + + public void setResults(@NonNull List setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"results\" is null."); + } + this.results = setterArg; + } + + private @NonNull Long executionTime; + + public @NonNull Long getExecutionTime() { + return executionTime; + } + + public void setExecutionTime(@NonNull Long setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"executionTime\" is null."); + } + this.executionTime = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + PigeonPipelineSnapshot() {} + + public static final class Builder { + + private @Nullable List results; + + public @NonNull Builder setResults(@NonNull List setterArg) { + this.results = setterArg; + return this; + } + + private @Nullable Long executionTime; + + public @NonNull Builder setExecutionTime(@NonNull Long setterArg) { + this.executionTime = setterArg; + return this; + } + + public @NonNull PigeonPipelineSnapshot build() { + PigeonPipelineSnapshot pigeonReturn = new PigeonPipelineSnapshot(); + pigeonReturn.setResults(results); + pigeonReturn.setExecutionTime(executionTime); + return pigeonReturn; + } + } + + @NonNull + public ArrayList toList() { + ArrayList toListResult = new ArrayList(2); + toListResult.add(results); + toListResult.add(executionTime); + return toListResult; + } + + static @NonNull PigeonPipelineSnapshot fromList(@NonNull ArrayList list) { + PigeonPipelineSnapshot pigeonResult = new PigeonPipelineSnapshot(); + Object results = list.get(0); + pigeonResult.setResults((List) results); + Object executionTime = list.get(1); + pigeonResult.setExecutionTime( + (executionTime == null) + ? null + : ((executionTime instanceof Integer) + ? (Integer) executionTime + : (Long) executionTime)); + return pigeonResult; + } + } + /** Generated class from Pigeon that represents data sent in messages. */ public static final class PigeonGetOptions { private @NonNull Source source; @@ -1660,12 +1851,16 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { case (byte) 136: return PigeonGetOptions.fromList((ArrayList) readValue(buffer)); case (byte) 137: - return PigeonQueryParameters.fromList((ArrayList) readValue(buffer)); + return PigeonPipelineResult.fromList((ArrayList) readValue(buffer)); case (byte) 138: - return PigeonQuerySnapshot.fromList((ArrayList) readValue(buffer)); + return PigeonPipelineSnapshot.fromList((ArrayList) readValue(buffer)); case (byte) 139: - return PigeonSnapshotMetadata.fromList((ArrayList) readValue(buffer)); + return PigeonQueryParameters.fromList((ArrayList) readValue(buffer)); case (byte) 140: + return PigeonQuerySnapshot.fromList((ArrayList) readValue(buffer)); + case (byte) 141: + return PigeonSnapshotMetadata.fromList((ArrayList) readValue(buffer)); + case (byte) 142: return PigeonTransactionCommand.fromList((ArrayList) readValue(buffer)); default: return super.readValueOfType(type, buffer); @@ -1701,17 +1896,23 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { } else if (value instanceof PigeonGetOptions) { stream.write(136); writeValue(stream, ((PigeonGetOptions) value).toList()); - } else if (value instanceof PigeonQueryParameters) { + } else if (value instanceof PigeonPipelineResult) { stream.write(137); + writeValue(stream, ((PigeonPipelineResult) value).toList()); + } else if (value instanceof PigeonPipelineSnapshot) { + stream.write(138); + writeValue(stream, ((PigeonPipelineSnapshot) value).toList()); + } else if (value instanceof PigeonQueryParameters) { + stream.write(139); writeValue(stream, ((PigeonQueryParameters) value).toList()); } else if (value instanceof PigeonQuerySnapshot) { - stream.write(138); + stream.write(140); writeValue(stream, ((PigeonQuerySnapshot) value).toList()); } else if (value instanceof PigeonSnapshotMetadata) { - stream.write(139); + stream.write(141); writeValue(stream, ((PigeonSnapshotMetadata) value).toList()); } else if (value instanceof PigeonTransactionCommand) { - stream.write(140); + stream.write(142); writeValue(stream, ((PigeonTransactionCommand) value).toList()); } else { super.writeValue(stream, value); @@ -1836,6 +2037,12 @@ void persistenceCacheIndexManagerRequest( @NonNull PersistenceCacheIndexManagerRequest request, @NonNull Result result); + void executePipeline( + @NonNull FirestorePigeonFirebaseApp app, + @NonNull List> stages, + @Nullable Map options, + @NonNull Result result); + /** The codec used by FirebaseFirestoreHostApi. */ static @NonNull MessageCodec getCodec() { return FirebaseFirestoreHostApiCodec.INSTANCE; @@ -2624,6 +2831,39 @@ public void error(Throwable error) { channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); + List> stagesArg = (List>) args.get(1); + Map optionsArg = (Map) args.get(2); + Result resultCallback = + new Result() { + public void success(PigeonPipelineSnapshot result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.executePipeline(appArg, stagesArg, optionsArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } } } } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionHelpers.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionHelpers.java new file mode 100644 index 000000000000..86c0877a902c --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionHelpers.java @@ -0,0 +1,159 @@ +/* + * Copyright 2026, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +package io.flutter.plugins.firebase.firestore.utils; + +import androidx.annotation.NonNull; +import com.google.firebase.Timestamp; +import com.google.firebase.firestore.Blob; +import com.google.firebase.firestore.DocumentReference; +import com.google.firebase.firestore.GeoPoint; +import com.google.firebase.firestore.VectorValue; +import com.google.firebase.firestore.pipeline.BooleanExpression; +import com.google.firebase.firestore.pipeline.Expression; +import java.util.List; +import java.util.Map; + +/** Helper utilities for parsing expressions and handling common patterns. */ +class ExpressionHelpers { + + /** + * Parses an "and" expression from a list of expression maps. Uses Expression.and() with varargs + * signature. + * + * @param exprMaps List of expression maps to combine with AND + * @param parser Reference to ExpressionParsers for recursive parsing + */ + @SuppressWarnings("unchecked") + static BooleanExpression parseAndExpression( + @NonNull List> exprMaps, @NonNull ExpressionParsers parser) { + if (exprMaps == null || exprMaps.isEmpty()) { + throw new IllegalArgumentException("'and' requires at least one expression"); + } + + BooleanExpression first = parser.parseBooleanExpression(exprMaps.get(0)); + if (exprMaps.size() == 1) { + return first; + } + + BooleanExpression[] rest = new BooleanExpression[exprMaps.size() - 1]; + for (int i = 1; i < exprMaps.size(); i++) { + rest[i - 1] = parser.parseBooleanExpression(exprMaps.get(i)); + } + return Expression.and(first, rest); + } + + /** + * Parses an "or" expression from a list of expression maps. Uses Expression.or() with varargs + * signature. + * + * @param exprMaps List of expression maps to combine with OR + * @param parser Reference to ExpressionParsers for recursive parsing + */ + @SuppressWarnings("unchecked") + static BooleanExpression parseOrExpression( + @NonNull List> exprMaps, @NonNull ExpressionParsers parser) { + if (exprMaps == null || exprMaps.isEmpty()) { + throw new IllegalArgumentException("'or' requires at least one expression"); + } + + BooleanExpression first = parser.parseBooleanExpression(exprMaps.get(0)); + if (exprMaps.size() == 1) { + return first; + } + + BooleanExpression[] rest = new BooleanExpression[exprMaps.size() - 1]; + for (int i = 1; i < exprMaps.size(); i++) { + rest[i - 1] = parser.parseBooleanExpression(exprMaps.get(i)); + } + return Expression.or(first, rest); + } + + /** + * Parses a "xor" expression from a list of expression maps. + * + * @param exprMaps List of expression maps to combine with XOR + * @param parser Reference to ExpressionParsers for recursive parsing + */ + @SuppressWarnings("unchecked") + static BooleanExpression parseXorExpression( + @NonNull List> exprMaps, @NonNull ExpressionParsers parser) { + if (exprMaps == null || exprMaps.isEmpty()) { + throw new IllegalArgumentException("'xor' requires at least one expression"); + } + + BooleanExpression first = parser.parseBooleanExpression(exprMaps.get(0)); + if (exprMaps.size() == 1) { + return first; + } + + BooleanExpression[] rest = new BooleanExpression[exprMaps.size() - 1]; + for (int i = 1; i < exprMaps.size(); i++) { + rest[i - 1] = parser.parseBooleanExpression(exprMaps.get(i)); + } + return Expression.xor(first, rest); + } + + /** + * Parses a constant value based on its type to match Android SDK constant() overloads. Valid + * types: String, Number, Boolean, Date, Timestamp, GeoPoint, byte[], Blob, DocumentReference, + * VectorValue + */ + static Expression parseConstantValue(Object value) { + + if (value == null) { + return Expression.nullValue(); + } + + if (value instanceof String) { + return Expression.constant((String) value); + } else if (value instanceof Number) { + return Expression.constant((Number) value); + } else if (value instanceof Boolean) { + return Expression.constant((Boolean) value); + } else if (value instanceof java.util.Date) { + return Expression.constant((java.util.Date) value); + } else if (value instanceof Timestamp) { + return Expression.constant((Timestamp) value); + } else if (value instanceof GeoPoint) { + return Expression.constant((GeoPoint) value); + } else if (value instanceof byte[]) { + return Expression.constant((byte[]) value); + } else if (value instanceof List) { + // Handle List from Dart which comes as List or List + // This represents byte[] (byte array) for constant expressions + @SuppressWarnings("unchecked") + List list = (List) value; + // Check if all elements are numbers (for byte array) + boolean isByteArray = true; + for (Object item : list) { + if (!(item instanceof Number)) { + isByteArray = false; + break; + } + } + if (isByteArray && !list.isEmpty()) { + byte[] byteArray = new byte[list.size()]; + for (int i = 0; i < list.size(); i++) { + byteArray[i] = ((Number) list.get(i)).byteValue(); + } + return Expression.constant(byteArray); + } + // If not a byte array, fall through to error + } else if (value instanceof Blob) { + return Expression.constant((Blob) value); + } else if (value instanceof DocumentReference) { + return Expression.constant((DocumentReference) value); + } else if (value instanceof VectorValue) { + return Expression.constant((VectorValue) value); + } + + throw new IllegalArgumentException( + "Constant value must be one of: String, Number, Boolean, Date, Timestamp, " + + "GeoPoint, byte[], Blob, DocumentReference, or VectorValue. Got: " + + value.getClass().getName()); + } +} diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java new file mode 100644 index 000000000000..f27d5fd2a42b --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java @@ -0,0 +1,683 @@ +/* + * Copyright 2026, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +package io.flutter.plugins.firebase.firestore.utils; + +import android.util.Log; +import androidx.annotation.NonNull; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.pipeline.AggregateFunction; +import com.google.firebase.firestore.pipeline.AggregateOptions; +import com.google.firebase.firestore.pipeline.AggregateStage; +import com.google.firebase.firestore.pipeline.AliasedAggregate; +import com.google.firebase.firestore.pipeline.BooleanExpression; +import com.google.firebase.firestore.pipeline.Expression; +import com.google.firebase.firestore.pipeline.FindNearestStage; +import com.google.firebase.firestore.pipeline.Selectable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Parses Dart pipeline expression maps into Android {@link Expression} / {@link BooleanExpression} + * types. {@link #parseBooleanExpression}'s default delegates to {@link #parseExpression} when the + * name is a value expression that yields a boolean (e.g. aliased comparisons). + */ +class ExpressionParsers { + private static final String TAG = "ExpressionParsers"; + + private final FirebaseFirestore firestore; + + ExpressionParsers(@NonNull FirebaseFirestore firestore) { + this.firestore = firestore; + } + + /** Binary operation on two expressions. Used instead of BiFunction for API 23 compatibility. */ + private interface BinaryExpressionOp { + R apply(Expression left, Expression right); + } + + @SuppressWarnings("unchecked") + private static Map argsOf(@NonNull Map expressionMap) { + Map args = (Map) expressionMap.get("args"); + return args != null ? args : new HashMap<>(); + } + + @SuppressWarnings("unchecked") + private Expression parseChild(@NonNull Map args, @NonNull String key) { + return parseExpression((Map) args.get(key)); + } + + /** Parses a list of nested expression maps (e.g. {@code values}) to {@link Expression}s. */ + private List parseExpressionMaps(@NonNull List> maps) { + Expression[] out = new Expression[maps.size()]; + for (int i = 0; i < maps.size(); i++) { + out[i] = parseExpression(maps.get(i)); + } + return Arrays.asList(out); + } + + private BooleanExpression parseBinaryComparisonNamed( + @NonNull String name, @NonNull Map args) { + switch (name) { + case "equal": + return parseBinaryComparison(args, (left, right) -> left.equal(right)); + case "not_equal": + return parseBinaryComparison(args, (left, right) -> left.notEqual(right)); + case "greater_than": + return parseBinaryComparison(args, (left, right) -> left.greaterThan(right)); + case "greater_than_or_equal": + return parseBinaryComparison(args, (left, right) -> left.greaterThanOrEqual(right)); + case "less_than": + return parseBinaryComparison(args, (left, right) -> left.lessThan(right)); + case "less_than_or_equal": + return parseBinaryComparison(args, (left, right) -> left.lessThanOrEqual(right)); + default: + throw new IllegalArgumentException("Not a binary comparison expression: " + name); + } + } + + @SuppressWarnings("unchecked") + private BooleanExpression parseEqualAny(@NonNull Map args) { + Map valueMap = (Map) args.get("value"); + List> valuesMaps = (List>) args.get("values"); + Expression value = parseExpression(valueMap); + return value.equalAny(parseExpressionMaps(valuesMaps)); + } + + @SuppressWarnings("unchecked") + private BooleanExpression parseNotEqualAny(@NonNull Map args) { + Map valueMap = (Map) args.get("value"); + List> valuesMaps = (List>) args.get("values"); + Expression value = parseExpression(valueMap); + return value.notEqualAny(parseExpressionMaps(valuesMaps)); + } + + @SuppressWarnings("unchecked") + private BooleanExpression parseArrayContainsElement(@NonNull Map args) { + Map arrayMap = (Map) args.get("array"); + Map elementMap = (Map) args.get("element"); + Expression array = parseExpression(arrayMap); + Expression element = parseExpression(elementMap); + return array.arrayContains(element); + } + + /** Parses an expression from a map representation. */ + @SuppressWarnings("unchecked") + Expression parseExpression(@NonNull Map expressionMap) { + String name = (String) expressionMap.get("name"); + if (name == null) { + if (expressionMap.containsKey("field_name")) { + String fieldName = (String) expressionMap.get("field_name"); + return Expression.field(fieldName); + } + Map argsCheck = (Map) expressionMap.get("args"); + if (argsCheck != null && argsCheck.containsKey("field")) { + String fieldName = (String) argsCheck.get("field"); + return Expression.field(fieldName); + } + throw new IllegalArgumentException("Expression must have a 'name' field"); + } + + Map args = argsOf(expressionMap); + + switch (name) { + case "null": + return Expression.nullValue(); + case "field": + { + String fieldName = (String) args.get("field"); + if (fieldName == null) { + throw new IllegalArgumentException("Field expression must have a 'field' argument"); + } + return Expression.field(fieldName); + } + case "constant": + { + Object value = args.get("value"); + if (value instanceof Map) { + Map valueMap = (Map) value; + String path = (String) valueMap.get("path"); + return Expression.constant(firestore.document(path)); + } + return ExpressionHelpers.parseConstantValue(value); + } + case "alias": + { + Map exprMap = (Map) args.get("expression"); + String alias = (String) args.get("alias"); + Expression expr = parseExpression(exprMap); + return expr.alias(alias); + } + case "equal": + case "not_equal": + case "greater_than": + case "greater_than_or_equal": + case "less_than": + case "less_than_or_equal": + return parseBinaryComparisonNamed(name, args); + case "add": + return parseBinaryOperation(args, (left, right) -> left.add(right)); + case "subtract": + return parseBinaryOperation(args, (left, right) -> left.subtract(right)); + case "multiply": + return parseBinaryOperation(args, (left, right) -> left.multiply(right)); + case "divide": + return parseBinaryOperation(args, (left, right) -> left.divide(right)); + case "modulo": + return parseBinaryOperation(args, (left, right) -> left.mod(right)); + case "and": + { + List> exprMaps = (List>) args.get("expressions"); + return ExpressionHelpers.parseAndExpression(exprMaps, this); + } + case "or": + { + List> exprMaps = (List>) args.get("expressions"); + return ExpressionHelpers.parseOrExpression(exprMaps, this); + } + case "xor": + { + List> exprMaps = (List>) args.get("expressions"); + return ExpressionHelpers.parseXorExpression(exprMaps, this); + } + case "not": + { + Map exprMap = (Map) args.get("expression"); + BooleanExpression expr = parseBooleanExpression(exprMap); + return Expression.not(expr); + } + case "concat": + { + List> exprMaps = (List>) args.get("expressions"); + if (exprMaps == null || exprMaps.size() < 2) { + throw new IllegalArgumentException("concat requires at least two expressions"); + } + Expression first = parseExpression(exprMaps.get(0)); + Expression second = parseExpression(exprMaps.get(1)); + if (exprMaps.size() == 2) { + return Expression.concat(first, second); + } + Object[] others = new Object[exprMaps.size() - 2]; + for (int i = 2; i < exprMaps.size(); i++) { + others[i - 2] = parseExpression(exprMaps.get(i)); + } + return Expression.concat(first, second, others); + } + case "length": + return Expression.length(parseChild(args, "expression")); + case "to_lower_case": + return Expression.toLower(parseChild(args, "expression")); + case "to_upper_case": + return Expression.toUpper(parseChild(args, "expression")); + case "trim": + return Expression.trim(parseChild(args, "expression")); + case "substring": + { + Map exprMap = (Map) args.get("expression"); + Map startMap = (Map) args.get("start"); + Map endMap = (Map) args.get("end"); + Expression stringExpr = parseExpression(exprMap); + Expression startExpr = parseExpression(startMap); + Expression endExpr = parseExpression(endMap); + Expression lengthExpr = Expression.subtract(endExpr, startExpr); + return Expression.substring(stringExpr, startExpr, lengthExpr); + } + case "split": + { + Map valueMap = (Map) args.get("expression"); + Map delimiterMap = (Map) args.get("delimiter"); + return Expression.split(parseExpression(valueMap), parseExpression(delimiterMap)); + } + case "join": + { + Map arrayMap = (Map) args.get("expression"); + Map delimiterMap = (Map) args.get("delimiter"); + return Expression.join(parseExpression(arrayMap), parseExpression(delimiterMap)); + } + case "abs": + return Expression.abs(parseChild(args, "expression")); + case "negate": + { + Expression expr = parseChild(args, "expression"); + return Expression.subtract(Expression.constant(0), expr); + } + case "array_concat": + { + Map firstMap = (Map) args.get("first"); + Map secondMap = (Map) args.get("second"); + return Expression.arrayConcat(parseExpression(firstMap), parseExpression(secondMap)); + } + case "array_concat_multiple": + { + List> arrays = (List>) args.get("arrays"); + if (arrays == null || arrays.size() < 2) { + throw new IllegalArgumentException( + "array_concat_multiple requires at least two arrays"); + } + Expression result = + Expression.arrayConcat( + parseExpression(arrays.get(0)), parseExpression(arrays.get(1))); + for (int i = 2; i < arrays.size(); i++) { + result = result.arrayConcat(parseExpression(arrays.get(i))); + } + return result; + } + case "array_length": + return Expression.arrayLength(parseChild(args, "expression")); + case "array_reverse": + return Expression.arrayReverse(parseChild(args, "expression")); + case "array_sum": + return Expression.arraySum(parseChild(args, "expression")); + case "array_slice": + throw new UnsupportedOperationException( + "Expression type 'array_slice' is not supported on Android Firestore pipeline API"); + case "if_absent": + { + Map exprMap = (Map) args.get("expression"); + Map elseMap = (Map) args.get("else"); + return Expression.ifAbsent(parseExpression(exprMap), parseExpression(elseMap)); + } + case "if_error": + { + Map exprMap = (Map) args.get("expression"); + Map catchMap = (Map) args.get("catch"); + return Expression.ifError(parseExpression(exprMap), parseExpression(catchMap)); + } + case "conditional": + { + Map conditionMap = (Map) args.get("condition"); + Map thenMap = (Map) args.get("then"); + Map elseMap = (Map) args.get("else"); + BooleanExpression condition = parseBooleanExpression(conditionMap); + Expression thenExpr = parseExpression(thenMap); + Expression elseExpr = parseExpression(elseMap); + return Expression.conditional(condition, thenExpr, elseExpr); + } + case "document_id": + return Expression.documentId(parseChild(args, "expression")); + case "document_id_from_ref": + { + String path = (String) args.get("doc_ref"); + if (path == null) { + throw new IllegalArgumentException("document_id_from_ref requires 'doc_ref' argument"); + } + return Expression.documentId(firestore.document(path)); + } + case "collection_id": + return Expression.collectionId(parseChild(args, "expression")); + case "map_get": + { + Map mapMap = (Map) args.get("map"); + Map keyMap = (Map) args.get("key"); + return Expression.mapGet(parseExpression(mapMap), parseExpression(keyMap)); + } + case "current_timestamp": + return Expression.currentTimestamp(); + case "timestamp_add": + { + Map timestampMap = (Map) args.get("timestamp"); + String unit = (String) args.get("unit"); + Map amountMap = (Map) args.get("amount"); + if (unit == null || amountMap == null) { + throw new IllegalArgumentException("timestamp_add requires 'unit' and 'amount'"); + } + Expression timestampExpr = parseExpression(timestampMap); + Expression amountExpr = parseExpression(amountMap); + return Expression.timestampAdd(timestampExpr, Expression.constant(unit), amountExpr); + } + case "timestamp_subtract": + { + Map timestampMap = (Map) args.get("timestamp"); + String unit = (String) args.get("unit"); + Map amountMap = (Map) args.get("amount"); + if (unit == null || amountMap == null) { + throw new IllegalArgumentException("timestamp_subtract requires 'unit' and 'amount'"); + } + Expression timestampExpr = parseExpression(timestampMap); + Expression amountExpr = parseExpression(amountMap); + return Expression.timestampSubtract(timestampExpr, Expression.constant(unit), amountExpr); + } + case "timestamp_truncate": + { + Map timestampMap = (Map) args.get("timestamp"); + String unit = (String) args.get("unit"); + if (unit == null) { + throw new IllegalArgumentException("timestamp_truncate requires 'unit'"); + } + return Expression.timestampTruncate(parseExpression(timestampMap), unit); + } + case "array": + { + List elements = (List) args.get("elements"); + if (elements == null) { + throw new IllegalArgumentException("array requires 'elements'"); + } + Object[] parsed = new Object[elements.size()]; + for (int i = 0; i < elements.size(); i++) { + Object el = elements.get(i); + if (el instanceof Map) { + parsed[i] = parseExpression((Map) el); + } else { + parsed[i] = ExpressionHelpers.parseConstantValue(el); + } + } + return Expression.array(Arrays.asList(parsed)); + } + case "map": + { + Map data = (Map) args.get("data"); + if (data == null) { + throw new IllegalArgumentException("map requires 'data'"); + } + Map parsed = new HashMap<>(); + for (Map.Entry e : data.entrySet()) { + Object v = e.getValue(); + if (v instanceof Map) { + @SuppressWarnings("unchecked") + Map nested = (Map) v; + if (nested.containsKey("name") && nested.containsKey("args")) { + parsed.put(e.getKey(), parseExpression(nested)); + } else { + parsed.put(e.getKey(), v); + } + } else { + parsed.put(e.getKey(), ExpressionHelpers.parseConstantValue(v)); + } + } + return Expression.map(parsed); + } + case "bit_and": + return parseBinaryOperation(args, (left, right) -> left.bitAnd(right)); + case "bit_or": + return parseBinaryOperation(args, (left, right) -> left.bitOr(right)); + case "bit_xor": + return parseBinaryOperation(args, (left, right) -> left.bitXor(right)); + case "bit_not": + return parseChild(args, "expression").bitNot(); + case "bit_left_shift": + { + Map exprMap = (Map) args.get("expression"); + Map amountMap = (Map) args.get("amount"); + return parseExpression(exprMap).bitLeftShift(parseExpression(amountMap)); + } + case "bit_right_shift": + { + Map exprMap = (Map) args.get("expression"); + Map amountMap = (Map) args.get("amount"); + return parseExpression(exprMap).bitRightShift(parseExpression(amountMap)); + } + case "is_absent": + return parseIsAbsent(args); + case "is_error": + return parseIsError(args); + case "exists": + return parseExists(args); + case "as_boolean": + return parseAsBoolean(args); + case "array_contains_all": + return parseArrayContainsAll(args); + case "array_contains_any": + return parseArrayContainsAny(args); + default: + Log.w(TAG, "Unsupported expression type: " + name); + throw new UnsupportedOperationException("Expression type not yet implemented: " + name); + } + } + + @SuppressWarnings("unchecked") + private BooleanExpression parseBinaryComparison( + @NonNull Map args, @NonNull BinaryExpressionOp operation) { + Map leftMap = (Map) args.get("left"); + Map rightMap = (Map) args.get("right"); + Expression left = parseExpression(leftMap); + Expression right = parseExpression(rightMap); + return operation.apply(left, right); + } + + @SuppressWarnings("unchecked") + private Expression parseBinaryOperation( + @NonNull Map args, @NonNull BinaryExpressionOp operation) { + Map leftMap = (Map) args.get("left"); + Map rightMap = (Map) args.get("right"); + Expression left = parseExpression(leftMap); + Expression right = parseExpression(rightMap); + return operation.apply(left, right); + } + + private BooleanExpression parseIsAbsent(@NonNull Map args) { + return parseChild(args, "expression").isAbsent(); + } + + private BooleanExpression parseIsError(@NonNull Map args) { + return parseChild(args, "expression").isError(); + } + + private BooleanExpression parseExists(@NonNull Map args) { + return parseChild(args, "expression").exists(); + } + + private BooleanExpression parseAsBoolean(@NonNull Map args) { + return parseChild(args, "expression").asBoolean(); + } + + @SuppressWarnings("unchecked") + private BooleanExpression parseArrayContainsAll(@NonNull Map args) { + Map arrayMap = (Map) args.get("array"); + Expression array = parseExpression(arrayMap); + if (args.get("values") != null) { + List> valuesMaps = (List>) args.get("values"); + return array.arrayContainsAll(parseExpressionMaps(valuesMaps)); + } + Map arrayExprMap = (Map) args.get("array_expression"); + Expression arrayExpr = parseExpression(arrayExprMap); + return array.arrayContainsAll(arrayExpr); + } + + @SuppressWarnings("unchecked") + private BooleanExpression parseArrayContainsAny(@NonNull Map args) { + Map arrayMap = (Map) args.get("array"); + List> valuesMaps = (List>) args.get("values"); + Expression array = parseExpression(arrayMap); + return array.arrayContainsAny(parseExpressionMaps(valuesMaps)); + } + + @SuppressWarnings("unchecked") + BooleanExpression parseBooleanExpression(@NonNull Map expressionMap) { + String name = (String) expressionMap.get("name"); + if (name == null) { + throw new IllegalArgumentException("BooleanExpression must have a 'name' field"); + } + + Map args = argsOf(expressionMap); + + switch (name) { + case "equal": + case "not_equal": + case "greater_than": + case "greater_than_or_equal": + case "less_than": + case "less_than_or_equal": + return parseBinaryComparisonNamed(name, args); + case "and": + { + List> exprMaps = (List>) args.get("expressions"); + return ExpressionHelpers.parseAndExpression(exprMaps, this); + } + case "or": + { + List> exprMaps = (List>) args.get("expressions"); + return ExpressionHelpers.parseOrExpression(exprMaps, this); + } + case "xor": + { + List> exprMaps = (List>) args.get("expressions"); + return ExpressionHelpers.parseXorExpression(exprMaps, this); + } + case "not": + { + Map exprMap = (Map) args.get("expression"); + BooleanExpression expr = parseBooleanExpression(exprMap); + return expr.not(); + } + case "is_absent": + return parseIsAbsent(args); + case "is_error": + return parseIsError(args); + case "exists": + return parseExists(args); + case "array_contains": + return parseArrayContainsElement(args); + case "array_contains_all": + return parseArrayContainsAll(args); + case "array_contains_any": + return parseArrayContainsAny(args); + case "equal_any": + return parseEqualAny(args); + case "not_equal_any": + return parseNotEqualAny(args); + case "as_boolean": + return parseAsBoolean(args); + default: + Expression expr = parseExpression(expressionMap); + if (expr instanceof BooleanExpression) { + return (BooleanExpression) expr; + } + Log.w(TAG, "Expression type '" + name + "' is not a BooleanExpression, attempting cast"); + throw new IllegalArgumentException( + "Expression type '" + name + "' cannot be used as a BooleanExpression"); + } + } + + @SuppressWarnings("unchecked") + Selectable parseSelectable(@NonNull Map expressionMap) { + Expression expr = parseExpression(expressionMap); + if (!(expr instanceof Selectable)) { + throw new IllegalArgumentException( + "Expression must be a Selectable (Field or AliasedExpression). Got: " + + expressionMap.get("name")); + } + return (Selectable) expr; + } + + @SuppressWarnings("unchecked") + AggregateFunction parseAggregateFunction(@NonNull Map aggregateMap) { + String functionName = (String) aggregateMap.get("function"); + if (functionName == null) { + functionName = (String) aggregateMap.get("name"); + } + Map args = (Map) aggregateMap.get("args"); + Expression expr = null; + if (args != null) { + Map exprMap = (Map) args.get("expression"); + expr = parseExpression(exprMap); + } + + switch (functionName) { + case "sum": + return AggregateFunction.sum(expr); + case "average": + return AggregateFunction.average(expr); + case "count": + return AggregateFunction.count(expr); + case "count_distinct": + return AggregateFunction.countDistinct(expr); + case "minimum": + return AggregateFunction.minimum(expr); + case "maximum": + return AggregateFunction.maximum(expr); + case "count_all": + return AggregateFunction.countAll(); + default: + throw new IllegalArgumentException("Unknown aggregate function: " + functionName); + } + } + + @SuppressWarnings("unchecked") + AliasedAggregate parseAliasedAggregate(@NonNull Map aggregateMap) { + String name = (String) aggregateMap.get("name"); + if ("alias".equals(name)) { + Map args = (Map) aggregateMap.get("args"); + String alias = (String) args.get("alias"); + Map aggregateFunctionMap = + (Map) args.get("aggregate_function"); + + AggregateFunction function = parseAggregateFunction(aggregateFunctionMap); + return function.alias(alias); + } + + String alias = (String) aggregateMap.get("alias"); + if (alias != null) { + AggregateFunction function = parseAggregateFunction(aggregateMap); + return function.alias(alias); + } + + throw new IllegalArgumentException( + "Aggregate function must have an alias. Expected AliasedAggregateFunction format."); + } + + @SuppressWarnings("unchecked") + AggregateStage parseAggregateStage(@NonNull Map stageMap) { + List> accumulatorMaps = + (List>) stageMap.get("accumulators"); + if (accumulatorMaps == null || accumulatorMaps.isEmpty()) { + throw new IllegalArgumentException("AggregateStage must have at least one accumulator"); + } + + AliasedAggregate[] accumulators = new AliasedAggregate[accumulatorMaps.size()]; + for (int i = 0; i < accumulatorMaps.size(); i++) { + accumulators[i] = parseAliasedAggregate(accumulatorMaps.get(i)); + } + + AggregateStage aggregateStage; + if (accumulators.length == 1) { + aggregateStage = AggregateStage.withAccumulators(accumulators[0]); + } else { + AliasedAggregate[] rest = new AliasedAggregate[accumulators.length - 1]; + System.arraycopy(accumulators, 1, rest, 0, rest.length); + aggregateStage = AggregateStage.withAccumulators(accumulators[0], rest); + } + + List> groupMaps = (List>) stageMap.get("groups"); + if (groupMaps != null && !groupMaps.isEmpty()) { + Selectable firstGroup = parseSelectable(groupMaps.get(0)); + + if (groupMaps.size() == 1) { + aggregateStage = aggregateStage.withGroups(firstGroup); + } else { + Object[] additionalGroups = new Object[groupMaps.size() - 1]; + for (int i = 1; i < groupMaps.size(); i++) { + Expression groupExpr = parseExpression(groupMaps.get(i)); + additionalGroups[i - 1] = groupExpr; + } + aggregateStage = aggregateStage.withGroups(firstGroup, additionalGroups); + } + } + + return aggregateStage; + } + + AggregateOptions parseAggregateOptions(@NonNull Map optionsMap) { + return new AggregateOptions(); + } + + FindNearestStage.DistanceMeasure parseDistanceMeasure(@NonNull String dartEnumName) { + switch (dartEnumName) { + case "cosine": + return FindNearestStage.DistanceMeasure.COSINE; + case "euclidean": + return FindNearestStage.DistanceMeasure.EUCLIDEAN; + case "dotProduct": + return FindNearestStage.DistanceMeasure.DOT_PRODUCT; + default: + throw new IllegalArgumentException( + "Unknown distance measure: " + + dartEnumName + + ". Expected: cosine, euclidean, or dotProduct"); + } + } +} diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineParser.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineParser.java new file mode 100644 index 000000000000..6029a28f7ef8 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineParser.java @@ -0,0 +1,140 @@ +/* + * Copyright 2026, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +package io.flutter.plugins.firebase.firestore.utils; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.android.gms.tasks.Task; +import com.google.android.gms.tasks.Tasks; +import com.google.firebase.firestore.DocumentReference; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.Pipeline; +import com.google.firebase.firestore.Pipeline.Snapshot; +import com.google.firebase.firestore.PipelineSource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class PipelineParser { + private static final String TAG = "PipelineParser"; + + /** + * Executes a pipeline from a list of stage maps. + * + * @param firestore The Firestore instance + * @param stages List of stage maps, each with 'stage' and 'args' fields + * @param options Optional execution options + * @return The pipeline snapshot result + */ + public static Snapshot executePipeline( + @NonNull FirebaseFirestore firestore, + @NonNull List> stages, + @Nullable Map options) + throws Exception { + Pipeline pipeline = buildPipeline(firestore, stages); + Task task; + if (options != null && !options.isEmpty()) { + Pipeline.ExecuteOptions executeOptions = parseExecuteOptions(options); + task = pipeline.execute(executeOptions); + } else { + task = pipeline.execute(); + } + return Tasks.await(task); + } + + private static Pipeline.ExecuteOptions parseExecuteOptions(@NonNull Map options) { + Pipeline.ExecuteOptions executeOptions = new Pipeline.ExecuteOptions(); + Object indexModeObj = options.get("indexMode"); + if (indexModeObj instanceof String) { + String indexModeStr = (String) indexModeObj; + if ("recommended".equalsIgnoreCase(indexModeStr)) { + executeOptions = + executeOptions.withIndexMode(Pipeline.ExecuteOptions.IndexMode.RECOMMENDED); + } + } + return executeOptions; + } + + /** + * Builds a Pipeline from a list of stage maps without executing it. Used when a stage (e.g. + * union) requires another pipeline as an argument. + */ + @SuppressWarnings("unchecked") + public static Pipeline buildPipeline( + @NonNull FirebaseFirestore firestore, @NonNull List> stages) { + if (stages.isEmpty()) { + throw new IllegalArgumentException("Pipeline must have at least one stage (source)."); + } + ExpressionParsers expressionParsers = new ExpressionParsers(firestore); + PipelineStageHandlers stageHandlers = new PipelineStageHandlers(expressionParsers); + PipelineSource pipelineSource = firestore.pipeline(); + Pipeline pipeline = null; + + for (int i = 0; i < stages.size(); i++) { + Map stageMap = stages.get(i); + String stageName = (String) stageMap.get("stage"); + if (stageName == null) { + throw new IllegalArgumentException("Stage must have a 'stage' field"); + } + + Map args = (Map) stageMap.get("args"); + + if (i == 0) { + pipeline = applySourceStage(pipelineSource, stageName, args, firestore); + } else { + pipeline = stageHandlers.applyStage(pipeline, stageName, args, firestore); + } + } + + return pipeline; + } + + /** + * Applies a source stage (collection, collection_group, documents, database) to PipelineSource. + * These are the only stages that can be the first stage and return a Pipeline instance. + */ + @SuppressWarnings("unchecked") + private static Pipeline applySourceStage( + @NonNull PipelineSource pipelineSource, + @NonNull String stageName, + @Nullable Map args, + @NonNull FirebaseFirestore firestore) { + if (args == null && !"database".equals(stageName)) { + throw new IllegalArgumentException("Stage args must not be null for stage: " + stageName); + } + switch (stageName) { + case "collection": + { + String path = (String) args.get("path"); + return pipelineSource.collection(path); + } + case "collection_group": + { + String path = (String) args.get("path"); + return pipelineSource.collectionGroup(path); + } + case "database": + { + return pipelineSource.database(); + } + case "documents": + { + List> docMaps = (List>) args; + List docRefs = new ArrayList<>(); + for (Map docMap : docMaps) { + String docPath = (String) docMap.get("path"); + docRefs.add(firestore.document(docPath)); + } + return pipelineSource.documents(docRefs.toArray(new DocumentReference[0])); + } + default: + throw new IllegalArgumentException( + "First stage must be one of: collection, collection_group, documents, database. Got: " + + stageName); + } + } +} diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java new file mode 100644 index 000000000000..cc0e6b0c35e6 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java @@ -0,0 +1,338 @@ +/* + * Copyright 2026, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +package io.flutter.plugins.firebase.firestore.utils; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.firebase.firestore.FirebaseFirestore; +import com.google.firebase.firestore.Pipeline; +import com.google.firebase.firestore.pipeline.AggregateOptions; +import com.google.firebase.firestore.pipeline.AggregateStage; +import com.google.firebase.firestore.pipeline.AliasedAggregate; +import com.google.firebase.firestore.pipeline.BooleanExpression; +import com.google.firebase.firestore.pipeline.Expression; +import com.google.firebase.firestore.pipeline.Field; +import com.google.firebase.firestore.pipeline.FindNearestOptions; +import com.google.firebase.firestore.pipeline.FindNearestStage; +import com.google.firebase.firestore.pipeline.Ordering; +import com.google.firebase.firestore.pipeline.SampleStage; +import com.google.firebase.firestore.pipeline.Selectable; +import com.google.firebase.firestore.pipeline.UnnestOptions; +import java.util.List; +import java.util.Map; + +/** Handles parsing and applying pipeline stages to Pipeline instances. */ +class PipelineStageHandlers { + private final ExpressionParsers parsers; + + PipelineStageHandlers(@NonNull ExpressionParsers parsers) { + this.parsers = parsers; + } + + /** Applies a pipeline stage to a Pipeline instance. */ + @SuppressWarnings("unchecked") + Pipeline applyStage( + @NonNull Pipeline pipeline, + @NonNull String stageName, + @Nullable Map args, + @NonNull FirebaseFirestore firestore) { + switch (stageName) { + case "where": + return handleWhere(pipeline, args); + case "limit": + return handleLimit(pipeline, args); + case "offset": + return handleOffset(pipeline, args); + case "sort": + return handleSort(pipeline, args); + case "select": + return handleSelect(pipeline, args); + case "add_fields": + return handleAddFields(pipeline, args); + case "remove_fields": + return handleRemoveFields(pipeline, args); + case "distinct": + return handleDistinct(pipeline, args); + case "aggregate": + return handleAggregate(pipeline, args); + case "aggregate_with_options": + return handleAggregateWithOptions(pipeline, args); + case "unnest": + return handleUnnest(pipeline, args); + case "replace_with": + return handleReplaceWith(pipeline, args); + case "union": + return handleUnion(pipeline, args, firestore); + case "sample": + return handleSample(pipeline, args); + case "find_nearest": + return handleFindNearest(pipeline, args); + default: + throw new IllegalArgumentException("Unknown pipeline stage: " + stageName); + } + } + + private Pipeline handleWhere(@NonNull Pipeline pipeline, @Nullable Map args) { + Map expressionMap = (Map) args.get("expression"); + BooleanExpression booleanExpression = parsers.parseBooleanExpression(expressionMap); + return pipeline.where(booleanExpression); + } + + private Pipeline handleLimit(@NonNull Pipeline pipeline, @Nullable Map args) { + Number limit = (Number) args.get("limit"); + return pipeline.limit(limit.intValue()); + } + + private Pipeline handleOffset(@NonNull Pipeline pipeline, @Nullable Map args) { + Number offset = (Number) args.get("offset"); + return pipeline.offset(offset.intValue()); + } + + @SuppressWarnings("unchecked") + private Pipeline handleSort(@NonNull Pipeline pipeline, @Nullable Map args) { + List> orderingMaps = (List>) args.get("orderings"); + if (orderingMaps == null || orderingMaps.isEmpty()) { + throw new IllegalArgumentException("'sort' requires at least one ordering"); + } + + Map firstMap = orderingMaps.get(0); + Expression expression = + parsers.parseExpression((Map) firstMap.get("expression")); + String direction = (String) firstMap.get("order_direction"); + Ordering firstOrdering = + "asc".equals(direction) ? expression.ascending() : expression.descending(); + + if (orderingMaps.size() == 1) { + return pipeline.sort(firstOrdering); + } + + Ordering[] additionalOrderings = new Ordering[orderingMaps.size() - 1]; + for (int i = 1; i < orderingMaps.size(); i++) { + Map map = orderingMaps.get(i); + expression = parsers.parseExpression((Map) map.get("expression")); + direction = (String) map.get("order_direction"); + additionalOrderings[i - 1] = + "asc".equals(direction) ? expression.ascending() : expression.descending(); + } + return pipeline.sort(firstOrdering, additionalOrderings); + } + + private Pipeline handleSelect(@NonNull Pipeline pipeline, @Nullable Map args) { + List> expressionMaps = (List>) args.get("expressions"); + + if (expressionMaps == null || expressionMaps.isEmpty()) { + throw new IllegalArgumentException("'select' requires at least one expression"); + } + + // Parse first expression as Selectable + Selectable firstSelection = parsers.parseSelectable(expressionMaps.get(0)); + + // Parse remaining expressions as varargs + if (expressionMaps.size() == 1) { + return pipeline.select(firstSelection); + } + + Object[] additionalSelections = new Object[expressionMaps.size() - 1]; + for (int i = 1; i < expressionMaps.size(); i++) { + Expression expr = parsers.parseExpression(expressionMaps.get(i)); + // Additional selections can be Selectable or any Object + additionalSelections[i - 1] = expr; + } + + return pipeline.select(firstSelection, additionalSelections); + } + + private Pipeline handleAddFields(@NonNull Pipeline pipeline, @Nullable Map args) { + List> expressionMaps = (List>) args.get("expressions"); + + if (expressionMaps == null || expressionMaps.isEmpty()) { + throw new IllegalArgumentException("'add_fields' requires at least one expression"); + } + + // Parse first expression as Selectable + Selectable firstField = parsers.parseSelectable(expressionMaps.get(0)); + + // Parse remaining expressions as Selectable varargs + if (expressionMaps.size() == 1) { + return pipeline.addFields(firstField); + } + + Selectable[] additionalFields = new Selectable[expressionMaps.size() - 1]; + for (int i = 1; i < expressionMaps.size(); i++) { + additionalFields[i - 1] = parsers.parseSelectable(expressionMaps.get(i)); + } + + return pipeline.addFields(firstField, additionalFields); + } + + private Pipeline handleRemoveFields( + @NonNull Pipeline pipeline, @Nullable Map args) { + List fieldPaths = (List) args.get("field_paths"); + + if (fieldPaths == null || fieldPaths.isEmpty()) { + throw new IllegalArgumentException("'remove_fields' requires at least one field path"); + } + + // Convert first field path string to Field + Field firstField = Expression.field(fieldPaths.get(0)); + + // Convert remaining field paths to Field varargs + if (fieldPaths.size() == 1) { + return pipeline.removeFields(firstField); + } + + Field[] additionalFields = new Field[fieldPaths.size() - 1]; + for (int i = 1; i < fieldPaths.size(); i++) { + additionalFields[i - 1] = Expression.field(fieldPaths.get(i)); + } + + return pipeline.removeFields(firstField, additionalFields); + } + + private Pipeline handleDistinct(@NonNull Pipeline pipeline, @Nullable Map args) { + List> expressionMaps = (List>) args.get("expressions"); + + if (expressionMaps == null || expressionMaps.isEmpty()) { + throw new IllegalArgumentException("'distinct' requires at least one expression"); + } + + // Parse first expression as Selectable + Selectable firstGroup = parsers.parseSelectable(expressionMaps.get(0)); + + // Parse remaining expressions as varargs (can be Selectable or Any) + if (expressionMaps.size() == 1) { + return pipeline.distinct(firstGroup); + } + + Object[] additionalGroups = new Object[expressionMaps.size() - 1]; + for (int i = 1; i < expressionMaps.size(); i++) { + Expression expr = parsers.parseExpression(expressionMaps.get(i)); + // Additional groups can be Selectable or any Object + additionalGroups[i - 1] = expr; + } + + return pipeline.distinct(firstGroup, additionalGroups); + } + + @SuppressWarnings("unchecked") + private Pipeline handleAggregate(@NonNull Pipeline pipeline, @Nullable Map args) { + List> aggregateMaps = + (List>) args.get("aggregate_functions"); + + if (aggregateMaps == null || aggregateMaps.isEmpty()) { + throw new IllegalArgumentException("'aggregate' requires at least one aggregate function"); + } + + AliasedAggregate firstAccumulator = parsers.parseAliasedAggregate(aggregateMaps.get(0)); + + if (aggregateMaps.size() == 1) { + return pipeline.aggregate(firstAccumulator); + } + + AliasedAggregate[] additionalAccumulators = new AliasedAggregate[aggregateMaps.size() - 1]; + for (int i = 1; i < aggregateMaps.size(); i++) { + additionalAccumulators[i - 1] = parsers.parseAliasedAggregate(aggregateMaps.get(i)); + } + + return pipeline.aggregate(firstAccumulator, additionalAccumulators); + } + + @SuppressWarnings("unchecked") + private Pipeline handleAggregateWithOptions( + @NonNull Pipeline pipeline, @Nullable Map args) { + Map aggregateStageMap = (Map) args.get("aggregate_stage"); + + AggregateStage aggregateStage = parsers.parseAggregateStage(aggregateStageMap); + + Map optionsMap = (Map) args.get("options"); + if (optionsMap != null && !optionsMap.isEmpty()) { + AggregateOptions options = parsers.parseAggregateOptions(optionsMap); + return pipeline.aggregate(aggregateStage, options); + } + return pipeline.aggregate(aggregateStage); + } + + private Pipeline handleUnnest(@NonNull Pipeline pipeline, @Nullable Map args) { + Map expressionMap = (Map) args.get("expression"); + Selectable expression = parsers.parseSelectable(expressionMap); + String indexField = (String) args.get("index_field"); + if (indexField != null) { + return pipeline.unnest(expression, new UnnestOptions().withIndexField(indexField)); + } else { + return pipeline.unnest(expression); + } + } + + private Pipeline handleReplaceWith( + @NonNull Pipeline pipeline, @Nullable Map args) { + Map expressionMap = (Map) args.get("expression"); + Expression expression = parsers.parseExpression(expressionMap); + return pipeline.replaceWith(expression); + } + + @SuppressWarnings("unchecked") + private Pipeline handleUnion( + @NonNull Pipeline pipeline, + @Nullable Map args, + @NonNull FirebaseFirestore firestore) { + List> nestedStages = (List>) args.get("pipeline"); + if (nestedStages == null || nestedStages.isEmpty()) { + throw new IllegalArgumentException("'union' requires a non-empty 'pipeline' argument"); + } + Pipeline otherPipeline = PipelineParser.buildPipeline(firestore, nestedStages); + return pipeline.union(otherPipeline); + } + + private Pipeline handleSample(@NonNull Pipeline pipeline, @Nullable Map args) { + // Sample stage parsing + Map sampleMap = (Map) args; + // Parse sample configuration + String type = (String) sampleMap.get("type"); + if ("percentage".equals(type)) { + double value = ((Number) sampleMap.get("value")).doubleValue(); + return pipeline.sample(SampleStage.withPercentage(value)); + } else { + int value = ((Number) sampleMap.get("value")).intValue(); + return pipeline.sample(SampleStage.withDocLimit(value)); + } + } + + @SuppressWarnings("unchecked") + private Pipeline handleFindNearest( + @NonNull Pipeline pipeline, @Nullable Map args) { + String vectorField = (String) args.get("vector_field"); + List vectorValue = (List) args.get("vector_value"); + String distanceMeasureStr = (String) args.get("distance_measure"); + Number limitObj = (Number) args.get("limit"); + + if (distanceMeasureStr == null) { + throw new IllegalArgumentException("'find_nearest' requires a 'distance_measure' argument"); + } + + // Convert Dart enum name to Android enum value + FindNearestStage.DistanceMeasure distanceMeasure = + parsers.parseDistanceMeasure(distanceMeasureStr); + + // Convert vector value to double array + double[] vectorArray = new double[vectorValue.size()]; + for (int i = 0; i < vectorValue.size(); i++) { + vectorArray[i] = vectorValue.get(i).doubleValue(); + } + + Field fieldExpr = Expression.field(vectorField); + + if (limitObj != null) { + return pipeline.findNearest( + vectorField, + Expression.vector(vectorArray), + distanceMeasure, + new FindNearestOptions().withLimit(limitObj.intValue())); + } else { + return pipeline.findNearest(fieldExpr, vectorArray, distanceMeasure); + } + } +} diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index e137837a8f4d..544b1f6a4d8b 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let library_version = "6.1.3" -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.11.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m index b7fa740fe68c..ab826056264f 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m @@ -15,6 +15,7 @@ #import "include/cloud_firestore/Private/FLTFirebaseFirestoreReader.h" #import "include/cloud_firestore/Private/FLTFirebaseFirestoreUtils.h" #import "include/cloud_firestore/Private/FLTLoadBundleStreamHandler.h" +#import "include/cloud_firestore/Private/FLTPipelineParser.h" #import "include/cloud_firestore/Private/FLTQuerySnapshotStreamHandler.h" #import "include/cloud_firestore/Private/FLTSnapshotsInSyncStreamHandler.h" #import "include/cloud_firestore/Private/FLTTransactionStreamHandler.h" @@ -73,6 +74,20 @@ - (NSString *)registerEventChannelWithPrefix:(NSString *)prefix static NSCache *_serverTimestampMap; +static id _Nullable FLTPipelineNullSafe(id value) { + return (value == nil || [value isKindOfClass:[NSNull class]]) ? nil : value; +} + +static NSNumber *_Nullable FLTPipelineTimestampToMs(id value) { + if (!value) return nil; + if ([value isKindOfClass:[NSNumber class]]) return value; + if ([value isKindOfClass:[FIRTimestamp class]]) { + FIRTimestamp *ts = value; + return @((int64_t)ts.seconds * 1000 + (int64_t)ts.nanoseconds / 1000000); + } + return nil; +} + @implementation FLTFirebaseFirestorePlugin { NSMutableDictionary *_eventChannels; NSMutableDictionary *> *_streamHandlers; @@ -883,4 +898,66 @@ - (void)aggregateQueryApp:(nonnull FirestorePigeonFirebaseApp *)app }]; } +- (void)executePipelineApp:(nonnull FirestorePigeonFirebaseApp *)app + stages:(nonnull NSArray *> *)stages + options:(nullable NSDictionary *)options + completion:(nonnull void (^)(PigeonPipelineSnapshot *_Nullable, + FlutterError *_Nullable))completion { + FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; + + [FLTPipelineParser + executePipelineWithFirestore:firestore + stages:stages + options:options + completion:^(id _Nullable snapshot, NSError *_Nullable error) { + if (error) { + completion(nil, [self convertToFlutterError:error]); + return; + } + if (snapshot == nil) { + completion( + nil, + [FlutterError errorWithCode:@"error" + message:@"Pipeline execution returned no result" + details:nil]); + return; + } + + NSMutableArray *pigeonResults = + [NSMutableArray array]; + NSArray *results = [snapshot results]; + if ([results isKindOfClass:[NSArray class]]) { + for (id result in results) { + id ref = [result reference]; + NSString *path = (ref && [ref respondsToSelector:@selector(path)]) + ? [ref path] + : FLTPipelineNullSafe([result documentID]); + NSNumber *createTime = + FLTPipelineTimestampToMs([result valueForKey:@"create_time"]); + NSNumber *updateTime = + FLTPipelineTimestampToMs([result valueForKey:@"update_time"]); + NSDictionary *data = FLTPipelineNullSafe([result data]); + PigeonPipelineResult *pigeonResult = + [PigeonPipelineResult makeWithDocumentPath:path + createTime:createTime + updateTime:updateTime + data:data]; + [pigeonResults addObject:pigeonResult]; + } + } + + NSNumber *executionTime = + FLTPipelineTimestampToMs([snapshot execution_time]); + if (executionTime == nil) { + executionTime = + @((int64_t)([[NSDate date] timeIntervalSince1970] * 1000)); + } + + PigeonPipelineSnapshot *pigeonSnapshot = + [PigeonPipelineSnapshot makeWithResults:pigeonResults + executionTime:executionTime]; + completion(pigeonSnapshot, nil); + }]; +} + @end diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestoreUtils.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestoreUtils.m index d49fbc7f4a79..db06c89e52a0 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestoreUtils.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestoreUtils.m @@ -21,6 +21,8 @@ - (FlutterStandardReader *_Nonnull)readerWithData:(NSData *)data { NSMutableDictionary *firestoreInstanceCache; +const NSInteger FLTFirebaseFirestoreErrorCodePipelineParse = -1; + @implementation FLTFirebaseFirestoreUtils + (NSString *)generateKeyForAppName:(NSString *)appName andDatabaseURL:(NSString *)databaseURL { @@ -240,6 +242,11 @@ + (NSArray *)ErrorCodeAndMessageFromNSError:(NSError *)error { code = @"unknown"; message = @"Unknown error or an error from a different error domain."; break; + case FLTFirebaseFirestoreErrorCodePipelineParse: + code = @"parse-error"; + message = (error.localizedDescription.length > 0) ? error.localizedDescription + : @"An unknown error occurred."; + break; default: code = @"unknown"; message = @"An unknown error occurred."; diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m new file mode 100644 index 000000000000..cc3d36f510dd --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m @@ -0,0 +1,1339 @@ +/* + * Copyright 2026, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#import "include/cloud_firestore/Private/FLTPipelineParser.h" +#import "include/cloud_firestore/Private/FLTFirebaseFirestoreUtils.h" + +#if TARGET_OS_OSX +#import +#import "FirebaseFirestoreInternal/FIRPipelineBridge.h" +#else +@import FirebaseFirestore; +#if __has_include("FirebaseFirestoreInternal/FIRPipelineBridge.h") +#import "FirebaseFirestoreInternal/FIRPipelineBridge.h" +#elif __has_include("FIRPipelineBridge.h") +#import "FIRPipelineBridge.h" +#endif +#endif + +#if __has_include("FirebaseFirestoreInternal/FIRVectorValue.h") +#import "FirebaseFirestoreInternal/FIRVectorValue.h" +#elif __has_include() +#import +#endif + +#import + +static NSString *const kPipelineNotAvailable = + @"Pipeline API is not available. Firestore Pipelines require Firebase iOS SDK with pipeline " + "support."; + +static NSError *pipelineUnavailableError(void) { + return [NSError errorWithDomain:@"FLTFirebaseFirestore" + code:FLTFirebaseFirestoreErrorCodePipelineParse + userInfo:@{NSLocalizedDescriptionKey : kPipelineNotAvailable}]; +} + +#if TARGET_OS_OSX +#if __has_include("FirebaseFirestoreInternal/FIRPipelineBridge.h") +#define FLT_PIPELINE_AVAILABLE 1 +#endif +#else +#if __has_include("FirebaseFirestoreInternal/FIRPipelineBridge.h") || \ + __has_include("FIRPipelineBridge.h") +#define FLT_PIPELINE_AVAILABLE 1 +#endif +#endif + +#if FLT_PIPELINE_AVAILABLE + +// Firebase iOS SDK versions differ: some expose initWithName:Args:Options:, others +// initWithName:Args:. +@interface FIRFunctionExprBridge (FLTSDKCompat) +- (instancetype)initWithName:(NSString *)name + Args:(NSArray *)args + Options:(NSDictionary *)options; +- (instancetype)initWithName:(NSString *)name Args:(NSArray *)args; +@end + +static FIRFunctionExprBridge *FLTNewFunctionExprBridge(NSString *name, + NSArray *args) { + FIRFunctionExprBridge *obj = [FIRFunctionExprBridge alloc]; + if ([obj respondsToSelector:@selector(initWithName:Args:Options:)]) { + return [obj initWithName:name Args:args Options:nil]; + } + return [obj initWithName:name Args:args]; +} + +static NSError *parseError(NSString *message) { + return [NSError errorWithDomain:@"FLTFirebaseFirestore" + code:FLTFirebaseFirestoreErrorCodePipelineParse + userInfo:@{NSLocalizedDescriptionKey : message}]; +} + +@interface FLTPipelineExpressionParser : NSObject +@property(nonatomic, strong) FIRFirestore *firestore; +- (instancetype)initWithFirestore:(FIRFirestore *)firestore; +- (FIRExprBridge *)parseExpression:(NSDictionary *)map error:(NSError **)error; +- (FIRExprBridge *)parseBooleanExpression:(NSDictionary *)map + error:(NSError **)error; +- (FIRExprBridge *)rightExprFromValue:(id)value error:(NSError **)error; +@end + +@implementation FLTPipelineExpressionParser + +- (instancetype)initWithFirestore:(FIRFirestore *)firestore { + self = [super init]; + if (self) { + _firestore = firestore; + } + return self; +} + +- (FIRExprBridge *)parseExpression:(NSDictionary *)map error:(NSError **)error { + NSString *name = map[@"name"]; + if (!name) { + NSDictionary *args = map[@"args"]; + if ([args isKindOfClass:[NSDictionary class]] && args[@"field"]) { + return [[FIRFieldBridge alloc] initWithName:args[@"field"]]; + } + if (error) *error = parseError(@"Expression must have a 'name' field"); + return nil; + } + + NSDictionary *args = map[@"args"]; + if (![args isKindOfClass:[NSDictionary class]]) args = @{}; + + if ([name isEqualToString:@"field"]) { + NSString *field = args[@"field"]; + if (!field) { + if (error) *error = parseError(@"Field expression requires 'field' argument"); + return nil; + } + return [[FIRFieldBridge alloc] initWithName:field]; + } + + if ([name isEqualToString:@"constant"]) { + id value = args[@"value"]; + if (value == nil) { + if (error) *error = parseError(@"Constant requires 'value' argument"); + return nil; + } + if ([value isKindOfClass:[NSDictionary class]]) { + NSString *path = ((NSDictionary *)value)[@"path"]; + if ([path isKindOfClass:[NSString class]] && self.firestore) { + FIRDocumentReference *docRef = [self.firestore documentWithPath:path]; + return [[FIRConstantBridge alloc] init:docRef]; + } + } + return [[FIRConstantBridge alloc] init:value]; + } + + if ([name isEqualToString:@"alias"]) { + id exprMap = args[@"expression"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"Alias requires 'expression'"); + return nil; + } + // No explicit AliasedExpression type in ObjC; aliases are dict keys when building stages. + // Parse and return the inner expression; the caller uses args[@"alias"] as the dict key. + return [self parseExpression:exprMap error:error]; + } + + if ([name isEqualToString:@"null"]) { + return [[FIRConstantBridge alloc] init:[NSNull null]]; + } + + if ([name isEqualToString:@"document_id_from_ref"]) { + NSString *path = args[@"doc_ref"]; + if (![path isKindOfClass:[NSString class]] || path.length == 0) { + if (error) *error = parseError(@"document_id_from_ref requires doc_ref path"); + return nil; + } + if (!self.firestore) { + if (error) *error = parseError(@"document_id_from_ref requires firestore"); + return nil; + } + FIRDocumentReference *docRef = [self.firestore documentWithPath:path]; + FIRExprBridge *refExpr = [[FIRConstantBridge alloc] init:docRef]; + return FLTNewFunctionExprBridge(@"document_id", @[ refExpr ]); + } + + // Swift asBoolean() is a type coercion, not a pipeline function named "as_boolean". + // Dart still sends as_boolean + expression; unwrap to the inner FIRExprBridge. + if ([name isEqualToString:@"as_boolean"]) { + id exprMap = args[@"expression"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"as_boolean requires expression"); + return nil; + } + return [self parseExpression:(NSDictionary *)exprMap error:error]; + } + + // Map Dart names to iOS SDK names where they differ + NSString *sdkName = name; + if ([name isEqualToString:@"bit_xor"]) sdkName = @"xor"; + if ([name isEqualToString:@"modulo"]) sdkName = @"mod"; + + // ------------------------------------------------------------------------- + // Binary expressions (left + right): comparisons, arithmetic, bitwise + // ------------------------------------------------------------------------- + static NSArray *binaryNames = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + binaryNames = @[ + @"equal", @"not_equal", @"greater_than", @"greater_than_or_equal", @"less_than", + @"less_than_or_equal", @"add", @"subtract", @"multiply", @"divide", @"mod", @"bit_and", + @"bit_or", @"bit_left_shift", @"bit_right_shift" + ]; + }); + if ([binaryNames containsObject:sdkName] || [name isEqualToString:@"bit_xor"]) { + id leftMap = args[@"left"]; + id rightMap = args[@"right"]; + if (![leftMap isKindOfClass:[NSDictionary class]] || + ![rightMap isKindOfClass:[NSDictionary class]]) { + if (error) + *error = + parseError([NSString stringWithFormat:@"%@ requires left and right expressions", name]); + return nil; + } + FIRExprBridge *left = [self parseExpression:leftMap error:error]; + FIRExprBridge *right = [self parseExpression:rightMap error:error]; + if (!left || !right) return nil; + return FLTNewFunctionExprBridge(sdkName, @[ left, right ]); + } + + // ------------------------------------------------------------------------- + // Unary expressions (single expression): exists, is_error, is_absent, not + // (as_boolean is handled above — unwrap only, not a pipeline function.) + // ------------------------------------------------------------------------- + NSArray *unaryNames = @[ @"exists", @"is_error", @"is_absent", @"not" ]; + if ([unaryNames containsObject:name]) { + id exprMap = args[@"expression"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError([NSString stringWithFormat:@"%@ requires expression", name]); + return nil; + } + FIRExprBridge *expr = [name isEqualToString:@"not"] + ? [self parseBooleanExpression:exprMap error:error] + : [self parseExpression:exprMap error:error]; + if (!expr) return nil; + return FLTNewFunctionExprBridge(name, @[ expr ]); + } + + // ------------------------------------------------------------------------- + // Unary with optional SDK name mapping: length, to_lower, to_upper, trim, + // abs, array_length, array_reverse, bit_not, document_id, collection_id + // ------------------------------------------------------------------------- + NSArray *unaryWithSdkName = @[ + @"length", @"to_lower_case", @"to_upper_case", @"trim", @"abs", @"array_length", + @"array_reverse", @"bit_not", @"document_id", @"collection_id" + ]; + if ([unaryWithSdkName containsObject:name]) { + id exprMap = args[@"expression"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError([NSString stringWithFormat:@"%@ requires expression", name]); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + if (!expr) return nil; + NSString *unarySdkName = name; + if ([name isEqualToString:@"to_lower_case"]) unarySdkName = @"to_lower"; + if ([name isEqualToString:@"to_upper_case"]) unarySdkName = @"to_upper"; + return FLTNewFunctionExprBridge(unarySdkName, @[ expr ]); + } + + // ------------------------------------------------------------------------- + // N-ary logical (expressions array): and, or, xor + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"and"] || [name isEqualToString:@"or"] || + [name isEqualToString:@"xor"]) { + NSArray *exprMaps = args[@"expressions"]; + if (![exprMaps isKindOfClass:[NSArray class]] || exprMaps.count == 0) { + if (error) + *error = + parseError([NSString stringWithFormat:@"%@ requires at least one expression", name]); + return nil; + } + NSMutableArray *all = [NSMutableArray array]; + for (id em in exprMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *e = [self parseBooleanExpression:em error:error]; + if (!e) return nil; + [all addObject:e]; + } + if (all.count == 0) { + if (error) + *error = + parseError([NSString stringWithFormat:@"%@ requires at least one expression", name]); + return nil; + } + return FLTNewFunctionExprBridge(name, all); + } + + // ------------------------------------------------------------------------- + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"equal_any"] || [name isEqualToString:@"not_equal_any"]) { + id valueMap = args[@"value"]; + NSArray *valuesMaps = args[@"values"]; + if (![valueMap isKindOfClass:[NSDictionary class]] || + ![valuesMaps isKindOfClass:[NSArray class]] || valuesMaps.count == 0) { + if (error) + *error = + parseError([NSString stringWithFormat:@"%@ requires value and non-empty values", name]); + return nil; + } + FIRExprBridge *valueExpr = [self parseExpression:valueMap error:error]; + if (!valueExpr) return nil; + NSMutableArray *valueExprs = [NSMutableArray array]; + for (id vm in valuesMaps) { + if (![vm isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *ve = [self parseExpression:vm error:error]; + if (!ve) return nil; + [valueExprs addObject:ve]; + } + if (valueExprs.count == 0) { + if (error) + *error = parseError([NSString stringWithFormat:@"%@ requires at least one value", name]); + return nil; + } + FIRExprBridge *valuesArrayExpr = FLTNewFunctionExprBridge(@"array", valueExprs); + return FLTNewFunctionExprBridge(name, @[ valueExpr, valuesArrayExpr ]); + } + + // ------------------------------------------------------------------------- + // array + element: array_contains + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array_contains"]) { + id arrayMap = args[@"array"]; + id elementMap = args[@"element"]; + if (![arrayMap isKindOfClass:[NSDictionary class]] || + ![elementMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"array_contains requires array and element"); + return nil; + } + FIRExprBridge *arrayExpr = [self parseExpression:arrayMap error:error]; + FIRExprBridge *elementExpr = [self parseExpression:elementMap error:error]; + if (!arrayExpr || !elementExpr) return nil; + return FLTNewFunctionExprBridge(name, @[ arrayExpr, elementExpr ]); + } + + // ------------------------------------------------------------------------- + // array + values[]: array_contains_all, array_contains_any + // SDK expects: array_contains_any(field, array(val1, val2, ...)) — two args. + // Reuse the "array" expression parser to build the values array. + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array_contains_all"] || + [name isEqualToString:@"array_contains_any"]) { + id arrayMap = args[@"array"]; + if (![arrayMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError([NSString stringWithFormat:@"%@ requires array", name]); + return nil; + } + FIRExprBridge *arrayExpr = [self parseExpression:arrayMap error:error]; + if (!arrayExpr) return nil; + + NSArray *valuesMaps = args[@"values"]; + if (![valuesMaps isKindOfClass:[NSArray class]]) valuesMaps = args[@"elements"]; + BOOL hasValues = [valuesMaps isKindOfClass:[NSArray class]] && valuesMaps.count > 0; + + if (hasValues) { + NSDictionary *arrayExprMap = @{@"name" : @"array", @"args" : @{@"elements" : valuesMaps}}; + FIRExprBridge *valuesArrayExpr = [self parseExpression:arrayExprMap error:error]; + if (!valuesArrayExpr) return nil; + return FLTNewFunctionExprBridge(name, @[ arrayExpr, valuesArrayExpr ]); + } + + if ([name isEqualToString:@"array_contains_all"]) { + id arrayExpressionMap = args[@"array_expression"]; + if ([arrayExpressionMap isKindOfClass:[NSDictionary class]]) { + FIRExprBridge *requiredArrayExpr = [self parseExpression:arrayExpressionMap error:error]; + if (!requiredArrayExpr) return nil; + return FLTNewFunctionExprBridge(name, @[ arrayExpr, requiredArrayExpr ]); + } + } + + if (error) + *error = parseError([NSString + stringWithFormat: + @"%@ requires array and values/elements, or array_contains_all with array_expression", + name]); + return nil; + } + + // ------------------------------------------------------------------------- + // expressions[]: concat (SDK: concat) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"concat"]) { + NSArray *exprMaps = args[@"expressions"]; + if (![exprMaps isKindOfClass:[NSArray class]] || exprMaps.count == 0) { + if (error) *error = parseError(@"concat requires non-empty expressions"); + return nil; + } + NSMutableArray *all = [NSMutableArray array]; + for (id em in exprMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *e = [self parseExpression:em error:error]; + if (!e) return nil; + [all addObject:e]; + } + if (all.count == 0) { + if (error) *error = parseError(@"concat requires at least one expression"); + return nil; + } + return FLTNewFunctionExprBridge(@"concat", all); + } + + // ------------------------------------------------------------------------- + // expression + start + end: substring (SDK: substring) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"substring"]) { + id exprMap = args[@"expression"]; + id startMap = args[@"start"]; + id endMap = args[@"end"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || + ![startMap isKindOfClass:[NSDictionary class]] || + ![endMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"substring requires expression, start, and end"); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *start = [self parseExpression:startMap error:error]; + FIRExprBridge *end = [self parseExpression:endMap error:error]; + if (!expr || !start || !end) return nil; + return FLTNewFunctionExprBridge(@"substring", @[ expr, start, end ]); + } + + // ------------------------------------------------------------------------- + // expression + find + replacement: replace (SDK: string_replace) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"replace"]) { + id exprMap = args[@"expression"]; + id findMap = args[@"find"]; + id replacementMap = args[@"replacement"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || + ![findMap isKindOfClass:[NSDictionary class]] || + ![replacementMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"replace requires expression, find, and replacement"); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *find = [self parseExpression:findMap error:error]; + FIRExprBridge *replacement = [self parseExpression:replacementMap error:error]; + if (!expr || !find || !replacement) return nil; + return FLTNewFunctionExprBridge(@"string_replace", @[ expr, find, replacement ]); + } + + // ------------------------------------------------------------------------- + // expression + delimiter: split, join (SDK: split, join) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"split"] || [name isEqualToString:@"join"]) { + id exprMap = args[@"expression"]; + id delimiterMap = args[@"delimiter"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || + ![delimiterMap isKindOfClass:[NSDictionary class]]) { + if (error) + *error = + parseError([NSString stringWithFormat:@"%@ requires expression and delimiter", name]); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *delimiter = [self parseExpression:delimiterMap error:error]; + if (!expr || !delimiter) return nil; + return FLTNewFunctionExprBridge(name, @[ expr, delimiter ]); + } + + // ------------------------------------------------------------------------- + // first + second: array_concat (SDK: array_concat) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array_concat"]) { + id firstMap = args[@"first"]; + id secondMap = args[@"second"]; + if (![firstMap isKindOfClass:[NSDictionary class]] || + ![secondMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"array_concat requires first and second"); + return nil; + } + FIRExprBridge *first = [self parseExpression:firstMap error:error]; + FIRExprBridge *second = [self parseExpression:secondMap error:error]; + if (!first || !second) return nil; + return FLTNewFunctionExprBridge(@"array_concat", @[ first, second ]); + } + + // ------------------------------------------------------------------------- + // arrays[]: array_concat_multiple (SDK: array_concat) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array_concat_multiple"]) { + NSArray *arraysMaps = args[@"arrays"]; + if (![arraysMaps isKindOfClass:[NSArray class]] || arraysMaps.count == 0) { + if (error) *error = parseError(@"array_concat_multiple requires non-empty arrays"); + return nil; + } + NSMutableArray *all = [NSMutableArray array]; + for (id am in arraysMaps) { + if (![am isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *e = [self parseExpression:am error:error]; + if (!e) return nil; + [all addObject:e]; + } + if (all.count == 0) { + if (error) *error = parseError(@"array_concat_multiple requires at least one array"); + return nil; + } + return FLTNewFunctionExprBridge(@"array_concat", all); + } + + // ------------------------------------------------------------------------- + // elements[]: array (construct) — Expression.array([...]) from Dart + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array"]) { + NSArray *elementsMaps = args[@"elements"]; + if (![elementsMaps isKindOfClass:[NSArray class]] || elementsMaps.count == 0) { + if (error) *error = parseError(@"array requires non-empty elements"); + return nil; + } + NSMutableArray *elementExprs = [NSMutableArray array]; + for (id em in elementsMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *e = [self parseExpression:em error:error]; + if (!e) return nil; + [elementExprs addObject:e]; + } + if (elementExprs.count == 0) { + if (error) *error = parseError(@"array requires at least one element"); + return nil; + } + return FLTNewFunctionExprBridge(@"array", elementExprs); + } + + // ------------------------------------------------------------------------- + // data: map (construct) — Expression.map({ "k": expr, ... }) from Dart + // SDK expects Args as alternating key (constant), value (expression). + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"map"]) { + NSDictionary *dataMap = args[@"data"]; + if (![dataMap isKindOfClass:[NSDictionary class]] || dataMap.count == 0) { + if (error) *error = parseError(@"map requires non-empty data"); + return nil; + } + NSMutableArray *mapArgs = [NSMutableArray array]; + for (NSString *key in dataMap) { + id valueMap = dataMap[key]; + if (![valueMap isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *keyExpr = [[FIRConstantBridge alloc] init:key]; + FIRExprBridge *valueExpr = [self parseExpression:valueMap error:error]; + if (!valueExpr) return nil; + [mapArgs addObject:keyExpr]; + [mapArgs addObject:valueExpr]; + } + if (mapArgs.count == 0) { + if (error) *error = parseError(@"map requires at least one key-value pair"); + return nil; + } + return FLTNewFunctionExprBridge(@"map", mapArgs); + } + + // ------------------------------------------------------------------------- + // map + key: map_get (SDK: map_get) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"map_get"]) { + id mapMap = args[@"map"]; + id keyMap = args[@"key"]; + if (![mapMap isKindOfClass:[NSDictionary class]] || + ![keyMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"map_get requires map and key"); + return nil; + } + FIRExprBridge *mapExpr = [self parseExpression:mapMap error:error]; + FIRExprBridge *keyExpr = [self parseExpression:keyMap error:error]; + if (!mapExpr || !keyExpr) return nil; + return FLTNewFunctionExprBridge(@"map_get", @[ mapExpr, keyExpr ]); + } + + // ------------------------------------------------------------------------- + // expression + else: if_absent (SDK: if_absent) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"if_absent"]) { + id exprMap = args[@"expression"]; + id elseMap = args[@"else"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || + ![elseMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"if_absent requires expression and else"); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *elseExpr = [self parseExpression:elseMap error:error]; + if (!expr || !elseExpr) return nil; + return FLTNewFunctionExprBridge(@"if_absent", @[ expr, elseExpr ]); + } + + // ------------------------------------------------------------------------- + // expression + catch: if_error (SDK: if_error) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"if_error"]) { + id exprMap = args[@"expression"]; + id catchMap = args[@"catch"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || + ![catchMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"if_error requires expression and catch"); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *catchExpr = [self parseExpression:catchMap error:error]; + if (!expr || !catchExpr) return nil; + return FLTNewFunctionExprBridge(@"if_error", @[ expr, catchExpr ]); + } + + // ------------------------------------------------------------------------- + // condition + then + else: conditional (SDK: conditional) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"conditional"]) { + id conditionMap = args[@"condition"]; + id thenMap = args[@"then"]; + id elseMap = args[@"else"]; + if (![conditionMap isKindOfClass:[NSDictionary class]] || + ![thenMap isKindOfClass:[NSDictionary class]] || + ![elseMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"conditional requires condition, then, and else"); + return nil; + } + FIRExprBridge *condition = [self parseBooleanExpression:conditionMap error:error]; + FIRExprBridge *thenExpr = [self parseExpression:thenMap error:error]; + FIRExprBridge *elseExpr = [self parseExpression:elseMap error:error]; + if (!condition || !thenExpr || !elseExpr) return nil; + return FLTNewFunctionExprBridge(@"conditional", @[ condition, thenExpr, elseExpr ]); + } + + // ------------------------------------------------------------------------- + // timestamp + amount + unit: timestamp_add, timestamp_subtract (SDK: Args ts, amount, unit) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"timestamp_add"] || [name isEqualToString:@"timestamp_subtract"]) { + id timestampMap = args[@"timestamp"]; + id unitVal = args[@"unit"]; + id amountMap = args[@"amount"]; + if (![timestampMap isKindOfClass:[NSDictionary class]] || !unitVal || + ![amountMap isKindOfClass:[NSDictionary class]]) { + if (error) + *error = parseError( + [NSString stringWithFormat:@"%@ requires timestamp, unit, and amount", name]); + return nil; + } + FIRExprBridge *timestampExpr = [self parseExpression:timestampMap error:error]; + FIRExprBridge *amountExpr = [self parseExpression:amountMap error:error]; + if (!timestampExpr || !amountExpr) return nil; + FIRExprBridge *unitExpr = [[FIRConstantBridge alloc] init:unitVal]; + return FLTNewFunctionExprBridge(name, @[ timestampExpr, unitExpr, amountExpr ]); + } + + // ------------------------------------------------------------------------- + // No args: current_timestamp (SDK: current_timestamp with empty Args) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"current_timestamp"]) { + return FLTNewFunctionExprBridge(@"current_timestamp", @[]); + } + + // ------------------------------------------------------------------------- + // timestamp + unit: timestamp_truncate (SDK: timestamp_trunc) + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"timestamp_truncate"]) { + id timestampMap = args[@"timestamp"]; + id unitVal = args[@"unit"]; + if (![timestampMap isKindOfClass:[NSDictionary class]] || !unitVal) { + if (error) *error = parseError(@"timestamp_truncate requires timestamp and unit"); + return nil; + } + FIRExprBridge *timestampExpr = [self parseExpression:timestampMap error:error]; + if (!timestampExpr) return nil; + FIRExprBridge *unitExpr = [[FIRConstantBridge alloc] init:unitVal]; + return FLTNewFunctionExprBridge(@"timestamp_trunc", @[ timestampExpr, unitExpr ]); + } + + // ------------------------------------------------------------------------- + // PipelineFilter (name "filter"): operator-based (and/or) or field-based + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"filter"]) { + return [self parseFilterExpressionWithArgs:args error:error]; + } + + if (error) *error = parseError([NSString stringWithFormat:@"Unsupported expression: %@", name]); + return nil; +} + +- (FIRExprBridge *)rightExprFromValue:(id)value error:(NSError **)error { + if ([value isKindOfClass:[NSDictionary class]]) { + return [self parseExpression:(NSDictionary *)value error:error]; + } + return [[FIRConstantBridge alloc] init:value]; +} + +- (FIRExprBridge *)parseFilterExpressionWithArgs:(NSDictionary *)args error:(NSError **)error { + // Operator-based: and/or with expressions array (from PipelineFilter.and / .or) + NSString *operator= args[@"operator"]; + NSArray *exprMaps = args[@"expressions"]; + if ([operator isKindOfClass:[NSString class]] && [exprMaps isKindOfClass:[NSArray class]]) { + if (exprMaps.count == 0) { + if (error) *error = parseError(@"filter with operator requires at least one expression"); + return nil; + } + if (exprMaps.count == 1) { + id em = exprMaps[0]; + if (![em isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"filter expressions must be maps"); + return nil; + } + return [self parseBooleanExpression:(NSDictionary *)em error:error]; + } + NSMutableArray *all = [NSMutableArray array]; + for (id em in exprMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *e = [self parseBooleanExpression:(NSDictionary *)em error:error]; + if (!e) return nil; + [all addObject:e]; + } + if (all.count == 0) return nil; + return FLTNewFunctionExprBridge(operator, all); + } + + // Field-based: field + isEqualTo, isGreaterThan, etc. + NSString *fieldName = args[@"field"]; + if (![fieldName isKindOfClass:[NSString class]]) { + if (error) *error = parseError(@"filter requires operator+expressions or field"); + return nil; + } + FIRExprBridge *fieldExpr = [[FIRFieldBridge alloc] initWithName:fieldName]; + + static NSArray *filterComparisonKeys = nil; + static dispatch_once_t filterOnce; + dispatch_once(&filterOnce, ^{ + filterComparisonKeys = @[ + @"isEqualTo", @"isNotEqualTo", @"isGreaterThan", @"isGreaterThanOrEqualTo", @"isLessThan", + @"isLessThanOrEqualTo", @"arrayContains", @"arrayContainsAny", @"whereIn", @"whereNotIn", + @"isNull", @"isNotNull" + ]; + }); + for (NSString *key in filterComparisonKeys) { + id value = args[key]; + if (value == nil) continue; + + if ([key isEqualToString:@"isEqualTo"]) { + FIRExprBridge *right = [self rightExprFromValue:value error:error]; + if (!right) return nil; + return FLTNewFunctionExprBridge(@"equal", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"isNotEqualTo"]) { + FIRExprBridge *right = [self rightExprFromValue:value error:error]; + if (!right) return nil; + return FLTNewFunctionExprBridge(@"not_equal", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"isGreaterThan"]) { + FIRExprBridge *right = [self rightExprFromValue:value error:error]; + if (!right) return nil; + return FLTNewFunctionExprBridge(@"greater_than", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"isGreaterThanOrEqualTo"]) { + FIRExprBridge *right = [self rightExprFromValue:value error:error]; + if (!right) return nil; + return FLTNewFunctionExprBridge(@"greater_than_or_equal", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"isLessThan"]) { + FIRExprBridge *right = [self rightExprFromValue:value error:error]; + if (!right) return nil; + return FLTNewFunctionExprBridge(@"less_than", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"isLessThanOrEqualTo"]) { + FIRExprBridge *right = [self rightExprFromValue:value error:error]; + if (!right) return nil; + return FLTNewFunctionExprBridge(@"less_than_or_equal", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"arrayContains"]) { + FIRExprBridge *right = [self rightExprFromValue:value error:error]; + if (!right) return nil; + return FLTNewFunctionExprBridge(@"array_contains", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"arrayContainsAny"] || [key isEqualToString:@"whereIn"]) { + NSArray *valuesList = [value isKindOfClass:[NSArray class]] ? value : @[]; + NSMutableArray *valueExprs = [NSMutableArray array]; + for (id v in valuesList) { + FIRExprBridge *ve = [self rightExprFromValue:v error:error]; + if (!ve) return nil; + [valueExprs addObject:ve]; + } + if (valueExprs.count == 0) { + if (error) *error = parseError(@"arrayContainsAny/whereIn requires non-empty list"); + return nil; + } + // SDK expects (value, array) not (value, v1, v2, ...); wrap in "array" expr. + FIRExprBridge *valuesArrayExpr = FLTNewFunctionExprBridge(@"array", valueExprs); + return FLTNewFunctionExprBridge(@"equal_any", @[ fieldExpr, valuesArrayExpr ]); + } + if ([key isEqualToString:@"whereNotIn"]) { + NSArray *valuesList = [value isKindOfClass:[NSArray class]] ? value : @[]; + NSMutableArray *valueExprs = [NSMutableArray array]; + for (id v in valuesList) { + FIRExprBridge *ve = [self rightExprFromValue:v error:error]; + if (!ve) return nil; + [valueExprs addObject:ve]; + } + if (valueExprs.count == 0) { + if (error) *error = parseError(@"whereNotIn requires non-empty list"); + return nil; + } + // SDK expects (value, array) not (value, v1, v2, ...); wrap in "array" expr. + FIRExprBridge *valuesArrayExpr = FLTNewFunctionExprBridge(@"array", valueExprs); + return FLTNewFunctionExprBridge(@"not_equal_any", @[ fieldExpr, valuesArrayExpr ]); + } + if ([key isEqualToString:@"isNull"]) { + FIRExprBridge *right = [[FIRConstantBridge alloc] init:[NSNull null]]; + return FLTNewFunctionExprBridge(@"equal", @[ fieldExpr, right ]); + } + if ([key isEqualToString:@"isNotNull"]) { + FIRExprBridge *right = [[FIRConstantBridge alloc] init:[NSNull null]]; + return FLTNewFunctionExprBridge(@"not_equal", @[ fieldExpr, right ]); + } + } + + if (error) + *error = + parseError(@"filter requires at least one comparison (isEqualTo, isGreaterThan, etc.)"); + return nil; +} + +- (FIRExprBridge *)parseBooleanExpression:(NSDictionary *)map + error:(NSError **)error { + return [self parseExpression:map error:error]; +} + +@end + +@implementation FLTPipelineParser + +/// Returns the key (alias or field name) for an expression map in select/distinct stages. +/// Uses args.alias if present; otherwise for "field" expressions uses args.field. Returns nil if +/// no key can be determined (caller should error). ++ (NSString *)keyForExpressionMap:(NSDictionary *)em error:(NSError **)error { + NSString *alias = [em valueForKeyPath:@"args.alias"]; + if ([alias isKindOfClass:[NSString class]] && alias.length > 0) { + return alias; + } + if ([em[@"name"] isEqualToString:@"field"]) { + NSString *field = [em valueForKeyPath:@"args.field"]; + if ([field isKindOfClass:[NSString class]]) return field; + if (error) *error = parseError(@"field expression must have args.field"); + return nil; + } + if (error) *error = parseError(@"expression must have alias or be a field reference"); + return nil; +} + ++ (NSArray *) + parseStagesWithFirestore:(FIRFirestore *)firestore + stages:(NSArray *> *)stages + error:(NSError **)error { + FLTPipelineExpressionParser *exprParser = + [[FLTPipelineExpressionParser alloc] initWithFirestore:firestore]; + NSMutableArray *stageBridges = [NSMutableArray array]; + NSError *parseErr = nil; + + for (NSUInteger i = 0; i < stages.count; i++) { + NSDictionary *stageMap = stages[i]; + if (![stageMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"Stage must be a map"); + return nil; + } + NSString *stageName = stageMap[@"stage"]; + if (![stageName isKindOfClass:[NSString class]]) { + if (error) *error = parseError(@"Stage must have a 'stage' field"); + return nil; + } + id argsObj = stageMap[@"args"]; + NSDictionary *args = [argsObj isKindOfClass:[NSDictionary class]] ? argsObj : @{}; + NSArray *argsArray = [argsObj isKindOfClass:[NSArray class]] ? argsObj : nil; + + FIRStageBridge *stage = nil; + + if (i == 0) { + if ([stageName isEqualToString:@"collection"]) { + NSString *path = args[@"path"]; + if (!path) { + if (error) *error = parseError(@"collection requires 'path'"); + return nil; + } + FIRCollectionReference *ref = [firestore collectionWithPath:path]; + stage = [[FIRCollectionSourceStageBridge alloc] initWithRef:ref firestore:firestore]; + } else if ([stageName isEqualToString:@"collection_group"]) { + NSString *path = args[@"path"]; + if (!path) { + if (error) *error = parseError(@"collection_group requires 'path'"); + return nil; + } + stage = [[FIRCollectionGroupSourceStageBridge alloc] initWithCollectionId:path]; + } else if ([stageName isEqualToString:@"database"]) { + stage = [[FIRDatabaseSourceStageBridge alloc] init]; + } else if ([stageName isEqualToString:@"documents"]) { + NSArray *docMaps = argsArray; + if (!docMaps || docMaps.count == 0) { + if (error) *error = parseError(@"documents requires array of document refs"); + return nil; + } + NSMutableArray *refs = [NSMutableArray array]; + for (id docMap in docMaps) { + if (![docMap isKindOfClass:[NSDictionary class]]) continue; + NSString *path = ((NSDictionary *)docMap)[@"path"]; + if (path) [refs addObject:[firestore documentWithPath:path]]; + } + stage = [[FIRDocumentsSourceStageBridge alloc] initWithDocuments:refs firestore:firestore]; + } else { + if (error) + *error = parseError( + [NSString stringWithFormat:@"First stage must be collection, collection_group, " + @"documents, or database. Got: %@", + stageName]); + return nil; + } + } else { + if ([stageName isEqualToString:@"where"]) { + id exprMap = args[@"expression"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"where requires expression"); + return nil; + } + FIRExprBridge *expr = [exprParser parseBooleanExpression:exprMap error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + stage = [[FIRWhereStageBridge alloc] initWithExpr:expr]; + } else if ([stageName isEqualToString:@"limit"]) { + NSNumber *limit = args[@"limit"]; + if (![limit isKindOfClass:[NSNumber class]]) { + if (error) *error = parseError(@"limit requires numeric limit"); + return nil; + } + stage = [[FIRLimitStageBridge alloc] initWithLimit:limit.intValue]; + } else if ([stageName isEqualToString:@"offset"]) { + NSNumber *offset = args[@"offset"]; + if (![offset isKindOfClass:[NSNumber class]]) { + if (error) *error = parseError(@"offset requires numeric offset"); + return nil; + } + stage = [[FIROffsetStageBridge alloc] initWithOffset:offset.intValue]; + } else if ([stageName isEqualToString:@"sort"]) { + NSArray *orderingMaps = args[@"orderings"]; + if (![orderingMaps isKindOfClass:[NSArray class]] || orderingMaps.count == 0) { + if (error) *error = parseError(@"sort requires at least one ordering"); + return nil; + } + NSMutableArray *orderings = [NSMutableArray array]; + for (id om in orderingMaps) { + if (![om isKindOfClass:[NSDictionary class]]) continue; + id exprMap = ((NSDictionary *)om)[@"expression"]; + NSString *dir = ((NSDictionary *)om)[@"order_direction"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *expr = [exprParser parseExpression:exprMap error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + NSString *direction = [dir isEqualToString:@"asc"] ? @"ascending" : @"descending"; + FIROrderingBridge *ordering = [[FIROrderingBridge alloc] initWithExpr:expr + Direction:direction]; + [orderings addObject:ordering]; + } + if (orderings.count == 0) { + if (error) *error = parseError(@"sort requires at least one ordering"); + return nil; + } + stage = [[FIRSorStageBridge alloc] initWithOrderings:orderings]; + } else if ([stageName isEqualToString:@"select"]) { + NSArray *exprMaps = args[@"expressions"]; + if (![exprMaps isKindOfClass:[NSArray class]] || exprMaps.count == 0) { + if (error) *error = parseError(@"select requires at least one expression"); + return nil; + } + NSMutableDictionary *fields = [NSMutableDictionary dictionary]; + for (id em in exprMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *expr = [exprParser parseExpression:em error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + NSString *key = [self keyForExpressionMap:em error:error]; + if (!key) return nil; + fields[key] = expr; + } + stage = [[FIRSelectStageBridge alloc] initWithSelections:fields]; + } else if ([stageName isEqualToString:@"add_fields"]) { + NSArray *exprMaps = args[@"expressions"]; + if (![exprMaps isKindOfClass:[NSArray class]] || exprMaps.count == 0) { + if (error) *error = parseError(@"add_fields requires at least one expression"); + return nil; + } + NSMutableDictionary *fields = [NSMutableDictionary dictionary]; + for (id em in exprMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *expr = [exprParser parseExpression:em error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + NSString *alias = [em valueForKeyPath:@"args.alias"]; + if (!alias) { + if (error) *error = parseError(@"add_fields expressions must have alias"); + return nil; + } + fields[alias] = expr; + } + stage = [[FIRAddFieldsStageBridge alloc] initWithFields:fields]; + } else if ([stageName isEqualToString:@"remove_fields"]) { + NSArray *paths = args[@"field_paths"]; + if (![paths isKindOfClass:[NSArray class]] || paths.count == 0) { + if (error) *error = parseError(@"remove_fields requires field_paths"); + return nil; + } + stage = [[FIRRemoveFieldsStageBridge alloc] initWithFields:paths]; + } else if ([stageName isEqualToString:@"distinct"]) { + NSArray *exprMaps = args[@"expressions"]; + if (![exprMaps isKindOfClass:[NSArray class]] || exprMaps.count == 0) { + if (error) *error = parseError(@"distinct requires at least one expression"); + return nil; + } + NSMutableDictionary *fields = [NSMutableDictionary dictionary]; + for (id em in exprMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *expr = [exprParser parseExpression:em error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + NSString *key = [self keyForExpressionMap:em error:error]; + if (!key) return nil; + fields[key] = expr; + } + stage = [[FIRDistinctStageBridge alloc] initWithGroups:fields]; + } else if ([stageName isEqualToString:@"replace_with"]) { + id exprMap = args[@"expression"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"replace_with requires expression"); + return nil; + } + FIRExprBridge *expr = [exprParser parseExpression:exprMap error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + stage = [[FIRReplaceWithStageBridge alloc] initWithExpr:expr]; + } else if ([stageName isEqualToString:@"union"]) { + NSArray *nestedStages = args[@"pipeline"]; + if (![nestedStages isKindOfClass:[NSArray class]] || nestedStages.count == 0) { + if (error) *error = parseError(@"union requires non-empty pipeline"); + return nil; + } + id otherPipeline = [self buildPipelineWithFirestore:firestore + stages:nestedStages + error:&parseErr]; + if (!otherPipeline) { + if (error) *error = parseErr; + return nil; + } + stage = [[FIRUnionStageBridge alloc] initWithOther:otherPipeline]; + } else if ([stageName isEqualToString:@"sample"]) { + NSString *type = args[@"type"]; + id val = args[@"value"]; + if ([type isEqualToString:@"percentage"]) { + double v = [val isKindOfClass:[NSNumber class]] ? [(NSNumber *)val doubleValue] : 0; + stage = [[FIRSampleStageBridge alloc] initWithPercentage:v]; + } else { + int v = [val isKindOfClass:[NSNumber class]] ? [(NSNumber *)val intValue] : 0; + stage = [[FIRSampleStageBridge alloc] initWithCount:v]; + } + } else if ([stageName isEqualToString:@"aggregate"]) { + stage = [self parseAggregateStageWithArgs:args exprParser:exprParser error:error]; + } else if ([stageName isEqualToString:@"aggregate_with_options"]) { + stage = [self parseAggregateStageWithOptionsArgs:args exprParser:exprParser error:error]; + } else if ([stageName isEqualToString:@"unnest"]) { + id exprMap = args[@"expression"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"unnest requires expression"); + return nil; + } + FIRExprBridge *fieldExpr = nil; + FIRExprBridge *aliasExpr = nil; + NSDictionary *exprDict = (NSDictionary *)exprMap; + NSString *aliasStr = nil; + if ([exprDict[@"name"] isEqualToString:@"alias"]) { + NSDictionary *aliasArgs = exprDict[@"args"]; + if ([aliasArgs isKindOfClass:[NSDictionary class]] && aliasArgs[@"expression"]) { + fieldExpr = [exprParser parseExpression:aliasArgs[@"expression"] error:&parseErr]; + if (!fieldExpr) { + if (error) *error = parseErr; + return nil; + } + aliasStr = + [aliasArgs[@"alias"] isKindOfClass:[NSString class]] ? aliasArgs[@"alias"] : nil; + } + } + if (!fieldExpr) { + fieldExpr = [exprParser parseExpression:exprMap error:&parseErr]; + if (!fieldExpr) { + if (error) *error = parseErr; + return nil; + } + if (!aliasStr && [exprDict[@"name"] isEqualToString:@"field"]) { + NSDictionary *fieldArgs = exprDict[@"args"]; + aliasStr = + [fieldArgs[@"field"] isKindOfClass:[NSString class]] ? fieldArgs[@"field"] : @"_"; + } + } + if (!aliasStr) aliasStr = @"_"; + aliasExpr = [[FIRFieldBridge alloc] initWithName:aliasStr]; + NSString *indexFieldStr = + [args[@"index_field"] isKindOfClass:[NSString class]] ? args[@"index_field"] : nil; + FIRExprBridge *indexFieldExpr = + (indexFieldStr.length > 0) ? [[FIRFieldBridge alloc] initWithName:indexFieldStr] : nil; + stage = [[FIRUnnestStageBridge alloc] initWithField:fieldExpr + alias:aliasExpr + indexField:indexFieldExpr]; + } else if ([stageName isEqualToString:@"find_nearest"]) { + NSString *vectorFieldName = args[@"vector_field"]; + NSArray *vectorValueArray = args[@"vector_value"]; + NSString *distanceMeasure = args[@"distance_measure"]; + NSNumber *limit = [args[@"limit"] isKindOfClass:[NSNumber class]] ? args[@"limit"] : nil; + NSString *distanceField = [args[@"distance_field"] isKindOfClass:[NSString class]] + ? args[@"distance_field"] + : nil; + if (![vectorFieldName isKindOfClass:[NSString class]] || vectorFieldName.length == 0) { + if (error) *error = parseError(@"find_nearest requires 'vector_field'"); + return nil; + } + if (![vectorValueArray isKindOfClass:[NSArray class]] || vectorValueArray.count == 0) { + if (error) *error = parseError(@"find_nearest requires non-empty 'vector_value'"); + return nil; + } + if (![distanceMeasure isKindOfClass:[NSString class]] || distanceMeasure.length == 0) { + if (error) *error = parseError(@"find_nearest requires 'distance_measure'"); + return nil; + } + FIRFieldBridge *embeddingField = [[FIRFieldBridge alloc] initWithName:vectorFieldName]; + NSMutableArray *numbers = + [NSMutableArray arrayWithCapacity:vectorValueArray.count]; + for (id v in vectorValueArray) { + if ([v isKindOfClass:[NSNumber class]]) { + [numbers addObject:(NSNumber *)v]; + } + } + if (numbers.count != (NSUInteger)vectorValueArray.count) { + if (error) *error = parseError(@"find_nearest vector_value must be an array of numbers"); + return nil; + } + FIRVectorValue *queryVector = [[FIRVectorValue alloc] initWithArray:numbers]; + stage = [[FIRFindNearestStageBridge alloc] initWithField:embeddingField + vectorValue:queryVector + distanceMeasure:distanceMeasure + limit:limit + distanceField:distanceField]; + } else { + if (error) + *error = parseError([NSString stringWithFormat:@"Unknown pipeline stage: %@", stageName]); + return nil; + } + } + + if (stage) [stageBridges addObject:stage]; + } + + if (stageBridges.count == 0) { + if (error && !*error) *error = parseError(@"No valid stages"); + return nil; + } + + return stageBridges; +} + ++ (FIRAggregateFunctionBridge *)aggregateFunctionFromMap:(NSDictionary *)funcMap + exprParser:(FLTPipelineExpressionParser *)exprParser + error:(NSError **)error { + NSString *name = funcMap[@"name"]; + if (![name isKindOfClass:[NSString class]]) { + if (error) *error = parseError(@"Aggregate function must have a 'name'"); + return nil; + } + // Map Dart aggregate function names to iOS SDK names (count_all -> count with no args; minimum -> + // min; maximum -> max) + NSString *iosName = name; + if ([name isEqualToString:@"count_all"]) { + iosName = @"count"; + } else if ([name isEqualToString:@"minimum"]) { + iosName = @"min"; + } else if ([name isEqualToString:@"maximum"]) { + iosName = @"max"; + } + NSDictionary *argsDict = funcMap[@"args"]; + NSMutableArray *argsArray = [NSMutableArray array]; + if ([argsDict isKindOfClass:[NSDictionary class]]) { + id exprMap = argsDict[@"expression"]; + if ([exprMap isKindOfClass:[NSDictionary class]]) { + FIRExprBridge *expr = [exprParser parseExpression:exprMap error:error]; + if (!expr) return nil; + [argsArray addObject:expr]; + } + } + return [[FIRAggregateFunctionBridge alloc] initWithName:iosName Args:argsArray]; +} + ++ (FIRStageBridge *)parseAggregateStageWithArgs:(NSDictionary *)args + exprParser:(FLTPipelineExpressionParser *)exprParser + error:(NSError **)error { + NSArray *accumulatorMaps = args[@"aggregate_functions"]; + if (![accumulatorMaps isKindOfClass:[NSArray class]] || accumulatorMaps.count == 0) { + if (error) *error = parseError(@"aggregate requires aggregate_functions"); + return nil; + } + return [self parseAggregateStageWithAccumulatorMaps:accumulatorMaps + groupMaps:nil + exprParser:exprParser + error:error]; +} + ++ (FIRStageBridge *)parseAggregateStageWithOptionsArgs:(NSDictionary *)args + exprParser:(FLTPipelineExpressionParser *)exprParser + error:(NSError **)error { + NSDictionary *stageMap = args[@"aggregate_stage"]; + if (![stageMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"aggregate_with_options requires aggregate_stage"); + return nil; + } + NSArray *accumulatorMaps = stageMap[@"accumulators"]; + if (![accumulatorMaps isKindOfClass:[NSArray class]] || accumulatorMaps.count == 0) { + accumulatorMaps = stageMap[@"aggregate_functions"]; + } + if (![accumulatorMaps isKindOfClass:[NSArray class]] || accumulatorMaps.count == 0) { + if (error) *error = parseError(@"aggregate_stage requires accumulators or aggregate_functions"); + return nil; + } + NSArray *groupMaps = stageMap[@"groups"]; + return [self parseAggregateStageWithAccumulatorMaps:accumulatorMaps + groupMaps:groupMaps + exprParser:exprParser + error:error]; +} + ++ (FIRStageBridge *)parseAggregateStageWithAccumulatorMaps:(NSArray *)accumulatorMaps + groupMaps:(nullable NSArray *)groupMaps + exprParser:(FLTPipelineExpressionParser *)exprParser + error:(NSError **)error { + NSError *parseErr = nil; + NSMutableDictionary *accumulators = + [NSMutableDictionary dictionary]; + for (id accMap in accumulatorMaps) { + if (![accMap isKindOfClass:[NSDictionary class]]) continue; + NSString *alias = nil; + NSDictionary *funcMap = nil; + if ([accMap[@"name"] isEqualToString:@"alias"]) { + NSDictionary *accArgs = accMap[@"args"]; + if (![accArgs isKindOfClass:[NSDictionary class]]) continue; + alias = accArgs[@"alias"]; + funcMap = accArgs[@"aggregate_function"]; + } + if (![alias isKindOfClass:[NSString class]] || ![funcMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"Each accumulator must have alias and aggregate_function"); + return nil; + } + FIRAggregateFunctionBridge *func = [self aggregateFunctionFromMap:funcMap + exprParser:exprParser + error:&parseErr]; + if (!func) { + if (error) *error = parseErr; + return nil; + } + accumulators[alias] = func; + } + if (accumulators.count == 0) { + if (error) *error = parseError(@"aggregate requires at least one valid accumulator"); + return nil; + } + + NSMutableDictionary *groups = [NSMutableDictionary dictionary]; + if ([groupMaps isKindOfClass:[NSArray class]] && groupMaps.count > 0) { + for (NSUInteger g = 0; g < groupMaps.count; g++) { + id gm = groupMaps[g]; + if (![gm isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *expr = [exprParser parseExpression:gm error:&parseErr]; + if (!expr) continue; + NSError *groupKeyError = nil; + NSString *groupKey = [self keyForExpressionMap:gm error:&groupKeyError]; + if (![groupKey isKindOfClass:[NSString class]] || groupKey.length == 0) { + if (error) + *error = + groupKeyError + ?: parseError( + @"aggregate group expression must be a field reference or have an alias"); + return nil; + } + groups[groupKey] = expr; + } + } + + return [[FIRAggregateStageBridge alloc] initWithAccumulators:accumulators groups:groups]; +} + ++ (void)executePipelineWithFirestore:(FIRFirestore *)firestore + stages:(NSArray *> *)stages + options:(nullable NSDictionary *)options + completion:(void (^)(id _Nullable snapshot, + NSError *_Nullable error))completion { + if (!stages || stages.count == 0) { + completion(nil, parseError(@"Pipeline requires at least one stage")); + return; + } + + NSError *parseErr = nil; + NSArray *stageBridges = [self parseStagesWithFirestore:firestore + stages:stages + error:&parseErr]; + if (!stageBridges) { + completion(nil, parseErr); + return; + } + + FIRPipelineBridge *pipeline = [[FIRPipelineBridge alloc] initWithStages:stageBridges + db:firestore]; + [pipeline executeWithCompletion:^(id snapshot, NSError *execError) { + if (execError) { + completion(nil, execError); + return; + } + completion(snapshot, nil); + }]; +} + ++ (id)buildPipelineWithFirestore:(FIRFirestore *)firestore + stages:(NSArray *> *)stages + error:(NSError **)error { + NSArray *stageBridges = [self parseStagesWithFirestore:firestore + stages:stages + error:error]; + if (!stageBridges) return nil; + return [[FIRPipelineBridge alloc] initWithStages:stageBridges db:firestore]; +} + +@end + +#else + +@implementation FLTPipelineParser + ++ (void)executePipelineWithFirestore:(FIRFirestore *)firestore + stages:(NSArray *> *)stages + options:(nullable NSDictionary *)options + completion:(void (^)(id _Nullable snapshot, + NSError *_Nullable error))completion { + completion(nil, pipelineUnavailableError()); +} + +@end + +#endif diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m index 55ad066b2f16..891377333685 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m @@ -168,6 +168,18 @@ + (nullable PigeonQuerySnapshot *)nullableFromList:(NSArray *)list; - (NSArray *)toList; @end +@interface PigeonPipelineResult () ++ (PigeonPipelineResult *)fromList:(NSArray *)list; ++ (nullable PigeonPipelineResult *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface PigeonPipelineSnapshot () ++ (PigeonPipelineSnapshot *)fromList:(NSArray *)list; ++ (nullable PigeonPipelineSnapshot *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + @interface PigeonGetOptions () + (PigeonGetOptions *)fromList:(NSArray *)list; + (nullable PigeonGetOptions *)nullableFromList:(NSArray *)list; @@ -410,6 +422,66 @@ - (NSArray *)toList { } @end +@implementation PigeonPipelineResult ++ (instancetype)makeWithDocumentPath:(nullable NSString *)documentPath + createTime:(nullable NSNumber *)createTime + updateTime:(nullable NSNumber *)updateTime + data:(nullable NSDictionary *)data { + PigeonPipelineResult *pigeonResult = [[PigeonPipelineResult alloc] init]; + pigeonResult.documentPath = documentPath; + pigeonResult.createTime = createTime; + pigeonResult.updateTime = updateTime; + pigeonResult.data = data; + return pigeonResult; +} ++ (PigeonPipelineResult *)fromList:(NSArray *)list { + PigeonPipelineResult *pigeonResult = [[PigeonPipelineResult alloc] init]; + pigeonResult.documentPath = GetNullableObjectAtIndex(list, 0); + pigeonResult.createTime = GetNullableObjectAtIndex(list, 1); + pigeonResult.updateTime = GetNullableObjectAtIndex(list, 2); + pigeonResult.data = GetNullableObjectAtIndex(list, 3); + return pigeonResult; +} ++ (nullable PigeonPipelineResult *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonPipelineResult fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.documentPath ?: [NSNull null]), + (self.createTime ?: [NSNull null]), + (self.updateTime ?: [NSNull null]), + (self.data ?: [NSNull null]), + ]; +} +@end + +@implementation PigeonPipelineSnapshot ++ (instancetype)makeWithResults:(NSArray *)results + executionTime:(NSNumber *)executionTime { + PigeonPipelineSnapshot *pigeonResult = [[PigeonPipelineSnapshot alloc] init]; + pigeonResult.results = results; + pigeonResult.executionTime = executionTime; + return pigeonResult; +} ++ (PigeonPipelineSnapshot *)fromList:(NSArray *)list { + PigeonPipelineSnapshot *pigeonResult = [[PigeonPipelineSnapshot alloc] init]; + pigeonResult.results = GetNullableObjectAtIndex(list, 0); + NSAssert(pigeonResult.results != nil, @""); + pigeonResult.executionTime = GetNullableObjectAtIndex(list, 1); + NSAssert(pigeonResult.executionTime != nil, @""); + return pigeonResult; +} ++ (nullable PigeonPipelineSnapshot *)nullableFromList:(NSArray *)list { + return (list) ? [PigeonPipelineSnapshot fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + (self.results ?: [NSNull null]), + (self.executionTime ?: [NSNull null]), + ]; +} +@end + @implementation PigeonGetOptions + (instancetype)makeWithSource:(Source)source serverTimestampBehavior:(ServerTimestampBehavior)serverTimestampBehavior { @@ -673,12 +745,16 @@ - (nullable id)readValueOfType:(UInt8)type { case 136: return [PigeonGetOptions fromList:[self readValue]]; case 137: - return [PigeonQueryParameters fromList:[self readValue]]; + return [PigeonPipelineResult fromList:[self readValue]]; case 138: - return [PigeonQuerySnapshot fromList:[self readValue]]; + return [PigeonPipelineSnapshot fromList:[self readValue]]; case 139: - return [PigeonSnapshotMetadata fromList:[self readValue]]; + return [PigeonQueryParameters fromList:[self readValue]]; case 140: + return [PigeonQuerySnapshot fromList:[self readValue]]; + case 141: + return [PigeonSnapshotMetadata fromList:[self readValue]]; + case 142: return [PigeonTransactionCommand fromList:[self readValue]]; default: return [super readValueOfType:type]; @@ -717,18 +793,24 @@ - (void)writeValue:(id)value { } else if ([value isKindOfClass:[PigeonGetOptions class]]) { [self writeByte:136]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonQueryParameters class]]) { + } else if ([value isKindOfClass:[PigeonPipelineResult class]]) { [self writeByte:137]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonQuerySnapshot class]]) { + } else if ([value isKindOfClass:[PigeonPipelineSnapshot class]]) { [self writeByte:138]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonSnapshotMetadata class]]) { + } else if ([value isKindOfClass:[PigeonQueryParameters class]]) { [self writeByte:139]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonTransactionCommand class]]) { + } else if ([value isKindOfClass:[PigeonQuerySnapshot class]]) { [self writeByte:140]; [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonSnapshotMetadata class]]) { + [self writeByte:141]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[PigeonTransactionCommand class]]) { + [self writeByte:142]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } @@ -1378,4 +1460,32 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, [channel setMessageHandler:nil]; } } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.executePipeline" + binaryMessenger:binaryMessenger + codec:FirebaseFirestoreHostApiGetCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(executePipelineApp:stages:options:completion:)], + @"FirebaseFirestoreHostApi api (%@) doesn't respond to " + @"@selector(executePipelineApp:stages:options:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSArray *> *arg_stages = GetNullableObjectAtIndex(args, 1); + NSDictionary *arg_options = GetNullableObjectAtIndex(args, 2); + [api executePipelineApp:arg_app + stages:arg_stages + options:arg_options + completion:^(PigeonPipelineSnapshot *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } } diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTFirebaseFirestoreUtils.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTFirebaseFirestoreUtils.h index b6fed78e7795..e04b30b5483e 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTFirebaseFirestoreUtils.h +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTFirebaseFirestoreUtils.h @@ -18,6 +18,10 @@ #import #import "FLTFirebaseFirestoreExtension.h" +/// Error code used by the pipeline parser for parse/unsupported expression errors. +/// Handled in ErrorCodeAndMessageFromNSError to return code "parse-error" and the error message. +FOUNDATION_EXPORT const NSInteger FLTFirebaseFirestoreErrorCodePipelineParse; + typedef NS_ENUM(UInt8, FirestoreDataType) { FirestoreDataTypeDateTime = 180, FirestoreDataTypeGeoPoint = 181, diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h new file mode 100644 index 000000000000..97c77f0e2a88 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h @@ -0,0 +1,23 @@ +/* + * Copyright 2026, the Chromium project authors. Please see the AUTHORS file + * for details. All rights reserved. Use of this source code is governed by a + * BSD-style license that can be found in the LICENSE file. + */ + +#import + +@class FIRFirestore; + +NS_ASSUME_NONNULL_BEGIN + +@interface FLTPipelineParser : NSObject + ++ (void)executePipelineWithFirestore:(FIRFirestore *)firestore + stages:(NSArray *> *)stages + options:(nullable NSDictionary *)options + completion: + (void (^)(id _Nullable snapshot, NSError *_Nullable error))completion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h index 79c560b14e79..f3955862ae04 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h @@ -165,6 +165,8 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @class PigeonDocumentSnapshot; @class PigeonDocumentChange; @class PigeonQuerySnapshot; +@class PigeonPipelineResult; +@class PigeonPipelineSnapshot; @class PigeonGetOptions; @class PigeonDocumentOption; @class PigeonTransactionCommand; @@ -243,6 +245,27 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @property(nonatomic, strong) PigeonSnapshotMetadata *metadata; @end +@interface PigeonPipelineResult : NSObject ++ (instancetype)makeWithDocumentPath:(nullable NSString *)documentPath + createTime:(nullable NSNumber *)createTime + updateTime:(nullable NSNumber *)updateTime + data:(nullable NSDictionary *)data; +@property(nonatomic, copy, nullable) NSString *documentPath; +@property(nonatomic, strong, nullable) NSNumber *createTime; +@property(nonatomic, strong, nullable) NSNumber *updateTime; +/// All fields in the result (from PipelineResult.data() on Android). +@property(nonatomic, strong, nullable) NSDictionary *data; +@end + +@interface PigeonPipelineSnapshot : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithResults:(NSArray *)results + executionTime:(NSNumber *)executionTime; +@property(nonatomic, strong) NSArray *results; +@property(nonatomic, strong) NSNumber *executionTime; +@end + @interface PigeonGetOptions : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; @@ -416,6 +439,11 @@ NSObject *FirebaseFirestoreHostApiGetCodec(void); - (void)persistenceCacheIndexManagerRequestApp:(FirestorePigeonFirebaseApp *)app request:(PersistenceCacheIndexManagerRequest)request completion:(void (^)(FlutterError *_Nullable))completion; +- (void)executePipelineApp:(FirestorePigeonFirebaseApp *)app + stages:(NSArray *> *)stages + options:(nullable NSDictionary *)options + completion:(void (^)(PigeonPipelineSnapshot *_Nullable, + FlutterError *_Nullable))completion; @end extern void FirebaseFirestoreHostApiSetup(id binaryMessenger, diff --git a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart index 8ec159100581..69c3a95dce00 100755 --- a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart @@ -56,7 +56,17 @@ part 'src/filters.dart'; part 'src/firestore.dart'; part 'src/load_bundle_task.dart'; part 'src/load_bundle_task_snapshot.dart'; +part 'src/pipeline_snapshot.dart'; part 'src/persistent_cache_index_manager.dart'; +part 'src/pipeline.dart'; +part 'src/pipeline_aggregate.dart'; +part 'src/pipeline_distance.dart'; +part 'src/pipeline_execute_options.dart'; +part 'src/pipeline_expression.dart'; +part 'src/pipeline_ordering.dart'; +part 'src/pipeline_sample.dart'; +part 'src/pipeline_source.dart'; +part 'src/pipeline_stage.dart'; part 'src/query.dart'; part 'src/query_document_snapshot.dart'; part 'src/query_snapshot.dart'; diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart index 3e11563bb332..35b09f3f5d3b 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart @@ -340,6 +340,26 @@ class FirebaseFirestore extends FirebasePluginPlatform { return null; } + /// Returns a [PipelineSource] for creating and executing pipelines. + /// + /// Pipelines allow you to perform complex queries and transformations on + /// Firestore data using a fluent API. + /// + /// Example: + /// ```dart + /// final snapshot = await FirebaseFirestore.instance + /// .pipeline() + /// .collection('users') + /// .where(Field('age').greaterThan(Constant(18))) + /// .sort(Field('name').ascending(), Field('age').descending()) + /// .limit(10) + /// .execute(); + /// ``` + // ignore: use_to_and_as_if_applicable + PipelineSource pipeline() { + return PipelineSource._(this); + } + /// Configures indexing for local query execution. Any previous index configuration is overridden. /// /// The index entries themselves are created asynchronously. You can continue to use queries that diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart new file mode 100644 index 000000000000..6e54e253172c --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart @@ -0,0 +1,827 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// A pipeline for querying and transforming Firestore data. +/// +/// A [Pipeline] is composed of a sequence of stages. Each stage processes the +/// output from the previous one, and the final stage's output is the result of +/// the pipeline's execution. +/// +/// Start with [FirebaseFirestore.pipeline] and a source stage (e.g. +/// [PipelineSource.collection]), then add transformation and filtering stages. +/// Call [execute] to run the pipeline. +/// +/// Example: +/// ```dart +/// final snapshot = await FirebaseFirestore.instance +/// .pipeline() +/// .collection('users') +/// .where(Expression.field('active').equal(true)) +/// .limit(10) +/// .execute(); +/// for (final result in snapshot.result) { +/// print(result.data()); +/// } +/// ``` +/// +/// **Note on execution:** The stages are conceptual. The Firestore backend may +/// optimize execution (e.g., reordering or merging stages) as long as the final +/// result remains the same. +/// +/// **Important limitations:** Pipelines operate on a request/response basis only. +/// They do not utilize or update the local SDK cache, and they do not support +/// realtime snapshot listeners. +class Pipeline { + final FirebaseFirestore _firestore; + final PipelinePlatform _delegate; + + Pipeline._(this._firestore, this._delegate) { + PipelinePlatform.verify(_delegate); + } + + /// Exposes the [stages] on the pipeline delegate. + /// + /// This should only be used for testing to ensure that all + /// pipeline stages are correctly set on the underlying delegate + /// when being tested from a different package. + @visibleForTesting + List> get stages { + return _delegate.stages; + } + + /// Executes this pipeline and returns the results as a [PipelineSnapshot]. + /// + /// Example: + /// ```dart + /// final snapshot = await firestore + /// .pipeline() + /// .collection('products') + /// .limit(5) + /// .execute(); + /// print('Got ${snapshot.result.length} documents'); + /// ``` + Future execute({ExecuteOptions? options}) async { + final optionsMap = options != null + ? { + 'indexMode': options.indexMode.name, + } + : null; + final platformSnapshot = await _delegate.execute(options: optionsMap); + return _convertPlatformSnapshot(platformSnapshot); + } + + /// Converts platform snapshot to public snapshot + PipelineSnapshot _convertPlatformSnapshot( + PipelineSnapshotPlatform platformSnapshot, + ) { + final results = platformSnapshot.results.map((platformResult) { + return PipelineResult( + document: platformResult.document != null + ? _JsonDocumentReference(_firestore, platformResult.document!) + : null, + createTime: platformResult.createTime, + updateTime: platformResult.updateTime, + data: platformResult.data, + ); + }).toList(); + + return PipelineSnapshot._(results, platformSnapshot.executionTime); + } + + // Pipeline Actions + + /// Adds new fields to outputs from previous stages. + /// + /// This stage allows you to compute values on-the-fly based on existing data + /// from previous stages or constants. You can create new fields or overwrite + /// existing ones. The added fields are defined using [Selectable]s, which can + /// be a [Field] (from [Expression.field]) or an expression with an alias via + /// [Expression.as]. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').addFields( + /// Expression.field('rating').as('bookRating'), + /// Expression.field('title').stringReplaceAllLiteral('Item', 'Doc').as('title_replaced'), + /// Expression.field('score').abs().as('abs_score'), + /// ); + /// ``` + Pipeline addFields( + Selectable selectable1, [ + Selectable? selectable2, + Selectable? selectable3, + Selectable? selectable4, + Selectable? selectable5, + Selectable? selectable6, + Selectable? selectable7, + Selectable? selectable8, + Selectable? selectable9, + Selectable? selectable10, + Selectable? selectable11, + Selectable? selectable12, + Selectable? selectable13, + Selectable? selectable14, + Selectable? selectable15, + Selectable? selectable16, + Selectable? selectable17, + Selectable? selectable18, + Selectable? selectable19, + Selectable? selectable20, + Selectable? selectable21, + Selectable? selectable22, + Selectable? selectable23, + Selectable? selectable24, + Selectable? selectable25, + Selectable? selectable26, + Selectable? selectable27, + Selectable? selectable28, + Selectable? selectable29, + Selectable? selectable30, + ]) { + final selectables = [selectable1]; + if (selectable2 != null) selectables.add(selectable2); + if (selectable3 != null) selectables.add(selectable3); + if (selectable4 != null) selectables.add(selectable4); + if (selectable5 != null) selectables.add(selectable5); + if (selectable6 != null) selectables.add(selectable6); + if (selectable7 != null) selectables.add(selectable7); + if (selectable8 != null) selectables.add(selectable8); + if (selectable9 != null) selectables.add(selectable9); + if (selectable10 != null) selectables.add(selectable10); + if (selectable11 != null) selectables.add(selectable11); + if (selectable12 != null) selectables.add(selectable12); + if (selectable13 != null) selectables.add(selectable13); + if (selectable14 != null) selectables.add(selectable14); + if (selectable15 != null) selectables.add(selectable15); + if (selectable16 != null) selectables.add(selectable16); + if (selectable17 != null) selectables.add(selectable17); + if (selectable18 != null) selectables.add(selectable18); + if (selectable19 != null) selectables.add(selectable19); + if (selectable20 != null) selectables.add(selectable20); + if (selectable21 != null) selectables.add(selectable21); + if (selectable22 != null) selectables.add(selectable22); + if (selectable23 != null) selectables.add(selectable23); + if (selectable24 != null) selectables.add(selectable24); + if (selectable25 != null) selectables.add(selectable25); + if (selectable26 != null) selectables.add(selectable26); + if (selectable27 != null) selectables.add(selectable27); + if (selectable28 != null) selectables.add(selectable28); + if (selectable29 != null) selectables.add(selectable29); + if (selectable30 != null) selectables.add(selectable30); + final stage = _AddFieldsStage(selectables); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Performs aggregation operations on the documents from previous stages. + /// + /// This stage allows you to calculate aggregate values over a set of documents. + /// Define aggregations using [AliasedAggregateFunction]s, typically by calling + /// [PipelineAggregateFunction.as] on [PipelineAggregateFunction] instances + /// such as [Expression.field] with [Expression.sum], [Expression.average], + /// or [CountAll]. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').aggregate( + /// Expression.field('score').sum().as('total_score'), + /// Expression.field('score').average().as('avg_score'), + /// CountAll().as('count'), + /// ); + /// ``` + Pipeline aggregate( + AliasedAggregateFunction aggregateFunction1, [ + AliasedAggregateFunction? aggregateFunction2, + AliasedAggregateFunction? aggregateFunction3, + AliasedAggregateFunction? aggregateFunction4, + AliasedAggregateFunction? aggregateFunction5, + AliasedAggregateFunction? aggregateFunction6, + AliasedAggregateFunction? aggregateFunction7, + AliasedAggregateFunction? aggregateFunction8, + AliasedAggregateFunction? aggregateFunction9, + AliasedAggregateFunction? aggregateFunction10, + AliasedAggregateFunction? aggregateFunction11, + AliasedAggregateFunction? aggregateFunction12, + AliasedAggregateFunction? aggregateFunction13, + AliasedAggregateFunction? aggregateFunction14, + AliasedAggregateFunction? aggregateFunction15, + AliasedAggregateFunction? aggregateFunction16, + AliasedAggregateFunction? aggregateFunction17, + AliasedAggregateFunction? aggregateFunction18, + AliasedAggregateFunction? aggregateFunction19, + AliasedAggregateFunction? aggregateFunction20, + AliasedAggregateFunction? aggregateFunction21, + AliasedAggregateFunction? aggregateFunction22, + AliasedAggregateFunction? aggregateFunction23, + AliasedAggregateFunction? aggregateFunction24, + AliasedAggregateFunction? aggregateFunction25, + AliasedAggregateFunction? aggregateFunction26, + AliasedAggregateFunction? aggregateFunction27, + AliasedAggregateFunction? aggregateFunction28, + AliasedAggregateFunction? aggregateFunction29, + AliasedAggregateFunction? aggregateFunction30, + ]) { + final functions = [aggregateFunction1]; + if (aggregateFunction2 != null) functions.add(aggregateFunction2); + if (aggregateFunction3 != null) functions.add(aggregateFunction3); + if (aggregateFunction4 != null) functions.add(aggregateFunction4); + if (aggregateFunction5 != null) functions.add(aggregateFunction5); + if (aggregateFunction6 != null) functions.add(aggregateFunction6); + if (aggregateFunction7 != null) functions.add(aggregateFunction7); + if (aggregateFunction8 != null) functions.add(aggregateFunction8); + if (aggregateFunction9 != null) functions.add(aggregateFunction9); + if (aggregateFunction10 != null) functions.add(aggregateFunction10); + if (aggregateFunction11 != null) functions.add(aggregateFunction11); + if (aggregateFunction12 != null) functions.add(aggregateFunction12); + if (aggregateFunction13 != null) functions.add(aggregateFunction13); + if (aggregateFunction14 != null) functions.add(aggregateFunction14); + if (aggregateFunction15 != null) functions.add(aggregateFunction15); + if (aggregateFunction16 != null) functions.add(aggregateFunction16); + if (aggregateFunction17 != null) functions.add(aggregateFunction17); + if (aggregateFunction18 != null) functions.add(aggregateFunction18); + if (aggregateFunction19 != null) functions.add(aggregateFunction19); + if (aggregateFunction20 != null) functions.add(aggregateFunction20); + if (aggregateFunction21 != null) functions.add(aggregateFunction21); + if (aggregateFunction22 != null) functions.add(aggregateFunction22); + if (aggregateFunction23 != null) functions.add(aggregateFunction23); + if (aggregateFunction24 != null) functions.add(aggregateFunction24); + if (aggregateFunction25 != null) functions.add(aggregateFunction25); + if (aggregateFunction26 != null) functions.add(aggregateFunction26); + if (aggregateFunction27 != null) functions.add(aggregateFunction27); + if (aggregateFunction28 != null) functions.add(aggregateFunction28); + if (aggregateFunction29 != null) functions.add(aggregateFunction29); + if (aggregateFunction30 != null) functions.add(aggregateFunction30); + + final stage = _AggregateStage(functions); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Performs optionally grouped aggregation operations on the documents from previous stages. + /// + /// This method allows you to calculate aggregate values over a set of documents, optionally + /// grouped by one or more fields or expressions. You can specify: + /// + /// - **Grouping Fields or Expressions**: One or more fields or functions to group the documents by. + /// For each distinct combination of values in these fields, a separate group is created. + /// If no grouping fields are provided, a single group containing all documents is used. + /// + /// - **Aggregate Functions**: One or more accumulation operations to perform within each group. + /// These are defined using [AliasedAggregateFunction] expressions, which are typically created + /// by calling `.as('alias')` on [PipelineAggregateFunction] instances. Each aggregation calculates + /// a value (e.g., sum, average, count) based on the documents within its group. + /// + /// Example: + /// ```dart + /// pipeline.aggregateWithOptions( + /// AggregateStageOptions( + /// accumulators: [ + /// Expression.field('likes').sum().as('total_likes'), + /// Expression.field('likes').average().as('avg_likes'), + /// ], + /// groups: [Expression.field('category')], + /// ), + /// ); + /// ``` + /// + /// With options: + /// ```dart + /// pipeline.aggregateWithOptions( + /// AggregateStageOptions( + /// accumulators: [ + /// Expression.field('likes').sum().as('total_likes'), + /// ], + /// ), + /// options: AggregateOptions(), + /// ); + /// ``` + Pipeline aggregateWithOptions( + AggregateStageOptions aggregateStage, { + AggregateOptions? options, + }) { + final stage = _AggregateStageWithOptions( + aggregateStage, + options ?? AggregateOptions(), + ); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Returns a set of distinct values from the inputs to this stage. + /// + /// This stage runs through the results from previous stages to include only + /// results with unique combinations of the given [Selectable] expressions + /// (e.g. [Expression.field], or expressions with [Expression.as]). + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').distinct( + /// Expression.field('category').as('category'), + /// ); + /// ``` + Pipeline distinct( + Selectable expression1, [ + Selectable? expression2, + Selectable? expression3, + Selectable? expression4, + Selectable? expression5, + Selectable? expression6, + Selectable? expression7, + Selectable? expression8, + Selectable? expression9, + Selectable? expression10, + Selectable? expression11, + Selectable? expression12, + Selectable? expression13, + Selectable? expression14, + Selectable? expression15, + Selectable? expression16, + Selectable? expression17, + Selectable? expression18, + Selectable? expression19, + Selectable? expression20, + Selectable? expression21, + Selectable? expression22, + Selectable? expression23, + Selectable? expression24, + Selectable? expression25, + Selectable? expression26, + Selectable? expression27, + Selectable? expression28, + Selectable? expression29, + Selectable? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + final stage = _DistinctStage(expressions); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Performs a vector similarity search. + /// + /// Orders the result set by most similar to least similar and returns + /// documents in that order. Requires a vector index on [vectorField]. + /// [vectorValue] is the query embedding; [distanceMeasure] specifies how to + /// compare vectors (e.g. [DistanceMeasure.cosine]). Use [limit] to return + /// only the first N documents. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').findNearest( + /// Field('embedding'), + /// [0.1, 0.2, 0.3], + /// DistanceMeasure.cosine, + /// limit: 10, + /// ); + /// ``` + Pipeline findNearest( + Field vectorField, + List vectorValue, + DistanceMeasure distanceMeasure, { + int? limit, + }) { + final stage = _FindNearestStage( + vectorField, + vectorValue, + distanceMeasure, + limit: limit, + ); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Limits the maximum number of documents returned by previous stages to + /// [limit]. + /// + /// Useful for pagination (with [offset]) or to cap data retrieval and + /// improve performance. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books') + /// .sort(Expression.field('rating').descending()) + /// .limit(10); + /// ``` + Pipeline limit(int limit) { + final stage = _LimitStage(limit); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Skips the first [offset] documents from the results of previous stages. + /// + /// Useful for implementing pagination; typically used with [limit] to control + /// the size of each page. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books') + /// .sort(Expression.field('published').descending()) + /// .offset(20) + /// .limit(20); + /// ``` + Pipeline offset(int offset) { + final stage = _OffsetStage(offset); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Removes fields from outputs of previous stages. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books') + /// .removeFields('rating', 'cost'); + /// ``` + Pipeline removeFields( + String fieldPath1, [ + String? fieldPath2, + String? fieldPath3, + String? fieldPath4, + String? fieldPath5, + String? fieldPath6, + String? fieldPath7, + String? fieldPath8, + String? fieldPath9, + String? fieldPath10, + String? fieldPath11, + String? fieldPath12, + String? fieldPath13, + String? fieldPath14, + String? fieldPath15, + String? fieldPath16, + String? fieldPath17, + String? fieldPath18, + String? fieldPath19, + String? fieldPath20, + String? fieldPath21, + String? fieldPath22, + String? fieldPath23, + String? fieldPath24, + String? fieldPath25, + String? fieldPath26, + String? fieldPath27, + String? fieldPath28, + String? fieldPath29, + String? fieldPath30, + ]) { + final fieldPaths = [fieldPath1]; + if (fieldPath2 != null) fieldPaths.add(fieldPath2); + if (fieldPath3 != null) fieldPaths.add(fieldPath3); + if (fieldPath4 != null) fieldPaths.add(fieldPath4); + if (fieldPath5 != null) fieldPaths.add(fieldPath5); + if (fieldPath6 != null) fieldPaths.add(fieldPath6); + if (fieldPath7 != null) fieldPaths.add(fieldPath7); + if (fieldPath8 != null) fieldPaths.add(fieldPath8); + if (fieldPath9 != null) fieldPaths.add(fieldPath9); + if (fieldPath10 != null) fieldPaths.add(fieldPath10); + if (fieldPath11 != null) fieldPaths.add(fieldPath11); + if (fieldPath12 != null) fieldPaths.add(fieldPath12); + if (fieldPath13 != null) fieldPaths.add(fieldPath13); + if (fieldPath14 != null) fieldPaths.add(fieldPath14); + if (fieldPath15 != null) fieldPaths.add(fieldPath15); + if (fieldPath16 != null) fieldPaths.add(fieldPath16); + if (fieldPath17 != null) fieldPaths.add(fieldPath17); + if (fieldPath18 != null) fieldPaths.add(fieldPath18); + if (fieldPath19 != null) fieldPaths.add(fieldPath19); + if (fieldPath20 != null) fieldPaths.add(fieldPath20); + if (fieldPath21 != null) fieldPaths.add(fieldPath21); + if (fieldPath22 != null) fieldPaths.add(fieldPath22); + if (fieldPath23 != null) fieldPaths.add(fieldPath23); + if (fieldPath24 != null) fieldPaths.add(fieldPath24); + if (fieldPath25 != null) fieldPaths.add(fieldPath25); + if (fieldPath26 != null) fieldPaths.add(fieldPath26); + if (fieldPath27 != null) fieldPaths.add(fieldPath27); + if (fieldPath28 != null) fieldPaths.add(fieldPath28); + if (fieldPath29 != null) fieldPaths.add(fieldPath29); + if (fieldPath30 != null) fieldPaths.add(fieldPath30); + + final stage = _RemoveFieldsStage(fieldPaths); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Fully overwrites each document with the value of the given expression. + /// + /// This stage allows you to emit a nested map or array as the document: each + /// document from the previous stage is replaced by the evaluated [expression] + /// (e.g. [Expression.field] referencing a nested map or array). + /// + /// Example: + /// ```dart + /// // Emit the 'parents' map as the document. + /// firestore.pipeline().collection('people') + /// .replaceWith(Expression.field('parents')); + /// ``` + Pipeline replaceWith(Expression expression) { + final stage = _ReplaceWithStage(expression); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Performs a pseudo-random sampling of the input documents. + /// + /// Use [PipelineSample.withSize] for a fixed number of documents, or + /// [PipelineSample.withPercentage] for a fraction of the result set. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books') + /// .sample(PipelineSample.withSize(10)); + /// firestore.pipeline().collection('books') + /// .sample(PipelineSample.withPercentage(0.5)); + /// ``` + Pipeline sample(PipelineSample sample) { + final stage = _SampleStage(sample); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Selects or creates a set of fields from the outputs of previous stages. + /// + /// Only the selected fields (with their aliases) appear in the output. Use + /// [Expression.field] with [Expression.as] for expressions. Use [addFields] + /// if you only want to add or overwrite fields while keeping the rest. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').select( + /// Expression.field('name').as('name'), + /// Expression.field('address').toUpperCase().as('upperAddress'), + /// ); + /// ``` + Pipeline select( + Selectable expression1, [ + Selectable? expression2, + Selectable? expression3, + Selectable? expression4, + Selectable? expression5, + Selectable? expression6, + Selectable? expression7, + Selectable? expression8, + Selectable? expression9, + Selectable? expression10, + Selectable? expression11, + Selectable? expression12, + Selectable? expression13, + Selectable? expression14, + Selectable? expression15, + Selectable? expression16, + Selectable? expression17, + Selectable? expression18, + Selectable? expression19, + Selectable? expression20, + Selectable? expression21, + Selectable? expression22, + Selectable? expression23, + Selectable? expression24, + Selectable? expression25, + Selectable? expression26, + Selectable? expression27, + Selectable? expression28, + Selectable? expression29, + Selectable? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + + final stage = _SelectStage(expressions); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Sorts the documents from previous stages based on one or more orderings. + /// + /// Orderings are applied in sequence (primary sort by the first, then by the + /// second, etc.). If documents have the same value for a field used for + /// sorting, the next ordering is used. Use [Expression.field] with + /// [Expression.descending] and [Expression.ascending]. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').sort( + /// Expression.field('rating').descending(), + /// Expression.field('title').ascending(), + /// ); + /// ``` + Pipeline sort( + Ordering order, [ + Ordering? order2, + Ordering? order3, + Ordering? order4, + Ordering? order5, + Ordering? order6, + Ordering? order7, + Ordering? order8, + Ordering? order9, + Ordering? order10, + Ordering? order11, + Ordering? order12, + Ordering? order13, + Ordering? order14, + Ordering? order15, + Ordering? order16, + Ordering? order17, + Ordering? order18, + Ordering? order19, + Ordering? order20, + Ordering? order21, + Ordering? order22, + Ordering? order23, + Ordering? order24, + Ordering? order25, + Ordering? order26, + Ordering? order27, + Ordering? order28, + Ordering? order29, + Ordering? order30, + ]) { + final orderings = [order]; + if (order2 != null) orderings.add(order2); + if (order3 != null) orderings.add(order3); + if (order4 != null) orderings.add(order4); + if (order5 != null) orderings.add(order5); + if (order6 != null) orderings.add(order6); + if (order7 != null) orderings.add(order7); + if (order8 != null) orderings.add(order8); + if (order9 != null) orderings.add(order9); + if (order10 != null) orderings.add(order10); + if (order11 != null) orderings.add(order11); + if (order12 != null) orderings.add(order12); + if (order13 != null) orderings.add(order13); + if (order14 != null) orderings.add(order14); + if (order15 != null) orderings.add(order15); + if (order16 != null) orderings.add(order16); + if (order17 != null) orderings.add(order17); + if (order18 != null) orderings.add(order18); + if (order19 != null) orderings.add(order19); + if (order20 != null) orderings.add(order20); + if (order21 != null) orderings.add(order21); + if (order22 != null) orderings.add(order22); + if (order23 != null) orderings.add(order23); + if (order24 != null) orderings.add(order24); + if (order25 != null) orderings.add(order25); + if (order26 != null) orderings.add(order26); + if (order27 != null) orderings.add(order27); + if (order28 != null) orderings.add(order28); + if (order29 != null) orderings.add(order29); + if (order30 != null) orderings.add(order30); + + final stage = _SortStage(orderings); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Takes a specified array from the input documents and outputs a document + /// for each element, with the element stored in a field named by the alias. + /// + /// For each document from the previous stage, this stage emits zero or more + /// documents (one per array element). Use [Expression.field].as() to specify + /// the array and the output field name. Optionally use [indexField] to add + /// the array index to each emitted document. + /// + /// Example: + /// ```dart + /// // Input: { "title": "Guide", "tags": ["comedy", "space"] } + /// // Output: one doc per tag with field "tag". + /// firestore.pipeline().collection('books') + /// .unnest(Expression.field('tags').as('tag')); + /// ``` + Pipeline unnest(Selectable expression, [String? indexField]) { + final stage = _UnnestStage(expression, indexField); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Performs a union of all documents from this pipeline and [pipeline], + /// including duplicates. + /// + /// Documents from the previous stage and from [pipeline] are combined. The + /// order of documents emitted from this stage is undefined. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').union( + /// firestore.pipeline().collection('magazines'), + /// ); + /// ``` + Pipeline union(Pipeline pipeline) { + final stage = _UnionStage(pipeline); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + + /// Filters the documents from previous stages to only include those matching + /// the specified [BooleanExpression]. + /// + /// This stage applies conditions to the data, similar to a WHERE clause. You + /// can use [Expression.field] with [Expression.equal], [Expression.greaterThan], + /// [Expression.lessThan], etc., and combine conditions with [Expression.and] + /// and [Expression.or]. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('books').where( + /// Expression.and( + /// Expression.field('rating').greaterThan(4.0), + /// Expression.field('genre').equal('Science Fiction'), + /// ), + /// ); + /// ``` + Pipeline where(BooleanExpression expression) { + final stage = _WhereStage(expression); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart new file mode 100644 index 000000000000..7598f42a947a --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_aggregate.dart @@ -0,0 +1,294 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base class for aggregate functions used in pipelines +abstract class PipelineAggregateFunction implements PipelineSerializable { + /// Assigns an alias to this aggregate function + AliasedAggregateFunction as(String alias) { + return AliasedAggregateFunction( + alias: alias, + aggregateFunction: this, + ); + } + + String get name; + + @override + Map toMap() { + return { + 'name': name, + }; + } +} + +/// Represents an aggregate function with an alias +class AliasedAggregateFunction implements PipelineSerializable { + final String _alias; + final PipelineAggregateFunction aggregateFunction; + + AliasedAggregateFunction({ + required String alias, + required this.aggregateFunction, + }) : _alias = alias; + + String get alias => _alias; + + @override + Map toMap() { + return { + 'name': 'alias', + 'args': { + 'alias': _alias, + 'aggregate_function': aggregateFunction.toMap(), + }, + }; + } +} + +/// Counts all documents in the pipeline result +class CountAll extends PipelineAggregateFunction { + CountAll(); + + @override + String get name => 'count_all'; +} + +/// Counts non-null values of the specified expression +class Count extends PipelineAggregateFunction { + final Expression expression; + + Count(this.expression); + + @override + String get name => 'count'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Sums numeric values of the specified expression +class Sum extends PipelineAggregateFunction { + final Expression expression; + + Sum(this.expression); + + @override + String get name => 'sum'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Calculates average of numeric values of the specified expression +class Average extends PipelineAggregateFunction { + final Expression expression; + + Average(this.expression); + + @override + String get name => 'average'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Counts distinct values of the specified expression +class CountDistinct extends PipelineAggregateFunction { + final Expression expression; + + CountDistinct(this.expression); + + @override + String get name => 'count_distinct'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Finds minimum value of the specified expression +class Minimum extends PipelineAggregateFunction { + final Expression expression; + + Minimum(this.expression); + + @override + String get name => 'minimum'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Finds maximum value of the specified expression +class Maximum extends PipelineAggregateFunction { + final Expression expression; + + Maximum(this.expression); + + @override + String get name => 'maximum'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Aggregate that picks the first value of [expression] across pipeline inputs. +/// +/// Use with [Pipeline.aggregate] or [AggregateStageOptions]. Corresponds to the +/// Firestore pipeline `first` accumulator. +class First extends PipelineAggregateFunction { + final Expression expression; + + First(this.expression); + + @override + String get name => 'first'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Aggregate that picks the last value of [expression] across pipeline inputs. +/// +/// Use with [Pipeline.aggregate] or [AggregateStageOptions]. Corresponds to the +/// Firestore pipeline `last` accumulator. +class Last extends PipelineAggregateFunction { + final Expression expression; + + Last(this.expression); + + @override + String get name => 'last'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Aggregate that collects all values of [expression] into an array. +/// +/// Order of elements is not guaranteed. Absent values become `null` in the result. +/// Corresponds to the Firestore pipeline `array_agg` accumulator. +class ArrayAgg extends PipelineAggregateFunction { + final Expression expression; + + ArrayAgg(this.expression); + + @override + String get name => 'array_agg'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Aggregate that collects distinct values of [expression] into an array. +/// +/// Order of elements is not guaranteed. Corresponds to the Firestore pipeline +/// `array_agg_distinct` accumulator. +class ArrayAggDistinct extends PipelineAggregateFunction { + final Expression expression; + + ArrayAggDistinct(this.expression); + + @override + String get name => 'array_agg_distinct'; + + @override + Map toMap() { + final map = super.toMap(); + map['args'] = { + 'expression': expression.toMap(), + }; + return map; + } +} + +/// Represents an aggregate stage with functions and optional grouping +class AggregateStageOptions implements PipelineSerializable { + final List accumulators; + final List? groups; + + AggregateStageOptions({ + required this.accumulators, + this.groups, + }); + + @override + Map toMap() { + final map = { + 'accumulators': accumulators.map((acc) => acc.toMap()).toList(), + }; + if (groups != null && groups!.isNotEmpty) { + map['groups'] = groups!.map((group) => group.toMap()).toList(); + } + return map; + } +} + +/// Options for aggregate operations +class AggregateOptions implements PipelineSerializable { + // Add any aggregate-specific options here as needed + // For now, this is a placeholder for future options + + AggregateOptions(); + + @override + Map toMap() { + return {}; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart new file mode 100644 index 000000000000..8f01b16de52e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_distance.dart @@ -0,0 +1,17 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Distance measure algorithms for vector similarity search +enum DistanceMeasure { + /// Cosine similarity + cosine, + + /// Euclidean distance + euclidean, + + /// Dot product + dotProduct, +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart new file mode 100644 index 000000000000..ee8b8e2eb42d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_execute_options.dart @@ -0,0 +1,20 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Index mode for pipeline execution +enum IndexMode { + /// Use recommended index mode + recommended, +} + +/// Options for executing a pipeline +class ExecuteOptions { + final IndexMode indexMode; + + const ExecuteOptions({ + this.indexMode = IndexMode.recommended, + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart new file mode 100644 index 000000000000..4f8f85e49c1e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart @@ -0,0 +1,3589 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base interface for pipeline serialization +mixin PipelineSerializable { + Map toMap(); +} + +/// Helper function to convert values to Expression (wraps in Constant if needed) +Expression _toExpression(Object? value) { + if (value == null) return Constant(null); + if (value is Expression) return value; + if (value is List) return Expression.array(value.cast()); + if (value is Map) { + return Expression.map(value.cast()); + } + return Constant(value); +} + +/// Valid unit strings for timestamp add/subtract/truncate expressions. +const Set _timestampUnits = { + 'microsecond', + 'millisecond', + 'second', + 'minute', + 'hour', + 'day', +}; + +void _validateTimestampUnit(String unit) { + if (!_timestampUnits.contains(unit)) { + throw ArgumentError( + "Timestamp unit must be one of: 'microsecond', 'millisecond', 'second', " + "'minute', 'hour', 'day'. Got: '$unit'", + ); + } +} + +/// Value types for [Expression.isType] and [Expression.isTypeStatic]. +enum Type { + /// `null` + nullValue('null'), + + /// `array` + array('array'), + + /// `boolean` + boolean('boolean'), + + /// `bytes` + bytes('bytes'), + + /// `timestamp` + timestamp('timestamp'), + + /// `geo_point` + geoPoint('geo_point'), + + /// `number` + number('number'), + + /// `int32` + int32('int32'), + + /// `int64` + int64('int64'), + + /// `float64` + float64('float64'), + + /// `decimal128` + decimal128('decimal128'), + + /// `map` + map('map'), + + /// `reference` + reference('reference'), + + /// `string` + string('string'), + + /// `vector` + vector('vector'), + + /// `max_key` + maxKey('max_key'), + + /// `min_key` + minKey('min_key'), + + /// `object_id` + objectId('object_id'), + + /// `regex` + regex('regex'), + + /// `request_timestamp` + requestTimestamp('request_timestamp'); + + const Type(this.typeValue); + + /// String passed to Firestore for `is_type` (same literals as the JS SDK). + final String typeValue; +} + +/// Base class for all pipeline expressions +abstract class Expression implements PipelineSerializable { + /// Creates an aliased expression + AliasedExpression as(String alias) { + return AliasedExpression( + alias: alias, + expression: this, + ); + } + + /// Creates a descending ordering for this expression + Ordering descending() { + return Ordering(this, OrderDirection.desc); + } + + /// Creates an ascending ordering for this expression + Ordering ascending() { + return Ordering(this, OrderDirection.asc); + } + + // ============================================================================ + // CONDITIONAL / LOGIC OPERATIONS + // ============================================================================ + + /// Returns an alternative expression if this expression is absent + Expression ifAbsent(Expression elseExpr) { + return _IfAbsentExpression(this, elseExpr); + } + + /// Returns an alternative value if this expression is absent + Expression ifAbsentValue(Object? elseValue) { + return _IfAbsentExpression(this, _toExpression(elseValue)); + } + + /// Returns an alternative expression if this expression errors + Expression ifError(Expression catchExpr) { + return _IfErrorExpression(this, catchExpr); + } + + /// Returns an alternative value if this expression errors + Expression ifErrorValue(Object? catchValue) { + return _IfErrorExpression(this, _toExpression(catchValue)); + } + + /// Checks if this expression is absent (null/undefined) + // ignore: use_to_and_as_if_applicable + BooleanExpression isAbsent() { + return _IsAbsentExpression(this); + } + + /// Checks if this expression produces an error + // ignore: use_to_and_as_if_applicable + BooleanExpression isError() { + return _IsErrorExpression(this); + } + + /// Checks if this field expression exists in the document + // ignore: use_to_and_as_if_applicable + BooleanExpression exists() { + return _ExistsExpression(this); + } + + // ============================================================================ + // TYPE CONVERSION + // ============================================================================ + + /// Casts this expression to a boolean expression + BooleanExpression asBoolean() { + return _AsBooleanExpression(this); + } + + // ============================================================================ + // BITWISE OPERATIONS + // ============================================================================ + + /// Performs bitwise AND with another expression + Expression bitAnd(Expression bitsOther) { + return _BitAndExpression(this, bitsOther); + } + + /// Performs bitwise AND with byte array + Expression bitAndBytes(List bitsOther) { + return _BitAndExpression(this, Constant(bitsOther)); + } + + /// Performs bitwise OR with another expression + Expression bitOr(Expression bitsOther) { + return _BitOrExpression(this, bitsOther); + } + + /// Performs bitwise OR with byte array + Expression bitOrBytes(List bitsOther) { + return _BitOrExpression(this, Constant(bitsOther)); + } + + /// Performs bitwise XOR with another expression + Expression bitXor(Expression bitsOther) { + return _BitXorExpression(this, bitsOther); + } + + /// Performs bitwise XOR with byte array + Expression bitXorBytes(List bitsOther) { + return _BitXorExpression(this, Constant(bitsOther)); + } + + /// Performs bitwise NOT on this expression + // ignore: use_to_and_as_if_applicable + Expression bitNot() { + return _BitNotExpression(this); + } + + /// Shifts bits left by an expression amount + Expression bitLeftShift(Expression numberExpr) { + return _BitLeftShiftExpression(this, numberExpr); + } + + /// Shifts bits left by a literal amount + Expression bitLeftShiftLiteral(int number) { + return _BitLeftShiftExpression(this, Constant(number)); + } + + /// Shifts bits right by an expression amount + Expression bitRightShift(Expression numberExpr) { + return _BitRightShiftExpression(this, numberExpr); + } + + /// Shifts bits right by a literal amount + Expression bitRightShiftLiteral(int number) { + return _BitRightShiftExpression(this, Constant(number)); + } + + // ============================================================================ + // DOCUMENT / PATH OPERATIONS + // ============================================================================ + + /// Returns the document ID from this path expression + // ignore: use_to_and_as_if_applicable + Expression documentId() { + return _DocumentIdExpression(this); + } + + /// Returns the collection ID from this path expression + // ignore: use_to_and_as_if_applicable + Expression collectionId() { + return _CollectionIdExpression(this); + } + + // ============================================================================ + // MAP OPERATIONS + // ============================================================================ + + /// Gets a value from this map expression by key expression + Expression mapGet(Expression key) { + return _MapGetExpression(this, key); + } + + /// Gets a value from this map expression by literal key + Expression mapGetLiteral(String key) { + return _MapGetExpression(this, Constant(key)); + } + + /// Returns a map expression with keys set to the given values (shallow update). + /// + /// [key] and [value] are the first pair. [moreKeyValues] must be alternating + /// keys and values. Setting a value to `null` keeps the key with a null value; + /// use map APIs that remove keys if you need deletion semantics. + Expression mapSet( + Object? key, + Object? value, [ + List? moreKeyValues, + ]) { + final pairs = [_toExpression(key), _toExpression(value)]; + if (moreKeyValues != null) { + for (final o in moreKeyValues) { + pairs.add(_toExpression(o)); + } + } + return _MapSetExpression(this, pairs); + } + + /// Returns an array of `{k, v}` map entries for this map expression. + // ignore: use_to_and_as_if_applicable + Expression mapEntries() { + return _MapEntriesExpression(this); + } + + // ============================================================================ + // ALIASING + // ============================================================================ + + /// Assigns an alias to this expression for use in output + Selectable alias(String alias) { + return AliasedExpression(alias: alias, expression: this); + } + + // ============================================================================ + // ARITHMETIC OPERATIONS + // ============================================================================ + + /// Adds this expression to another expression + Expression add(Expression other) { + return _AddExpression(this, other); + } + + /// Adds a number to this expression + Expression addNumber(num other) { + return _AddExpression(this, Constant(other)); + } + + /// Subtracts another expression from this expression + Expression subtract(Expression other) { + return _SubtractExpression(this, other); + } + + /// Subtracts a number from this expression + Expression subtractNumber(num other) { + return _SubtractExpression(this, Constant(other)); + } + + /// Multiplies this expression by another expression + Expression multiply(Expression other) { + return _MultiplyExpression(this, other); + } + + /// Multiplies this expression by a number + Expression multiplyNumber(num other) { + return _MultiplyExpression(this, Constant(other)); + } + + /// Divides this expression by another expression + Expression divide(Expression other) { + return _DivideExpression(this, other); + } + + /// Divides this expression by a number + Expression divideNumber(num other) { + return _DivideExpression(this, Constant(other)); + } + + /// Returns the remainder of dividing this expression by another + Expression modulo(Expression other) { + return _ModuloExpression(this, other); + } + + /// Returns the remainder of dividing this expression by a number + Expression moduloNumber(num other) { + return _ModuloExpression(this, Constant(other)); + } + + /// Returns the absolute value of this expression + // ignore: use_to_and_as_if_applicable + Expression abs() { + return _AbsExpression(this); + } + + /// Truncates this numeric expression toward zero. + /// + /// If [decimals] is omitted, truncates to an integer. If provided, truncates to + /// that many fractional digits (Firestore pipeline `trunc`). + Expression trunc([Expression? decimals]) { + return _TruncExpression(this, decimals); + } + + // ============================================================================ + // COMPARISON OPERATIONS (return BooleanExpression) + // ============================================================================ + + /// Checks if this expression equals another expression + BooleanExpression equal(Expression other) { + return _EqualExpression(this, other); + } + + /// Checks if this expression equals a value + BooleanExpression equalValue(Object? value) { + return _EqualExpression(this, _toExpression(value)); + } + + /// Checks if this expression does not equal another expression + BooleanExpression notEqual(Expression other) { + return _NotEqualExpression(this, other); + } + + /// Checks if this expression does not equal a value + BooleanExpression notEqualValue(Object? value) { + return _NotEqualExpression(this, _toExpression(value)); + } + + /// Checks if this expression is greater than another expression + BooleanExpression greaterThan(Expression other) { + return _GreaterThanExpression(this, other); + } + + /// Checks if this expression is greater than a value + BooleanExpression greaterThanValue(Object? value) { + return _GreaterThanExpression(this, _toExpression(value)); + } + + /// Checks if this expression is greater than or equal to another expression + BooleanExpression greaterThanOrEqual(Expression other) { + return _GreaterThanOrEqualExpression(this, other); + } + + /// Checks if this expression is greater than or equal to a value + BooleanExpression greaterThanOrEqualValue(Object? value) { + return _GreaterThanOrEqualExpression(this, _toExpression(value)); + } + + /// Checks if this expression is less than another expression + BooleanExpression lessThan(Expression other) { + return _LessThanExpression(this, other); + } + + /// Checks if this expression is less than a value + BooleanExpression lessThanValue(Object? value) { + return _LessThanExpression(this, _toExpression(value)); + } + + /// Checks if this expression is less than or equal to another expression + BooleanExpression lessThanOrEqual(Expression other) { + return _LessThanOrEqualExpression(this, other); + } + + /// Checks if this expression is less than or equal to a value + BooleanExpression lessThanOrEqualValue(Object? value) { + return _LessThanOrEqualExpression(this, _toExpression(value)); + } + + // ============================================================================ + // STRING OPERATIONS + // ============================================================================ + + /// Returns the length of this string expression + // ignore: use_to_and_as_if_applicable + Expression length() { + return _LengthExpression(this); + } + + /// Concatenates this expression with other expressions/values + Expression concat(List others) { + final expressions = [this]; + for (final other in others) { + expressions.add(_toExpression(other)); + } + return _ConcatExpression(expressions); + } + + /// Converts this string expression to lowercase + Expression toLowerCase() { + return _ToLowerCaseExpression(this); + } + + /// Converts this string expression to uppercase + Expression toUpperCase() { + return _ToUpperCaseExpression(this); + } + + /// Extracts a substring from this string expression + Expression substring(Expression start, Expression end) { + return _SubstringExpression(this, start, end); + } + + /// Extracts a substring using literal indices + Expression substringLiteral(int start, int end) { + return _SubstringExpression(this, Constant(start), Constant(end)); + } + + /// Replaces all occurrences of a pattern in this string (stringReplaceAll) + Expression stringReplaceAll(Expression find, Expression replacement) { + return _StringReplaceAllExpression(this, find, replacement); + } + + /// Replaces all occurrences of a string literal + Expression stringReplaceAllLiteral(String find, String replacement) { + return _StringReplaceAllExpression( + this, + Constant(find), + Constant(replacement), + ); + } + + /// Splits this string expression by a delimiter + Expression split(Expression delimiter) { + return _SplitExpression(this, delimiter); + } + + /// Splits this string by a literal delimiter + Expression splitLiteral(String delimiter) { + return _SplitExpression(this, Constant(delimiter)); + } + + /// Joins array elements with a delimiter + Expression join(Expression delimiter) { + return _JoinExpression(this, delimiter); + } + + /// Joins array elements with a literal delimiter + Expression joinLiteral(String delimiter) { + return _JoinExpression(this, Constant(delimiter)); + } + + /// Trims whitespace from this string expression + // ignore: use_to_and_as_if_applicable + Expression trim() { + return _TrimExpression(this); + } + + /// Returns the first regex match of [pattern] in this string expression. + Expression regexFind(Object? pattern) { + return _RegexFindExpression(this, _toExpression(pattern)); + } + + /// Returns all regex matches of [pattern] in this string expression. + Expression regexFindAll(Object? pattern) { + return _RegexFindAllExpression(this, _toExpression(pattern)); + } + + /// Replaces the first occurrence of [find] with [replacement]. + Expression stringReplaceOne(Expression find, Expression replacement) { + return _StringReplaceOneExpression(this, find, replacement); + } + + /// Replaces the first occurrence of string literals [find] with [replacement]. + Expression stringReplaceOneLiteral(String find, String replacement) { + return _StringReplaceOneExpression( + this, + Constant(find), + Constant(replacement), + ); + } + + /// Returns the index of [search] in this string, or an absent/error value if not found. + Expression stringIndexOf(Object? search) { + return _StringIndexOfExpression(this, _toExpression(search)); + } + + /// Repeats this string [repetitions] times ([repetitions] may be an [Expression] or number). + Expression stringRepeat(Object? repetitions) { + return _StringRepeatExpression(this, _toExpression(repetitions)); + } + + /// Trims leading whitespace, or the characters in [valueToTrim] when given. + Expression ltrim([Object? valueToTrim]) { + return valueToTrim == null + ? _LtrimExpression(this, null) + : _LtrimExpression(this, _toExpression(valueToTrim)); + } + + /// Trims trailing whitespace, or the characters in [valueToTrim] when given. + Expression rtrim([Object? valueToTrim]) { + return valueToTrim == null + ? _RtrimExpression(this, null) + : _RtrimExpression(this, _toExpression(valueToTrim)); + } + + /// Returns the Firestore value type of this expression as a string (e.g. + /// `int64`, `timestamp`). Possible values align with [Type]. + // ignore: use_to_and_as_if_applicable + Expression type() { + return _TypeExpression(this); + } + + /// Whether this expression evaluates to the given backend [Type]. + // ignore: use_to_and_as_if_applicable + BooleanExpression isType(Type valueType) { + return _IsTypeExpression(this, valueType); + } + + // ============================================================================ + // ARRAY OPERATIONS + // ============================================================================ + + /// Concatenates this array with another array expression + Expression arrayConcat(Object? secondArray) { + return _ArrayConcatExpression(this, _toExpression(secondArray)); + } + + /// Concatenates this array with multiple arrays/values + Expression arrayConcatMultiple(List otherArrays) { + final expressions = [this]; + for (final other in otherArrays) { + expressions.add(_toExpression(other)); + } + return _ArrayConcatMultipleExpression(expressions); + } + + /// Checks if this array contains an element expression + BooleanExpression arrayContainsElement(Expression element) { + return _ArrayContainsExpression(this, element); + } + + /// Checks if this array contains a value + BooleanExpression arrayContainsValue(Object? element) { + return _ArrayContainsExpression(this, _toExpression(element)); + } + + /// Checks if this array contains any of the given values or expressions + BooleanExpression arrayContainsAny(List values) { + return _ArrayContainsAnyExpression( + this, + values.map(_toExpression).toList(), + ); + } + + /// Checks if this array contains all of the given values or expressions + BooleanExpression arrayContainsAll(List values) { + return _ArrayContainsAllValuesExpression( + this, + values.map(_toExpression).toList(), + ); + } + + /// Checks if this array contains all elements of [arrayExpression] + /// (e.g. [arrayExpression] can be [Expression.array] of fields/literals). + BooleanExpression arrayContainsAllFrom(Expression arrayExpression) { + return _ArrayContainsAllExpression(this, arrayExpression); + } + + /// Returns the length of this array expression + // ignore: use_to_and_as_if_applicable + Expression arrayLength() { + return _ArrayLengthExpression(this); + } + + /// Reverses this array expression + // ignore: use_to_and_as_if_applicable + Expression arrayReverse() { + return _ArrayReverseExpression(this); + } + + /// Returns the sum of numeric elements in this array + // ignore: use_to_and_as_if_applicable + Expression arraySum() { + return _ArraySumExpression(this); + } + + /// First element of this array expression. + // ignore: use_to_and_as_if_applicable + Expression arrayFirst() { + return _ArrayFirstExpression(this); + } + + /// First [n] elements of this array expression. + Expression arrayFirstN(Object? n) { + return _ArrayFirstNExpression(this, _toExpression(n)); + } + + /// Last element of this array expression. + // ignore: use_to_and_as_if_applicable + Expression arrayLast() { + return _ArrayLastExpression(this); + } + + /// Last [n] elements of this array expression. + Expression arrayLastN(Object? n) { + return _ArrayLastNExpression(this, _toExpression(n)); + } + + /// Maximum element of this array (per-document), not the aggregate [maximum] accumulator. + // ignore: use_to_and_as_if_applicable + Expression arrayMaximum() { + return _ArrayMaximumExpression(this); + } + + /// The [n] largest elements of this array. + Expression arrayMaximumN(Object? n) { + return _ArrayMaximumNExpression(this, _toExpression(n)); + } + + /// Minimum element of this array (per-document), not the aggregate [minimum] accumulator. + // ignore: use_to_and_as_if_applicable + Expression arrayMinimum() { + return _ArrayMinimumExpression(this); + } + + /// The [n] smallest elements of this array. + Expression arrayMinimumN(Object? n) { + return _ArrayMinimumNExpression(this, _toExpression(n)); + } + + /// Index of the first occurrence of [element] in this array. + Expression arrayIndexOf(Object? element) { + return _ArrayIndexOfExpression(this, _toExpression(element), isLast: false); + } + + /// Index of the last occurrence of [element] in this array. + Expression arrayLastIndexOf(Object? element) { + return _ArrayIndexOfExpression(this, _toExpression(element), isLast: true); + } + + /// Array of all indices where [element] occurs in this array. + Expression arrayIndexOfAll(Object? element) { + return _ArrayIndexOfAllExpression(this, _toExpression(element)); + } + + // ============================================================================ + // AGGREGATE FUNCTIONS + // ============================================================================ + + /// Creates a sum aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction sum() { + return Sum(this); + } + + /// Creates an average aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction average() { + return Average(this); + } + + /// Creates a count aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction count() { + return Count(this); + } + + /// Creates a count distinct aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction countDistinct() { + return CountDistinct(this); + } + + /// Creates a minimum aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction minimum() { + return Minimum(this); + } + + /// Creates a maximum aggregation function from this expression + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction maximum() { + return Maximum(this); + } + + /// Aggregate: first value across inputs. See [First]. + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction first() { + return First(this); + } + + /// Aggregate: last value across inputs. See [Last]. + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction last() { + return Last(this); + } + + /// Aggregate: collect values into an array. See [ArrayAgg]. + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction arrayAgg() { + return ArrayAgg(this); + } + + /// Aggregate: collect distinct values into an array. See [ArrayAggDistinct]. + // ignore: use_to_and_as_if_applicable + PipelineAggregateFunction arrayAggDistinct() { + return ArrayAggDistinct(this); + } + + String get name; + + @override + Map toMap() { + return { + 'name': name, + }; + } + + // ============================================================================ + // STATIC FACTORY METHODS + // ============================================================================ + + /// Creates a constant expression from a string value + static Expression constantString(String value) => Constant(value); + + /// Creates a constant expression from a number value + static Expression constantNumber(num value) => Constant(value); + + /// Creates a constant expression from a boolean value + static Expression constantBoolean(bool value) => Constant(value); + + /// Creates a constant expression from a DateTime value + static Expression constantDateTime(DateTime value) => Constant(value); + + /// Creates a constant expression from a Timestamp value + static Expression constantTimestamp(Timestamp value) => Constant(value); + + /// Creates a constant expression from a GeoPoint value + static Expression constantGeoPoint(GeoPoint value) => Constant(value); + + /// Creates a constant expression from a Blob value + static Expression constantBlob(Blob value) => Constant(value); + + /// Creates a constant expression from a DocumentReference value + static Expression constantDocumentReference(DocumentReference value) => + Constant(value); + + /// Creates a constant expression from a byte array value + static Expression constantBytes(List value) => Constant(value); + + /// Creates a constant expression from a VectorValue value + static Expression constantVector(VectorValue value) => Constant(value); + + /// Creates a constant expression from any value (convenience) + /// + /// Valid types: String, num, bool, DateTime, Timestamp, GeoPoint, List (byte[]), + /// Blob, DocumentReference, VectorValue + static Expression constant(Object? value) { + if (value == null) { + return Constant(null); + } + // Validate that the value is one of the accepted types + if (value is! String && + value is! num && + value is! bool && + value is! DateTime && + value is! Timestamp && + value is! GeoPoint && + value is! List && + value is! Blob && + value is! DocumentReference && + value is! VectorValue) { + throw ArgumentError( + 'Constant value must be one of: String, num, bool, DateTime, Timestamp, ' + 'GeoPoint, List (byte[]), Blob, DocumentReference, or VectorValue. ' + 'Got: ${value.runtimeType}', + ); + } + return Constant(value); + } + + /// Creates a field reference expression from a field path string + static Field field(String fieldPath) => Field(fieldPath); + + /// Creates a field reference expression from a FieldPath object + static Field fieldPath(FieldPath fieldPath) => Field(fieldPath.toString()); + + /// Creates a null value expression + static Expression nullValue() => _NullExpression(); + + /// Creates a conditional (ternary) expression + static Expression conditional( + BooleanExpression condition, + Expression thenExpr, + Expression elseExpr, + ) { + return _ConditionalExpression(condition, thenExpr, elseExpr); + } + + /// Creates a conditional expression with literal values + static Expression conditionalValues( + BooleanExpression condition, + Object? thenValue, + Object? elseValue, + ) { + return _ConditionalExpression( + condition, + _toExpression(thenValue), + _toExpression(elseValue), + ); + } + + /// Creates an array expression from elements + static Expression array(List elements) { + return _ArrayExpression( + elements.map(_toExpression).toList(), + ); + } + + /// Creates a map expression from key-value pairs + static Expression map(Map data) { + return _MapExpression(data.map((k, v) => MapEntry(k, _toExpression(v)))); + } + + /// Returns the current timestamp + static Expression currentTimestamp() { + return _CurrentTimestampExpression(); + } + + /// Adds time to a timestamp expression. + /// + /// [unit] must be one of: `microsecond`, `millisecond`, `second`, `minute`, + /// `hour`, `day`. + static Expression timestampAdd( + Expression timestamp, + String unit, + Expression amount, + ) { + _validateTimestampUnit(unit); + return _TimestampAddExpression(timestamp, unit, amount); + } + + /// Adds time to a timestamp with a literal amount. + /// + /// [unit] must be one of: `microsecond`, `millisecond`, `second`, `minute`, + /// `hour`, `day`. + static Expression timestampAddLiteral( + Expression timestamp, + String unit, + int amount, + ) { + _validateTimestampUnit(unit); + return _TimestampAddExpression(timestamp, unit, Constant(amount)); + } + + /// Subtracts time from a timestamp expression. + /// + /// [unit] must be one of: `microsecond`, `millisecond`, `second`, `minute`, + /// `hour`, `day`. + static Expression timestampSubtract( + Expression timestamp, + String unit, + Expression amount, + ) { + _validateTimestampUnit(unit); + return _TimestampSubtractExpression(timestamp, unit, amount); + } + + /// Subtracts time from a timestamp with a literal amount. + /// + /// [unit] must be one of: `microsecond`, `millisecond`, `second`, `minute`, + /// `hour`, `day`. + static Expression timestampSubtractLiteral( + Expression timestamp, + String unit, + int amount, + ) { + _validateTimestampUnit(unit); + return _TimestampSubtractExpression(timestamp, unit, Constant(amount)); + } + + /// Truncates a timestamp to a specific unit. + /// + /// [unit] must be one of: `microsecond`, `millisecond`, `second`, `minute`, + /// `hour`, `day`. + static Expression timestampTruncate( + Expression timestamp, + String unit, + ) { + _validateTimestampUnit(unit); + return _TimestampTruncateExpression(timestamp, unit); + } + + /// Creates a document ID expression from a DocumentReference + static Expression documentIdFromRef(DocumentReference docRef) { + return _DocumentIdFromRefExpression(docRef); + } + + /// Checks if a value is in a list (IN operator) + static BooleanExpression equalAny( + Expression value, + List values, + ) { + return _EqualAnyExpression(value, values.map(_toExpression).toList()); + } + + /// Checks if a value is not in a list (NOT IN operator) + static BooleanExpression notEqualAny( + Expression value, + List values, + ) { + return _NotEqualAnyExpression(value, values.map(_toExpression).toList()); + } + + /// Checks if a field exists in the document + static BooleanExpression existsField(String fieldName) { + return _ExistsExpression(Field(fieldName)); + } + + /// Returns an expression if another is absent + static Expression ifAbsentStatic( + Expression ifExpr, + Expression elseExpr, + ) { + return _IfAbsentExpression(ifExpr, elseExpr); + } + + /// Returns a value if an expression is absent + static Expression ifAbsentValueStatic( + Expression ifExpr, + Object? elseValue, + ) { + return _IfAbsentExpression(ifExpr, _toExpression(elseValue)); + } + + /// Checks if an expression is absent + static BooleanExpression isAbsentStatic(Expression value) { + return _IsAbsentExpression(value); + } + + /// Checks if a field is absent + static BooleanExpression isAbsentField(String fieldName) { + return _IsAbsentExpression(Field(fieldName)); + } + + /// Returns an expression if another errors + static Expression ifErrorStatic( + Expression tryExpr, + Expression catchExpr, + ) { + return _IfErrorExpression(tryExpr, catchExpr); + } + + /// Checks if an expression produces an error + static BooleanExpression isErrorStatic(Expression expr) { + return _IsErrorExpression(expr); + } + + /// Negates a boolean expression + static BooleanExpression not(BooleanExpression expression) { + return _NotExpression(expression); + } + + /// Combines boolean expressions with a logical XOR + static BooleanExpression xor( + BooleanExpression expression1, [ + BooleanExpression? expression2, + BooleanExpression? expression3, + BooleanExpression? expression4, + BooleanExpression? expression5, + BooleanExpression? expression6, + BooleanExpression? expression7, + BooleanExpression? expression8, + BooleanExpression? expression9, + BooleanExpression? expression10, + BooleanExpression? expression11, + BooleanExpression? expression12, + BooleanExpression? expression13, + BooleanExpression? expression14, + BooleanExpression? expression15, + BooleanExpression? expression16, + BooleanExpression? expression17, + BooleanExpression? expression18, + BooleanExpression? expression19, + BooleanExpression? expression20, + BooleanExpression? expression21, + BooleanExpression? expression22, + BooleanExpression? expression23, + BooleanExpression? expression24, + BooleanExpression? expression25, + BooleanExpression? expression26, + BooleanExpression? expression27, + BooleanExpression? expression28, + BooleanExpression? expression29, + BooleanExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + return _XorExpression(expressions); + } + + /// Combines boolean expressions with a logical AND + static BooleanExpression and( + BooleanExpression expression1, [ + BooleanExpression? expression2, + BooleanExpression? expression3, + BooleanExpression? expression4, + BooleanExpression? expression5, + BooleanExpression? expression6, + BooleanExpression? expression7, + BooleanExpression? expression8, + BooleanExpression? expression9, + BooleanExpression? expression10, + BooleanExpression? expression11, + BooleanExpression? expression12, + BooleanExpression? expression13, + BooleanExpression? expression14, + BooleanExpression? expression15, + BooleanExpression? expression16, + BooleanExpression? expression17, + BooleanExpression? expression18, + BooleanExpression? expression19, + BooleanExpression? expression20, + BooleanExpression? expression21, + BooleanExpression? expression22, + BooleanExpression? expression23, + BooleanExpression? expression24, + BooleanExpression? expression25, + BooleanExpression? expression26, + BooleanExpression? expression27, + BooleanExpression? expression28, + BooleanExpression? expression29, + BooleanExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + return _AndExpression(expressions); + } + + /// Combines boolean expressions with a logical OR + static BooleanExpression or( + BooleanExpression expression1, [ + BooleanExpression? expression2, + BooleanExpression? expression3, + BooleanExpression? expression4, + BooleanExpression? expression5, + BooleanExpression? expression6, + BooleanExpression? expression7, + BooleanExpression? expression8, + BooleanExpression? expression9, + BooleanExpression? expression10, + BooleanExpression? expression11, + BooleanExpression? expression12, + BooleanExpression? expression13, + BooleanExpression? expression14, + BooleanExpression? expression15, + BooleanExpression? expression16, + BooleanExpression? expression17, + BooleanExpression? expression18, + BooleanExpression? expression19, + BooleanExpression? expression20, + BooleanExpression? expression21, + BooleanExpression? expression22, + BooleanExpression? expression23, + BooleanExpression? expression24, + BooleanExpression? expression25, + BooleanExpression? expression26, + BooleanExpression? expression27, + BooleanExpression? expression28, + BooleanExpression? expression29, + BooleanExpression? expression30, + ]) { + final expressions = [expression1]; + if (expression2 != null) expressions.add(expression2); + if (expression3 != null) expressions.add(expression3); + if (expression4 != null) expressions.add(expression4); + if (expression5 != null) expressions.add(expression5); + if (expression6 != null) expressions.add(expression6); + if (expression7 != null) expressions.add(expression7); + if (expression8 != null) expressions.add(expression8); + if (expression9 != null) expressions.add(expression9); + if (expression10 != null) expressions.add(expression10); + if (expression11 != null) expressions.add(expression11); + if (expression12 != null) expressions.add(expression12); + if (expression13 != null) expressions.add(expression13); + if (expression14 != null) expressions.add(expression14); + if (expression15 != null) expressions.add(expression15); + if (expression16 != null) expressions.add(expression16); + if (expression17 != null) expressions.add(expression17); + if (expression18 != null) expressions.add(expression18); + if (expression19 != null) expressions.add(expression19); + if (expression20 != null) expressions.add(expression20); + if (expression21 != null) expressions.add(expression21); + if (expression22 != null) expressions.add(expression22); + if (expression23 != null) expressions.add(expression23); + if (expression24 != null) expressions.add(expression24); + if (expression25 != null) expressions.add(expression25); + if (expression26 != null) expressions.add(expression26); + if (expression27 != null) expressions.add(expression27); + if (expression28 != null) expressions.add(expression28); + if (expression29 != null) expressions.add(expression29); + if (expression30 != null) expressions.add(expression30); + return _OrExpression(expressions); + } + + /// Joins array elements with a delimiter + static Expression joinStatic( + Expression arrayExpression, + Expression delimiterExpression, + ) { + return _JoinExpression(arrayExpression, delimiterExpression); + } + + /// Joins array elements with a literal delimiter + static Expression joinStaticLiteral( + Expression arrayExpression, + String delimiter, + ) { + return _JoinExpression(arrayExpression, Constant(delimiter)); + } + + /// Joins a field's array with a delimiter + static Expression joinField( + String arrayFieldName, + String delimiter, + ) { + return _JoinExpression(Field(arrayFieldName), Constant(delimiter)); + } + + /// Concatenates arrays + static Expression arrayConcatStatic( + Expression firstArray, + Expression secondArray, + List? otherArrays, + ) { + final expressions = [firstArray, secondArray]; + if (otherArrays != null) { + for (final other in otherArrays) { + expressions.add(_toExpression(other)); + } + } + return _ArrayConcatMultipleExpression(expressions); + } + + /// Returns the length of an expression + static Expression lengthStatic(Expression expr) { + return _LengthExpression(expr); + } + + /// Returns the length of a field + static Expression lengthField(String fieldName) { + return _LengthExpression(Field(fieldName)); + } + + /// Returns the absolute value of an expression + static Expression absStatic(Expression numericExpr) { + return _AbsExpression(numericExpr); + } + + /// Returns the absolute value of a field + static Expression absField(String numericField) { + return _AbsExpression(Field(numericField)); + } + + /// Adds two expressions + static Expression addStatic( + Expression first, + Expression second, + ) { + return _AddExpression(first, second); + } + + /// Adds an expression and a number + static Expression addStaticNumber( + Expression first, + num second, + ) { + return _AddExpression(first, Constant(second)); + } + + /// Adds a field and an expression + static Expression addField( + String numericFieldName, + Expression second, + ) { + return _AddExpression(Field(numericFieldName), second); + } + + /// Adds a field and a number + static Expression addFieldNumber( + String numericFieldName, + num second, + ) { + return _AddExpression(Field(numericFieldName), Constant(second)); + } + + /// Subtracts two expressions + static Expression subtractStatic( + Expression minuend, + Expression subtrahend, + ) { + return _SubtractExpression(minuend, subtrahend); + } + + /// Multiplies two expressions + static Expression multiplyStatic( + Expression multiplicand, + Expression multiplier, + ) { + return _MultiplyExpression(multiplicand, multiplier); + } + + /// Divides two expressions + static Expression divideStatic( + Expression dividend, + Expression divisor, + ) { + return _DivideExpression(dividend, divisor); + } + + /// Returns modulo of two expressions + static Expression moduloStatic( + Expression dividend, + Expression divisor, + ) { + return _ModuloExpression(dividend, divisor); + } + + /// Compares two expressions for equality + static BooleanExpression equalStatic( + Expression left, + Expression right, + ) { + return _EqualExpression(left, right); + } + + /// Compares expression with value for equality + static BooleanExpression equalStaticValue( + Expression left, + Object? right, + ) { + return _EqualExpression(left, _toExpression(right)); + } + + /// Compares field with value for equality + static BooleanExpression equalField( + String fieldName, + Object? value, + ) { + return _EqualExpression(Field(fieldName), _toExpression(value)); + } + + /// Compares two expressions for inequality + static BooleanExpression notEqualStatic( + Expression left, + Expression right, + ) { + return _NotEqualExpression(left, right); + } + + /// Compares expression with value for inequality + static BooleanExpression notEqualStaticValue( + Expression left, + Object? right, + ) { + return _NotEqualExpression(left, _toExpression(right)); + } + + /// Greater than comparison + static BooleanExpression greaterThanStatic( + Expression left, + Expression right, + ) { + return _GreaterThanExpression(left, right); + } + + /// Greater than comparison with value + static BooleanExpression greaterThanStaticValue( + Expression left, + Object? right, + ) { + return _GreaterThanExpression(left, _toExpression(right)); + } + + /// Greater than comparison for field + static BooleanExpression greaterThanField( + String fieldName, + Object? value, + ) { + return _GreaterThanExpression(Field(fieldName), _toExpression(value)); + } + + /// Greater than or equal comparison + static BooleanExpression greaterThanOrEqualStatic( + Expression left, + Expression right, + ) { + return _GreaterThanOrEqualExpression(left, right); + } + + /// Less than comparison + static BooleanExpression lessThanStatic( + Expression left, + Expression right, + ) { + return _LessThanExpression(left, right); + } + + /// Less than comparison with value + static BooleanExpression lessThanStaticValue( + Expression left, + Object? right, + ) { + return _LessThanExpression(left, _toExpression(right)); + } + + /// Less than comparison for field + static BooleanExpression lessThanField( + String fieldName, + Object? value, + ) { + return _LessThanExpression(Field(fieldName), _toExpression(value)); + } + + /// Less than or equal comparison + static BooleanExpression lessThanOrEqualStatic( + Expression left, + Expression right, + ) { + return _LessThanOrEqualExpression(left, right); + } + + /// Concatenates expressions + static Expression concatStatic( + Expression first, + Expression second, + List? others, + ) { + final expressions = [first, second]; + if (others != null) { + for (final other in others) { + expressions.add(_toExpression(other)); + } + } + return _ConcatExpression(expressions); + } + + /// Converts to lowercase + static Expression toLowerCaseStatic(Expression stringExpr) { + return _ToLowerCaseExpression(stringExpr); + } + + /// Converts field to lowercase + static Expression toLowerCaseField(String stringField) { + return _ToLowerCaseExpression(Field(stringField)); + } + + /// Converts to uppercase + static Expression toUpperCaseStatic(Expression stringExpr) { + return _ToUpperCaseExpression(stringExpr); + } + + /// Converts field to uppercase + static Expression toUpperCaseField(String stringField) { + return _ToUpperCaseExpression(Field(stringField)); + } + + /// Trims whitespace + static Expression trimStatic(Expression stringExpr) { + return _TrimExpression(stringExpr); + } + + /// Trims field whitespace + static Expression trimField(String stringField) { + return _TrimExpression(Field(stringField)); + } + + /// Extracts substring + static Expression substringStatic( + Expression stringExpr, + Expression start, + Expression end, + ) { + return _SubstringExpression(stringExpr, start, end); + } + + /// Replaces all occurrences in string (stringReplaceAll) + static Expression stringReplaceAllStatic( + Expression stringExpr, + Expression find, + Expression replacement, + ) { + return _StringReplaceAllExpression(stringExpr, find, replacement); + } + + /// Splits string + static Expression splitStatic( + Expression stringExpr, + Expression delimiter, + ) { + return _SplitExpression(stringExpr, delimiter); + } + + /// Reverses array + static Expression arrayReverseStatic(Expression array) { + return _ArrayReverseExpression(array); + } + + /// Reverses field array + static Expression arrayReverseField(String arrayFieldName) { + return _ArrayReverseExpression(Field(arrayFieldName)); + } + + /// Sums array + static Expression arraySumStatic(Expression array) { + return _ArraySumExpression(array); + } + + /// Sums field array + static Expression arraySumField(String arrayFieldName) { + return _ArraySumExpression(Field(arrayFieldName)); + } + + /// Gets array length + static Expression arrayLengthStatic(Expression array) { + return _ArrayLengthExpression(array); + } + + /// Gets field array length + static Expression arrayLengthField(String arrayFieldName) { + return _ArrayLengthExpression(Field(arrayFieldName)); + } + + /// Checks array contains + static BooleanExpression arrayContainsElementStatic( + Expression array, + Expression element, + ) { + return _ArrayContainsExpression(array, element); + } + + /// Checks field array contains + static BooleanExpression arrayContainsField( + String arrayFieldName, + Object? element, + ) { + return _ArrayContainsExpression( + Field(arrayFieldName), + _toExpression(element), + ); + } + + /// Checks if [array] contains all elements of [arrayExpression] + /// (e.g. [arrayExpression] can be [Expression.array] of fields/literals). + static BooleanExpression arrayContainsAllWithExpression( + Expression array, + Expression arrayExpression, + ) { + return _ArrayContainsAllExpression(array, arrayExpression); + } + + /// Checks if [array] contains all of the specified [values]. + static BooleanExpression arrayContainsAllValues( + Expression array, + List values, + ) { + return _ArrayContainsAllValuesExpression( + array, + values.map(_toExpression).toList(), + ); + } + + /// Checks if the array field [arrayFieldName] contains all elements of + /// [arrayExpression]. + static BooleanExpression arrayContainsAllField( + String arrayFieldName, + Expression arrayExpression, + ) { + return arrayContainsAllWithExpression( + Field(arrayFieldName), + arrayExpression, + ); + } + + /// Creates a raw/custom function expression + static Expression rawFunction( + String name, + List args, + ) { + return _RawFunctionExpression(name, args); + } + + /// A random value between 0 (inclusive) and 1 (exclusive) per evaluation + /// (Firestore pipeline `rand`). + static Expression rand() { + return _RandExpression(); + } + + /// Same as [Expression.isType] but usable as a static helper for any [expression]. + static BooleanExpression isTypeStatic( + Expression expression, + Type valueType, + ) { + return _IsTypeExpression(expression, valueType); + } +} + +/// Base class for function expressions +abstract class FunctionExpression extends Expression {} + +/// Base class for selectable expressions (can be used in select stage) +abstract class Selectable extends Expression { + String get aliasName; + Expression get expression; +} + +/// Represents an aliased expression wrapper +class AliasedExpression extends Selectable { + final String _alias; + + @override + String get aliasName => _alias; + + @override + final Expression expression; + + AliasedExpression({ + required String alias, + required this.expression, + }) : _alias = alias; + + @override + String get name => 'alias'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'alias': _alias, + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a field reference in a pipeline expression +class Field extends Selectable { + final String fieldName; + + Field(this.fieldName); + + @override + String get name => 'field'; + + @override + String get aliasName => fieldName; + + @override + Expression get expression => this; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'field': fieldName, + }, + }; + } +} + +/// Represents a null value expression +class _NullExpression extends Expression { + _NullExpression(); + + @override + String get name => 'null'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'value': null, + }, + }; + } +} + +/// Represents a constant value in a pipeline expression +/// +/// Valid types: String, num, bool, DateTime, Timestamp, GeoPoint, List (byte[]), +/// Blob, DocumentReference, VectorValue, or null +class Constant extends Expression { + final Object? value; + + Constant(this.value) { + if (value != null) { + // Validate that the value is one of the accepted types + if (value is! String && + value is! num && + value is! bool && + value is! DateTime && + value is! Timestamp && + value is! GeoPoint && + value is! List && + value is! Blob && + value is! DocumentReference && + value is! VectorValue) { + throw ArgumentError( + 'Constant value must be one of: String, num, bool, DateTime, Timestamp, ' + 'GeoPoint, List (byte[]), Blob, DocumentReference, or VectorValue. ' + 'Got: ${value.runtimeType}', + ); + } + } + } + + @override + String get name => 'constant'; + + @override + Map toMap() { + Object? serializedValue = value; + if (value is DocumentReference) { + serializedValue = {'path': (value! as DocumentReference).path}; + } + return { + 'name': name, + 'args': {'value': serializedValue}, + }; + } +} + +/// Represents a concatenation function expression +class Concat extends FunctionExpression { + final List expressions; + + Concat(this.expressions); + + @override + String get name => 'concat'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a concat function expression (internal) +class _ConcatExpression extends FunctionExpression { + final List expressions; + + _ConcatExpression(this.expressions); + + @override + String get name => 'concat'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a length function expression +class _LengthExpression extends FunctionExpression { + final Expression expression; + + _LengthExpression(this.expression); + + @override + String get name => 'length'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a toLowerCase function expression +class _ToLowerCaseExpression extends FunctionExpression { + final Expression expression; + + _ToLowerCaseExpression(this.expression); + + @override + String get name => 'to_lower_case'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a toUpperCase function expression +class _ToUpperCaseExpression extends FunctionExpression { + final Expression expression; + + _ToUpperCaseExpression(this.expression); + + @override + String get name => 'to_upper_case'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a substring function expression +class _SubstringExpression extends FunctionExpression { + final Expression expression; + final Expression start; + final Expression end; + + _SubstringExpression(this.expression, this.start, this.end); + + @override + String get name => 'substring'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'start': start.toMap(), + 'end': end.toMap(), + }, + }; + } +} + +/// Represents a string_replace_all function expression +class _StringReplaceAllExpression extends FunctionExpression { + final Expression expression; + final Expression find; + final Expression replacement; + + _StringReplaceAllExpression(this.expression, this.find, this.replacement); + + @override + String get name => 'string_replace_all'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'find': find.toMap(), + 'replacement': replacement.toMap(), + }, + }; + } +} + +/// Represents a split function expression +class _SplitExpression extends FunctionExpression { + final Expression expression; + final Expression delimiter; + + _SplitExpression(this.expression, this.delimiter); + + @override + String get name => 'split'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'delimiter': delimiter.toMap(), + }, + }; + } +} + +/// Represents a join function expression +class _JoinExpression extends FunctionExpression { + final Expression expression; + final Expression delimiter; + + _JoinExpression(this.expression, this.delimiter); + + @override + String get name => 'join'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'delimiter': delimiter.toMap(), + }, + }; + } +} + +/// Represents a trim function expression +class _TrimExpression extends FunctionExpression { + final Expression expression; + + _TrimExpression(this.expression); + + @override + String get name => 'trim'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Base class for boolean expressions used in filtering +abstract class BooleanExpression extends Expression {} + +// ============================================================================ +// PATTERN DEMONSTRATION - Concrete Function Expression Classes +// ============================================================================ + +/// Represents an addition function expression +class _AddExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _AddExpression(this.left, this.right); + + @override + String get name => 'add'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a subtraction function expression +class _SubtractExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _SubtractExpression(this.left, this.right); + + @override + String get name => 'subtract'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents an equality comparison function expression +class _EqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _EqualExpression(this.left, this.right); + + @override + String get name => 'equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a greater-than comparison function expression +class _GreaterThanExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _GreaterThanExpression(this.left, this.right); + + @override + String get name => 'greater_than'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a multiply function expression +class _MultiplyExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _MultiplyExpression(this.left, this.right); + + @override + String get name => 'multiply'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a divide function expression +class _DivideExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _DivideExpression(this.left, this.right); + + @override + String get name => 'divide'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a modulo function expression +class _ModuloExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _ModuloExpression(this.left, this.right); + + @override + String get name => 'modulo'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents an absolute value function expression +class _AbsExpression extends FunctionExpression { + final Expression expression; + + _AbsExpression(this.expression); + + @override + String get name => 'abs'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a negation function expression +/// Represents a not-equal comparison function expression +class _NotEqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _NotEqualExpression(this.left, this.right); + + @override + String get name => 'not_equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a greater-than-or-equal comparison function expression +class _GreaterThanOrEqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _GreaterThanOrEqualExpression(this.left, this.right); + + @override + String get name => 'greater_than_or_equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a less-than comparison function expression +class _LessThanExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _LessThanExpression(this.left, this.right); + + @override + String get name => 'less_than'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a less-than-or-equal comparison function expression +class _LessThanOrEqualExpression extends BooleanExpression { + final Expression left; + final Expression right; + + _LessThanOrEqualExpression(this.left, this.right); + + @override + String get name => 'less_than_or_equal'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +// ============================================================================ +// ARRAY OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an array concat function expression +class _ArrayConcatExpression extends FunctionExpression { + final Expression firstArray; + final Expression secondArray; + + _ArrayConcatExpression(this.firstArray, this.secondArray); + + @override + String get name => 'array_concat'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'first': firstArray.toMap(), + 'second': secondArray.toMap(), + }, + }; + } +} + +/// Represents an array concat multiple function expression +class _ArrayConcatMultipleExpression extends FunctionExpression { + final List arrays; + + _ArrayConcatMultipleExpression(this.arrays); + + @override + String get name => 'array_concat_multiple'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'arrays': arrays.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents an array contains function expression +class _ArrayContainsExpression extends BooleanExpression { + final Expression array; + final Expression element; + + _ArrayContainsExpression(this.array, this.element); + + @override + String get name => 'array_contains'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'array': array.toMap(), + 'element': element.toMap(), + }, + }; + } +} + +/// Represents an arrayContainsAny function expression +class _ArrayContainsAnyExpression extends BooleanExpression { + final Expression array; + final List values; + + _ArrayContainsAnyExpression(this.array, this.values); + + @override + String get name => 'array_contains_any'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'array': array.toMap(), + 'values': values.map((v) => v.toMap()).toList(), + }, + }; + } +} + +/// Represents an arrayContainsAll function expression (array + list of values) +class _ArrayContainsAllValuesExpression extends BooleanExpression { + final Expression array; + final List values; + + _ArrayContainsAllValuesExpression(this.array, this.values); + + @override + String get name => 'array_contains_all'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'array': array.toMap(), + 'values': values.map((v) => v.toMap()).toList(), + }, + }; + } +} + +/// Represents an arrayContainsAll function expression (array + array expression) +class _ArrayContainsAllExpression extends BooleanExpression { + final Expression array; + final Expression arrayExpression; + + _ArrayContainsAllExpression(this.array, this.arrayExpression); + + @override + String get name => 'array_contains_all'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'array': array.toMap(), + 'array_expression': arrayExpression.toMap(), + }, + }; + } +} + +/// Represents an array length function expression +class _ArrayLengthExpression extends FunctionExpression { + final Expression expression; + + _ArrayLengthExpression(this.expression); + + @override + String get name => 'array_length'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an array reverse function expression +class _ArrayReverseExpression extends FunctionExpression { + final Expression expression; + + _ArrayReverseExpression(this.expression); + + @override + String get name => 'array_reverse'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an array sum function expression +class _ArraySumExpression extends FunctionExpression { + final Expression expression; + + _ArraySumExpression(this.expression); + + @override + String get name => 'array_sum'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +// ============================================================================ +// CONDITIONAL / LOGIC OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an ifAbsent function expression +class _IfAbsentExpression extends FunctionExpression { + final Expression expression; + final Expression elseExpr; + + _IfAbsentExpression(this.expression, this.elseExpr); + + @override + String get name => 'if_absent'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'else': elseExpr.toMap(), + }, + }; + } +} + +/// Represents an ifError function expression +class _IfErrorExpression extends Expression { + final Expression expression; + final Expression catchExpr; + + _IfErrorExpression(this.expression, this.catchExpr); + + @override + String get name => 'if_error'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'catch': catchExpr.toMap(), + }, + }; + } +} + +/// Represents an isAbsent function expression +class _IsAbsentExpression extends BooleanExpression { + final Expression expression; + + _IsAbsentExpression(this.expression); + + @override + String get name => 'is_absent'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an isError function expression +class _IsErrorExpression extends BooleanExpression { + final Expression expression; + + _IsErrorExpression(this.expression); + + @override + String get name => 'is_error'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents an exists function expression +class _ExistsExpression extends BooleanExpression { + final Expression expression; + + _ExistsExpression(this.expression); + + @override + String get name => 'exists'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a not (negation) function expression +class _NotExpression extends BooleanExpression { + final BooleanExpression expression; + + _NotExpression(this.expression); + + @override + String get name => 'not'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +class _XorExpression extends BooleanExpression { + final List expressions; + + _XorExpression(this.expressions); + + @override + String get name => 'xor'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expressions': expressions.map((e) => e.toMap()).toList(), + }, + }; + } +} + +class _AndExpression extends BooleanExpression { + final List expressions; + + _AndExpression(this.expressions); + + @override + String get name => 'and'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expressions': expressions.map((e) => e.toMap()).toList(), + }, + }; + } +} + +class _OrExpression extends BooleanExpression { + final List expressions; + + _OrExpression(this.expressions); + + @override + String get name => 'or'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expressions': expressions.map((e) => e.toMap()).toList(), + }, + }; + } +} + +/// Represents a conditional (ternary) function expression +class _ConditionalExpression extends FunctionExpression { + final BooleanExpression condition; + final Expression thenExpr; + final Expression elseExpr; + + _ConditionalExpression(this.condition, this.thenExpr, this.elseExpr); + + @override + String get name => 'conditional'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'condition': condition.toMap(), + 'then': thenExpr.toMap(), + 'else': elseExpr.toMap(), + }, + }; + } +} + +// ============================================================================ +// TYPE CONVERSION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an asBoolean function expression +class _AsBooleanExpression extends BooleanExpression { + final Expression expression; + + _AsBooleanExpression(this.expression); + + @override + String get name => 'as_boolean'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +// ============================================================================ +// BITWISE OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a bitAnd function expression +class _BitAndExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _BitAndExpression(this.left, this.right); + + @override + String get name => 'bit_and'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a bitOr function expression +class _BitOrExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _BitOrExpression(this.left, this.right); + + @override + String get name => 'bit_or'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a bitXor function expression +class _BitXorExpression extends FunctionExpression { + final Expression left; + final Expression right; + + _BitXorExpression(this.left, this.right); + + @override + String get name => 'bit_xor'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'left': left.toMap(), + 'right': right.toMap(), + }, + }; + } +} + +/// Represents a bitNot function expression +class _BitNotExpression extends FunctionExpression { + final Expression expression; + + _BitNotExpression(this.expression); + + @override + String get name => 'bit_not'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a bitLeftShift function expression +class _BitLeftShiftExpression extends FunctionExpression { + final Expression expression; + final Expression amount; + + _BitLeftShiftExpression(this.expression, this.amount); + + @override + String get name => 'bit_left_shift'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'amount': amount.toMap(), + }, + }; + } +} + +/// Represents a bitRightShift function expression +class _BitRightShiftExpression extends FunctionExpression { + final Expression expression; + final Expression amount; + + _BitRightShiftExpression(this.expression, this.amount); + + @override + String get name => 'bit_right_shift'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'amount': amount.toMap(), + }, + }; + } +} + +// ============================================================================ +// DOCUMENT / PATH OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a documentId function expression +class _DocumentIdExpression extends FunctionExpression { + final Expression expression; + + _DocumentIdExpression(this.expression); + + @override + String get name => 'document_id'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a collectionId function expression +class _CollectionIdExpression extends FunctionExpression { + final Expression expression; + + _CollectionIdExpression(this.expression); + + @override + String get name => 'collection_id'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Represents a documentIdFromRef function expression +class _DocumentIdFromRefExpression extends FunctionExpression { + final DocumentReference docRef; + + _DocumentIdFromRefExpression(this.docRef); + + @override + String get name => 'document_id_from_ref'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'doc_ref': docRef.path, + }, + }; + } +} + +// ============================================================================ +// MAP OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a mapGet function expression +class _MapGetExpression extends FunctionExpression { + final Expression map; + final Expression key; + + _MapGetExpression(this.map, this.key); + + @override + String get name => 'map_get'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'map': map.toMap(), + 'key': key.toMap(), + }, + }; + } +} + +// ============================================================================ +// TIMESTAMP OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents a currentTimestamp function expression +class _CurrentTimestampExpression extends FunctionExpression { + _CurrentTimestampExpression(); + + @override + String get name => 'current_timestamp'; + + @override + Map toMap() { + return { + 'name': name, + }; + } +} + +/// Represents a timestamp_add function expression. +/// Unit must be one of: microsecond, millisecond, second, minute, hour, day. +class _TimestampAddExpression extends FunctionExpression { + final Expression timestamp; + final String unit; + final Expression amount; + + _TimestampAddExpression(this.timestamp, this.unit, this.amount); + + @override + String get name => 'timestamp_add'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'timestamp': timestamp.toMap(), + 'unit': unit, + 'amount': amount.toMap(), + }, + }; + } +} + +/// Represents a timestamp_subtract function expression. +/// Unit must be one of: microsecond, millisecond, second, minute, hour, day. +class _TimestampSubtractExpression extends FunctionExpression { + final Expression timestamp; + final String unit; + final Expression amount; + + _TimestampSubtractExpression(this.timestamp, this.unit, this.amount); + + @override + String get name => 'timestamp_subtract'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'timestamp': timestamp.toMap(), + 'unit': unit, + 'amount': amount.toMap(), + }, + }; + } +} + +/// Represents a timestamp_truncate function expression. +/// Unit must be one of: microsecond, millisecond, second, minute, hour, day. +class _TimestampTruncateExpression extends FunctionExpression { + final Expression timestamp; + final String unit; + + _TimestampTruncateExpression(this.timestamp, this.unit); + + @override + String get name => 'timestamp_truncate'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'timestamp': timestamp.toMap(), + 'unit': unit, + }, + }; + } +} + +// ============================================================================ +// SPECIAL OPERATION EXPRESSION CLASSES +// ============================================================================ + +/// Represents an equalAny (IN) function expression +class _EqualAnyExpression extends BooleanExpression { + final Expression value; + final List values; + + _EqualAnyExpression(this.value, this.values); + + @override + String get name => 'equal_any'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'value': value.toMap(), + 'values': values.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a notEqualAny (NOT IN) function expression +class _NotEqualAnyExpression extends BooleanExpression { + final Expression value; + final List values; + + _NotEqualAnyExpression(this.value, this.values); + + @override + String get name => 'not_equal_any'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'value': value.toMap(), + 'values': values.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents an array expression +class _ArrayExpression extends FunctionExpression { + final List elements; + + _ArrayExpression(this.elements); + + @override + String get name => 'array'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'elements': elements.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Represents a map expression +class _MapExpression extends FunctionExpression { + final Map data; + + _MapExpression(this.data); + + @override + String get name => 'map'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'data': data.map((k, v) => MapEntry(k, v.toMap())), + }, + }; + } +} + +/// Serialized pipeline function `map_set` (map plus alternating key/value pairs). +class _MapSetExpression extends FunctionExpression { + final Expression map; + final List keyValues; + + _MapSetExpression(this.map, this.keyValues) { + if (keyValues.isEmpty || keyValues.length.isOdd) { + throw ArgumentError('mapSet requires one or more key/value pairs'); + } + } + + @override + String get name => 'map_set'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'map': map.toMap(), + 'key_values': keyValues.map((e) => e.toMap()).toList(), + }, + }; + } +} + +/// Serialized pipeline function `map_entries`. +class _MapEntriesExpression extends FunctionExpression { + final Expression expression; + + _MapEntriesExpression(this.expression); + + @override + String get name => 'map_entries'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `regex_find`. +class _RegexFindExpression extends FunctionExpression { + final Expression expression; + final Expression pattern; + + _RegexFindExpression(this.expression, this.pattern); + + @override + String get name => 'regex_find'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'pattern': pattern.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `regex_find_all`. +class _RegexFindAllExpression extends FunctionExpression { + final Expression expression; + final Expression pattern; + + _RegexFindAllExpression(this.expression, this.pattern); + + @override + String get name => 'regex_find_all'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'pattern': pattern.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `string_replace_one`. +class _StringReplaceOneExpression extends FunctionExpression { + final Expression expression; + final Expression find; + final Expression replacement; + + _StringReplaceOneExpression(this.expression, this.find, this.replacement); + + @override + String get name => 'string_replace_one'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'find': find.toMap(), + 'replacement': replacement.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `string_index_of`. +class _StringIndexOfExpression extends FunctionExpression { + final Expression expression; + final Expression search; + + _StringIndexOfExpression(this.expression, this.search); + + @override + String get name => 'string_index_of'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'search': search.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `string_repeat`. +class _StringRepeatExpression extends FunctionExpression { + final Expression expression; + final Expression repetitions; + + _StringRepeatExpression(this.expression, this.repetitions); + + @override + String get name => 'string_repeat'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'repetitions': repetitions.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `ltrim`. +class _LtrimExpression extends FunctionExpression { + final Expression expression; + final Expression? value; + + _LtrimExpression(this.expression, this.value); + + @override + String get name => 'ltrim'; + + @override + Map toMap() { + final args = { + 'expression': expression.toMap(), + }; + if (value != null) { + args['value'] = value!.toMap(); + } + return { + 'name': name, + 'args': args, + }; + } +} + +/// Serialized pipeline function `rtrim`. +class _RtrimExpression extends FunctionExpression { + final Expression expression; + final Expression? value; + + _RtrimExpression(this.expression, this.value); + + @override + String get name => 'rtrim'; + + @override + Map toMap() { + final args = { + 'expression': expression.toMap(), + }; + if (value != null) { + args['value'] = value!.toMap(); + } + return { + 'name': name, + 'args': args, + }; + } +} + +/// Serialized pipeline function `type` (runtime type name of the value). +class _TypeExpression extends FunctionExpression { + final Expression expression; + + _TypeExpression(this.expression); + + @override + String get name => 'type'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Serialized pipeline boolean function `is_type`. +class _IsTypeExpression extends BooleanExpression { + final Expression expression; + final Type valueType; + + _IsTypeExpression(this.expression, this.valueType); + + @override + String get name => 'is_type'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'type': valueType.typeValue, + }, + }; + } +} + +/// Serialized pipeline function `trunc`. +class _TruncExpression extends FunctionExpression { + final Expression expression; + final Expression? decimals; + + _TruncExpression(this.expression, this.decimals); + + @override + String get name => 'trunc'; + + @override + Map toMap() { + final args = { + 'expression': expression.toMap(), + }; + if (decimals != null) { + args['decimals'] = decimals!.toMap(); + } + return { + 'name': name, + 'args': args, + }; + } +} + +/// Serialized pipeline function `rand`. +class _RandExpression extends FunctionExpression { + _RandExpression(); + + @override + String get name => 'rand'; + + @override + Map toMap() { + return { + 'name': name, + 'args': {}, + }; + } +} + +/// Serialized pipeline function `array_first`. +class _ArrayFirstExpression extends FunctionExpression { + final Expression expression; + + _ArrayFirstExpression(this.expression); + + @override + String get name => 'array_first'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `array_first_n`. +class _ArrayFirstNExpression extends FunctionExpression { + final Expression expression; + final Expression n; + + _ArrayFirstNExpression(this.expression, this.n); + + @override + String get name => 'array_first_n'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'n': n.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `array_last`. +class _ArrayLastExpression extends FunctionExpression { + final Expression expression; + + _ArrayLastExpression(this.expression); + + @override + String get name => 'array_last'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `array_last_n`. +class _ArrayLastNExpression extends FunctionExpression { + final Expression expression; + final Expression n; + + _ArrayLastNExpression(this.expression, this.n); + + @override + String get name => 'array_last_n'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'n': n.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `maximum` on an array value (not the aggregate). +class _ArrayMaximumExpression extends FunctionExpression { + final Expression expression; + + _ArrayMaximumExpression(this.expression); + + @override + String get name => 'maximum'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `maximum_n`. +class _ArrayMaximumNExpression extends FunctionExpression { + final Expression expression; + final Expression n; + + _ArrayMaximumNExpression(this.expression, this.n); + + @override + String get name => 'maximum_n'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'n': n.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `minimum` on an array value (not the aggregate). +class _ArrayMinimumExpression extends FunctionExpression { + final Expression expression; + + _ArrayMinimumExpression(this.expression); + + @override + String get name => 'minimum'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `minimum_n`. +class _ArrayMinimumNExpression extends FunctionExpression { + final Expression expression; + final Expression n; + + _ArrayMinimumNExpression(this.expression, this.n); + + @override + String get name => 'minimum_n'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'n': n.toMap(), + }, + }; + } +} + +/// Serialized pipeline function `array_index_of` (first or last occurrence). +class _ArrayIndexOfExpression extends FunctionExpression { + final Expression expression; + final Expression element; + final bool isLast; + + _ArrayIndexOfExpression( + this.expression, + this.element, { + required this.isLast, + }); + + @override + String get name => 'array_index_of'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'element': element.toMap(), + 'occurrence': Constant(isLast ? 'last' : 'first').toMap(), + }, + }; + } +} + +/// Serialized pipeline function `array_index_of_all`. +class _ArrayIndexOfAllExpression extends FunctionExpression { + final Expression expression; + final Expression element; + + _ArrayIndexOfAllExpression(this.expression, this.element); + + @override + String get name => 'array_index_of_all'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'element': element.toMap(), + }, + }; + } +} + +/// Represents a raw function expression +class _RawFunctionExpression extends FunctionExpression { + final String functionName; + final List args; + + _RawFunctionExpression(this.functionName, this.args); + + @override + String get name => functionName; + + @override + Map toMap() { + return { + 'name': name, + 'args': args.map((expr) => expr.toMap()).toList(), + }; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart new file mode 100644 index 000000000000..b55687fa5d8b --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_ordering.dart @@ -0,0 +1,30 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Direction for ordering results +enum OrderDirection { + /// Ascending order + asc, + + /// Descending order + desc, +} + +/// Represents an ordering specification for pipeline sorting +class Ordering implements PipelineSerializable { + final Expression expression; + final OrderDirection direction; + + Ordering(this.expression, this.direction); + + @override + Map toMap() { + return { + 'expression': expression.toMap(), + 'order_direction': direction == OrderDirection.asc ? 'asc' : 'desc', + }; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart new file mode 100644 index 000000000000..4136c9922872 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_sample.dart @@ -0,0 +1,43 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base class for pipeline sampling strategies +abstract class PipelineSample implements PipelineSerializable { + const PipelineSample(); + + /// Creates a sample with a fixed size + factory PipelineSample.withSize(int size) = _PipelineSampleSize; + + /// Creates a sample with a percentage + factory PipelineSample.withPercentage(double percentage) = + _PipelineSamplePercentage; +} + +/// Sample stage with a fixed size +class _PipelineSampleSize extends PipelineSample { + final int size; + + const _PipelineSampleSize(this.size); + + @override + Map toMap() => { + 'type': 'size', + 'value': size, + }; +} + +/// Sample stage with a percentage +class _PipelineSamplePercentage extends PipelineSample { + final double percentage; + + const _PipelineSamplePercentage(this.percentage); + + @override + Map toMap() => { + 'type': 'percentage', + 'value': percentage, + }; +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_snapshot.dart new file mode 100644 index 000000000000..1a078d31945e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_snapshot.dart @@ -0,0 +1,41 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Represents the results of a Pipeline query, including the data and metadata. +class PipelineResult { + /// The document reference, or null if no document was returned. + final DocumentReference>? document; + + /// The time the document was created. + final DateTime? createTime; + + /// The time the document was last updated (at the time the snapshot was generated). + final DateTime? updateTime; + + /// Retrieves all fields in the result as a map. + final Map? _data; + + PipelineResult({ + this.document, + this.createTime, + this.updateTime, + Map? data, + }) : _data = data; + + /// Retrieves all fields in the result as a map. + Map? data() => _data; +} + +/// A [PipelineSnapshot] contains the results of a pipeline execution. It can be iterated to retrieve the individual [PipelineResult] objects. +class PipelineSnapshot { + /// List of all the results + final List result; + + /// The time at which the pipeline producing this result is executed. + final DateTime executionTime; + + PipelineSnapshot._(this.result, this.executionTime); +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart new file mode 100644 index 000000000000..69d4be991a5d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_source.dart @@ -0,0 +1,67 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Provides methods to create pipelines from different sources +class PipelineSource { + final FirebaseFirestore _firestore; + + PipelineSource._(this._firestore); + + /// Creates a pipeline from a collection path + Pipeline collection(String collectionPath) { + if (collectionPath.isEmpty) { + throw ArgumentError('A collection path must be a non-empty string.'); + } else if (collectionPath.contains('//')) { + throw ArgumentError('A collection path must not contain "//".'); + } + + final stage = _CollectionPipelineStage(collectionPath); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); + } + + /// Creates a pipeline from a collection reference + Pipeline collectionReference( + CollectionReference> collectionReference, + ) { + final stage = _CollectionPipelineStage(collectionReference.path); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); + } + + /// Creates a pipeline from a collection group + Pipeline collectionGroup(String collectionId) { + if (collectionId.isEmpty) { + throw ArgumentError('A collection ID must be a non-empty string.'); + } else if (collectionId.contains('/')) { + throw ArgumentError( + 'A collection ID passed to collectionGroup() cannot contain "/".', + ); + } + + final stage = _CollectionGroupPipelineStage(collectionId); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); + } + + /// Creates a pipeline from a list of document references + Pipeline documents(List>> documents) { + if (documents.isEmpty) { + throw ArgumentError('Documents list must not be empty.'); + } + + final stage = _DocumentsPipelineStage(documents); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); + } + + /// Creates a pipeline from the entire database + Pipeline database() { + final stage = _DatabasePipelineStage(); + final delegate = _firestore._delegate.pipeline([stage.toMap()]); + return Pipeline._(_firestore, delegate); + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart new file mode 100644 index 000000000000..abc1555f8854 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart @@ -0,0 +1,419 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +/// Base sealed class for all pipeline stages +sealed class PipelineStage implements PipelineSerializable { + String get name; +} + +/// Stage representing a collection source +final class _CollectionPipelineStage extends PipelineStage { + final String collectionPath; + + _CollectionPipelineStage(this.collectionPath); + + @override + String get name => 'collection'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'path': collectionPath, + }, + }; + } +} + +/// Stage representing a documents source +final class _DocumentsPipelineStage extends PipelineStage { + final List>> documents; + + _DocumentsPipelineStage(this.documents); + + @override + String get name => 'documents'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': documents + .map( + (doc) => { + 'path': doc.path, + }, + ) + .toList(), + }; + } +} + +/// Stage representing a database source +final class _DatabasePipelineStage extends PipelineStage { + _DatabasePipelineStage(); + + @override + String get name => 'database'; + + @override + Map toMap() { + return { + 'stage': name, + }; + } +} + +/// Stage representing a collection group source +final class _CollectionGroupPipelineStage extends PipelineStage { + final String collectionPath; + + _CollectionGroupPipelineStage(this.collectionPath); + + @override + String get name => 'collection_group'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'path': collectionPath, + }, + }; + } +} + +/// Stage for adding fields to documents +final class _AddFieldsStage extends PipelineStage { + final List expressions; + + _AddFieldsStage(this.expressions); + + @override + String get name => 'add_fields'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Stage for aggregating data +final class _AggregateStage extends PipelineStage { + final List aggregateFunctions; + + _AggregateStage(this.aggregateFunctions); + + @override + String get name => 'aggregate'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'aggregate_functions': + aggregateFunctions.map((func) => func.toMap()).toList(), + }, + }; + } +} + +/// Stage for aggregating data with options and grouping +final class _AggregateStageWithOptions extends PipelineStage { + final AggregateStageOptions aggregateStage; + final AggregateOptions? options; + + _AggregateStageWithOptions(this.aggregateStage, this.options); + + @override + String get name => 'aggregate_with_options'; + + @override + Map toMap() { + final map = aggregateStage.toMap(); + final optionsMap = options?.toMap(); + return { + 'stage': name, + 'args': { + 'aggregate_stage': map, + 'options': optionsMap, + }, + }; + } +} + +/// Stage for getting distinct values +final class _DistinctStage extends PipelineStage { + final List expressions; + + _DistinctStage(this.expressions); + + @override + String get name => 'distinct'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Stage for finding nearest vectors +final class _FindNearestStage extends PipelineStage { + final Field vectorField; + final List vectorValue; + final DistanceMeasure distanceMeasure; + final int? limit; + + _FindNearestStage( + this.vectorField, + this.vectorValue, + this.distanceMeasure, { + this.limit, + }); + + @override + String get name => 'find_nearest'; + + @override + Map toMap() { + final map = { + 'stage': name, + 'args': { + 'vector_field': vectorField.fieldName, + 'vector_value': vectorValue, + 'distance_measure': distanceMeasure.name, + }, + }; + if (limit != null) { + map['args']['limit'] = limit; + } + return map; + } +} + +/// Stage for limiting results +final class _LimitStage extends PipelineStage { + final int limit; + + _LimitStage(this.limit); + + @override + String get name => 'limit'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'limit': limit, + }, + }; + } +} + +/// Stage for offsetting results +final class _OffsetStage extends PipelineStage { + final int offset; + + _OffsetStage(this.offset); + + @override + String get name => 'offset'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'offset': offset, + }, + }; + } +} + +/// Stage for removing fields +final class _RemoveFieldsStage extends PipelineStage { + final List fieldPaths; + + _RemoveFieldsStage(this.fieldPaths); + + @override + String get name => 'remove_fields'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'field_paths': fieldPaths, + }, + }; + } +} + +/// Stage for replacing documents +final class _ReplaceWithStage extends PipelineStage { + final Expression expression; + + _ReplaceWithStage(this.expression); + + @override + String get name => 'replace_with'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} + +/// Stage for sampling documents +final class _SampleStage extends PipelineStage { + final PipelineSample sample; + + _SampleStage(this.sample); + + @override + String get name => 'sample'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': sample.toMap(), + }; + } +} + +/// Stage for selecting specific fields +final class _SelectStage extends PipelineStage { + final List expressions; + + _SelectStage(this.expressions); + + @override + String get name => 'select'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expressions': expressions.map((expr) => expr.toMap()).toList(), + }, + }; + } +} + +/// Stage for sorting results +final class _SortStage extends PipelineStage { + final List orderings; + + _SortStage(this.orderings); + + @override + String get name => 'sort'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'orderings': orderings + .map( + (o) => { + 'expression': o.expression.toMap(), + 'order_direction': + o.direction == OrderDirection.asc ? 'asc' : 'desc', + }, + ) + .toList(), + }, + }; + } +} + +/// Stage for unnesting arrays +final class _UnnestStage extends PipelineStage { + final Selectable expression; + final String? indexField; + + _UnnestStage(this.expression, this.indexField); + + @override + String get name => 'unnest'; + + @override + Map toMap() { + final map = { + 'stage': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + if (indexField != null) { + map['args']['index_field'] = indexField; + } + return map; + } +} + +/// Stage for union with another pipeline +final class _UnionStage extends PipelineStage { + final Pipeline pipeline; + + _UnionStage(this.pipeline); + + @override + String get name => 'union'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'pipeline': pipeline.stages, + }, + }; + } +} + +/// Stage for filtering documents +final class _WhereStage extends PipelineStage { + final BooleanExpression expression; + + _WhereStage(this.expression); + + @override + String get name => 'where'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': { + 'expression': expression.toMap(), + }, + }; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m new file mode 120000 index 000000000000..0ab2d722c4a0 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m @@ -0,0 +1 @@ +../../../../ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m \ No newline at end of file diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h new file mode 120000 index 000000000000..fb086ff6b78c --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h @@ -0,0 +1 @@ +../../../../../../../ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTPipelineParser.h \ No newline at end of file diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/.gitignore b/packages/cloud_firestore/cloud_firestore/pipeline_example/.gitignore new file mode 100644 index 000000000000..3820a95c65c3 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/.metadata b/packages/cloud_firestore/cloud_firestore/pipeline_example/.metadata new file mode 100644 index 000000000000..2f3a59454284 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + base_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + - platform: android + create_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + base_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + - platform: ios + create_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + base_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + - platform: linux + create_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + base_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + - platform: macos + create_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + base_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + - platform: web + create_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + base_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + - platform: windows + create_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + base_revision: a0e9b9dbf78c8a5ef39b45a7efd40ed2de19c1a7 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/README.md b/packages/cloud_firestore/cloud_firestore/pipeline_example/README.md new file mode 100644 index 000000000000..115008c73129 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/README.md @@ -0,0 +1,16 @@ +# pipeline_example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/analysis_options.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/analysis_options.yaml new file mode 100644 index 000000000000..2f61fa3242f7 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/analysis_options.yaml @@ -0,0 +1,34 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +analyzer: + # Pipeline e2e tests uses firebase_options.dart injected in CI; exclude integration tests + # from analyze so analyze-ci passes. + exclude: + - integration_test/** + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/.gitignore b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/.gitignore new file mode 100644 index 000000000000..be3943c96d8e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/build.gradle.kts b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/build.gradle.kts new file mode 100644 index 000000000000..9300930bc97a --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/build.gradle.kts @@ -0,0 +1,47 @@ +plugins { + id("com.android.application") + // START: FlutterFire Configuration + id("com.google.gms.google-services") + // END: FlutterFire Configuration + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.example.pipeline_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.pipeline_example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/debug/AndroidManifest.xml b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000000..399f6981d5d3 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/AndroidManifest.xml b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..8a1e2a2fd055 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/kotlin/com/example/pipeline_example/MainActivity.kt b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/kotlin/com/example/pipeline_example/MainActivity.kt new file mode 100644 index 000000000000..205920783386 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/kotlin/com/example/pipeline_example/MainActivity.kt @@ -0,0 +1,5 @@ +package com.example.pipeline_example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000000..f74085f3f6a2 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable/launch_background.xml b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000000..304732f88420 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values-night/styles.xml b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000000..06952be745f9 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values/styles.xml b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000000..cb1ef88056ed --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/profile/AndroidManifest.xml b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000000..399f6981d5d3 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/build.gradle.kts b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/build.gradle.kts new file mode 100644 index 000000000000..dbee657bb5b9 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle.properties b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle.properties new file mode 100644 index 000000000000..fbee1d8cdafc --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle/wrapper/gradle-wrapper.properties b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..e4ef43fb98df --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/android/settings.gradle.kts b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/settings.gradle.kts new file mode 100644 index 000000000000..174f408284fe --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/android/settings.gradle.kts @@ -0,0 +1,29 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + // START: FlutterFire Configuration + id("com.google.gms.google-services") version("4.3.15") apply false + // END: FlutterFire Configuration + id("org.jetbrains.kotlin.android") version "2.2.20" apply false +} + +include(":app") diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_add_fields_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_add_fields_e2e.dart new file mode 100644 index 000000000000..323e30163e35 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_add_fields_e2e.dart @@ -0,0 +1,42 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:firebase_core/firebase_core.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineAddFieldsTests() { + group('Pipeline addFields', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test( + 'addFields with expression returns expected transformed data', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('add-fields')) + .sort(Expression.field('title').ascending()) + .addFields(Expression.field('score').abs().as('abs_score')) + .limit(3) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'title': 'alpha', 'score': -7, 'abs_score': 7}, + {'title': 'beta', 'score': 42, 'abs_score': 42}, + {'title': 'gamma', 'score': 0, 'abs_score': 0}, + ]); + }, + ); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_aggregate_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_aggregate_e2e.dart new file mode 100644 index 000000000000..200b491dc964 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_aggregate_e2e.dart @@ -0,0 +1,109 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/foundation.dart' show kIsWeb; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineAggregateTests() { + group('Pipeline aggregate', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('aggregate count and sum returns expected single result', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('aggregate')) + .aggregate( + CountAll().as('total'), + Expression.field('score').sum().as('total_score'), + ) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'total': 4, 'total_score': 100}, + ]); + }); + + test( + 'aggregateWithOptions with groups returns one row per group', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('aggregate')) + .aggregateWithOptions( + AggregateStageOptions( + accumulators: [ + Expression.field('score').sum().as('total_score'), + CountAll().as('count'), + ], + groups: [Expression.field('category')], + ), + ) + .execute(); + expectResultCount(snapshot, 2); + final results = snapshot.result.map((r) => r.data()!).toList(); + results.sort( + (a, b) => + (a['category'] as String).compareTo(b['category'] as String), + ); + expect(results[0]['category'], 'x'); + expect(results[0]['total_score'], 30); + expect(results[0]['count'], 2); + expect(results[1]['category'], 'y'); + expect(results[1]['total_score'], 70); + expect(results[1]['count'], 2); + }, + ); + + test('aggregate first and last score with sort', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('aggregate')) + .sort(Expression.field('score').ascending()) + .aggregate( + Expression.field('score').first().as('first_s'), + Expression.field('score').last().as('last_s'), + ) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'first_s': 10, 'last_s': 40}, + ]); + }, skip: !kIsWeb); + + test('aggregate array_agg and array_agg_distinct on category', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('aggregate')) + .sort(Expression.field('score').ascending()) + .aggregate( + Expression.field('category').arrayAgg().as('cats'), + Expression.field('category').arrayAggDistinct().as('cats_d'), + ) + .execute(); + expectResultCount(snapshot, 1); + final data = snapshot.result[0].data()!; + final cats = data['cats'] as List; + expect(cats.length, 4); + expect(cats.map((e) => e as String).toSet(), {'x', 'y'}); + final catsD = data['cats_d'] as List; + expect(catsD.length, 2); + expect(catsD.map((e) => e as String).toSet(), {'x', 'y'}); + }, skip: !kIsWeb); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_execute_options_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_execute_options_e2e.dart new file mode 100644 index 000000000000..4968b3aba36a --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_execute_options_e2e.dart @@ -0,0 +1,37 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineExecuteOptionsTests() { + group('Pipeline execute with options', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('execute with ExecuteOptions returns expected results', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('add-fields')) + .sort(Expression.field('title').ascending()) + .limit(2) + .execute( + options: const ExecuteOptions(indexMode: IndexMode.recommended), + ); + expectResultCount(snapshot, 2); + expect(snapshot.result[0].data()!['title'], 'alpha'); + expect(snapshot.result[1].data()!['title'], 'beta'); + }, skip: true); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart new file mode 100644 index 000000000000..e67e2fbdf0f5 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart @@ -0,0 +1,1088 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, TargetPlatform, kIsWeb; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineExpressionsTests() { + group('Pipeline expressions in where and addFields', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + /// Single doc: `test==expressions`, `score==50` (see pipeline seed). + Future expressionsDocScore50(Selectable field) { + return firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(50)) + .addFields(field) + .limit(1) + .execute(); + } + + test('where with greaterThan filters and returns expected docs', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').greaterThan(Expression.constant(50))) + .sort(Expression.field('score').ascending()) + .limit(5) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'score': 60, 'a': 1, 'b': 2}, + {'score': 70, 'a': 10, 'b': 20}, + {'score': 80, 'a': 0, 'b': 100}, + ]); + }); + + test('addFields with add expression returns expected values', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .sort(Expression.field('score').ascending()) + .addFields( + Expression.field('a').add(Expression.field('b')).as('sum_ab'), + ) + .limit(5) + .execute(); + expectResultCount(snapshot, 5); + expectResultsData(snapshot, [ + {'score': 40, 'a': 5, 'b': 5, 'sum_ab': 10}, + {'score': 50, 'a': 1, 'b': 2, 'sum_ab': 3}, + {'score': 60, 'a': 1, 'b': 2, 'sum_ab': 3}, + {'score': 70, 'a': 10, 'b': 20, 'sum_ab': 30}, + {'score': 80, 'a': 0, 'b': 100, 'sum_ab': 100}, + ]); + }); + + test('addFields with conditional returns expected band', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .sort(Expression.field('score').ascending()) + .addFields( + Expression.conditional( + Expression.field('score').greaterThan(Expression.constant(50)), + Expression.constant('high'), + Expression.constant('low'), + ).as('band'), + ) + .limit(5) + .execute(); + expectResultCount(snapshot, 5); + expectResultsData(snapshot, [ + {'score': 40, 'band': 'low'}, + {'score': 50, 'band': 'low'}, + {'score': 60, 'band': 'high'}, + {'score': 70, 'band': 'high'}, + {'score': 80, 'band': 'high'}, + ]); + }); + + test('addFields with arrayLength returns length for array field', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .sort(Expression.field('score').ascending()) + .addFields(Expression.field('tags').arrayLength().as('tags_len')) + .limit(5) + .execute(); + expectResultCount(snapshot, 5); + final withTags = snapshot.result + .where((r) => r.data()!['tags_len'] == 2) + .toList(); + expect(withTags.length, 1); + expect(withTags.first.data()!['score'], 50); + }); + + test('where with lessThan filters correctly', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').lessThan(Expression.constant(60))) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 2); + expectResultsData(snapshot, [ + {'score': 40, 'a': 5, 'b': 5}, + {'score': 50, 'a': 1, 'b': 2}, + ]); + }); + + test('where with equalValue filters correctly', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(50)) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'score': 50, 'a': 1, 'b': 2}, + ]); + }); + + test('where with equal(Expression) filters correctly', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equal(Expression.constant(50))) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'score': 50, 'a': 1, 'b': 2}, + ]); + }); + + test('where with notEqualValue filters correctly', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').notEqualValue(50)) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 4); + expectResultsData(snapshot, [ + {'score': 40, 'a': 5, 'b': 5}, + {'score': 60, 'a': 1, 'b': 2}, + {'score': 70, 'a': 10, 'b': 20}, + {'score': 80, 'a': 0, 'b': 100}, + ]); + }); + + test('where with notEqual(Expression) filters correctly', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').notEqual(Expression.constant(50))) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 4); + expectResultsData(snapshot, [ + {'score': 40, 'a': 5, 'b': 5}, + {'score': 60, 'a': 1, 'b': 2}, + {'score': 70, 'a': 10, 'b': 20}, + {'score': 80, 'a': 0, 'b': 100}, + ]); + }); + + test( + 'where with greaterThanValue and lessThanValue filter correctly', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').greaterThanValue(40)) + .where(Expression.field('score').lessThanValue(80)) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'score': 50, 'a': 1, 'b': 2}, + {'score': 60, 'a': 1, 'b': 2}, + {'score': 70, 'a': 10, 'b': 20}, + ]); + }, + ); + + test( + 'where with greaterThanOrEqual and lessThanOrEqual filter correctly', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where( + Expression.field( + 'score', + ).greaterThanOrEqual(Expression.constant(50)), + ) + .where( + Expression.field( + 'score', + ).lessThanOrEqual(Expression.constant(70)), + ) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'score': 50, 'a': 1, 'b': 2}, + {'score': 60, 'a': 1, 'b': 2}, + {'score': 70, 'a': 10, 'b': 20}, + ]); + }, + ); + + test( + 'addFields with subtract, multiply, divide, modulo return expected values', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .sort(Expression.field('score').ascending()) + .addFields( + Expression.field('a').subtract(Expression.field('b')).as('diff'), + Expression.field( + 'a', + ).multiply(Expression.field('b')).as('product'), + Expression.field( + 'score', + ).divide(Expression.constant(10)).as('score_div_10'), + Expression.field( + 'score', + ).modulo(Expression.constant(30)).as('score_mod_30'), + ) + .limit(3) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + { + 'score': 40, + 'a': 5, + 'b': 5, + 'diff': 0, + 'product': 25, + 'score_div_10': 4, + 'score_mod_30': 10, + }, + { + 'score': 50, + 'a': 1, + 'b': 2, + 'diff': -1, + 'product': 2, + 'score_div_10': 5, + 'score_mod_30': 20, + }, + { + 'score': 60, + 'a': 1, + 'b': 2, + 'diff': -1, + 'product': 2, + 'score_div_10': 6, + 'score_mod_30': 0, + }, + ]); + }, + ); + + test('where with and returns intersection', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where( + Expression.and( + Expression.field('score').greaterThan(Expression.constant(40)), + Expression.field('score').lessThan(Expression.constant(80)), + ), + ) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'score': 50, 'a': 1, 'b': 2}, + {'score': 60, 'a': 1, 'b': 2}, + {'score': 70, 'a': 10, 'b': 20}, + ]); + }); + + test('where with or returns union', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where( + Expression.or( + Expression.field('score').equalValue(40), + Expression.field('score').equalValue(80), + ), + ) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 2); + expectResultsData(snapshot, [ + {'score': 40, 'a': 5, 'b': 5}, + {'score': 80, 'a': 0, 'b': 100}, + ]); + }); + + test('where with not inverts condition', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where( + Expression.not( + Expression.field( + 'score', + ).greaterThanOrEqual(Expression.constant(60)), + ), + ) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 2); + expectResultsData(snapshot, [ + {'score': 40, 'a': 5, 'b': 5}, + {'score': 50, 'a': 1, 'b': 2}, + ]); + }); + + test( + 'addFields with ifAbsentValue uses default when field missing', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .sort(Expression.field('score').ascending()) + .addFields( + Expression.field( + 'tags', + ).ifAbsentValue('default_value').as('tags_or_empty'), + ) + .limit(2) + .execute(); + expectResultCount(snapshot, 2); + expect(snapshot.result[0].data()!['tags_or_empty'], 'default_value'); + expect(snapshot.result[1].data()!['tags_or_empty'], ['p', 'q']); + }, + ); + + test( + 'addFields with ifAbsent(Expression) uses else expression when field missing', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .sort(Expression.field('score').ascending()) + .addFields( + Expression.field('tags') + .ifAbsent(Expression.constant('default_value')) + .as('tags_or_default'), + ) + .limit(2) + .execute(); + expectResultCount(snapshot, 2); + expect(snapshot.result[0].data()!['tags_or_default'], 'default_value'); + expect(snapshot.result[1].data()!['tags_or_default'], ['p', 'q']); + }, + ); + + test( + 'where arrayContainsValue filters docs with array containing value', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('tags').arrayContainsValue('p')) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + { + 'score': 50, + 'a': 1, + 'b': 2, + 'tags': ['p', 'q'], + }, + ]); + }, + ); + + test( + 'where arrayContainsElement(Expression) filters docs with array containing element', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where( + Expression.field( + 'tags', + ).arrayContainsElement(Expression.constant('q')), + ) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + { + 'score': 50, + 'a': 1, + 'b': 2, + 'tags': ['p', 'q'], + }, + ]); + }, + ); + + test( + 'addFields with string expressions (concat, length, toLower, toUpper, trim)', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('s').concat(['!']).as('s_concat'), + Expression.field('s').length().as('s_len'), + Expression.field('s').toLowerCase().as('s_lower'), + Expression.field('s').toUpperCase().as('s_upper'), + Expression.field('s').trim().as('s_trim'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + { + 'score': 60, + 's_concat': ' AbC !', + 's_len': 7, + 's_lower': ' abc ', + 's_upper': ' ABC ', + 's_trim': 'AbC', + }, + ]); + }, + ); + + test('addFields with substring returns expected slice', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(70)) + .addFields( + Expression.field('s') + .substring(Expression.constant(0), Expression.constant(1)) + .as('s_first'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['s_first'], 'x'); + }); + + test('addFields with map_get returns nested value', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('m').mapGet(Expression.constant('x')).as('m_x'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['m_x'], 10); + }); + + test('where with exists filters docs where tags exists', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('tags').exists()) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['score'], 50); + }); + + test( + 'where with xor returns docs matching exactly one condition', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where( + Expression.xor( + Expression.field('score').equalValue(40), + Expression.field('score').equalValue(50), + ), + ) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 2); + expectResultsData(snapshot, [ + {'score': 40}, + {'score': 50}, + ]); + }, + ); + + test('where with equalAny and notEqualAny filters correctly', () async { + final inSnapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.equalAny(Expression.field('score'), [40, 70])) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(inSnapshot, 2); + expectResultsData(inSnapshot, [ + {'score': 40}, + {'score': 70}, + ]); + + final notInSnapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.notEqualAny(Expression.field('score'), [40, 70])) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(notInSnapshot, 3); + expectResultsData(notInSnapshot, [ + {'score': 50}, + {'score': 60}, + {'score': 80}, + ]); + }); + + test('addFields split', () async { + final snapshot = await expressionsDocScore50( + Expression.field('s').splitLiteral('-').as('s_split'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['s_split'], ['a', 'b', 'c']); + }); + + test('addFields join', () async { + final snapshot = await expressionsDocScore50( + Expression.field('tags').joinLiteral('|').as('tags_joined'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['tags_joined'], 'p|q'); + }); + + test('addFields arrayConcat', () async { + final snapshot = await expressionsDocScore50( + Expression.field('arr').arrayConcat([9]).as('arr_concat'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['arr_concat'], [2, 4, 6, 9]); + }); + + test('addFields arrayConcatMultiple', () async { + final snapshot = await expressionsDocScore50( + Expression.field('arr') + .arrayConcatMultiple([ + [10], + [11], + ]) + .as('arr_concat_multi'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['arr_concat_multi'], [2, 4, 6, 10, 11]); + }); + + test('addFields arrayContainsAny', () async { + final snapshot = await expressionsDocScore50( + Expression.field('arr').arrayContainsAny([2, 99]).as('arr_has_any'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['arr_has_any'], true); + }); + + test('addFields arrayContainsAll values', () async { + final snapshot = await expressionsDocScore50( + Expression.field( + 'arr', + ).arrayContainsAll([2, 4]).as('arr_has_all_values'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['arr_has_all_values'], true); + }); + + test('addFields arrayContainsAllFrom expression', () async { + final snapshot = await expressionsDocScore50( + Expression.field('arr') + .arrayContainsAllFrom(Expression.array([Expression.constant(2), 4])) + .as('arr_has_all_expr'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['arr_has_all_expr'], true); + }); + + test('addFields map constructor', () async { + final snapshot = await expressionsDocScore50( + Expression.map({ + 'left': Expression.field('a'), + 'right': Expression.field('b'), + }).as('mapped'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['mapped'], {'left': 1, 'right': 2}); + }); + + test('addFields nullValue', () async { + final snapshot = await expressionsDocScore50( + Expression.nullValue().as('explicit_null'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['explicit_null'], null); + }); + + test('addFields ifError uses catch when expression errors', () async { + final snapshot = await expressionsDocScore50( + Expression.field( + 'score', + ).divide(Expression.constant(0)).ifErrorValue('safe').as('safe_div'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['safe_div'], 'safe'); + }); + + test('addFields isAbsent true for missing field', () async { + final snapshot = await expressionsDocScore50( + Expression.field('missing_field').isAbsent().as('missing_absent'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['missing_absent'], true); + }); + + test('addFields isError false for missing field', () async { + final snapshot = await expressionsDocScore50( + Expression.field('missing_field').isError().as('missing_error'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['missing_error'], false); + }); + + test('addFields asBoolean coerces numeric field', () async { + final snapshot = await expressionsDocScore50( + Expression.field('a').asBoolean().as('a_bool'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['a_bool'], 1); + }); + + test( + 'addFields bitwise expressions (bitAnd/Or/Xor/Not/shifts)', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field( + 'bit_a', + ).bitAnd(Expression.constant(3)).as('b_and'), + Expression.field( + 'bit_a', + ).bitOr(Expression.constant(1)).as('b_or'), + Expression.field( + 'bit_a', + ).bitXor(Expression.constant(7)).as('b_xor'), + Expression.field('bit_a').bitNot().as('b_not'), + Expression.field('bit_a').bitLeftShiftLiteral(1).as('b_lsh'), + Expression.field('bit_a').bitRightShiftLiteral(1).as('b_rsh'), + ) + .limit(1) + .execute(); + + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'b_and': 2, 'b_or': 7, 'b_xor': 1, 'b_lsh': 12, 'b_rsh': 3}, + ]); + expect(snapshot.result[0].data()!['b_not'], isNotNull); + }, + // Bitwise pipeline addFields not supported on Android native SDK yet. + skip: true, + ); + + test('addFields documentId, collectionId and documentIdFromRef', () async { + final col = firestore.collection('pipeline-e2e'); + final seedQuery = await col + .where('test', isEqualTo: 'expressions') + .where('score', isEqualTo: 60) + .limit(1) + .get(); + expect(seedQuery.docs, isNotEmpty); + final docRef = seedQuery.docs.first.reference; + final expectedDocId = seedQuery.docs.first.id; + + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('__name__').documentId().as('doc_id'), + Expression.field('__name__').collectionId().as('coll_id'), + Expression.documentIdFromRef(docRef).as('doc_id_from_ref'), + ) + .limit(1) + .execute(); + + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + { + 'coll_id': 'pipeline-e2e', + 'doc_id': expectedDocId, + 'doc_id_from_ref': expectedDocId, + }, + ]); + }, skip: kIsWeb); + + test( + 'addFields with currentTimestamp, timestampAdd/Subtract/Truncate', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.currentTimestamp().as('now'), + Expression.timestampAddLiteral( + Expression.field('ts'), + 'day', + 1, + ).as('ts_plus_1d'), + Expression.timestampSubtractLiteral( + Expression.field('ts'), + 'hour', + 1, + ).as('ts_minus_1h'), + Expression.timestampTruncate( + Expression.field('ts'), + 'day', + ).as('ts_day'), + ) + .limit(1) + .execute(); + + expectResultCount(snapshot, 1); + final data = snapshot.result[0].data()!; + expect(data['now'], isNotNull); + expect(data['ts_plus_1d'], isNotNull); + expect(data['ts_minus_1h'], isNotNull); + expect(data['ts_day'], isNotNull); + }, + skip: kIsWeb, + ); + + test('select with alias() returns renamed field', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .select(Expression.field('score').alias('renamed_score')) + .limit(1) + .execute(); + + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['renamed_score'], 60); + }); + + test('addFields with array_reverse returns reversed array', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(50)) + .addFields(Expression.field('tags').arrayReverse().as('tags_rev')) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['tags_rev'], ['q', 'p']); + }); + + test( + 'arraySum addFields succeeds on Android', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .addFields(Expression.array([1, 2, 3]).arraySum().as('x')) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['x'], 6); + }, + skip: defaultTargetPlatform != TargetPlatform.android, + ); + + test( + 'unsupported expression returns parse-error with informative message', + () async { + try { + await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .addFields(Expression.array([1, 2, 3]).arraySum().as('x')) + .limit(1) + .execute(); + return; + } on FirebaseException catch (e) { + expect(e.code, 'parse-error'); + expect(e.message, isNotNull); + expect(e.message!, contains('Unsupported expression')); + } + }, + skip: + defaultTargetPlatform != TargetPlatform.iOS && + defaultTargetPlatform != TargetPlatform.macOS, + ); + + test('addFields regexFind on email', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('email').regexFind('@.+').as('domain_part'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['domain_part'], '@example.com'); + }, skip: !kIsWeb); + + test('addFields regexFindAll on email', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('email').regexFindAll('[a-z]+').as('chunks'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + final chunks = snapshot.result[0].data()!['chunks'] as List?; + expect(chunks, isNotNull); + expect(chunks, contains('demo')); + expect(chunks, contains('com')); + }, skip: !kIsWeb); + + test( + 'addFields stringReplaceOne stringIndexOf stringRepeat on s', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(70)) + .addFields( + Expression.field('s').stringReplaceOneLiteral('x', 'Z').as('s1'), + Expression.field('s').stringIndexOf('y').as('iy'), + Expression.field('s').stringRepeat(2).as('s2'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'s1': 'Zy', 'iy': 1, 's2': 'xyxy'}, + ]); + }, + skip: !kIsWeb, + ); + + test('addFields ltrim rtrim on padded s', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('s').ltrim().as('lt'), + Expression.field('s').rtrim().as('rt'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'lt': 'AbC ', 'rt': ' AbC'}, + ]); + }, skip: !kIsWeb); + + test('addFields mapSet and mapEntries on m', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('m').mapSet('z', 99).as('m2'), + Expression.field('m').mapEntries().as('entries'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + final data = snapshot.result[0].data()!; + expect(data['m2'], {'x': 10, 'y': 20, 'z': 99}); + final entries = data['entries'] as List?; + expect(entries, isNotNull); + expect(entries!.length, 2); + }, skip: !kIsWeb); + + test('addFields type(score) is int64 string', () async { + final snapshot = await expressionsDocScore50( + Expression.field('score').type().as('stype'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['stype'], 'int64'); + }, skip: !kIsWeb); + + test('where isType int64 on score keeps integer score docs', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').isType(Type.int64)) + .sort(Expression.field('score').ascending()) + .execute(); + expectResultCount(snapshot, 5); + }, skip: !kIsWeb); + + test('addFields trunc pi and rand', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('pi').trunc().as('pi0'), + Expression.field('pi').trunc(Expression.constant(2)).as('pi2'), + Expression.rand().as('r'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + final data = snapshot.result[0].data()!; + expect(data['pi0'], 3); + expect(data['pi2'], closeTo(3.14, 0.01)); + expect(data['r'], isA()); + }, skip: !kIsWeb); + + test('addFields arrayFirst arrayLast on tags', () async { + final snapshot = await expressionsDocScore50( + Expression.field('tags').arrayFirst().as('t0'), + ); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'t0': 'p'}, + ]); + final snap2 = await expressionsDocScore50( + Expression.field('tags').arrayLast().as('t1'), + ); + expect(snap2.result[0].data()!['t1'], 'q'); + }, skip: !kIsWeb); + + test('addFields arrayFirstN arrayLastN on tags', () async { + final snapshot = await expressionsDocScore50( + Expression.field('tags').arrayFirstN(1).as('head'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['head'], ['p']); + final snap2 = await expressionsDocScore50( + Expression.field('tags').arrayLastN(1).as('tail'), + ); + expect(snap2.result[0].data()!['tail'], ['q']); + }, skip: !kIsWeb); + + test('addFields arrayMaximum arrayMinimum on arr', () async { + final snapshot = await expressionsDocScore50( + Expression.field('arr').arrayMaximum().as('mx'), + ); + expectResultCount(snapshot, 1); + expect(snapshot.result[0].data()!['mx'], 6); + final snap2 = await expressionsDocScore50( + Expression.field('arr').arrayMinimum().as('mn'), + ); + expect(snap2.result[0].data()!['mn'], 2); + }, skip: !kIsWeb); + + test('addFields arrayMaximumN arrayMinimumN on arr', () async { + final snapshot = await expressionsDocScore50( + Expression.field('arr').arrayMaximumN(2).as('top2'), + ); + expectResultCount(snapshot, 1); + final top2 = snapshot.result[0].data()!['top2'] as List; + expect(top2.length, 2); + expect(top2.map((e) => e as int).toSet(), {4, 6}); + final snap2 = await expressionsDocScore50( + Expression.field('arr').arrayMinimumN(2).as('bot2'), + ); + final bot2 = snap2.result[0].data()!['bot2'] as List; + expect(bot2.length, 2); + expect(bot2.map((e) => e as int).toSet(), {2, 4}); + }, skip: !kIsWeb); + + test( + 'addFields arrayIndexOf arrayLastIndexOf arrayIndexOfAll on dup_tags', + () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(60)) + .addFields( + Expression.field('dup_tags').arrayIndexOf('a').as('i0'), + Expression.field('dup_tags').arrayLastIndexOf('a').as('i1'), + Expression.field('dup_tags').arrayIndexOfAll('a').as('all'), + ) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + { + 'i0': 0, + 'i1': 2, + 'all': [0, 2], + }, + ]); + }, + skip: !kIsWeb, + ); + + test('Expression.isTypeStatic equals where isType', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.isTypeStatic(Expression.field('score'), Type.int64)) + .sort(Expression.field('score').ascending()) + .limit(2) + .execute(); + expectResultCount(snapshot, 2); + }, skip: !kIsWeb); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_filter_sort_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_filter_sort_e2e.dart new file mode 100644 index 000000000000..95e52f52e5b4 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_filter_sort_e2e.dart @@ -0,0 +1,89 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:firebase_core/firebase_core.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineFilterSortTests() { + group('Pipeline where, sort, limit, offset, distinct', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('where + limit returns expected count and data', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('filter-sort')) + .where(Expression.field('active').equalValue(true)) + .sort(Expression.field('score').ascending()) + .limit(5) + .execute(); + expectResultCount(snapshot, 4); + expectResultsData(snapshot, [ + {'active': true, 'score': 10, 'category': 'a'}, + {'active': true, 'score': 15, 'category': 'b'}, + {'active': true, 'score': 20, 'category': 'b'}, + {'active': true, 'score': 30, 'category': 'c'}, + ]); + }); + + test('sort + limit returns expected order', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('filter-sort')) + .sort(Expression.field('score').descending()) + .limit(3) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'score': 30, 'category': 'c'}, + {'score': 20, 'category': 'b'}, + {'score': 15, 'category': 'b'}, + ]); + }); + + test('offset + limit returns expected slice', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('filter-sort')) + .sort(Expression.field('score').ascending()) + .offset(2) + .limit(5) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'score': 15, 'category': 'b'}, + {'score': 20, 'category': 'b'}, + {'score': 30, 'category': 'c'}, + ]); + }); + + test('distinct returns unique category values', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('filter-sort')) + .distinct(Expression.field('category').as('category')) + .sort(Expression.field('category').ascending()) + .limit(10) + .execute(); + expectResultCount(snapshot, 3); + final categories = snapshot.result + .map((r) => r.data()!['category']) + .toList(); + expect(categories..sort(), ['a', 'b', 'c']); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_find_nearest_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_find_nearest_e2e.dart new file mode 100644 index 000000000000..35d5b6e75062 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_find_nearest_e2e.dart @@ -0,0 +1,45 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void runPipelineFindNearestTests() { + group('Pipeline findNearest', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test( + 'findNearest returns results ordered by distance when vector index exists', + () async { + final pipeline = firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('find-nearest')) + .findNearest( + Field('embedding'), + [0.1, 0.2, 0.3], + DistanceMeasure.cosine, + limit: 5, + ); + final snapshot = await pipeline.execute(); + expect(snapshot, isNotNull); + expect(snapshot.result, isA>()); + if (snapshot.result.isNotEmpty) { + final first = snapshot.result.first.data(); + if (first != null && first.containsKey('label')) { + expect(first['label'], 'near'); + } + } + }, + ); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart new file mode 100644 index 000000000000..b7a977b6e8ad --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart @@ -0,0 +1,52 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Pipeline E2E runs against live Firebase (do not use emulator). + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:pipeline_example/firebase_options.dart'; + +import 'pipeline_add_fields_e2e.dart'; +import 'pipeline_aggregate_e2e.dart'; +import 'pipeline_expressions_e2e.dart'; +import 'pipeline_filter_sort_e2e.dart'; +import 'pipeline_find_nearest_e2e.dart'; +import 'pipeline_remove_fields_e2e.dart'; +import 'pipeline_replace_with_e2e.dart'; +import 'pipeline_sample_e2e.dart'; +import 'pipeline_seed.dart'; +import 'pipeline_select_e2e.dart'; +import 'pipeline_unnest_union_e2e.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('pipeline (live)', () { + setUpAll(() async { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + final firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + firestore.settings = const Settings(persistenceEnabled: true); + await seedPipelineE2ECollections(firestore); + }); + + runPipelineFilterSortTests(); + runPipelineAddFieldsTests(); + runPipelineSelectTests(); + runPipelineRemoveFieldsTests(); + runPipelineReplaceWithTests(); + runPipelineAggregateTests(); + runPipelineUnnestUnionTests(); + runPipelineSampleTests(); + runPipelineFindNearestTests(); + runPipelineExpressionsTests(); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_remove_fields_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_remove_fields_e2e.dart new file mode 100644 index 000000000000..51840cbd4691 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_remove_fields_e2e.dart @@ -0,0 +1,44 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineRemoveFieldsTests() { + group('Pipeline removeFields', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('removeFields drops specified fields only', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('remove-fields')) + .sort(Expression.field('keep').ascending()) + .removeFields('internal_id', 'debug_flag') + .limit(3) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'keep': 'x'}, + {'keep': 'y'}, + {'keep': 'z'}, + ]); + for (final r in snapshot.result) { + final data = r.data()!; + expect(data.containsKey('internal_id'), false); + expect(data.containsKey('debug_flag'), false); + } + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_replace_with_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_replace_with_e2e.dart new file mode 100644 index 000000000000..68f3730180f5 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_replace_with_e2e.dart @@ -0,0 +1,53 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineReplaceWithTests() { + group('Pipeline replaceWith', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('replaceWith emits nested map as document', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('replace-with')) + .sort(Expression.field('name').ascending()) + .replaceWith(Expression.field('nested')) + .limit(1) + .execute(); + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + {'father': 'John Doe Sr.', 'mother': 'Jane Doe'}, + ]); + }); + + test('replaceWith emits each nested map as a result document', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('replace-with')) + .sort(Expression.field('name').ascending()) + .replaceWith(Expression.field('nested')) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'father': 'John Doe Sr.', 'mother': 'Jane Doe'}, + {'a': 1, 'b': 2}, + {'x': 'foo', 'y': 'bar'}, + ]); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_sample_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_sample_e2e.dart new file mode 100644 index 000000000000..4357d8c23df6 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_sample_e2e.dart @@ -0,0 +1,47 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineSampleTests() { + group('Pipeline sample', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('sample withSize returns exactly requested count', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('sample')) + .sample(PipelineSample.withSize(5)) + .execute(); + expectResultCount(snapshot, 5); + for (final r in snapshot.result) { + expect(r.data(), isNotNull); + expect(r.data()!.containsKey('n'), true); + } + }); + + test('sample withPercentage returns results in expected range', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('sample')) + .sample(PipelineSample.withPercentage(0.2)) + .execute(); + expect(snapshot.result.length, greaterThanOrEqualTo(0)); + expect(snapshot.result.length, lessThanOrEqualTo(10)); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart new file mode 100644 index 000000000000..7df0783a15c4 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart @@ -0,0 +1,183 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; + +const String _col = 'pipeline-e2e'; +const int _maxBatchSize = 500; + +Future seedPipelineE2ECollections(FirebaseFirestore firestore) async { + final docs = >[ + ..._withTest('filter-sort', [ + {'active': true, 'score': 10, 'category': 'a'}, + {'active': true, 'score': 20, 'category': 'b'}, + {'active': false, 'score': 5, 'category': 'a'}, + {'active': true, 'score': 30, 'category': 'c'}, + {'active': true, 'score': 15, 'category': 'b'}, + ]), + ..._withTest('add-fields', [ + {'title': 'alpha', 'score': -7}, + {'title': 'beta', 'score': 42}, + {'title': 'gamma', 'score': 0}, + ]), + ..._withTest('select', [ + {'name': 'doc1', 'score': 1}, + {'name': 'doc2', 'score': 2}, + {'name': 'doc3', 'score': 3}, + ]), + ..._withTest('remove-fields', [ + {'keep': 'x', 'internal_id': 'id1', 'debug_flag': true}, + {'keep': 'y', 'internal_id': 'id2', 'debug_flag': false}, + {'keep': 'z', 'internal_id': 'id3', 'debug_flag': true}, + ]), + ..._withTest('replace-with', [ + { + 'name': 'Doc 1', + 'nested': {'father': 'John Doe Sr.', 'mother': 'Jane Doe'}, + }, + { + 'name': 'Doc 2', + 'nested': {'a': 1, 'b': 2}, + }, + { + 'name': 'Doc 3', + 'nested': {'x': 'foo', 'y': 'bar'}, + }, + ]), + ..._withTest('aggregate', [ + {'score': 10, 'category': 'x'}, + {'score': 20, 'category': 'x'}, + {'score': 30, 'category': 'y'}, + {'score': 40, 'category': 'y'}, + ]), + ..._withTest('unnest', [ + { + 'tags': ['dart', 'flutter'], + }, + { + 'tags': ['firestore'], + }, + { + 'tags': ['dart', 'firestore'], + }, + ]), + ..._withTest('union-a', [ + {'id': 'a1'}, + {'id': 'a2'}, + {'id': 'a3'}, + ]), + ..._withTest('union-b', [ + {'id': 'b1'}, + {'id': 'b2'}, + {'id': 'b3'}, + ]), + ..._withTest('sample', [ + {'n': 1}, + {'n': 2}, + {'n': 3}, + {'n': 4}, + {'n': 5}, + {'n': 6}, + {'n': 7}, + {'n': 8}, + {'n': 9}, + {'n': 10}, + ]), + ..._withTest('find-nearest', [ + { + 'embedding': VectorValue([0.1, 0.2, 0.3]), + 'label': 'near', + }, + { + 'embedding': VectorValue([0.15, 0.25, 0.35]), + 'label': 'near2', + }, + { + 'embedding': VectorValue([1.0, 0.0, 0.0]), + 'label': 'far', + }, + ]), + ..._withTest('expressions', [ + { + 'score': 60, + 'a': 1, + 'b': 2, + 's': ' AbC ', + 'm': {'x': 10, 'y': 20}, + 'email': 'demo@example.com', + 'pi': 3.14159, + 'dup_tags': ['a', 'b', 'a'], + 'bit_a': 6, + 'bit_b': 3, + 'arr': [1, 2, 3], + 'arr_b': [4, 5], + 'maybe_null': null, + 'ts': Timestamp.fromMillisecondsSinceEpoch(1700000000000), + }, + { + 'score': 70, + 'a': 10, + 'b': 20, + 's': 'xy', + 'm': {'x': 1}, + 'bit_a': 5, + 'bit_b': 1, + 'arr': [7, 8, 9], + 'arr_b': [10], + 'ts': Timestamp.fromMillisecondsSinceEpoch(1700003600000), + }, + {'score': 40, 'a': 5, 'b': 5}, + {'score': 80, 'a': 0, 'b': 100, 's': 'Hi'}, + { + 'score': 50, + 'a': 1, + 'b': 2, + 'tags': ['p', 'q'], + 'arr': [2, 4, 6], + 'arr_b': [8], + 's': 'a-b-c', + 'ts': Timestamp.fromMillisecondsSinceEpoch(1700007200000), + }, + ]), + ]; + await _clearAndSeed(firestore, _col, docs); +} + +List> _withTest( + String test, + List> maps, +) { + return maps.map((m) => {'test': test, ...m}).toList(); +} + +Future _clearAndSeed( + FirebaseFirestore firestore, + String collectionPath, + List> docs, +) async { + final col = firestore.collection(collectionPath); + final snapshot = await col.get(); + for (final chunk in _chunk(snapshot.docs, _maxBatchSize)) { + final batch = firestore.batch(); + for (final doc in chunk) { + batch.delete(doc.reference); + } + await batch.commit(); + } + var docIndex = 0; + for (final chunk in _chunk(docs, _maxBatchSize)) { + final batch = firestore.batch(); + for (final data in chunk) { + batch.set(col.doc('seed_$docIndex'), data); + docIndex++; + } + await batch.commit(); + } +} + +Iterable> _chunk(List list, int size) sync* { + for (var i = 0; i < list.length; i += size) { + yield list.sublist(i, i + size > list.length ? list.length : i + size); + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_select_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_select_e2e.dart new file mode 100644 index 000000000000..4b14ad5864c8 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_select_e2e.dart @@ -0,0 +1,42 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineSelectTests() { + group('Pipeline select', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('select returns only selected fields in expected order', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('select')) + .sort(Expression.field('score').ascending()) + .select( + Expression.field('name').as('name'), + Expression.field('score').as('score'), + ) + .limit(3) + .execute(); + expectResultCount(snapshot, 3); + expectResultsData(snapshot, [ + {'name': 'doc1', 'score': 1}, + {'name': 'doc2', 'score': 2}, + {'name': 'doc3', 'score': 3}, + ]); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_test_helpers.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_test_helpers.dart new file mode 100644 index 000000000000..34a0cef69cfd --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_test_helpers.dart @@ -0,0 +1,50 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter_test/flutter_test.dart'; + +/// Asserts that [snapshot] has exactly [count] results. +void expectResultCount(PipelineSnapshot snapshot, int count) { + expect( + snapshot.result.length, + count, + reason: 'Expected $count pipeline results', + ); +} + +/// Asserts that [snapshot] has the same number of results as [expectedData] +/// and each result's data() deep-equals the corresponding expected map. +/// Keys in [expectedData] are checked; extra keys in actual data are ignored +/// when [exactMatch] is false (default). Set [exactMatch] to true to require +/// identical keys. +void expectResultsData( + PipelineSnapshot snapshot, + List> expectedData, { + bool exactMatch = false, +}) { + expect( + snapshot.result.length, + expectedData.length, + reason: 'Result count mismatch', + ); + for (var i = 0; i < expectedData.length; i++) { + final result = snapshot.result[i]; + final data = result.data(); + expect(data, isNotNull, reason: 'Result $i has null data'); + final actual = data!; + final expected = expectedData[i]; + if (exactMatch) { + expect(actual, expected, reason: 'Result $i data mismatch'); + } else { + for (final entry in expected.entries) { + expect( + actual[entry.key], + entry.value, + reason: 'Result $i field ${entry.key}', + ); + } + } + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_unnest_union_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_unnest_union_e2e.dart new file mode 100644 index 000000000000..dac760d19043 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_unnest_union_e2e.dart @@ -0,0 +1,63 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'pipeline_test_helpers.dart'; + +void runPipelineUnnestUnionTests() { + group('Pipeline unnest and union', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('unnest produces one row per array element with tag field', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('unnest')) + .unnest(Expression.field('tags').as('tag')) + .sort(Expression.field('tag').ascending()) + .limit(10) + .execute(); + expectResultCount(snapshot, 5); + final tags = snapshot.result + .map((r) => r.data()!['tag'] as String) + .toList(); + expect(tags..sort(), [ + 'dart', + 'dart', + 'firestore', + 'firestore', + 'flutter', + ]); + }); + + test( + 'union concatenates both pipelines with deterministic total count', + () async { + final other = firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('union-b')) + .limit(5); + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('union-a')) + .limit(5) + .union(other) + .execute(); + expectResultCount(snapshot, 6); + }, + ); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/.gitignore b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/.gitignore new file mode 100644 index 000000000000..7a7f9873ad7d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/AppFrameworkInfo.plist b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000000..1dc6cf7652ba --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 13.0 + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Debug.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000000..ec97fc6f3021 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Release.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000000..c4855bfe2000 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Podfile b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Podfile new file mode 100644 index 000000000000..6649374d4c19 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '15.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +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 + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.pbxproj b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..238fb056204e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,741 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 2B45BBBA04F26970F9DC2428 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9D2411717BE352C92EC6263 /* Pods_RunnerTests.framework */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D3B189D93111F21B593E07CE /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = FC9AF0E7C3463CF0E820724D /* GoogleService-Info.plist */; }; + ED8175A9DDB4B6F569867736 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 344F3B3BBCDBB7DF16FCD695 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 060D24293863437D08A9EF6D /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 0A1494B03E7E4E5E8FCD37E4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 24A69F3F28EEBABDA3E3C6E5 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 344F3B3BBCDBB7DF16FCD695 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9A6E43430478085B3F4B8179 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 9B52183BF5A24CC0FD358BC5 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + D44D6373BC6CC1B25B52520C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + D9D2411717BE352C92EC6263 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FC9AF0E7C3463CF0E820724D /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7A5921923875F445DD42E396 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2B45BBBA04F26970F9DC2428 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ED8175A9DDB4B6F569867736 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33AEEB36D1DBFD083FE19F82 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 344F3B3BBCDBB7DF16FCD695 /* Pods_Runner.framework */, + D9D2411717BE352C92EC6263 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 726BAFFB79E9610C171E5B05 /* Pods */ = { + isa = PBXGroup; + children = ( + 9B52183BF5A24CC0FD358BC5 /* Pods-Runner.debug.xcconfig */, + D44D6373BC6CC1B25B52520C /* Pods-Runner.release.xcconfig */, + 0A1494B03E7E4E5E8FCD37E4 /* Pods-Runner.profile.xcconfig */, + 060D24293863437D08A9EF6D /* Pods-RunnerTests.debug.xcconfig */, + 24A69F3F28EEBABDA3E3C6E5 /* Pods-RunnerTests.release.xcconfig */, + 9A6E43430478085B3F4B8179 /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + FC9AF0E7C3463CF0E820724D /* GoogleService-Info.plist */, + 726BAFFB79E9610C171E5B05 /* Pods */, + 33AEEB36D1DBFD083FE19F82 /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 11FC74FA85B59C7E267B4550 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 7A5921923875F445DD42E396 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 6F498101593ECA79F30C31E4 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + B4380A12E6068F3FEA627E84 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + D3B189D93111F21B593E07CE /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 11FC74FA85B59C7E267B4550 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 6F498101593ECA79F30C31E4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + B4380A12E6068F3FEA627E84 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + inputPaths = ( + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = YYX2P3XVJ7; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 060D24293863437D08A9EF6D /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 24A69F3F28EEBABDA3E3C6E5 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9A6E43430478085B3F4B8179 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = YYX2P3XVJ7; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = YYX2P3XVJ7; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..919434a6254f --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..e3773d42e24c --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..21a3cc14c74e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000000..b6363034812b --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..d36b1fab2d9d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 zcmeHN2~<R zh`|8`A_PQ1nSu(UMFx?8j8PC!!VDphaL#`F42fd#7Vlc`zIE4n%Y~eiz4y1j|NDpi z?<@|pSJ-HM`qifhf@m%MamgwK83`XpBA<+azdF#2QsT{X@z0A9Bq>~TVErigKH1~P zRX-!h-f0NJ4Mh++{D}J+K>~~rq}d%o%+4dogzXp7RxX4C>Km5XEI|PAFDmo;DFm6G zzjVoB`@qW98Yl0Kvc-9w09^PrsobmG*Eju^=3f?0o-t$U)TL1B3;sZ^!++3&bGZ!o-*6w?;oOhf z=A+Qb$scV5!RbG+&2S}BQ6YH!FKb0``VVX~T$dzzeSZ$&9=X$3)_7Z{SspSYJ!lGE z7yig_41zpQ)%5dr4ff0rh$@ky3-JLRk&DK)NEIHecf9c*?Z1bUB4%pZjQ7hD!A0r-@NF(^WKdr(LXj|=UE7?gBYGgGQV zidf2`ZT@pzXf7}!NH4q(0IMcxsUGDih(0{kRSez&z?CFA0RVXsVFw3^u=^KMtt95q z43q$b*6#uQDLoiCAF_{RFc{!H^moH_cmll#Fc^KXi{9GDl{>%+3qyfOE5;Zq|6#Hb zp^#1G+z^AXfRKaa9HK;%b3Ux~U@q?xg<2DXP%6k!3E)PA<#4$ui8eDy5|9hA5&{?v z(-;*1%(1~-NTQ`Is1_MGdQ{+i*ccd96ab$R$T3=% zw_KuNF@vI!A>>Y_2pl9L{9h1-C6H8<)J4gKI6{WzGBi<@u3P6hNsXG=bRq5c+z;Gc3VUCe;LIIFDmQAGy+=mRyF++u=drBWV8-^>0yE9N&*05XHZpPlE zxu@?8(ZNy7rm?|<+UNe0Vs6&o?l`Pt>P&WaL~M&#Eh%`rg@Mbb)J&@DA-wheQ>hRV z<(XhigZAT z>=M;URcdCaiO3d^?H<^EiEMDV+7HsTiOhoaMX%P65E<(5xMPJKxf!0u>U~uVqnPN7T!X!o@_gs3Ct1 zlZ_$5QXP4{Aj645wG_SNT&6m|O6~Tsl$q?nK*)(`{J4b=(yb^nOATtF1_aS978$x3 zx>Q@s4i3~IT*+l{@dx~Hst21fR*+5}S1@cf>&8*uLw-0^zK(+OpW?cS-YG1QBZ5q! zgTAgivzoF#`cSz&HL>Ti!!v#?36I1*l^mkrx7Y|K6L#n!-~5=d3;K<;Zqi|gpNUn_ z_^GaQDEQ*jfzh;`j&KXb66fWEk1K7vxQIMQ_#Wu_%3 z4Oeb7FJ`8I>Px;^S?)}2+4D_83gHEq>8qSQY0PVP?o)zAv3K~;R$fnwTmI-=ZLK`= zTm+0h*e+Yfr(IlH3i7gUclNH^!MU>id$Jw>O?2i0Cila#v|twub21@e{S2v}8Z13( zNDrTXZVgris|qYm<0NU(tAPouG!QF4ZNpZPkX~{tVf8xY690JqY1NVdiTtW+NqyRP zZ&;T0ikb8V{wxmFhlLTQ&?OP7 z;(z*<+?J2~z*6asSe7h`$8~Se(@t(#%?BGLVs$p``;CyvcT?7Y!{tIPva$LxCQ&4W z6v#F*);|RXvI%qnoOY&i4S*EL&h%hP3O zLsrFZhv&Hu5tF$Lx!8(hs&?!Kx5&L(fdu}UI5d*wn~A`nPUhG&Rv z2#ixiJdhSF-K2tpVL=)5UkXRuPAFrEW}7mW=uAmtVQ&pGE-&az6@#-(Te^n*lrH^m@X-ftVcwO_#7{WI)5v(?>uC9GG{lcGXYJ~Q8q zbMFl7;t+kV;|;KkBW2!P_o%Czhw&Q(nXlxK9ak&6r5t_KH8#1Mr-*0}2h8R9XNkr zto5-b7P_auqTJb(TJlmJ9xreA=6d=d)CVbYP-r4$hDn5|TIhB>SReMfh&OVLkMk-T zYf%$taLF0OqYF?V{+6Xkn>iX@TuqQ?&cN6UjC9YF&%q{Ut3zv{U2)~$>-3;Dp)*(? zg*$mu8^i=-e#acaj*T$pNowo{xiGEk$%DusaQiS!KjJH96XZ-hXv+jk%ard#fu=@Q z$AM)YWvE^{%tDfK%nD49=PI|wYu}lYVbB#a7wtN^Nml@CE@{Gv7+jo{_V?I*jkdLD zJE|jfdrmVbkfS>rN*+`#l%ZUi5_bMS<>=MBDNlpiSb_tAF|Zy`K7kcp@|d?yaTmB^ zo?(vg;B$vxS|SszusORgDg-*Uitzdi{dUV+glA~R8V(?`3GZIl^egW{a919!j#>f` znL1o_^-b`}xnU0+~KIFLQ)$Q6#ym%)(GYC`^XM*{g zv3AM5$+TtDRs%`2TyR^$(hqE7Y1b&`Jd6dS6B#hDVbJlUXcG3y*439D8MrK!2D~6gn>UD4Imctb z+IvAt0iaW73Iq$K?4}H`7wq6YkTMm`tcktXgK0lKPmh=>h+l}Y+pDtvHnG>uqBA)l zAH6BV4F}v$(o$8Gfo*PB>IuaY1*^*`OTx4|hM8jZ?B6HY;F6p4{`OcZZ(us-RVwDx zUzJrCQlp@mz1ZFiSZ*$yX3c_#h9J;yBE$2g%xjmGF4ca z&yL`nGVs!Zxsh^j6i%$a*I3ZD2SoNT`{D%mU=LKaEwbN(_J5%i-6Va?@*>=3(dQy` zOv%$_9lcy9+(t>qohkuU4r_P=R^6ME+wFu&LA9tw9RA?azGhjrVJKy&8=*qZT5Dr8g--d+S8zAyJ$1HlW3Olryt`yE zFIph~Z6oF&o64rw{>lgZISC6p^CBer9C5G6yq%?8tC+)7*d+ib^?fU!JRFxynRLEZ zj;?PwtS}Ao#9whV@KEmwQgM0TVP{hs>dg(1*DiMUOKHdQGIqa0`yZnHk9mtbPfoLx zo;^V6pKUJ!5#n`w2D&381#5#_t}AlTGEgDz$^;u;-vxDN?^#5!zN9ngytY@oTv!nc zp1Xn8uR$1Z;7vY`-<*?DfPHB;x|GUi_fI9@I9SVRv1)qETbNU_8{5U|(>Du84qP#7 z*l9Y$SgA&wGbj>R1YeT9vYjZuC@|{rajTL0f%N@>3$DFU=`lSPl=Iv;EjuGjBa$Gw zHD-;%YOE@<-!7-Mn`0WuO3oWuL6tB2cpPw~Nvuj|KM@))ixuDK`9;jGMe2d)7gHin zS<>k@!x;!TJEc#HdL#RF(`|4W+H88d4V%zlh(7#{q2d0OQX9*FW^`^_<3r$kabWAB z$9BONo5}*(%kx zOXi-yM_cmB3>inPpI~)duvZykJ@^^aWzQ=eQ&STUa}2uT@lV&WoRzkUoE`rR0)`=l zFT%f|LA9fCw>`enm$p7W^E@U7RNBtsh{_-7vVz3DtB*y#*~(L9+x9*wn8VjWw|Q~q zKFsj1Yl>;}%MG3=PY`$g$_mnyhuV&~O~u~)968$0b2!Jkd;2MtAP#ZDYw9hmK_+M$ zb3pxyYC&|CuAbtiG8HZjj?MZJBFbt`ryf+c1dXFuC z0*ZQhBzNBd*}s6K_G}(|Z_9NDV162#y%WSNe|FTDDhx)K!c(mMJh@h87@8(^YdK$&d*^WQe8Z53 z(|@MRJ$Lk-&ii74MPIs80WsOFZ(NX23oR-?As+*aq6b?~62@fSVmM-_*cb1RzZ)`5$agEiL`-E9s7{GM2?(KNPgK1(+c*|-FKoy}X(D_b#etO|YR z(BGZ)0Ntfv-7R4GHoXp?l5g#*={S1{u-QzxCGng*oWr~@X-5f~RA14b8~B+pLKvr4 zfgL|7I>jlak9>D4=(i(cqYf7#318!OSR=^`xxvI!bBlS??`xxWeg?+|>MxaIdH1U~#1tHu zB{QMR?EGRmQ_l4p6YXJ{o(hh-7Tdm>TAX380TZZZyVkqHNzjUn*_|cb?T? zt;d2s-?B#Mc>T-gvBmQZx(y_cfkXZO~{N zT6rP7SD6g~n9QJ)8F*8uHxTLCAZ{l1Y&?6v)BOJZ)=R-pY=Y=&1}jE7fQ>USS}xP#exo57uND0i*rEk@$;nLvRB@u~s^dwRf?G?_enN@$t* zbL%JO=rV(3Ju8#GqUpeE3l_Wu1lN9Y{D4uaUe`g>zlj$1ER$6S6@{m1!~V|bYkhZA z%CvrDRTkHuajMU8;&RZ&itnC~iYLW4DVkP<$}>#&(`UO>!n)Po;Mt(SY8Yb`AS9lt znbX^i?Oe9r_o=?})IHKHoQGKXsps_SE{hwrg?6dMI|^+$CeC&z@*LuF+P`7LfZ*yr+KN8B4{Nzv<`A(wyR@!|gw{zB6Ha ziwPAYh)oJ(nlqSknu(8g9N&1hu0$vFK$W#mp%>X~AU1ay+EKWcFdif{% z#4!4aoVVJ;ULmkQf!ke2}3hqxLK>eq|-d7Ly7-J9zMpT`?dxo6HdfJA|t)?qPEVBDv z{y_b?4^|YA4%WW0VZd8C(ZgQzRI5(I^)=Ub`Y#MHc@nv0w-DaJAqsbEHDWG8Ia6ju zo-iyr*sq((gEwCC&^TYBWt4_@|81?=B-?#P6NMff(*^re zYqvDuO`K@`mjm_Jd;mW_tP`3$cS?R$jR1ZN09$YO%_iBqh5ftzSpMQQtxKFU=FYmP zeY^jph+g<4>YO;U^O>-NFLn~-RqlHvnZl2yd2A{Yc1G@Ga$d+Q&(f^tnPf+Z7serIU};17+2DU_f4Z z@GaPFut27d?!YiD+QP@)T=77cR9~MK@bd~pY%X(h%L={{OIb8IQmf-!xmZkm8A0Ga zQSWONI17_ru5wpHg3jI@i9D+_Y|pCqVuHJNdHUauTD=R$JcD2K_liQisqG$(sm=k9;L* z!L?*4B~ql7uioSX$zWJ?;q-SWXRFhz2Jt4%fOHA=Bwf|RzhwqdXGr78y$J)LR7&3T zE1WWz*>GPWKZ0%|@%6=fyx)5rzUpI;bCj>3RKzNG_1w$fIFCZ&UR0(7S?g}`&Pg$M zf`SLsz8wK82Vyj7;RyKmY{a8G{2BHG%w!^T|Njr!h9TO2LaP^_f22Q1=l$QiU84ao zHe_#{S6;qrC6w~7{y(hs-?-j?lbOfgH^E=XcSgnwW*eEz{_Z<_Px$?ny*JR5%f>l)FnDQ543{x%ZCiu33$Wg!pQFfT_}?5Q|_VSlIbLC`dpoMXL}9 zHfd9&47Mo(7D231gb+kjFxZHS4-m~7WurTH&doVX2KI5sU4v(sJ1@T9eCIKPjsqSr z)C01LsCxk=72-vXmX}CQD#BD;Cthymh&~=f$Q8nn0J<}ZrusBy4PvRNE}+1ceuj8u z0mW5k8fmgeLnTbWHGwfKA3@PdZxhn|PypR&^p?weGftrtCbjF#+zk_5BJh7;0`#Wr zgDpM_;Ax{jO##IrT`Oz;MvfwGfV$zD#c2xckpcXC6oou4ML~ezCc2EtnsQTB4tWNg z?4bkf;hG7IMfhgNI(FV5Gs4|*GyMTIY0$B=_*mso9Ityq$m^S>15>-?0(zQ<8Qy<_TjHE33(?_M8oaM zyc;NxzRVK@DL6RJnX%U^xW0Gpg(lXp(!uK1v0YgHjs^ZXSQ|m#lV7ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 zcmds$`#;kQ7{|XelZftyR5~xW7?MLxS4^|Hw3&P7^y)@A9Fj{Xm1~_CIV^XZ%SLBn zA;!r`GqGHg=7>xrB{?psZQs88ZaedDoagm^KF{a*>G|dJWRSe^I$DNW008I^+;Kjt z>9p3GNR^I;v>5_`+91i(*G;u5|L+Bu6M=(afLjtkya#yZ175|z$pU~>2#^Z_pCZ7o z1c6UNcv2B3?; zX%qdxCXQpdKRz=#b*q0P%b&o)5ZrNZt7$fiETSK_VaY=mb4GK`#~0K#~9^ zcY!`#Af+4h?UMR-gMKOmpuYeN5P*RKF!(tb`)oe0j2BH1l?=>y#S5pMqkx6i{*=V9JF%>N8`ewGhRE(|WohnD59R^$_36{4>S zDFlPC5|k?;SPsDo87!B{6*7eqmMdU|QZ84>6)Kd9wNfh90=y=TFQay-0__>=<4pk& zYDjgIhL-jQ9o>z32K)BgAH+HxamL{ZL~ozu)Qqe@a`FpH=oQRA8=L-m-1dam(Ix2V z?du;LdMO+ooBelr^_y4{|44tmgH^2hSzPFd;U^!1p>6d|o)(-01z{i&Kj@)z-yfWQ)V#3Uo!_U}q3u`(fOs`_f^ueFii1xBNUB z6MecwJN$CqV&vhc+)b(p4NzGGEgwWNs z@*lUV6LaduZH)4_g!cE<2G6#+hJrWd5(|p1Z;YJ7ifVHv+n49btR}dq?HHDjl{m$T z!jLZcGkb&XS2OG~u%&R$(X+Z`CWec%QKt>NGYvd5g20)PU(dOn^7%@6kQb}C(%=vr z{?RP(z~C9DPnL{q^@pVw@|Vx~@3v!9dCaBtbh2EdtoNHm4kGxp>i#ct)7p|$QJs+U z-a3qtcPvhihub?wnJqEt>zC@)2suY?%-96cYCm$Q8R%-8$PZYsx3~QOLMDf(piXMm zB=<63yQk1AdOz#-qsEDX>>c)EES%$owHKue;?B3)8aRd}m~_)>SL3h2(9X;|+2#7X z+#2)NpD%qJvCQ0a-uzZLmz*ms+l*N}w)3LRQ*6>|Ub-fyptY(keUxw+)jfwF5K{L9 z|Cl_w=`!l_o><384d&?)$6Nh(GAm=4p_;{qVn#hI8lqewW7~wUlyBM-4Z|)cZr?Rh z=xZ&Ol>4(CU85ea(CZ^aO@2N18K>ftl8>2MqetAR53_JA>Fal`^)1Y--Am~UDa4th zKfCYpcXky$XSFDWBMIl(q=Mxj$iMBX=|j9P)^fDmF(5(5$|?Cx}DKEJa&XZP%OyE`*GvvYQ4PV&!g2|L^Q z?YG}tx;sY@GzMmsY`7r$P+F_YLz)(e}% zyakqFB<6|x9R#TdoP{R$>o7y(-`$$p0NxJ6?2B8tH)4^yF(WhqGZlM3=9Ibs$%U1w zWzcss*_c0=v_+^bfb`kBFsI`d;ElwiU%frgRB%qBjn@!0U2zZehBn|{%uNIKBA7n= zzE`nnwTP85{g;8AkYxA68>#muXa!G>xH22D1I*SiD~7C?7Za+9y7j1SHiuSkKK*^O zsZ==KO(Ua#?YUpXl{ViynyT#Hzk=}5X$e04O@fsMQjb}EMuPWFO0e&8(2N(29$@Vd zn1h8Yd>6z(*p^E{c(L0Lg=wVdupg!z@WG;E0k|4a%s7Up5C0c)55XVK*|x9RQeZ1J@1v9MX;>n34(i>=YE@Iur`0Vah(inE3VUFZNqf~tSz{1fz3Fsn_x4F>o(Yo;kpqvBe-sbwH(*Y zu$JOl0b83zu$JMvy<#oH^Wl>aWL*?aDwnS0iEAwC?DK@aT)GHRLhnz2WCvf3Ba;o=aY7 z2{Asu5MEjGOY4O#Ggz@@J;q*0`kd2n8I3BeNuMmYZf{}pg=jTdTCrIIYuW~luKecn z+E-pHY%ohj@uS0%^ z&(OxwPFPD$+#~`H?fMvi9geVLci(`K?Kj|w{rZ9JgthFHV+=6vMbK~0)Ea<&WY-NC zy-PnZft_k2tfeQ*SuC=nUj4H%SQ&Y$gbH4#2sT0cU0SdFs=*W*4hKGpuR1{)mV;Qf5pw4? zfiQgy0w3fC*w&Bj#{&=7033qFR*<*61B4f9K%CQvxEn&bsWJ{&winp;FP!KBj=(P6 z4Z_n4L7cS;ao2)ax?Tm|I1pH|uLpDSRVghkA_UtFFuZ0b2#>!8;>-_0ELjQSD-DRd z4im;599VHDZYtnWZGAB25W-e(2VrzEh|etsv2YoP#VbIZ{aFkwPrzJ#JvCvA*mXS& z`}Q^v9(W4GiSs}#s7BaN!WA2bniM$0J(#;MR>uIJ^uvgD3GS^%*ikdW6-!VFUU?JV zZc2)4cMsX@j z5HQ^e3BUzOdm}yC-xA%SY``k$rbfk z;CHqifhU*jfGM@DkYCecD9vl*qr58l6x<8URB=&%{!Cu3RO*MrKZ4VO}V6R0a zZw3Eg^0iKWM1dcTYZ0>N899=r6?+adUiBKPciJw}L$=1f4cs^bio&cr9baLF>6#BM z(F}EXe-`F=f_@`A7+Q&|QaZ??Txp_dB#lg!NH=t3$G8&06MFhwR=Iu*Im0s_b2B@| znW>X}sy~m#EW)&6E&!*0%}8UAS)wjt+A(io#wGI@Z2S+Ms1Cxl%YVE800007ip7{`C_J2TxPmfw%h$|%acrYHt)Re^PB%O&&=~a zhS(%I#+V>J-vjIib^<+s%ludY7y^C(P8nmqn9fp!i+?vr`bziDE=bx`%2W#Xyrj|i z!XQ4v1%L`m{7KT7q+LZNB^h8Ha2e=`Wp65^0;J00)_^G=au=8Yo;1b`CV&@#=jIBo zjN^JNVfYSs)+kDdGe7`1&8!?MQYKS?DuHZf3iogk_%#9E|5S zWeHrmAo>P;ejX7mwq#*}W25m^ZI+{(Z8fI?4jM_fffY0nok=+88^|*_DwcW>mR#e+ zX$F_KMdb6sRz!~7KkyN0G(3XQ+;z3X%PZ4gh;n-%62U<*VUKNv(D&Q->Na@Xb&u5Q3`3DGf+a8O5x7c#7+R+EAYl@R5us)CIw z7sT@_y~Ao@uL#&^LIh&QceqiT^+lb0YbFZt_SHOtWA%mgPEKVNvVgCsXy{5+zl*X8 zCJe)Q@y>wH^>l4;h1l^Y*9%-23TSmE>q5nI@?mt%n;Sj4Qq`Z+ib)a*a^cJc%E9^J zB;4s+K@rARbcBLT5P=@r;IVnBMKvT*)ew*R;&8vu%?Z&S>s?8?)3*YawM0P4!q$Kv zMmKh3lgE~&w&v%wVzH3Oe=jeNT=n@Y6J6TdHWTjXfX~-=1A1Bw`EW8rn}MqeI34nh zexFeA?&C3B2(E?0{drE@DA2pu(A#ElY&6el60Rn|Qpn-FkfQ8M93AfWIr)drgDFEU zghdWK)^71EWCP(@(=c4kfH1Y(4iugD4fve6;nSUpLT%!)MUHs1!zJYy4y||C+SwQ! z)KM&$7_tyM`sljP2fz6&Z;jxRn{Wup8IOUx8D4uh&(=O zx-7$a;U><*5L^!%xRlw)vAbh;sdlR||& ze}8_8%)c2Fwy=F&H|LM+p{pZB5DKTx>Y?F1N%BlZkXf!}JeGuMZk~LPi7{cidvUGB zAJ4LVeNV%XO>LTrklB#^-;8nb;}6l;1oW&WS=Mz*Az!4cqqQzbOSFq`$Q%PfD7srM zpKgP-D_0XPTRX*hAqeq0TDkJ;5HB1%$3Np)99#16c{ zJImlNL(npL!W|Gr_kxl1GVmF5&^$^YherS7+~q$p zt}{a=*RiD2Ikv6o=IM1kgc7zqpaZ;OB)P!1zz*i3{U()Dq#jG)egvK}@uFLa`oyWZ zf~=MV)|yJn`M^$N%ul5);JuQvaU1r2wt(}J_Qgyy`qWQI`hEeRX0uC@c1(dQ2}=U$ tNIIaX+dr)NRWXcxoR{>fqI{SF_dm1Ylv~=3YHI)h002ovPDHLkV1g(pWS;;4 literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 zcmVjJBgitF5mAp-i>4+KS_oR{|13AP->1TD4=w)g|)JHOx|a2Wk1Va z!k)vP$UcQ#mdj%wNQoaJ!w>jv_6&JPyutpQps?s5dmDQ>`%?Bvj>o<%kYG!YW6H-z zu`g$@mp`;qDR!51QaS}|ZToSuAGcJ7$2HF0z`ln4t!#Yg46>;vGG9N9{V@9z#}6v* zfP?}r6b{*-C*)(S>NECI_E~{QYzN5SXRmVnP<=gzP+_Sp(Aza_hKlZ{C1D&l*(7IKXxQC1Z9#6wx}YrGcn~g%;icdw>T0Rf^w0{ z$_wn1J+C0@!jCV<%Go5LA45e{5gY9PvZp8uM$=1}XDI+9m7!A95L>q>>oe0$nC->i zeexUIvq%Uk<-$>DiDb?!In)lAmtuMWxvWlk`2>4lNuhSsjAf2*2tjT`y;@d}($o)S zn(+W&hJ1p0xy@oxP%AM15->wPLp{H!k)BdBD$toBpJh+crWdsNV)qsHaqLg2_s|Ih z`8E9z{E3sA!}5aKu?T!#enD(wLw?IT?k-yWVHZ8Akz4k5(TZJN^zZgm&zM28sfTD2BYJ|Fde3Xzh;;S` z=GXTnY4Xc)8nYoz6&vF;P7{xRF-{|2Xs5>a5)@BrnQ}I(_x7Cgpx#5&Td^4Q9_FnQ zX5so*;#8-J8#c$OlA&JyPp$LKUhC~-e~Ij!L%uSMu!-VZG7Hx-L{m2DVR2i=GR(_% zCVD!4N`I)&Q5S`?P&fQZ=4#Dgt_v2-DzkT}K(9gF0L(owe-Id$Rc2qZVLqI_M_DyO z9@LC#U28_LU{;wGZ&))}0R2P4MhajKCd^K#D+JJ&JIXZ_p#@+7J9A&P<0kdRujtQ_ zOy>3=C$kgi6$0pW06KaLz!21oOryKM3ZUOWqppndxfH}QpgjEJ`j7Tzn5bk6K&@RA?vl##y z$?V~1E(!wB5rH`>3nc&@)|#<1dN2cMzzm=PGhQ|Yppne(C-Vlt450IXc`J4R0W@I7 zd1e5uW6juvO%ni(WX7BsKx3MLngO7rHO;^R5I~0^nE^9^E_eYLgiR9&KnJ)pBbfno zSVnW$0R+&6jOOsZ82}nJ126+c|%svPo;TeUku<2G7%?$oft zyaO;tVo}(W)VsTUhq^XmFi#2z%-W9a{7mXn{uzivYQ_d6b7VJG{77naW(vHt-uhnY zVN#d!JTqVh(7r-lhtXVU6o})aZbDt_;&wJVGl2FKYFBFpU-#9U)z#(A%=IVnqytR$SY-sO( z($oNE09{D^@OuYPz&w~?9>Fl5`g9u&ecFGhqX=^#fmR=we0CJw+5xna*@oHnkahk+ z9aWeE3v|An+O5%?4fA&$Fgu~H_YmqR!yIU!bFCk4!#pAj%(lI(A5n)n@Id#M)O9Yx zJU9oKy{sRAIV3=5>(s8n{8ryJ!;ho}%pn6hZKTKbqk=&m=f*UnK$zW3YQP*)pw$O* zIfLA^!-bmBl6%d_n$#tP8Zd_(XdA*z*WH|E_yILwjtI~;jK#v-6jMl^?<%Y%`gvpwv&cFb$||^v4D&V=aNy?NGo620jL3VZnA%s zH~I|qPzB~e(;p;b^gJr7Ure#7?8%F0m4vzzPy^^(q4q1OdthF}Fi*RmVZN1OwTsAP zn9CZP`FazX3^kG(KodIZ=Kty8DLTy--UKfa1$6XugS zk%6v$Kmxt6U!YMx0JQ)0qX*{CXwZZk$vEROidEc7=J-1;peNat!vS<3P-FT5po>iE z!l3R+<`#x|+_hw!HjQGV=8!q|76y8L7N8gP3$%0kfush|u0uU^?dKBaeRSBUpOZ0c z62;D&Mdn2}N}xHRFTRI?zRv=>=AjHgH}`2k4WK=#AHB)UFrR-J87GgX*x5fL^W2#d z=(%K8-oZfMO=i{aWRDg=FX}UubM4eotRDcn;OR#{3q=*?3mE3_oJ-~prjhxh%PgQT zyn)Qozaq0@o&|LEgS{Ind4Swsr;b`u185hZPOBLL<`d2%^Yp1?oL)=jnLi;Zo0ZDliTtQ^b5SmfIMe{T==zZkbvn$KTQGlbG8w}s@M3TZnde;1Am46P3juKb zl9GU&3F=q`>j!`?SyH#r@O59%@aMX^rx}Nxe<>NqpUp5=lX1ojGDIR*-D^SDuvCKF z?3$xG(gVUsBERef_YjPFl^rU9EtD{pt z0CXwpN7BN3!8>hajGaTVk-wl=9rxmfWtIhC{mheHgStLi^+Nz12a?4r(fz)?3A%at zMlvQmL<2-R)-@G1wJ0^zQK%mR=r4d{Y3fHp){nWXUL#|CqXl(+v+qDh>FkF9`eWrW zfr^D%LNfOcTNvtx0JXR35J0~Jpi2#P3Q&80w+nqNfc}&G0A~*)lGHKv=^FE+b(37|)zL;KLF>oiGfb(?&1 zV3XRu!Sw>@quKiab%g6jun#oZ%!>V#A%+lNc?q>6+VvyAn=kf_6z^(TZUa4Eelh{{ zqFX-#dY(EV@7l$NE&kv9u9BR8&Ojd#ZGJ6l8_BW}^r?DIS_rU2(XaGOK z225E@kH5Opf+CgD^{y29jD4gHbGf{1MD6ggQ&%>UG4WyPh5q_tb`{@_34B?xfSO*| zZv8!)q;^o-bz`MuxXk*G^}(6)ACb@=Lfs`Hxoh>`Y0NE8QRQ!*p|SH@{r8=%RKd4p z+#Ty^-0kb=-H-O`nAA3_6>2z(D=~Tbs(n8LHxD0`R0_ATFqp-SdY3(bZ3;VUM?J=O zKCNsxsgt@|&nKMC=*+ZqmLHhX1KHbAJs{nGVMs6~TiF%Q)P@>!koa$%oS zjXa=!5>P`vC-a}ln!uH1ooeI&v?=?v7?1n~P(wZ~0>xWxd_Aw;+}9#eULM7M8&E?Y zC-ZLhi3RoM92SXUb-5i-Lmt5_rfjE{6y^+24`y$1lywLyHO!)Boa7438K4#iLe?rh z2O~YGSgFUBH?og*6=r9rme=peP~ah`(8Zt7V)j5!V0KPFf_mebo3z95U8(up$-+EA^9dTRLq>Yl)YMBuch9%=e5B`Vnb>o zt03=kq;k2TgGe4|lGne&zJa~h(UGutjP_zr?a7~#b)@15XNA>Dj(m=gg2Q5V4-$)D|Q9}R#002ovPDHLkV1o7DH3k3x literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 zcmV-m2cP(fP)x~L`~4d)Rspd&<9kFh{hn*KP1LP0~$;u(LfAu zp%fx&qLBcRHx$G|3q(bv@+b;o0*D|jwD-Q9uQR(l*ST}s+uPgQ-MeFwZ#GS?b332? z&Tk$&_miXn3IGq)AmQ)3sisq{raD4(k*bHvpCe-TdWq^NRTEVM)i9xbgQ&ccnUVx* zEY%vS%gDcSg=!tuIK8$Th2_((_h^+7;R|G{n06&O2#6%LK`a}n?h_fL18btz<@lFG za}xS}u?#DBMB> zw^b($1Z)`9G?eP95EKi&$eOy@K%h;ryrR3la%;>|o*>CgB(s>dDcNOXg}CK9SPmD? zmr-s{0wRmxUnbDrYfRvnZ@d z6johZ2sMX{YkGSKWd}m|@V7`Degt-43=2M?+jR%8{(H$&MLLmS;-|JxnX2pnz;el1jsvqQz}pGSF<`mqEXRQ5sC4#BbwnB_4` zc5bFE-Gb#JV3tox9fp-vVEN{(tOCpRse`S+@)?%pz+zVJXSooTrNCUg`R6`hxwb{) zC@{O6MKY8tfZ5@!yy=p5Y|#+myRL=^{tc(6YgAnkg3I(Cd!r5l;|;l-MQ8B`;*SCE z{u)uP^C$lOPM z5d~UhKhRRmvv{LIa^|oavk1$QiEApSrP@~Jjbg`<*dW4TO?4qG%a%sTPUFz(QtW5( zM)lA+5)0TvH~aBaOAs|}?u2FO;yc-CZ1gNM1dAxJ?%m?YsGR`}-xk2*dxC}r5j$d* zE!#Vtbo69h>V4V`BL%_&$} z+oJAo@jQ^Tk`;%xw-4G>hhb&)B?##U+(6Fi7nno`C<|#PVA%$Y{}N-?(Gc$1%tr4Pc}}hm~yY#fTOe!@v9s-ik$dX~|ygArPhByaXn8 zpI^FUjNWMsTFKTP3X7m?UK)3m zp6rI^_zxRYrx6_QmhoWoDR`fp4R7gu6;gdO)!KexaoO2D88F9x#TM1(9Bn7g;|?|o z)~$n&Lh#hCP6_LOPD>a)NmhW})LADx2kq=X7}7wYRj-0?dXr&bHaRWCfSqvzFa=sn z-8^gSyn-RmH=BZ{AJZ~!8n5621GbUJV7Qvs%JNv&$%Q17s_X%s-41vAPfIR>;x0Wlqr5?09S>x#%Qkt>?(&XjFRY}*L6BeQ3 z<6XEBh^S7>AbwGm@XP{RkeEKj6@_o%oV?hDuUpUJ+r#JZO?!IUc;r0R?>mi)*ZpQ) z#((dn=A#i_&EQn|hd)N$#A*fjBFuiHcYvo?@y1 z5|fV=a^a~d!c-%ZbMNqkMKiSzM{Yq=7_c&1H!mXk60Uv32dV;vMg&-kQ)Q{+PFtwc zj|-uQ;b^gts??J*9VxxOro}W~Q9j4Em|zSRv)(WSO9$F$s=Ydu%Q+5DOid~lwk&we zY%W(Z@ofdwPHncEZzZgmqS|!gTj3wQq9rxQy+^eNYKr1mj&?tm@wkO*9@UtnRMG>c aR{jt9+;fr}hV%pg00001^@s67{VYS000c7NklQEG_j zup^)eW&WUIApqy$=APz8jE@awGp)!bsTjDbrJO`$x^ZR^dr;>)LW>{ zs70vpsD38v)19rI=GNk1b(0?Js9~rjsQsu*K;@SD40RB-3^gKU-MYC7G!Bw{fZsqp zih4iIi;Hr_xZ033Iu{sQxLS=}yBXgLMn40d++>aQ0#%8D1EbGZp7+ z5=mK?t31BkVYbGOxE9`i748x`YgCMwL$qMsChbSGSE1`p{nSmadR zcQ#R)(?!~dmtD0+D2!K zR9%!Xp1oOJzm(vbLvT^$IKp@+W2=-}qTzTgVtQ!#Y7Gxz}stUIm<1;oBQ^Sh2X{F4ibaOOx;5ZGSNK z0maF^@(UtV$=p6DXLgRURwF95C=|U8?osGhgOED*b z7woJ_PWXBD>V-NjQAm{~T%sjyJ{5tn2f{G%?J!KRSrrGvQ1(^`YLA5B!~eycY(e5_ z*%aa{at13SxC(=7JT7$IQF~R3sy`Nn%EMv!$-8ZEAryB*yB1k&stni)=)8-ODo41g zkJu~roIgAih94tb=YsL%iH5@^b~kU9M-=aqgXIrbtxMpFy5mekFm#edF9z7RQ6V}R zBIhbXs~pMzt0VWy1Fi$^fh+1xxLDoK09&5&MJl(q#THjPm(0=z2H2Yfm^a&E)V+a5 zbi>08u;bJsDRUKR9(INSc7XyuWv(JsD+BB*0hS)FO&l&7MdViuur@-<-EHw>kHRGY zqoT}3fDv2-m{NhBG8X}+rgOEZ;amh*DqN?jEfQdqxdj08`Sr=C-KmT)qU1 z+9Cl)a1mgXxhQiHVB}l`m;-RpmKy?0*|yl?FXvJkFxuu!fKlcmz$kN(a}i*saM3nr z0!;a~_%Xqy24IxA2rz<+08=B-Q|2PT)O4;EaxP^6qixOv7-cRh?*T?zZU`{nIM-at zTKYWr9rJ=tppQ9I#Z#mLgINVB!pO-^FOcvFw6NhV0gztuO?g ztoA*C-52Q-Z-P#xB4HAY3KQVd%dz1S4PA3vHp0aa=zAO?FCt zC_GaTyVBg2F!bBr3U@Zy2iJgIAt>1sf$JWA9kh{;L+P*HfUBX1Zy{4MgNbDfBV_ly z!y#+753arsZUt@366jIC0klaC@ckuk!qu=pAyf7&QmiBUT^L1&tOHzsK)4n|pmrVT zs2($4=?s~VejTFHbFdDOwG;_58LkIj1Fh@{glkO#F1>a==ymJS$z;gdedT1zPx4Kj ztjS`y_C}%af-RtpehdQDt3a<=W5C4$)9W@QAse;WUry$WYmr51ml9lkeunUrE`-3e zmq1SgSOPNEE-Mf+AGJ$g0M;3@w!$Ej;hMh=v=I+Lpz^n%Pg^MgwyqOkNyu2c^of)C z1~ALor3}}+RiF*K4+4{(1%1j3pif1>sv0r^mTZ?5Jd-It!tfPfiG_p$AY*Vfak%FG z4z#;wLtw&E&?}w+eKG^=#jF7HQzr8rV0mY<1YAJ_uGz~$E13p?F^fPSzXSn$8UcI$ z8er9{5w5iv0qf8%70zV71T1IBB1N}R5Kp%NO0=5wJalZt8;xYp;b{1K) zHY>2wW-`Sl{=NpR%iu3(u6l&)rc%%cSA#aV7WCowfbFR4wcc{LQZv~o1u_`}EJA3>ki`?9CKYTA!rhO)if*zRdd}Kn zEPfYbhoVE~!FI_2YbC5qAj1kq;xP6%J8+?2PAs?`V3}nyFVD#sV3+uP`pi}{$l9U^ zSz}_M9f7RgnnRhaoIJgT8us!1aB&4!*vYF07Hp&}L zCRlop0oK4DL@ISz{2_BPlezc;xj2|I z23RlDNpi9LgTG_#(w%cMaS)%N`e>~1&a3<{Xy}>?WbF>OOLuO+j&hc^YohQ$4F&ze z+hwnro1puQjnKm;vFG~o>`kCeUIlkA-2tI?WBKCFLMBY=J{hpSsQ=PDtU$=duS_hq zHpymHt^uuV1q@uc4bFb{MdG*|VoW@15Osrqt2@8ll0qO=j*uOXn{M0UJX#SUztui9FN4)K3{9!y8PC-AHHvpVTU;x|-7P+taAtyglk#rjlH2 z5Gq8ik}BPaGiM{#Woyg;*&N9R2{J0V+WGB69cEtH7F?U~Kbi6ksi*`CFXsi931q7Y zGO82?whBhN%w1iDetv%~wM*Y;E^)@Vl?VDj-f*RX>{;o_=$fU!&KAXbuadYZ46Zbg z&6jMF=49$uL^73y;;N5jaHYv)BTyfh&`qVLYn?`o6BCA_z-0niZz=qPG!vonK3MW_ zo$V96zM!+kJRs{P-5-rQVse0VBH*n6A58)4uc&gfHMa{gIhV2fGf{st>E8sKyP-$8zp~wJX^A*@DI&-;8>gANXZj zU)R+Y)PB?=)a|Kj>8NXEu^S_h^7R`~Q&7*Kn!xyvzVv&^>?^iu;S~R2e-2fJx-oUb cX)(b1KSk$MOV07*qoM6N<$f&6$jw%VRuvdN2+38CZWny1cRtlsl+0_KtW)EU14Ei(F!UtWuj4IK+3{sK@>rh zs1Z;=(DD&U6+tlyL?UnHVN^&g6QhFi2#HS+*qz;(>63G(`|jRtW|nz$Pv7qTovP!^ zP_jES{mr@O-02w%!^a?^1ZP!_KmQiz0L~jZ=W@Qt`8wzOoclQsAS<5YdH;a(4bGLE zk8s}1If(PSIgVi!XE!5kA?~z*sobvNyohr;=Q_@h2@$6Flyej3J)D-6YfheRGl`HEcPk|~huT_2-U?PfL=4BPV)f1o!%rQ!NMt_MYw-5bUSwQ9Z&zC>u zOrl~UJglJNa%f50Ok}?WB{on`Ci`p^Y!xBA?m@rcJXLxtrE0FhRF3d*ir>yzO|BD$ z3V}HpFcCh6bTzY}Nt_(W%QYd3NG)jJ4<`F<1Od) zfQblTdC&h2lCz`>y?>|9o2CdvC8qZeIZt%jN;B7Hdn2l*k4M4MFEtq`q_#5?}c$b$pf_3y{Y!cRDafZBEj-*OD|gz#PBDeu3QoueOesLzB+O zxjf2wvf6Wwz>@AiOo2mO4=TkAV+g~%_n&R;)l#!cBxjuoD$aS-`IIJv7cdX%2{WT7 zOm%5rs(wqyPE^k5SIpUZ!&Lq4<~%{*>_Hu$2|~Xa;iX*tz8~G6O3uFOS?+)tWtdi| zV2b#;zRN!m@H&jd=!$7YY6_}|=!IU@=SjvGDFtL;aCtw06U;-v^0%k0FOyESt z1Wv$={b_H&8FiRV?MrzoHWd>%v6KTRU;-v^Miiz+@q`(BoT!+<37CKhoKb)|8!+RG z6BQFU^@fRW;s8!mOf2QViKQGk0TVER6EG1`#;Nm39Do^PoT!+<37AD!%oJe86(=et zZ~|sLzU>V-qYiU6V8$0GmU7_K8|Fd0B?+9Un1BhKAz#V~Fk^`mJtlCX#{^8^M8!me z8Yg;8-~>!e<-iG;h*0B1kBKm}hItVGY6WnjVpgnTTAC$rqQ^v)4KvOtpY|sIj@WYg zyw##ZZ5AC2IKNC;^hwg9BPk0wLStlmBr;E|$5GoAo$&Ui_;S9WY62n3)i49|T%C#i017z3J=$RF|KyZWnci*@lW4 z=AKhNN6+m`Q!V3Ye68|8y@%=am>YD0nG99M)NWc20%)gwO!96j7muR}Fr&54SxKP2 zP30S~lt=a*qDlbu3+Av57=9v&vr<6g0&`!8E2fq>I|EJGKs}t|{h7+KT@)LfIV-3K zK)r_fr2?}FFyn*MYoLC>oV-J~eavL2ho4a4^r{E-8m2hi>~hA?_vIG4a*KT;2eyl1 zh_hUvUJpNCFwBvRq5BI*srSle>c6%n`#VNsyC|MGa{(P&08p=C9+WUw9Hl<1o9T4M zdD=_C0F7#o8A_bRR?sFNmU0R6tW`ElnF8p53IdHo#S9(JoZCz}fHwJ6F<&?qrpVqE zte|m%89JQD+XwaPU#%#lVs-@-OL);|MdfINd6!XwP2h(eyafTUsoRkA%&@fe?9m@jw-v(yTTiV2(*fthQH9}SqmsRPVnwwbV$1E(_lkmo&S zF-truCU914_$jpqjr(>Ha4HkM4YMT>m~NosUu&UZ>zirfHo%N6PPs9^_o$WqPA0#5 z%tG>qFCL+b*0s?sZ;Sht0nE7Kl>OVXy=gjWxxK;OJ3yGd7-pZf7JYNcZo2*1SF`u6 zHJyRRxGw9mDlOiXqVMsNe#WX`fC`vrtjSQ%KmLcl(lC>ZOQzG^%iql2w-f_K@r?OE zwCICifM#L-HJyc7Gm>Ern?+Sk3&|Khmu4(~3qa$(m6Ub^U0E5RHq49za|XklN#?kP zl;EstdW?(_4D>kwjWy2f!LM)y?F94kyU3`W!6+AyId-89v}sXJpuic^NLL7GJItl~ zsiuB98AI-(#Mnm|=A-R6&2fwJ0JVSY#Q>&3$zFh|@;#%0qeF=j5Ajq@4i0tIIW z&}sk$&fGwoJpe&u-JeGLi^r?dO`m=y(QO{@h zQqAC7$rvz&5+mo3IqE?h=a~6m>%r5Quapvzq;{y~p zJpyXOBgD9VrW7@#p6l7O?o3feml(DtSL>D^R) zZUY%T2b0-vBAFN7VB;M88!~HuOXi4KcI6aRQ&h|XQ0A?m%j2=l1f0cGP}h(oVfJ`N zz#PpmFC*ieab)zJK<4?^k=g%OjPnkANzbAbmGZHoVRk*mTfm75s_cWVa`l*f$B@xu z5E*?&@seIo#*Y~1rBm!7sF9~~u6Wrj5oICUOuz}CS)jdNIznfzCA(stJ(7$c^e5wN z?lt>eYgbA!kvAR7zYSD&*r1$b|(@;9dcZ^67R0 zXAXJKa|5Sdmj!g578Nwt6d$sXuc&MWezA0Whd`94$h{{?1IwXP4)Tx4obDK%xoFZ_Z zjjHJ_P@R_e5blG@yEjnaJb`l;s%Lb2&=8$&Ct-fV`E^4CUs)=jTk!I}2d&n!f@)bm z@ z_4Dc86+3l2*p|~;o-Sb~oXb_RuLmoifDU^&Te$*FevycC0*nE3Xws8gsWp|Rj2>SM zns)qcYj?^2sd8?N!_w~4v+f-HCF|a$TNZDoNl$I1Uq87euoNgKb6&r26TNrfkUa@o zfdiFA@p{K&mH3b8i!lcoz)V{n8Q@g(vR4ns4r6w;K z>1~ecQR0-<^J|Ndg5fvVUM9g;lbu-){#ghGw(fg>L zh)T5Ljb%lWE;V9L!;Cqk>AV1(rULYF07ZBJbGb9qbSoLAd;in9{)95YqX$J43-dY7YU*k~vrM25 zxh5_IqO0LYZW%oxQ5HOzmk4x{atE*vipUk}sh88$b2tn?!ujEHn`tQLe&vo}nMb&{ zio`xzZ&GG6&ZyN3jnaQy#iVqXE9VT(3tWY$n-)uWDQ|tc{`?fq2F`oQ{;d3aWPg4Hp-(iE{ry>MIPWL> iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000000..89c2725b70f1 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000000..f2e259c7c939 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/Main.storyboard b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000000..f3c28516fb38 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Info.plist b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Info.plist new file mode 100644 index 000000000000..68b861da4bf1 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Info.plist @@ -0,0 +1,72 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Pipeline Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + pipeline_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneDelegateClassName + FlutterSceneDelegate + UISceneConfigurationName + flutter + UISceneStoryboardFile + Main + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Runner-Bridging-Header.h b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000000..308a2a560b42 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/RunnerTests/RunnerTests.swift b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000000..b0d10f2e4304 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,10 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart new file mode 100644 index 000000000000..1875e5da6ece --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart @@ -0,0 +1,1377 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/material.dart'; + +// Import after file is generated through flutterfire_cli. +// import 'firebase_options.dart'; + +const String _collectionId = 'pipeline_test_2'; + +bool shouldUseFirestoreEmulator = false; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + // Enable this line instead once you have the firebase_options.dart generated and + // imported through flutterfire_cli. + // await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + if (shouldUseFirestoreEmulator) { + FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080); + } + runApp(const PipelineExampleApp()); +} + +class PipelineExampleApp extends StatelessWidget { + const PipelineExampleApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Pipeline Example', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const PipelineExamplePage(), + ); + } +} + +class _PipelineExamplePageState extends State { + final List _log = []; + bool _loading = false; + List>> _seedDocRefs = []; + + final _firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + + void _logMessage(String message) { + setState(() { + _log.insert( + 0, + '[${DateTime.now().toString().substring(11, 19)}] $message', + ); + }); + } + + void _logError(String context, Object error, StackTrace? st) { + debugPrint('$context: $error'); + if (st != null) debugPrintStack(stackTrace: st); + } + + Future _seedCollection() async { + if (_loading) return; + setState(() { + _loading = true; + _log.clear(); + }); + _logMessage('Seeding collection "$_collectionId"...'); + + try { + final col = _firestore.collection(_collectionId); + + final batch = _firestore.batch(); + _seedDocRefs = []; + + final items = [ + {'title': 'Item A', 'score': 10, 'year': 2022, 'category': 'tech'}, + {'title': 'Item B', 'score': 25, 'year': 2023, 'category': 'tech'}, + {'title': 'Item C', 'score': 5, 'year': 2021, 'category': 'news'}, + {'title': 'Item D', 'score': 40, 'year': 2023, 'category': 'news'}, + {'title': 'Item E', 'score': 15, 'year': 2022, 'category': 'tech'}, + {'title': 'Item F', 'score': 30, 'year': 2024, 'category': 'news'}, + { + 'title': 'Item G', + 'score': 20, + 'year': 2023, + 'tags': ['x', 'y', 'z'], + }, + { + 'title': 'Item H', + 'score': 20, + 'year': 2023, + 'items': {'a': 'b', 'c': 'd'}, + }, + // For string expressions: trim, substring, stringReplaceAll, split, join + {'title': ' Padded ', 'score': 7, 'year': 2022, 'category': 'tech'}, + // For abs and conditional + { + 'title': 'Item Negative', + 'score': -12, + 'year': 2023, + 'category': 'news', + }, + // For array_length, array_sum, array_slice, array_concat + { + 'title': 'Item With Arrays', + 'score': 50, + 'scores': [10, 20, 30], + 'tags': ['p', 'q', 'r'], + 'year': 2024, + }, + // For if_absent (missing optional_field) + {'title': 'Item No Optional', 'score': 11, 'year': 2022}, + // Matches integration_test pipeline_seed "expressions" (for NOT / OR tests). + { + 'test': 'expressions', + 'score': 60, + 'a': 1, + 'b': 2, + 's': ' AbC ', + 'm': {'x': 10, 'y': 20}, + }, + { + 'test': 'expressions', + 'score': 70, + 'a': 10, + 'b': 20, + 's': 'xy', + 'm': {'x': 1}, + }, + {'test': 'expressions', 'score': 40, 'a': 5, 'b': 5}, + {'test': 'expressions', 'score': 80, 'a': 0, 'b': 100, 's': 'Hi'}, + { + 'test': 'expressions', + 'score': 50, + 'a': 1, + 'b': 2, + 'tags': ['p', 'q'], + }, + { + 'title': 'Regex Email Doc', + 'score': 99, + 'year': 2024, + 'category': 'tech', + 'email': 'demo@example.com', + 'pi': 3.14159, + }, + { + 'title': 'Dup Tags', + 'score': 8, + 'year': 2023, + 'category': 'tech', + 'tags': ['a', 'b', 'a'], + }, + ]; + + for (final item in items) { + final ref = col.doc(); + batch.set(ref, item); + if (_seedDocRefs.length < 2) _seedDocRefs.add(ref); + } + await batch.commit(); + _logMessage('Seeded ${items.length} documents.'); + } catch (e, st) { + _logError('Seed error', e, st); + } finally { + setState(() => _loading = false); + } + } + + /// Seeds the same data using individual set() calls (no batch). Useful for + /// debugging emulator issues where batch writes might behave differently. + Future _seedCollectionNoBatch() async { + if (_loading) return; + setState(() { + _loading = true; + _log.clear(); + }); + _logMessage('Seeding collection "$_collectionId" (no batch)...'); + + try { + final col = _firestore.collection(_collectionId); + _seedDocRefs = []; + + final items = [ + {'title': 'Item A', 'score': 10, 'year': 2022, 'category': 'tech'}, + {'title': 'Item B', 'score': 25, 'year': 2023, 'category': 'tech'}, + {'title': 'Item C', 'score': 5, 'year': 2021, 'category': 'news'}, + {'title': 'Item D', 'score': 40, 'year': 2023, 'category': 'news'}, + {'title': 'Item E', 'score': 15, 'year': 2022, 'category': 'tech'}, + {'title': 'Item F', 'score': 30, 'year': 2024, 'category': 'news'}, + { + 'title': 'Item G', + 'score': 20, + 'year': 2023, + 'tags': ['x', 'y', 'z'], + }, + { + 'title': 'Item H', + 'score': 20, + 'year': 2023, + 'items': {'a': 'b', 'c': 'd'}, + }, + {'title': ' Padded ', 'score': 7, 'year': 2022, 'category': 'tech'}, + { + 'title': 'Item Negative', + 'score': -12, + 'year': 2023, + 'category': 'news', + }, + { + 'title': 'Item With Arrays', + 'score': 50, + 'scores': [10, 20, 30], + 'tags': ['p', 'q', 'r'], + 'year': 2024, + }, + {'title': 'Item No Optional', 'score': 11, 'year': 2022}, + { + 'test': 'expressions', + 'score': 60, + 'a': 1, + 'b': 2, + 's': ' AbC ', + 'm': {'x': 10, 'y': 20}, + }, + { + 'test': 'expressions', + 'score': 70, + 'a': 10, + 'b': 20, + 's': 'xy', + 'm': {'x': 1}, + }, + {'test': 'expressions', 'score': 40, 'a': 5, 'b': 5}, + {'test': 'expressions', 'score': 80, 'a': 0, 'b': 100, 's': 'Hi'}, + { + 'test': 'expressions', + 'score': 50, + 'a': 1, + 'b': 2, + 'tags': ['p', 'q'], + }, + { + 'title': 'Regex Email Doc', + 'score': 99, + 'year': 2024, + 'category': 'tech', + 'email': 'demo@example.com', + 'pi': 3.14159, + }, + { + 'title': 'Dup Tags', + 'score': 8, + 'year': 2023, + 'category': 'tech', + 'tags': ['a', 'b', 'a'], + }, + ]; + + for (final item in items) { + final ref = col.doc(); + await ref.set(item); + if (_seedDocRefs.length < 2) _seedDocRefs.add(ref); + } + _logMessage('Seeded ${items.length} documents (no batch).'); + } catch (e, st) { + _logError('Seed (no batch) error', e, st); + } finally { + setState(() => _loading = false); + } + } + + Future _runPipeline( + String description, + Future Function() run, + ) async { + if (_loading) return; + setState(() { + _loading = true; + _log.clear(); + }); + _logMessage(description); + + try { + final snapshot = await run(); + _logMessage( + 'Found ${snapshot.result.length} result(s). Execution: ${snapshot.executionTime}', + ); + for (final r in snapshot.result) { + _logMessage(' doc: ${r.data()?.toString()}'); + } + } catch (e, st) { + _logError(description, e, st); + } finally { + setState(() => _loading = false); + } + } + + // 1: where + limit + Future _runPipeline1() => _runPipeline( + 'Pipeline 1: collection → where(score > 10) → limit(3)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('score').greaterThan(Expression.constant(10))) + .limit(3) + .execute(), + ); + + // 1b: execute with ExecuteOptions (indexMode: recommended) + Future _runPipelineExecuteOptions() => _runPipeline( + 'Pipeline 1b: same as 1 but execute(options: ExecuteOptions(indexMode: recommended))', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('score').greaterThan(Expression.constant(10))) + .limit(3) + .execute( + options: const ExecuteOptions(indexMode: IndexMode.recommended), + ), + ); + + // 2: select + Future _runPipeline2() => _runPipeline( + 'Pipeline 2: collection → where(year > 2022) → select(title, score, year) → limit(4)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('year').greaterThan(Expression.constant(2022))) + .select( + Expression.field('title'), + Expression.field('score'), + Expression.field('year'), + ) + .limit(4) + .execute(), + ); + + // 3: aggregate + Future _runPipeline3() => _runPipeline( + 'Pipeline 3: collection → aggregate(sum, avg, count_all)', + () => _firestore + .pipeline() + .collection(_collectionId) + .aggregate( + Expression.field('score').sum().as('total_score'), + Expression.field('score').average().as('avg_score'), + CountAll().as('doc_count'), + ) + .execute(), + ); + + // 4: addFields + Future _runPipeline4() => _runPipeline( + 'Pipeline 4: collection → addFields(score+100 as bonus) → limit(2)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field( + 'score', + ).add(Expression.constant(100)).as('bonus_score'), + ) + .limit(2) + .execute(), + ); + + // 5: distinct + Future _runPipeline5() => _runPipeline( + 'Pipeline 5: collection → distinct(category) → limit(5)', + () => _firestore + .pipeline() + .collection(_collectionId) + .distinct(Expression.field('category')) + .limit(5) + .execute(), + ); + + // 6: offset + Future _runPipeline6() => _runPipeline( + 'Pipeline 6: collection → limit(4) → offset(2)', + () => _firestore + .pipeline() + .collection(_collectionId) + .limit(4) + .offset(2) + .execute(), + ); + + // 7: removeFields + Future _runPipeline7() => _runPipeline( + 'Pipeline 7: collection → removeFields(category) → limit(2)', + () => _firestore + .pipeline() + .collection(_collectionId) + .removeFields('category') + .limit(2) + .execute(), + ); + + // 8: replaceWith + Future _runPipeline8() => _runPipeline( + 'Pipeline 8: collection → replaceWith(constant) → limit(1)', + () => _firestore + .pipeline() + .collection(_collectionId) + .replaceWith(Expression.field('items')) + // .limit(1) + .execute(), + ); + + // 9: sample + Future _runPipeline9() => _runPipeline( + 'Pipeline 9: collection → sample(size: 3)', + () => _firestore + .pipeline() + .collection(_collectionId) + .sample(PipelineSample.withSize(3)) + .execute(), + ); + + // 10: sort + Future _runPipeline10() => _runPipeline( + 'Pipeline 10: collection → sort(score desc) → limit(3)', + () => _firestore + .pipeline() + .collection(_collectionId) + .sort(Expression.field('score').descending()) + .limit(3) + .execute(), + ); + + // 11: aggregateStage with groups + Future _runPipeline11() => _runPipeline( + 'Pipeline 11: collection → aggregateStage(groups: category)', + () => _firestore + .pipeline() + .collection(_collectionId) + .aggregateWithOptions( + AggregateStageOptions( + accumulators: [ + Expression.field('score').sum().as('total'), + CountAll().as('count'), + ], + groups: [Expression.field('category')], + ), + ) + .execute(), + ); + + // 12: collectionGroup + Future _runPipeline12() => _runPipeline( + 'Pipeline 12: collectionGroup → limit(2)', + () => + _firestore.pipeline().collectionGroup(_collectionId).limit(2).execute(), + ); + + // 13: documents + Future _runPipeline13() async { + final col = _firestore.collection(_collectionId); + final ref1 = col.doc(); + final ref2 = col.doc(); + final refs = [ref1, ref2]; + await ref1.set({'title': 'Pipeline 13 doc 1', 'n': 1}); + await ref2.set({'title': 'Pipeline 13 doc 2', 'n': 2}); + return _runPipeline( + 'Pipeline 13: documents(ref1, ref2) → addFields(extra)', + () => _firestore + .pipeline() + .documents(refs) + .addFields(Expression.constant(1).as('extra')) + .execute(), + ); + } + + // 14: database + Future _runPipeline14() => _runPipeline( + 'Pipeline 14: database() → limit(2)', + () => _firestore.pipeline().database().execute(), + ); + + // 15: findNearest (may fail without vector index) + Future _runPipeline15() => _runPipeline( + 'Pipeline 15: collection → findNearest (needs vector index)', + () => _firestore + .pipeline() + .collection(_collectionId) + .findNearest( + Field('embedding'), + [0.1, 0.2, 0.3], + DistanceMeasure.cosine, + limit: 2, + ) + .execute(), + ); + + // 16: unnest + Future _runPipeline16() => _runPipeline( + 'Pipeline 16: collection → where(has tags) → unnest(tags) → limit(5)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('tags').exists()) + .unnest(Expression.field('tags'), 'index') + .limit(5) + .execute(), + ); + + // 17: union + Future _runPipeline17() => _runPipeline( + 'Pipeline 17: collection limit 2 → union(collection offset 2 limit 2)', + () { + final p2 = _firestore + .pipeline() + .collection(_collectionId) + .offset(2) + .limit(2); + return _firestore + .pipeline() + .collection(_collectionId) + .limit(2) + .union(p2) + .execute(); + }, + ); + + // 18: Constant — one addFields field per supported constant type + Future _runPipeline18() { + final docRef = _firestore.collection(_collectionId).doc('constant-test'); + // _firestore.doc() + return _runPipeline( + 'Pipeline 18: constant types — null, String, int, double, bool, ' + 'DateTime, Timestamp, GeoPoint, List, Blob, DocumentReference, VectorValue', + () => _firestore + .pipeline() + .collection(_collectionId) + .limit(1) + .addFields( + // VectorValue + Constant(VectorValue([1.0, 2.0, 3.0])).as('c_vector'), + + Constant(null).as('c_null'), + // String + Constant('hello').as('c_string'), + // int + Constant(42).as('c_int'), + // double + Constant(3.14).as('c_double'), + // bool + Constant(true).as('c_bool'), + // DateTime + Constant(DateTime.utc(2024, 6, 15, 12, 0, 0)).as('c_date_time'), + // Timestamp + Constant(Timestamp(1718449200, 0)).as('c_timestamp'), + // GeoPoint + Constant(const GeoPoint(37.7749, -122.4194)).as('c_geo_point'), + // List (raw bytes) + Constant([72, 101, 108, 108, 111]).as('c_bytes'), + // // Blob + // Constant(Blob(Uint8List.fromList([1, 2, 3, 4, 5]))).as('c_blob'), + // DocumentReference + Constant(docRef).as('c_doc_ref'), + ) + .execute(), + ); + } + + // 19: Expression.and + Future _runPipeline19() => _runPipeline( + 'Pipeline 19: collection → where(and(score > 50, year >= 2022)) → select(title, score, year) → limit(5)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where( + Expression.and( + Expression.field('score').greaterThan(Expression.constant(20)), + Expression.field( + 'year', + ).greaterThanOrEqual(Expression.constant(2022)), + ), + ) + .select( + Expression.field('title'), + Expression.field('score'), + Expression.field('year'), + ) + .limit(5) + .execute(), + ); + + // 20: Expression.or + Future _runPipeline20() => _runPipeline( + 'Pipeline 20: collection → where(or(score > 80, year < 2021)) → select(title, score, year) → limit(5)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where( + Expression.or( + Expression.field('score').greaterThan(Expression.constant(30)), + Expression.field('year').lessThan(Expression.constant(2022)), + ), + ) + .select( + Expression.field('title'), + Expression.field('score'), + Expression.field('year'), + ) + .limit(5) + .execute(), + ); + + // 20b: Expression.not (same pattern as pipeline_expressions_e2e "where with not") + Future _runPipeline20b() => _runPipeline( + 'Pipeline 20b: where(test=expressions) + NOT(score>=60) + sort(score)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('test').equalValue('expressions')) + .where( + Expression.not( + Expression.field( + 'score', + ).greaterThanOrEqual(Expression.constant(60)), + ), + ) + .sort(Expression.field('score').ascending()) + .execute(), + ); + + // 21: arrayContainsAny + Future _runPipeline21() => _runPipeline( + 'Pipeline 21: collection → where(tags arrayContainsAny [x, z]) → select(title, tags) → limit(5)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('tags').arrayContainsAny(['x', 'z'])) + .select(Expression.field('title'), Expression.field('tags')) + .limit(5) + .execute(), + ); + + // ── New expression examples (22+) ───────────────────────────────────── + + // 22: concat + Future _runPipeline22() => _runPipeline( + 'Pipeline 22: addFields concat(title, " | ", category)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field( + 'title', + ).concat([' | ', Expression.field('category')]).as('title_category'), + ) + .limit(3) + .execute(), + ); + + // 23: length (string) + Future _runPipeline23() => _runPipeline( + 'Pipeline 23: addFields title.length()', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields(Expression.field('title').length().as('title_len')) + .limit(4) + .execute(), + ); + + // 24: toLowerCase / toUpperCase + Future _runPipeline24() => _runPipeline( + 'Pipeline 24: addFields toLowerCase(title), toUpperCase(category)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field('title').toLowerCase().as('title_lower'), + Expression.field('category').toUpperCase().as('category_upper'), + ) + .limit(3) + .execute(), + ); + + // 25: trim + Future _runPipeline25() => _runPipeline( + 'Pipeline 25: where(has title) → addFields trim(title)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('title').exists()) + .addFields(Expression.field('title').trim().as('title_trimmed')) + .limit(5) + .execute(), + ); + + // 26: substring + Future _runPipeline26() => _runPipeline( + 'Pipeline 26: addFields substring(title, 0, 5)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field('title').substringLiteral(0, 5).as('title_prefix'), + ) + .limit(4) + .execute(), + ); + + // 27: stringReplaceAll + // Future _runPipeline27() => _runPipeline( + // 'Pipeline 27: addFields stringReplaceAll(title, "Item", "Doc")', + // () => _firestore + // .pipeline() + // .collection(_collectionId) + // .addFields( + // Expression.field('title') + // .stringReplaceAllLiteral('Item', 'Doc') + // .as('title_replaced'), + // ) + // .limit(3) + // .execute(), + // ); + + // 28: split + Future _runPipeline28() => _runPipeline( + 'Pipeline 28: addFields split(title, " ")', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field('title').splitLiteral(' ').as('title_parts'), + ) + .limit(3) + .execute(), + ); + + // 29: join + Future _runPipeline29() => _runPipeline( + 'Pipeline 29: where(has tags) → addFields join(tags, "-")', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('tags').exists()) + .addFields(Expression.field('tags').joinLiteral('-').as('tags_joined')) + .limit(3) + .execute(), + ); + + // 30: if_absent + Future _runPipeline30() => _runPipeline( + 'Pipeline 30: addFields if_absent(optional_field, "default")', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field( + 'optional_field', + ).ifAbsentValue('default').as('opt_or_default'), + ) + .limit(4) + .execute(), + ); + + // 30b: if_error (e.g. safe divide) + Future _runPipeline30b() => _runPipeline( + 'Pipeline 30b: addFields score/0 with ifError("N/A")', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field( + 'score', + ).divide(Expression.constant(0)).ifErrorValue('N/A').as('safe_ratio'), + ) + .limit(2) + .execute(), + ); + + // 31: conditional + Future _runPipeline31() => _runPipeline( + 'Pipeline 31: addFields conditional(score > 20, "high", "low")', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.conditionalValues( + Expression.field('score').greaterThan(Expression.constant(20)), + 'high', + 'low', + ).as('score_tier'), + ) + .limit(5) + .execute(), + ); + + // 32: document_id (current document ID) + Future _runPipeline32() => _runPipeline( + 'Pipeline 32: addFields documentId()', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields(Expression.field('__path__').documentId().as('doc_id')) + .limit(3) + .execute(), + ); + + // 33: collection_id (current collection ID) + Future _runPipeline33() => _runPipeline( + 'Pipeline 33: addFields collectionId()', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields(Expression.field('__path__').collectionId().as('coll_id')) + .limit(2) + .execute(), + ); + + // 34: map_get, map_keys, map_values + Future _runPipeline34() => _runPipeline( + 'Pipeline 34: where(has items) → addFields mapGet, mapKeys, mapValues', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('items').exists()) + .addFields(Expression.field('items').mapGetLiteral('a').as('items_a')) + .limit(2) + .execute(), + ); + + // 35: current_timestamp, timestamp_add, timestamp_subtract, timestamp_truncate + Future _runPipeline35() => _runPipeline( + 'Pipeline 35: addFields currentTimestamp, timestampAdd(1 day)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.currentTimestamp().as('now'), + Expression.timestampAddLiteral( + Expression.currentTimestamp(), + 'day', + 1, + ).as('tomorrow'), + ) + .limit(1) + .execute(), + ); + + // 36: abs + Future _runPipeline36() => _runPipeline( + 'Pipeline 36: addFields abs(score)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields(Expression.field('score').abs().as('score_abs')) + .limit(5) + .execute(), + ); + + // 37: array_length + Future _runPipeline37() => _runPipeline( + 'Pipeline 37: where(has tags) → addFields arrayLength(tags)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('tags').exists()) + .addFields(Expression.field('tags').arrayLength().as('tags_len')) + .limit(5) + .execute(), + ); + + Future _runPipeline37b() => _runPipeline( + 'Pipeline 37b: where(has scores) → addFields arraySum(scores)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('scores').exists()) + .addFields(Expression.field('scores').arraySum().as('scores_total')) + .limit(3) + .execute(), + ); + + // 38: array_concat + Future _runPipeline38() => _runPipeline( + 'Pipeline 38: where(has tags) → addFields arrayConcat(tags, [extra])', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('tags').exists()) + .addFields( + Expression.field('tags').arrayConcat(['extra']).as('tags_extended'), + ) + .limit(2) + .execute(), + ); + + // 40: array (construct) + Future _runPipeline40() => _runPipeline( + 'Pipeline 40: addFields array([title, score, year])', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.array([ + Expression.field('title'), + Expression.field('score'), + Expression.field('year'), + ]).as('tuple'), + ) + .limit(2) + .execute(), + ); + + // 41: map (construct) + Future _runPipeline41() => _runPipeline( + 'Pipeline 41: addFields map({ t: title, s: score })', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.map({ + 't': Expression.field('title'), + 's': Expression.field('score'), + }).as('mini_map'), + ) + .limit(2) + .execute(), + ); + + // 42: array_contains_all (values list) + Future _runPipeline42() => _runPipeline( + 'Pipeline 42: where(tags arrayContainsAll [x, y]) → select title, tags', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('tags').arrayContainsAll(['x', 'y'])) + .select(Expression.field('title'), Expression.field('tags')) + .limit(5) + .execute(), + ); + + // 43: equal_any (IN) + Future _runPipeline43() => _runPipeline( + 'Pipeline 43: where(score equalAny [10, 25, 40]) → select title, score', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.equalAny(Expression.field('score'), [10, 25, 40])) + .select(Expression.field('title'), Expression.field('score')) + .limit(5) + .execute(), + ); + + // 44: not_equal_any (NOT IN) + Future _runPipeline44() => _runPipeline( + 'Pipeline 44: where(category notEqualAny [news]) → select title, category', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.notEqualAny(Expression.field('category'), ['news'])) + .select(Expression.field('title'), Expression.field('category')) + .limit(5) + .execute(), + ); + + // 45: asBoolean (coerce numeric to boolean) + Future _runPipeline45() => _runPipeline( + 'Pipeline 45: addFields asBoolean(score)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields(Expression.field('score').asBoolean().as('score_bool')) + .limit(4) + .execute(), + ); + + // 46: isError (missing field vs divide-by-zero) + Future _runPipeline46() => _runPipeline( + 'Pipeline 46: addFields isError(missing field), isError(score/0)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields( + Expression.field('missing_field').isError().as('missing_is_err'), + Expression.field( + 'score', + ).divide(Expression.constant(0)).isError().as('div0_is_err'), + ) + .limit(3) + .execute(), + ); + + // ── New pipeline expressions (regex, map, string, array, agg) ─────────── + + Future _runPipeline47() => _runPipeline( + 'Pipeline 47: where(has email) → addFields regexFind(@.+)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('email').exists()) + .addFields(Expression.field('email').regexFind('@.+').as('at_domain')) + .limit(5) + .execute(), + ); + + Future _runPipeline48() => _runPipeline( + 'Pipeline 48: where(has email) → addFields regexFindAll([a-z]+)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('email').exists()) + .addFields( + Expression.field('email').regexFindAll('[a-z]+').as('word_chunks'), + ) + .limit(5) + .execute(), + ); + + Future _runPipeline49() => _runPipeline( + 'Pipeline 49: test=expressions + has s → stringReplaceOne, stringIndexOf, stringRepeat', + () => _firestore + .pipeline() + .collection(_collectionId) + .where( + Expression.and( + Expression.field('test').equalValue('expressions'), + Expression.field('s').exists(), + ), + ) + .addFields( + Expression.field( + 's', + ).stringReplaceOneLiteral('A', 'Z').as('s_replace_one'), + Expression.field('s').stringIndexOf('y').as('idx_y'), + Expression.field('s').stringRepeat(2).as('s_twice'), + ) + .limit(8) + .execute(), + ); + + Future _runPipeline50() => _runPipeline( + 'Pipeline 50: title " Padded " → ltrim, rtrim', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('title').equalValue(' Padded ')) + .addFields( + Expression.field('title').ltrim().as('lt'), + Expression.field('title').rtrim().as('rt'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline51() => _runPipeline( + 'Pipeline 51: where(has items) → mapSet(z), mapEntries()', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('items').exists()) + .addFields( + Expression.field('items').mapSet('z', 'added').as('items_plus'), + Expression.field('items').mapEntries().as('items_entries'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline52() => _runPipeline( + 'Pipeline 52: addFields type(score)', + () => _firestore + .pipeline() + .collection(_collectionId) + .addFields(Expression.field('score').type().as('score_type')) + .limit(6) + .execute(), + ); + + Future _runPipeline53() => _runPipeline( + 'Pipeline 53: where(score isType int64) → select title, score', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('score').isType(Type.int64)) + .select(Expression.field('title'), Expression.field('score')) + .limit(8) + .execute(), + ); + + Future _runPipeline54() => _runPipeline( + 'Pipeline 54: where(has pi) → trunc(pi), trunc(2dp), rand()', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('pi').exists()) + .addFields( + Expression.field('pi').trunc().as('pi_trunc'), + Expression.field('pi').trunc(Expression.constant(2)).as('pi_2'), + Expression.rand().as('rnd'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline55() => _runPipeline( + 'Pipeline 55: title Item G → arrayFirst, arrayLast(tags)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('title').equalValue('Item G')) + .addFields( + Expression.field('tags').arrayFirst().as('tag_first'), + Expression.field('tags').arrayLast().as('tag_last'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline56() => _runPipeline( + 'Pipeline 56: Item G → arrayFirstN(2), arrayLastN(2)(tags)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('title').equalValue('Item G')) + .addFields( + Expression.field('tags').arrayFirstN(2).as('tags_head'), + Expression.field('tags').arrayLastN(2).as('tags_tail'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline57() => _runPipeline( + 'Pipeline 57: where(has scores) → arrayMaximum, arrayMinimum', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('scores').exists()) + .addFields( + Expression.field('scores').arrayMaximum().as('smax'), + Expression.field('scores').arrayMinimum().as('smin'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline58() => _runPipeline( + 'Pipeline 58: where(has scores) → arrayMaximumN(2), arrayMinimumN(2)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('scores').exists()) + .addFields( + Expression.field('scores').arrayMaximumN(2).as('top2'), + Expression.field('scores').arrayMinimumN(2).as('bottom2'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline59() => _runPipeline( + 'Pipeline 59: Dup Tags → arrayIndexOf(a), arrayLastIndexOf(a), arrayIndexOfAll(a)', + () => _firestore + .pipeline() + .collection(_collectionId) + .where(Expression.field('title').equalValue('Dup Tags')) + .addFields( + Expression.field('tags').arrayIndexOf('a').as('idx_first_a'), + Expression.field('tags').arrayLastIndexOf('a').as('idx_last_a'), + Expression.field('tags').arrayIndexOfAll('a').as('all_a'), + ) + .limit(3) + .execute(), + ); + + Future _runPipeline60() => _runPipeline( + 'Pipeline 60: aggregate first(score), last(score)', + () => _firestore + .pipeline() + .collection(_collectionId) + .limit(50) + .aggregate( + Expression.field('score').first().as('first_score'), + Expression.field('score').last().as('last_score'), + ) + .execute(), + ); + + Future _runPipeline61() => _runPipeline( + 'Pipeline 61: limit 25 → aggregate array_agg(title)', + () => _firestore + .pipeline() + .collection(_collectionId) + .limit(25) + .aggregate(Expression.field('title').arrayAgg().as('all_titles')) + .execute(), + ); + + Future _runPipeline62() => _runPipeline( + 'Pipeline 62: limit 25 → aggregate array_agg_distinct(category)', + () => _firestore + .pipeline() + .collection(_collectionId) + .limit(25) + .aggregate(Expression.field('category').arrayAggDistinct().as('cats')) + .execute(), + ); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Pipeline Example'), + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + ), + body: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(12, 12, 12, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text( + '1. Seed data, then run pipeline queries. Errors go to console only.', + style: TextStyle(fontWeight: FontWeight.w500), + ), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: FilledButton( + onPressed: _loading ? null : _seedCollection, + child: const Text('Seed collection'), + ), + ), + const SizedBox(width: 8), + Expanded( + child: FilledButton( + onPressed: _loading ? null : _seedCollectionNoBatch, + child: const Text('Seed (no batch)'), + ), + ), + ], + ), + if (_loading) const LinearProgressIndicator(), + ], + ), + ), + const SizedBox(height: 8), + Expanded( + flex: 1, + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Wrap( + spacing: 8, + runSpacing: 8, + children: [ + _btn('1: where+limit', _runPipeline1), + _btn('1b: execute(options)', _runPipelineExecuteOptions), + _btn('2: select', _runPipeline2), + _btn('3: aggregate', _runPipeline3), + _btn('4: addFields', _runPipeline4), + _btn('5: distinct', _runPipeline5), + _btn('6: offset', _runPipeline6), + _btn('7: removeFields', _runPipeline7), + _btn('8: replaceWith', _runPipeline8), + _btn('9: sample', _runPipeline9), + _btn('10: sort', _runPipeline10), + _btn('11: aggregateStage', _runPipeline11), + _btn('12: collectionGroup', _runPipeline12), + _btn('13: documents', _runPipeline13), + _btn('14: database', _runPipeline14), + _btn('15: findNearest', _runPipeline15), + _btn('16: unnest', _runPipeline16), + _btn('17: union', _runPipeline17), + _btn('18: constants', _runPipeline18), + _btn('19: and', _runPipeline19), + _btn('20: or', _runPipeline20), + _btn('20b: NOT (score≥60)', _runPipeline20b), + _btn('21: arrayContainsAny', _runPipeline21), + _btn('22: concat', _runPipeline22), + _btn('23: length', _runPipeline23), + _btn('24: lower/upper', _runPipeline24), + _btn('25: trim', _runPipeline25), + _btn('26: substring', _runPipeline26), + _btn('28: split', _runPipeline28), + _btn('29: join', _runPipeline29), + _btn('30: if_absent', _runPipeline30), + _btn('30b: if_error', _runPipeline30b), + _btn('31: conditional', _runPipeline31), + _btn('32: documentId', _runPipeline32), + _btn('33: collectionId', _runPipeline33), + _btn('34: mapGet/Keys/Vals', _runPipeline34), + _btn('35: timestamp', _runPipeline35), + _btn('36: abs', _runPipeline36), + _btn('37: arrayLen', _runPipeline37), + _btn('37b: arraySum', _runPipeline37b), + _btn('38: arrayConcat', _runPipeline38), + _btn('40: array()', _runPipeline40), + _btn('41: map()', _runPipeline41), + _btn('42: arrayContainsAll', _runPipeline42), + _btn('43: equalAny', _runPipeline43), + _btn('44: notEqualAny', _runPipeline44), + _btn('45: asBoolean', _runPipeline45), + _btn('46: isError', _runPipeline46), + _btn('47: regexFind', _runPipeline47), + _btn('48: regexFindAll', _runPipeline48), + _btn('49: string idx/repeat', _runPipeline49), + _btn('50: ltrim/rtrim', _runPipeline50), + _btn('51: mapSet/entries', _runPipeline51), + _btn('52: type(score)', _runPipeline52), + _btn('53: isType int64', _runPipeline53), + _btn('54: trunc/rand', _runPipeline54), + _btn('55: array first/last', _runPipeline55), + _btn('56: arrayFirstN/LastN', _runPipeline56), + _btn('57: array max/min', _runPipeline57), + _btn('58: arrayMaxN/MinN', _runPipeline58), + _btn('59: arrayIndexOf*', _runPipeline59), + _btn('60: agg first/last', _runPipeline60), + _btn('61: agg array_agg', _runPipeline61), + _btn('62: agg array_agg_dist', _runPipeline62), + ], + ), + ), + ), + const Divider(height: 1), + Expanded( + flex: 2, + child: _log.isEmpty + ? const Center( + child: Text( + 'Log output will appear here.\nTap "Seed collection" then run a pipeline.', + textAlign: TextAlign.center, + ), + ) + : ListView.builder( + padding: const EdgeInsets.all(8), + itemCount: _log.length, + itemBuilder: (context, i) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: SelectableText( + _log[i], + style: const TextStyle( + fontFamily: 'monospace', + fontSize: 12, + ), + ), + ); + }, + ), + ), + ], + ), + ); + } + + Widget _btn(String label, VoidCallback onPressed) { + return FilledButton.tonal( + onPressed: _loading ? null : onPressed, + child: Text(label), + ); + } +} + +class PipelineExamplePage extends StatefulWidget { + const PipelineExamplePage({super.key}); + + @override + State createState() => _PipelineExamplePageState(); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/.gitignore b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/.gitignore new file mode 100644 index 000000000000..746adbb6b9e1 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Debug.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 000000000000..4b81f9b2d200 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Release.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 000000000000..5caa9d1579e4 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Podfile b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Podfile new file mode 100644 index 000000000000..ff5ddb3b8bdc --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', '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 + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.pbxproj b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..0d3da44c98d4 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,805 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 4D21D57616F29244D9E0BEDC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92A5244FE5D2154A5DCF67B1 /* Pods_Runner.framework */; }; + 64BEAD2D383FBE055A9293F9 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD0A02E97A5F21BBF52ECDE7 /* Pods_RunnerTests.framework */; }; + C00753EECC149CA245836275 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 68F38BAC755C5AD9D75FABDC /* GoogleService-Info.plist */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* pipeline_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = pipeline_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 450310D9B717CF9798DF9983 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 4C6E70E606BD35A2DDE28810 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 68F38BAC755C5AD9D75FABDC /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 80B3CDA44BB01B7665B13AC4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 80C48A48FDB72942482DF20F /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 92A5244FE5D2154A5DCF67B1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + BD0A02E97A5F21BBF52ECDE7 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C6DA53DEF649E7FAF765B034 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + EAA74D9E6B471BF39D05E2D5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 64BEAD2D383FBE055A9293F9 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 4D21D57616F29244D9E0BEDC /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2ACCD496E1849E7F631515BA /* Pods */ = { + isa = PBXGroup; + children = ( + 80B3CDA44BB01B7665B13AC4 /* Pods-Runner.debug.xcconfig */, + EAA74D9E6B471BF39D05E2D5 /* Pods-Runner.release.xcconfig */, + 4C6E70E606BD35A2DDE28810 /* Pods-Runner.profile.xcconfig */, + 80C48A48FDB72942482DF20F /* Pods-RunnerTests.debug.xcconfig */, + C6DA53DEF649E7FAF765B034 /* Pods-RunnerTests.release.xcconfig */, + 450310D9B717CF9798DF9983 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 68F38BAC755C5AD9D75FABDC /* GoogleService-Info.plist */, + 2ACCD496E1849E7F631515BA /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* pipeline_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 92A5244FE5D2154A5DCF67B1 /* Pods_Runner.framework */, + BD0A02E97A5F21BBF52ECDE7 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 99A85E0C4CFD12F263C48149 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 8E689660D67B59A471E12131 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + AFC4EC65143ED624B99B07E7 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* pipeline_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + C00753EECC149CA245836275 /* GoogleService-Info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 8E689660D67B59A471E12131 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 99A85E0C4CFD12F263C48149 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + AFC4EC65143ED624B99B07E7 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 80C48A48FDB72942482DF20F /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pipeline_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/pipeline_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C6DA53DEF649E7FAF765B034 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pipeline_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/pipeline_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 450310D9B717CF9798DF9983 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pipeline_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/pipeline_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..75fc171f713c --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..21a3cc14c74e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/AppDelegate.swift b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/AppDelegate.swift new file mode 100644 index 000000000000..b3c176141221 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..a2ec33f19f11 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..82b6f9d9a33e198f5747104729e1fcef999772a5 GIT binary patch literal 102994 zcmeEugo5nb1G~3xi~y`}h6XHx5j$(L*3|5S2UfkG$|UCNI>}4f?MfqZ+HW-sRW5RKHEm z^unW*Xx{AH_X3Xdvb%C(Bh6POqg==@d9j=5*}oEny_IS;M3==J`P0R!eD6s~N<36C z*%-OGYqd0AdWClO!Z!}Y1@@RkfeiQ$Ib_ z&fk%T;K9h`{`cX3Hu#?({4WgtmkR!u3ICS~|NqH^fdNz>51-9)OF{|bRLy*RBv#&1 z3Oi_gk=Y5;>`KbHf~w!`u}!&O%ou*Jzf|Sf?J&*f*K8cftMOKswn6|nb1*|!;qSrlw= zr-@X;zGRKs&T$y8ENnFU@_Z~puu(4~Ir)>rbYp{zxcF*!EPS6{(&J}qYpWeqrPWW< zfaApz%<-=KqxrqLLFeV3w0-a0rEaz9&vv^0ZfU%gt9xJ8?=byvNSb%3hF^X_n7`(fMA;C&~( zM$cQvQ|g9X)1AqFvbp^B{JEX$o;4iPi?+v(!wYrN{L}l%e#5y{j+1NMiT-8=2VrCP zmFX9=IZyAYA5c2!QO96Ea-6;v6*$#ZKM-`%JCJtrA3d~6h{u+5oaTaGE)q2b+HvdZ zvHlY&9H&QJ5|uG@wDt1h99>DdHy5hsx)bN`&G@BpxAHh$17yWDyw_jQhhjSqZ=e_k z_|r3=_|`q~uA47y;hv=6-o6z~)gO}ZM9AqDJsR$KCHKH;QIULT)(d;oKTSPDJ}Jx~G#w-(^r<{GcBC*~4bNjfwHBumoPbU}M)O za6Hc2ik)2w37Yyg!YiMq<>Aov?F2l}wTe+>h^YXcK=aesey^i)QC_p~S zp%-lS5%)I29WfywP(r4@UZ@XmTkqo51zV$|U|~Lcap##PBJ}w2b4*kt7x6`agP34^ z5fzu_8rrH+)2u*CPcr6I`gL^cI`R2WUkLDE5*PX)eJU@H3HL$~o_y8oMRoQ0WF9w| z6^HZDKKRDG2g;r8Z4bn+iJNFV(CG;K-j2>aj229gl_C6n12Jh$$h!}KVhn>*f>KcH z;^8s3t(ccVZ5<{>ZJK@Z`hn_jL{bP8Yn(XkwfRm?GlEHy=T($8Z1Mq**IM`zxN9>-yXTjfB18m_$E^JEaYn>pj`V?n#Xu;Z}#$- zw0Vw;T*&9TK$tKI7nBk9NkHzL++dZ^;<|F6KBYh2+XP-b;u`Wy{~79b%IBZa3h*3^ zF&BKfQ@Ej{7ku_#W#mNJEYYp=)bRMUXhLy2+SPMfGn;oBsiG_6KNL8{p1DjuB$UZB zA)a~BkL)7?LJXlCc}bB~j9>4s7tlnRHC5|wnycQPF_jLl!Avs2C3^lWOlHH&v`nGd zf&U!fn!JcZWha`Pl-B3XEe;(ks^`=Z5R zWyQR0u|do2`K3ec=YmWGt5Bwbu|uBW;6D8}J3{Uep7_>L6b4%(d=V4m#(I=gkn4HT zYni3cnn>@F@Wr<hFAY3Y~dW+3bte;70;G?kTn4Aw5nZ^s5|47 z4$rCHCW%9qa4)4vE%^QPMGf!ET!^LutY$G zqdT(ub5T5b+wi+OrV}z3msoy<4)`IPdHsHJggmog0K*pFYMhH!oZcgc5a)WmL?;TPSrerTVPp<#s+imF3v#!FuBNNa`#6 z!GdTCF|IIpz#(eV^mrYKThA4Bnv&vQet@%v9kuRu3EHx1-2-it@E`%9#u`)HRN#M? z7aJ{wzKczn#w^`OZ>Jb898^Xxq)0zd{3Tu7+{-sge-rQ z&0PME&wIo6W&@F|%Z8@@N3)@a_ntJ#+g{pUP7i?~3FirqU`rdf8joMG^ld?(9b7Iv z>TJgBg#)(FcW)h!_if#cWBh}f+V08GKyg|$P#KTS&%=!+0a%}O${0$i)kn9@G!}En zv)_>s?glPiLbbx)xk(lD-QbY(OP3;MSXM5E*P&_`Zks2@46n|-h$Y2L7B)iH{GAAq19h5-y0q>d^oy^y+soJu9lXxAe%jcm?=pDLFEG2kla40e!5a}mpe zdL=WlZ=@U6{>g%5a+y-lx)01V-x;wh%F{=qy#XFEAqcd+m}_!lQ)-9iiOL%&G??t| z?&NSdaLqdPdbQs%y0?uIIHY7rw1EDxtQ=DU!i{)Dkn~c$LG5{rAUYM1j5*G@oVn9~ zizz{XH(nbw%f|wI=4rw^6mNIahQpB)OQy10^}ACdLPFc2@ldVi|v@1nWLND?)53O5|fg`RZW&XpF&s3@c-R?aad!$WoH6u0B|}zt)L($E^@U- zO#^fxu9}Zw7Xl~nG1FVM6DZSR0*t!4IyUeTrnp@?)Z)*!fhd3)&s(O+3D^#m#bAem zpf#*aiG_0S^ofpm@9O7j`VfLU0+{$x!u^}3!zp=XST0N@DZTp!7LEVJgqB1g{psNr za0uVmh3_9qah14@M_pi~vAZ#jc*&aSm$hCNDsuQ-zPe&*Ii#2=2gP+DP4=DY z_Y0lUsyE6yaV9)K)!oI6+*4|spx2at*30CAx~6-5kfJzQ`fN8$!lz%hz^J6GY?mVH zbYR^JZ(Pmj6@vy-&!`$5soyy-NqB^8cCT40&R@|6s@m+ZxPs=Bu77-+Os7+bsz4nA3DrJ8#{f98ZMaj-+BD;M+Jk?pgFcZIb}m9N z{ct9T)Kye&2>l^39O4Q2@b%sY?u#&O9PO4@t0c$NUXG}(DZJ<;_oe2~e==3Z1+`Zo zFrS3ns-c}ZognVBHbg#e+1JhC(Yq7==rSJQ8J~}%94(O#_-zJKwnBXihl#hUd9B_>+T& z7eHHPRC?5ONaUiCF7w|{J`bCWS7Q&xw-Sa={j-f)n5+I=9s;E#fBQB$`DDh<^mGiF zu-m_k+)dkBvBO(VMe2O4r^sf3;sk9K!xgXJU>|t9Vm8Ty;fl5pZzw z9j|}ZD}6}t;20^qrS?YVPuPRS<39d^y0#O1o_1P{tN0?OX!lc-ICcHI@2#$cY}_CY zev|xdFcRTQ_H)1fJ7S0*SpPs8e{d+9lR~IZ^~dKx!oxz?=Dp!fD`H=LH{EeC8C&z-zK$e=!5z8NL=4zx2{hl<5z*hEmO=b-7(k5H`bA~5gT30Sjy`@-_C zKM}^so9Ti1B;DovHByJkTK87cfbF16sk-G>`Q4-txyMkyQS$d}??|Aytz^;0GxvOs zPgH>h>K+`!HABVT{sYgzy3CF5ftv6hI-NRfgu613d|d1cg^jh+SK7WHWaDX~hlIJ3 z>%WxKT0|Db1N-a4r1oPKtF--^YbP=8Nw5CNt_ZnR{N(PXI>Cm$eqi@_IRmJ9#)~ZHK_UQ8mi}w^`+4$OihUGVz!kW^qxnCFo)-RIDbA&k-Y=+*xYv5y4^VQ9S)4W5Pe?_RjAX6lS6Nz#!Hry=+PKx2|o_H_3M`}Dq{Bl_PbP(qel~P@=m}VGW*pK96 zI@fVag{DZHi}>3}<(Hv<7cVfWiaVLWr@WWxk5}GDEbB<+Aj;(c>;p1qmyAIj+R!`@#jf$ zy4`q23L-72Zs4j?W+9lQD;CYIULt%;O3jPWg2a%Zs!5OW>5h1y{Qof!p&QxNt5=T( zd5fy&7=hyq;J8%86YBOdc$BbIFxJx>dUyTh`L z-oKa=OhRK9UPVRWS`o2x53bAv+py)o)kNL6 z9W1Dlk-g6Ht@-Z^#6%`9S9`909^EMj?9R^4IxssCY-hYzei^TLq7Cj>z$AJyaU5=z zl!xiWvz0U8kY$etrcp8mL;sYqGZD!Hs-U2N{A|^oEKA482v1T%cs%G@X9M?%lX)p$ zZoC7iYTPe8yxY0Jne|s)fCRe1mU=Vb1J_&WcIyP|x4$;VSVNC`M+e#oOA`#h>pyU6 z?7FeVpk`Hsu`~T3i<_4<5fu?RkhM;@LjKo6nX>pa%8dSdgPO9~Jze;5r>Tb1Xqh5q z&SEdTXevV@PT~!O6z|oypTk7Qq+BNF5IQ(8s18c=^0@sc8Gi|3e>VKCsaZ?6=rrck zl@oF5Bd0zH?@15PxSJIRroK4Wa?1o;An;p0#%ZJ^tI=(>AJ2OY0GP$E_3(+Zz4$AQ zW)QWl<4toIJ5TeF&gNXs>_rl}glkeG#GYbHHOv-G!%dJNoIKxn)FK$5&2Zv*AFic! z@2?sY&I*PSfZ8bU#c9fdIJQa_cQijnj39-+hS@+~e*5W3bj%A}%p9N@>*tCGOk+cF zlcSzI6j%Q|2e>QG3A<86w?cx6sBtLNWF6_YR?~C)IC6_10SNoZUHrCpp6f^*+*b8` zlx4ToZZuI0XW1W)24)92S)y0QZa);^NRTX6@gh8@P?^=#2dV9s4)Q@K+gnc{6|C}& zDLHr7nDOLrsH)L@Zy{C_2UrYdZ4V{|{c8&dRG;wY`u>w%$*p>PO_}3`Y21pk?8Wtq zGwIXTulf7AO2FkPyyh2TZXM1DJv>hI`}x`OzQI*MBc#=}jaua&czSkI2!s^rOci|V zFkp*Vbiz5vWa9HPFXMi=BV&n3?1?%8#1jq?p^3wAL`jgcF)7F4l<(H^!i=l-(OTDE zxf2p71^WRIExLf?ig0FRO$h~aA23s#L zuZPLkm>mDwBeIu*C7@n@_$oSDmdWY7*wI%aL73t~`Yu7YwE-hxAATmOi0dmB9|D5a zLsR7OQcA0`vN9m0L|5?qZ|jU+cx3_-K2!K$zDbJ$UinQy<9nd5ImWW5n^&=Gg>Gsh zY0u?m1e^c~Ug39M{{5q2L~ROq#c{eG8Oy#5h_q=#AJj2Yops|1C^nv0D1=fBOdfAG z%>=vl*+_w`&M7{qE#$xJJp_t>bSh7Mpc(RAvli9kk3{KgG5K@a-Ue{IbU{`umXrR3ra5Y7xiX42+Q%N&-0#`ae_ z#$Y6Wa++OPEDw@96Zz##PFo9sADepQe|hUy!Zzc2C(L`k9&=a8XFr+!hIS>D2{pdGP1SzwyaGLiH3j--P>U#TWw90t8{8Bt%m7Upspl#=*hS zhy|(XL6HOqBW}Og^tLX7 z+`b^L{O&oqjwbxDDTg2B;Yh2(fW>%S5Pg8^u1p*EFb z`(fbUM0`afawYt%VBfD&b3MNJ39~Ldc@SAuzsMiN%E}5{uUUBc7hc1IUE~t-Y9h@e7PC|sv$xGx=hZiMXNJxz5V(np%6u{n24iWX#!8t#>Ob$in<>dw96H)oGdTHnU zSM+BPss*5)Wz@+FkooMxxXZP1{2Nz7a6BB~-A_(c&OiM)UUNoa@J8FGxtr$)`9;|O z(Q?lq1Q+!E`}d?KemgC!{nB1JJ!B>6J@XGQp9NeQvtbM2n7F%v|IS=XWPVZY(>oq$ zf=}8O_x`KOxZoGnp=y24x}k6?gl_0dTF!M!T`={`Ii{GnT1jrG9gPh)R=RZG8lIR| z{ZJ6`x8n|y+lZuy${fuEDTAf`OP!tGySLXD}ATJO5UoZv|Xo3%7O~L63+kw}v)Ci=&tWx3bQJfL@5O18CbPlkR^IcKA zy1=^Vl-K-QBP?9^R`@;czcUw;Enbbyk@vJQB>BZ4?;DM%BUf^eZE+sOy>a){qCY6Y znYy;KGpch-zf=5|p#SoAV+ie8M5(Xg-{FoLx-wZC9IutT!(9rJ8}=!$!h%!J+vE2e z(sURwqCC35v?1>C1L)swfA^sr16{yj7-zbT6Rf26-JoEt%U?+|rQ zeBuGohE?@*!zR9)1P|3>KmJSgK*fOt>N>j}LJB`>o(G#Dduvx7@DY7};W7K;Yj|8O zGF<+gTuoIKe7Rf+LQG3-V1L^|E;F*}bQ-{kuHq}| ze_NwA7~US19sAZ)@a`g*zkl*ykv2v3tPrb4Og2#?k6Lc7@1I~+ew48N&03hW^1Cx+ zfk5Lr4-n=#HYg<7ka5i>2A@ZeJ60gl)IDX!!p zzfXZQ?GrT>JEKl7$SH!otzK6=0dIlqN)c23YLB&Krf9v-{@V8p+-e2`ujFR!^M%*; ze_7(Jh$QgoqwB!HbX=S+^wqO15O_TQ0-qX8f-|&SOuo3ZE{{9Jw5{}>MhY}|GBhO& zv48s_B=9aYQfa;d>~1Z$y^oUUaDer>7ve5+Gf?rIG4GZ!hRKERlRNgg_C{W_!3tsI2TWbX8f~MY)1Q`6Wj&JJ~*;ay_0@e zzx+mE-pu8{cEcVfBqsnm=jFU?H}xj@%CAx#NO>3 z_re3Rq%d1Y7VkKy{=S73&p;4^Praw6Y59VCP6M?!Kt7{v#DG#tz?E)`K95gH_mEvb z%$<~_mQ$ad?~&T=O0i0?`YSp?E3Dj?V>n+uTRHAXn`l!pH9Mr}^D1d@mkf+;(tV45 zH_yfs^kOGLXlN*0GU;O&{=awxd?&`{JPRr$z<1HcAO2K`K}92$wC}ky&>;L?#!(`w z68avZGvb728!vgw>;8Z8I@mLtI`?^u6R>sK4E7%=y)jpmE$fH!Dj*~(dy~-2A5Cm{ zl{1AZw`jaDmfvaB?jvKwz!GC}@-Dz|bFm1OaPw(ia#?>vF7Y5oh{NVbyD~cHB1KFn z9C@f~X*Wk3>sQH9#D~rLPslAd26@AzMh=_NkH_yTNXx6-AdbAb z{Ul89YPHslD?xAGzOlQ*aMYUl6#efCT~WI zOvyiewT=~l1W(_2cEd(8rDywOwjM-7P9!8GCL-1<9KXXO=6%!9=W++*l1L~gRSxLVd8K=A7&t52ql=J&BMQu{fa6y zXO_e>d?4X)xp2V8e3xIQGbq@+vo#&n>-_WreTTW0Yr?|YRPP43cDYACMQ(3t6(?_k zfgDOAU^-pew_f5U#WxRXB30wcfDS3;k~t@b@w^GG&<5n$Ku?tT(%bQH(@UHQGN)N|nfC~7?(etU`}XB)$>KY;s=bYGY#kD%i9fz= z2nN9l?UPMKYwn9bX*^xX8Y@%LNPFU>s#Ea1DaP%bSioqRWi9JS28suTdJycYQ+tW7 zrQ@@=13`HS*dVKaVgcem-45+buD{B;mUbY$YYULhxK)T{S?EB<8^YTP$}DA{(&)@S zS#<8S96y9K2!lG^VW-+CkfXJIH;Vo6wh)N}!08bM$I7KEW{F6tqEQ?H@(U zAqfi%KCe}2NUXALo;UN&k$rU0BLNC$24T_mcNY(a@lxR`kqNQ0z%8m>`&1ro40HX} z{{3YQ;2F9JnVTvDY<4)x+88i@MtXE6TBd7POk&QfKU-F&*C`isS(T_Q@}K)=zW#K@ zbXpcAkTT-T5k}Wj$dMZl7=GvlcCMt}U`#Oon1QdPq%>9J$rKTY8#OmlnNWBYwafhx zqFnym@okL#Xw>4SeRFejBnZzY$jbO)e^&&sHBgMP%Ygfi!9_3hp17=AwLBNFTimf0 zw6BHNXw19Jg_Ud6`5n#gMpqe%9!QB^_7wAYv8nrW94A{*t8XZu0UT&`ZHfkd(F{Px zD&NbRJP#RX<=+sEeGs2`9_*J2OlECpR;4uJie-d__m*(aaGE}HIo+3P{my@;a~9Y$ zHBXVJ83#&@o6{M+pE9^lI<4meLLFN_3rwgR4IRyp)~OF0n+#ORrcJ2_On9-78bWbG zuCO0esc*n1X3@p1?lN{qWS?l7J$^jbpeel{w~51*0CM+q9@9X=>%MF(ce~om(}?td zjkUmdUR@LOn-~6LX#=@a%rvj&>DFEoQscOvvC@&ZB5jVZ-;XzAshwx$;Qf@U41W=q zOSSjQGQV8Qi3*4DngNMIM&Cxm7z*-K`~Bl(TcEUxjQ1c=?)?wF8W1g;bAR%sM#LK( z_Op?=P%)Z+J!>vpN`By0$?B~Out%P}kCriDq@}In&fa_ZyKV+nLM0E?hfxuu%ciUz z>yAk}OydbWNl7{)#112j&qmw;*Uj&B;>|;Qwfc?5wIYIHH}s6Mve@5c5r+y)jK9i( z_}@uC(98g)==AGkVN?4>o@w=7x9qhW^ zB(b5%%4cHSV?3M?k&^py)j*LK16T^Ef4tb05-h-tyrjt$5!oo4spEfXFK7r_Gfv7#x$bsR7T zs;dqxzUg9v&GjsQGKTP*=B(;)be2aN+6>IUz+Hhw-n>^|`^xu*xvjGPaDoFh2W4-n z@Wji{5Y$m>@Vt7TE_QVQN4*vcfWv5VY-dT0SV=l=8LAEq1go*f zkjukaDV=3kMAX6GAf0QOQHwP^{Z^=#Lc)sh`QB)Ftl&31jABvq?8!3bt7#8vxB z53M{4{GR4Hl~;W3r}PgXSNOt477cO62Yj(HcK&30zsmWpvAplCtpp&mC{`2Ue*Bwu zF&UX1;w%`Bs1u%RtGPFl=&sHu@Q1nT`z={;5^c^^S~^?2-?<|F9RT*KQmfgF!7=wD@hytxbD;=9L6PZrK*1<4HMObNWehA62DtTy)q5H|57 z9dePuC!1;0MMRRl!S@VJ8qG=v^~aEU+}2Qx``h1LII!y{crP2ky*R;Cb;g|r<#ryo zju#s4dE?5CTIZKc*O4^3qWflsQ(voX>(*_JP7>Q&$%zCAIBTtKC^JUi@&l6u&t0hXMXjz_y!;r@?k|OU9aD%938^TZ>V? zqJmom_6dz4DBb4Cgs_Ef@}F%+cRCR%UMa9pi<-KHN;t#O@cA%(LO1Rb=h?5jiTs93 zPLR78p+3t>z4|j=<>2i4b`ketv}9Ax#B0)hn7@bFl;rDfP8p7u9XcEb!5*PLKB(s7wQC2kzI^@ae)|DhNDmSy1bOLid%iIap@24A(q2XI!z_hkl-$1T10 z+KKugG4-}@u8(P^S3PW4x>an;XWEF-R^gB{`t8EiP{ZtAzoZ!JRuMRS__-Gg#Qa3{<;l__CgsF+nfmFNi}p z>rV!Y6B@cC>1up)KvaEQiAvQF!D>GCb+WZsGHjDeWFz?WVAHP65aIA8u6j6H35XNYlyy8>;cWe3ekr};b;$9)0G`zsc9LNsQ&D?hvuHRpBxH)r-1t9|Stc*u<}Ol&2N+wPMom}d15_TA=Aprp zjN-X3*Af$7cDWMWp##kOH|t;c2Pa9Ml4-)o~+7P;&q8teF-l}(Jt zTGKOQqJTeT!L4d}Qw~O0aanA$Vn9Rocp-MO4l*HK)t%hcp@3k0%&_*wwpKD6ThM)R z8k}&7?)YS1ZYKMiy?mn>VXiuzX7$Ixf7EW8+C4K^)m&eLYl%#T=MC;YPvD&w#$MMf zQ=>`@rh&&r!@X&v%ZlLF42L_c=5dSU^uymKVB>5O?AouR3vGv@ei%Z|GX5v1GK2R* zi!!}?+-8>J$JH^fPu@)E6(}9$d&9-j51T^n-e0Ze%Q^)lxuex$IL^XJ&K2oi`wG}QVGk2a7vC4X?+o^z zsCK*7`EUfSuQA*K@Plsi;)2GrayQOG9OYF82Hc@6aNN5ulqs1Of-(iZQdBI^U5of^ zZg2g=Xtad7$hfYu6l~KDQ}EU;oIj(3nO#u9PDz=eO3(iax7OCmgT2p_7&^3q zg7aQ;Vpng*)kb6=sd5?%j5Dm|HczSChMo8HHq_L8R;BR5<~DVyU$8*Tk5}g0eW5x7 z%d)JFZ{(Y<#OTKLBA1fwLM*fH7Q~7Sc2Ne;mVWqt-*o<;| z^1@vo_KTYaMnO$7fbLL+qh#R$9bvnpJ$RAqG+z8h|} z3F5iwG*(sCn9Qbyg@t0&G}3fE0jGq3J!JmG2K&$urx^$z95) z7h?;4vE4W=v)uZ*Eg3M^6f~|0&T)2D;f+L_?M*21-I1pnK(pT$5l#QNlT`SidYw~o z{`)G)Asv#cue)Ax1RNWiRUQ(tQ(bzd-f2U4xlJK+)ZWBxdq#fp=A>+Qc%-tl(c)`t z$e2Ng;Rjvnbu7((;v4LF9Y1?0el9hi!g>G{^37{ z`^s-03Z5jlnD%#Mix19zkU_OS|86^_x4<0(*YbPN}mi-$L?Z4K(M|2&VV*n*ZYN_UqI?eKZi3!b)i z%n3dzUPMc-dc|q}TzvPy!VqsEWCZL(-eURDRG4+;Eu!LugSSI4Fq$Ji$Dp08`pfP_C5Yx~`YKcywlMG;$F z)R5!kVml_Wv6MSpeXjG#g?kJ0t_MEgbXlUN3k|JJ%N>|2xn8yN>>4qxh!?dGI}s|Y zDTKd^JCrRSN+%w%D_uf=Tj6wIV$c*g8D96jb^Kc#>5Fe-XxKC@!pIJw0^zu;`_yeb zhUEm-G*C=F+jW%cP(**b61fTmPn2WllBr4SWNdKe*P8VabZsh0-R|?DO=0x`4_QY) zR7sthW^*BofW7{Sak&S1JdiG?e=SfL24Y#w_)xrBVhGB-13q$>mFU|wd9Xqe-o3{6 zSn@@1@&^)M$rxb>UmFuC+pkio#T;mSnroMVZJ%nZ!uImi?%KsIX#@JU2VY(`kGb1A z7+1MEG)wd@)m^R|a2rXeviv$!emwcY(O|M*xV!9%tBzarBOG<4%gI9SW;Um_gth4=gznYzOFd)y8e+3APCkL)i-OI`;@7-mCJgE`js(M} z;~ZcW{{FMVVO)W>VZ}ILouF#lWGb%Couu}TI4kubUUclW@jEn6B_^v!Ym*(T*4HF9 zWhNKi8%sS~viSdBtnrq!-Dc5(G^XmR>DFx8jhWvR%*8!m*b*R8e1+`7{%FACAK`7 zzdy8TmBh?FVZ0vtw6npnWwM~XjF2fNvV#ZlGG z?FxHkXHN>JqrBYoPo$)zNC7|XrQfcqmEXWud~{j?La6@kbHG@W{xsa~l1=%eLly8B z4gCIH05&Y;6O2uFSopNqP|<$ml$N40^ikxw0`o<~ywS1(qKqQN!@?Ykl|bE4M?P+e zo$^Vs_+x)iuw?^>>`$&lOQOUkZ5>+OLnRA)FqgpDjW&q*WAe(_mAT6IKS9;iZBl8M z<@=Y%zcQUaSBdrs27bVK`c$)h6A1GYPS$y(FLRD5Yl8E3j0KyH08#8qLrsc_qlws; znMV%Zq8k+&T2kf%6ZO^2=AE9>?a587g%-={X}IS~P*I(NeCF9_9&`)|ok0iiIun zo+^odT0&Z4k;rn7I1v87=z!zKU(%gfB$(1mrRYeO$sbqM22Kq68z9wgdg8HBxp>_< zn9o%`f?sVO=IN#5jSX&CGODWlZfQ9A)njK2O{JutYwRZ?n0G_p&*uwpE`Md$iQxrd zoQfF^b8Ou)+3BO_3_K5y*~?<(BF@1l+@?Z6;^;U>qlB)cdro;rxOS1M{Az$s^9o5sXDCg8yD<=(pKI*0e zLk>@lo#&s0)^*Q+G)g}C0IErqfa9VbL*Qe=OT@&+N8m|GJF7jd83vY#SsuEv2s{Q> z>IpoubNs>D_5?|kXGAPgF@mb_9<%hjU;S0C8idI)a=F#lPLuQJ^7OnjJlH_Sks9JD zMl1td%YsWq3YWhc;E$H1<0P$YbSTqs`JKY%(}svsifz|h8BHguL82dBl+z0^YvWk8 zGy;7Z0v5_FJ2A$P0wIr)lD?cPR%cz>kde!=W%Ta^ih+Dh4UKdf7ip?rBz@%y2&>`6 zM#q{JXvW9ZlaSk1oD!n}kSmcDa2v6T^Y-dy+#fW^y>eS8_%<7tWXUp8U@s$^{JFfKMjDAvR z$YmVB;n3ofl!ro9RNT!TpQpcycXCR}$9k5>IPWDXEenQ58os?_weccrT+Bh5sLoiH zZ_7~%t(vT)ZTEO= zb0}@KaD{&IyK_sd8b$`Qz3%UA`nSo zn``!BdCeN!#^G;lK@G2ron*0jQhbdw)%m$2;}le@z~PSLnU-z@tL)^(p%P>OO^*Ff zNRR9oQ`W+x^+EU+3BpluwK77|B3=8QyT|$V;02bn_LF&3LhLA<#}{{)jE)}CiW%VEU~9)SW+=F%7U-iYlQ&q!#N zwI2{(h|Pi&<8_fqvT*}FLN^0CxN}#|3I9G_xmVg$gbn2ZdhbmGk7Q5Q2Tm*ox8NMo zv`iaZW|ZEOMyQga5fts?&T-eCCC9pS0mj7v0SDkD=*^MxurP@89v&Z#3q{FM!a_nr zb?KzMv`BBFOew>4!ft@A&(v-kWXny-j#egKef|#!+3>26Qq0 zv!~8ev4G`7Qk>V1TaMT-&ziqoY3IJp8_S*%^1j73D|=9&;tDZH^!LYFMmME4*Wj(S zRt~Q{aLb_O;wi4u&=}OYuj}Lw*j$@z*3>4&W{)O-oi@9NqdoU!=U%d|se&h?^$Ip# z)BY+(1+cwJz!yy4%l(aLC;T!~Ci>yAtXJb~b*yr&v7f{YCU8P|N1v~H`xmGsG)g)y z4%mv=cPd`s7a*#OR7f0lpD$ueP>w8qXj0J&*7xX+U!uat5QNk>zwU$0acn5p=$88L=jn_QCSYkTV;1~(yUem#0gB`FeqY98sf=>^@ z_MCdvylv~WL%y_%y_FE1)j;{Szj1+K7Lr_y=V+U zk6Tr;>XEqlEom~QGL!a+wOf(@ZWoxE<$^qHYl*H1a~kk^BLPn785%nQb$o;Cuz0h& za9LMx^bKEbPS%e8NM33Jr|1T|ELC(iE!FUci38xW_Y7kdHid#2ie+XZhP;2!Z;ZAM zB_cXKm)VrPK!SK|PY00Phwrpd+x0_Aa;}cDQvWKrwnQrqz##_gvHX2ja?#_{f#;bz`i>C^^ zTLDy;6@HZ~XQi7rph!mz9k!m;KchA)uMd`RK4WLK7)5Rl48m#l>b(#`WPsl<0j z-sFkSF6>Nk|LKnHtZ`W_NnxZP62&w)S(aBmmjMDKzF%G;3Y?FUbo?>b5;0j8Lhtc4 zr*8d5Y9>g@FFZaViw7c16VsHcy0u7M%6>cG1=s=Dtx?xMJSKIu9b6GU8$uSzf43Y3 zYq|U+IWfH;SM~*N1v`KJo!|yfLxTFS?oHsr3qvzeVndVV^%BWmW6re_S!2;g<|Oao z+N`m#*i!)R%i1~NO-xo{qpwL0ZrL7hli;S z3L0lQ_z}z`fdK39Mg~Zd*%mBdD;&5EXa~@H(!###L`ycr7gW`f)KRuqyHL3|uyy3h zSS^td#E&Knc$?dXs*{EnPYOp^-vjAc-h4z#XkbG&REC7;0>z^^Z}i8MxGKerEY z>l?(wReOlXEsNE5!DO&ZWyxY)gG#FSZs%fXuzA~XIAPVp-%yb2XLSV{1nH6{)5opg z(dZKckn}Q4Li-e=eUDs1Psg~5zdn1>ql(*(nn6)iD*OcVkwmKL(A{fix(JhcVB&}V zVt*Xb!{gzvV}dc446>(D=SzfCu7KB`oMjv6kPzSv&B>>HLSJP|wN`H;>oRw*tl#N) z*zZ-xwM7D*AIsBfgqOjY1Mp9aq$kRa^dZU_xw~KxP;|q(m+@e+YSn~`wEJzM|Ippb zzb@%;hB7iH4op9SqmX?j!KP2chsb79(mFossBO-Zj8~L}9L%R%Bw<`^X>hjkCY5SG z7lY!8I2mB#z)1o;*3U$G)3o0A&{0}#B;(zPd2`OF`Gt~8;0Re8nIseU z_yzlf$l+*-wT~_-cYk$^wTJ@~7i@u(CZs9FVkJCru<*yK8&>g+t*!JqCN6RH%8S-P zxH8+Cy#W?!;r?cLMC(^BtAt#xPNnwboI*xWw#T|IW^@3|q&QYY6Ehxoh@^URylR|T zne-Y6ugE^7p5bkRDWIh)?JH5V^ub82l-LuVjDr7UT^g`q4dB&mBFRWGL_C?hoeL(% zo}ocH5t7|1Mda}T!^{Qt9vmA2ep4)dQSZO>?Eq8}qRp&ZJ?-`Tnw+MG(eDswP(L*X3ahC2Ad0_wD^ff9hfzb%Jd`IXx5 zae@NMzBXJDwJS?7_%!TB^E$N8pvhOHDK$7YiOelTY`6KX8hK6YyT$tk*adwN>s^Kp zwM3wGVPhwKU*Yq-*BCs}l`l#Tej(NQ>jg*S0TN%D+GcF<14Ms6J`*yMY;W<-mMN&-K>((+P}+t+#0KPGrzjP zJ~)=Bcz%-K!L5ozIWqO(LM)l_9lVOc4*S65&DKM#TqsiWNG{(EZQw!bc>qLW`=>p-gVJ;T~aN2D_- z{>SZC=_F+%hNmH6ub%Ykih0&YWB!%sd%W5 zHC2%QMP~xJgt4>%bU>%6&uaDtSD?;Usm}ari0^fcMhi_)JZgb1g5j zFl4`FQ*%ROfYI}e7RIq^&^a>jZF23{WB`T>+VIxj%~A-|m=J7Va9FxXV^%UwccSZd zuWINc-g|d6G5;95*%{e;9S(=%yngpfy+7ao|M7S|Jb0-4+^_q-uIqVS&ufU880UDH*>(c)#lt2j zzvIEN>>$Y(PeALC-D?5JfH_j+O-KWGR)TKunsRYKLgk7eu4C{iF^hqSz-bx5^{z0h ze2+u>Iq0J4?)jIo)}V!!m)%)B;a;UfoJ>VRQ*22+ncpe9f4L``?v9PH&;5j{WF?S_C>Lq>nkChZB zjF8(*v0c(lU^ZI-)_uGZnnVRosrO4`YinzI-RSS-YwjYh3M`ch#(QMNw*)~Et7Qpy z{d<3$4FUAKILq9cCZpjvKG#yD%-juhMj>7xIO&;c>_7qJ%Ae8Z^m)g!taK#YOW3B0 zKKSMOd?~G4h}lrZbtPk)n*iOC1~mDhASGZ@N{G|dF|Q^@1ljhe=>;wusA&NvY*w%~ zl+R6B^1yZiF)YN>0ms%}qz-^U-HVyiN3R9k1q4)XgDj#qY4CE0)52%evvrrOc898^ z*^)XFR?W%g0@?|6Mxo1ZBp%(XNv_RD-<#b^?-Fs+NL^EUW=iV|+Vy*F%;rBz~pN7%-698U-VMfGEVnmEz7fL1p)-5sLT zL;Iz>FCLM$p$c}g^tbkGK1G$IALq1Gd|We@&TtW!?4C7x4l*=4oF&&sr0Hu`x<5!m zhX&&Iyjr?AkNXU_5P_b^Q3U9sy#f6ZF@2C96$>1k*E-E%DjwvA{VL0PdU~suN~DZo zm{T!>sRdp`Ldpp9olrH@(J$QyGq!?#o1bUo=XP2OEuT3`XzI>s^0P{manUaE4pI%! zclQq;lbT;nx7v3tR9U)G39h?ryrxzd0xq4KX7nO?piJZbzT_CU&O=T(Vt;>jm?MgC z2vUL#*`UcMsx%w#vvjdamHhmN!(y-hr~byCA-*iCD};#l+bq;gkwQ0oN=AyOf@8ow>Pj<*A~2*dyjK}eYdN);%!t1 z6Y=|cuEv-|5BhA?n2Db@4s%y~(%Wse4&JXw=HiO48%c6LB~Z0SL1(k^9y?ax%oj~l zf7(`iAYLdPRq*ztFC z7VtAb@s{as%&Y;&WnyYl+6Wm$ru*u!MKIg_@01od-iQft0rMjIj8e7P9eKvFnx_X5 zd%pDg-|8<>T2Jdqw>AII+fe?CgP+fL(m0&U??QL8YzSjV{SFi^vW~;wN@or_(q<0Y zRt~L}#JRcHOvm$CB)T1;;7U>m%)QYBLTR)KTARw%zoDxgssu5#v{UEVIa<>{8dtkm zXgbCGp$tfue+}#SD-PgiNT{Zu^YA9;4BnM(wZ9-biRo_7pN}=aaimjYgC=;9@g%6< zxol5sT_$<8{LiJ6{l1+sV)Z_QdbsfEAEMw!5*zz6)Yop?T0DMtR_~wfta)E6_G@k# zZRP11D}$ir<`IQ`<(kGfAS?O-DzCyuzBq6dxGTNNTK?r^?zT30mLY!kQ=o~Hv*k^w zvq!LBjW=zzIi%UF@?!g9vt1CqdwV(-2LYy2=E@Z?B}JDyVkluHtzGsWuI1W5svX~K z&?UJ45$R7g>&}SFnLnmw09R2tUgmr_w6mM9C}8GvQX>nL&5R#xBqnp~Se(I>R42`T zqZe9p6G(VzNB3QD><8+y%{e%6)sZDRXTR|MI zM#eZmao-~_`N|>Yf;a;7yvd_auTG#B?Vz5D1AHx=zpVUFe7*hME z+>KH5h1In8hsVhrstc>y0Q!FHR)hzgl+*Q&5hU9BVJlNGRkXiS&06eOBV^dz3;4d5 zeYX%$62dNOprZV$px~#h1RH?_E%oD6y;J;pF%~y8M)8pQ0olYKj6 zE+hd|7oY3ot=j9ZZ))^CCPADL6Jw%)F@A{*coMApcA$7fZ{T@3;WOQ352F~q6`Mgi z$RI6$8)a`Aaxy<8Bc;{wlDA%*%(msBh*xy$L-cBJvQ8hj#FCyT^%+Phw1~PaqyDou^JR0rxDkSrmAdjeYDFDZ`E z)G3>XtpaSPDlydd$RGHg;#4|4{aP5c_Om z2u5xgnhnA)K%8iU==}AxPxZCYC)lyOlj9as#`5hZ=<6<&DB%i_XCnt5=pjh?iusH$ z>)E`@HNZcAG&RW3Ys@`Ci{;8PNzE-ZsPw$~Wa!cP$ye+X6;9ceE}ah+3VY7Mx}#0x zbqYa}eO*FceiY2jNS&2cH9Y}(;U<^^cWC5Ob&)dZedvZA9HewU3R;gRQ)}hUdf+~Q zS_^4ds*W1T#bxS?%RH&<739q*n<6o|mV;*|1s>ly-Biu<2*{!!0#{_234&9byvn0* z5=>{95Zfb{(?h_Jk#ocR$FZ78O*UTOxld~0UF!kyGM|nH%B*qf)Jy}N!uT9NGeM19 z-@=&Y0yGGo_dw!FD>juk%P$6$qJkj}TwLBoefi;N-$9LAeV|)|-ET&culW9Sb_pc_ zp{cXI0>I0Jm_i$nSvGnYeLSSj{ccVS2wyL&0x~&5v;3Itc82 z5lIAkfn~wcY-bQB$G!ufWt%qO;P%&2B_R5UKwYxMemIaFm)qF1rA zc>gEihb=jBtsXCi0T%J37s&kt*3$s7|6)L(%UiY)6axuk{6RWIS8^+u;)6!R?Sgap z9|6<0bx~AgVi|*;zL@2x>Pbt2Bz*uv4x-`{F)XatTs`S>unZ#P^ZiyjpfL_q2z^fqgR-fbOcG=Y$q>ozkw1T6dH8-)&ww+z?E0 zR|rV(9bi6zpX3Ub>PrPK!{X>e$C66qCXAeFm)Y+lX8n2Olt7PNs*1^si)j!QmFV#t z0P2fyf$N^!dyTot&`Ew5{i5u<8D`8U`qs(KqaWq5iOF3x2!-z65-|HsyYz(MAKZ?< zCpQR;E)wn%s|&q(LVm0Ab>gdmCFJeKwVTnv@Js%!At;I=A>h=l=p^&<4;Boc{$@h< z38v`3&2wJtka@M}GS%9!+SpJ}sdtoYzMevVbnH+d_eMxN@~~ zZq@k)7V5f8u!yAX2qF3qjS7g%n$JuGrMhQF!&S^7(%Y{rP*w2FWj(v_J{+Hg*}wdWOd~pHQ19&n3RWeljK9W%sz&Y3Tm3 zR`>6YR54%qBHGa)2xbs`9cs_EsNHxsfraEgZ)?vrtooeA0sPKJK7an){ngtV@{SBa zkO6ORr1_Xqp+`a0e}sC*_y(|RKS13ikmHp3C^XkE@&wjbGWrt^INg^9lDz#B;bHiW zkK4{|cg08b!yHFSgPca5)vF&gqCgeu+c82%&FeM^Bb}GUxLy-zo)}N;#U?sJ2?G2BNe*9u_7kE5JeY!it=f`A_4gV3} z`M!HXZy#gN-wS!HvHRqpCHUmjiM;rVvpkC!voImG%OFVN3k(QG@X%e``VJSJ@Z7tb z*Onlf>z^D+&$0!4`IE$;2-NSO9HQWd+UFW(r;4hh;(j^p4H-~6OE!HQp^96v?{9Zt z;@!ZcccV%C2s6FMP#qvo4kG6C04A>XILt>JW}%0oE&HM5f6 zYLD!;My>CW+j<~=Wzev{aYtx2ZNw|ptTFV(4;9`6Tmbz6K1)fv4qPXa2mtoPt&c?P zhmO+*o8uP3ykL6E$il00@TDf6tOW7fmo?Oz_6GU^+5J=c22bWyuH#aNj!tT-^IHrJ zu{aqTYw@q;&$xDE*_kl50Jb*dp`(-^p={z}`rqECTi~3 z>0~A7L6X)=L5p#~$V}gxazgGT7$3`?a)zen>?TvAuQ+KAIAJ-s_v}O6@`h9n-sZk> z`3{IJeb2qu9w=P*@q>iC`5wea`KxCxrx{>(4{5P+!cPg|pn~;n@DiZ0Y>;k5mnKeS z!LIfT4{Lgd=MeysR5YiQKCeNhUQ;Os1kAymg6R!u?j%LF z4orCszIq_n52ulpes{(QN|zirdtBsc{9^Z72Ycb2ht?G^opkT_#|4$wa9`)8k3ilU z%ntAi`nakS1r10;#k^{-ZGOD&Z2|k=p40hRh5D7(&JG#Cty|ECOvwsSHkkSa)36$4 z?;v#%@D(=Raw(HP5s>#4Bm?f~n1@ebH}2tv#7-0l-i^H#H{PC|F@xeNS+Yw{F-&wH z07)bj8MaE6`|6NoqKM~`4%X> zKFl&7g1$Z3HB>lxn$J`P`6GSb6CE6_^NA1V%=*`5O!zP$a7Vq)IwJAki~XBLf=4TF zPYSL}>4nOGZ`fyHChq)jy-f{PKFp6$plHB2=;|>%Z^%)ecVue(*mf>EH_uO^+_zm? zJATFa9SF~tFwR#&0xO{LLf~@}s_xvCPU8TwIJgBs%FFzjm`u?1699RTui;O$rrR{# z1^MqMl5&6)G%@_k*$U5Kxq84!AdtbZ!@8FslBML}<`(Jr zenXrC6bFJP=R^FMBg7P?Pww-!a%G@kJH_zezKvuWU0>m1uyy}#Vf<$>u?Vzo3}@O% z1JR`B?~Tx2)Oa|{DQ_)y9=oY%haj!80GNHw3~qazgU-{|q+Bl~H94J!a%8UR?XsZ@ z0*ZyQugyru`V9b(0OrJOKISfi89bSVR zQy<+i_1XY}4>|D%X_`IKZUPz6=TDb)t1mC9eg(Z=tv zq@|r37AQM6A%H%GaH3szv1L^ku~H%5_V*fv$UvHl*yN4iaqWa69T2G8J2f3kxc7UE zOia@p0YNu_q-IbT%RwOi*|V|&)e5B-u>4=&n@`|WzH}BK4?33IPpXJg%`b=dr_`hU z8JibW_3&#uIN_#D&hX<)x(__jUT&lIH$!txEC@cXv$7yB&Rgu){M`9a`*PH} zRcU)pMWI2O?x;?hzR{WdzKt^;_pVGJAKKd)F$h;q=Vw$MP1XSd<;Mu;EU5ffyKIg+ z&n-Nb?h-ERN7(fix`htopPIba?0Gd^y(4EHvfF_KU<4RpN0PgVxt%7Yo99X*Pe|zR z?ytK&5qaZ$0KSS$3ZNS$$k}y(2(rCl=cuYZg{9L?KVgs~{?5adxS))Upm?LDo||`H zV)$`FF3icFmxcQshXX*1k*w3O+NjBR-AuE70=UYM*7>t|I-oix=bzDwp2*RoIwBp@r&vZukG; zyi-2zdyWJ3+E?{%?>e2Ivk`fAn&Ho(KhGSVE4C-zxM-!j01b~mTr>J|5={PrZHOgO zw@ND3=z(J7D>&C7aw{zT>GHhL2BmUX0GLt^=31RRPSnjoUO9LYzh_yegyPoAKhAQE z>#~O27dR4&LdQiak6={9_{LN}Z>;kyVYKH^d^*!`JVSXJlx#&r4>VnP$zb{XoTb=> zZsLvh>keP3fkLTIDdpf-@(ADfq4=@X=&n>dyU0%dwD{zsjCWc;r`-e~X$Q3NTz_TJ zOXG|LMQQIjGXY3o5tBm9>k6y<6XNO<=9H@IXF;63rzsC=-VuS*$E{|L_i;lZmHOD< zY92;>4spdeRn4L6pY4oUKZG<~+8U-q7ZvNOtW0i*6Q?H`9#U3M*k#4J;ek(MwF02x zUo1wgq9o6XG#W^mxl>pAD)Ll-V5BNsdVQ&+QS0+K+?H-gIBJ-ccB1=M_hxB6qcf`C zJ?!q!J4`kLhAMry4&a_0}up{CFevcjBl|N(uDM^N5#@&-nQt2>z*U}eJGi}m5f}l|IRVj-Q;a>wcLpK5RRWJ> zysdd$)Nv0tS?b~bw1=gvz3L_ZAIdDDPj)y|bp1;LE`!av!rODs-tlc}J#?erTgXRX z$@ph%*~_wr^bQYHM7<7=Q=45v|Hk7T=mDpW@OwRy3A_v`ou@JX5h!VI*e((v*5Aq3 zVYfB4<&^Dq5%^?~)NcojqK`(VXP$`#w+&VhQOn%;4pCkz;NEH6-FPHTQ+7I&JE1+Ozq-g43AEZV>ceQ^9PCx zZG@OlEF~!Lq@5dttlr%+gNjRyMwJdJU(6W_KpuVnd{3Yle(-p#6erIRc${l&qx$HA z89&sp=rT7MJ=DuTL1<5{)wtUfpPA|Gr6Q2T*=%2RFm@jyo@`@^*{5{lFPgv>84|pv z%y{|cVNz&`9C*cUely>-PRL)lHVErAKPO!NQ3<&l5(>Vp(MuJnrOf^4qpIa!o3D7( z1bjn#Vv$#or|s7Hct5D@%;@48mM%ISY7>7@ft8f?q~{s)@BqGiupoK1BAg?PyaDQ1 z`YT8{0Vz{zBwJ={I4)#ny{RP{K1dqzAaQN_aaFC%Z>OZ|^VhhautjDavGtsQwx@WH zr|1UKk^+X~S*RjCY_HN!=Jx>b6J8`Q(l4y|mc<6jnkHVng^Wk(A13-;AhawATsmmE#H%|8h}f1frs2x@Fwa_|ea+$tdG2Pz{7 z!ox^w^>^Cv4e{Xo7EQ7bxCe8U+LZG<_e$RnR?p3t?s^1Mb!ieB z#@45r*PTc_yjh#P=O8Zogo+>1#|a2nJvhOjIqKK1U&6P)O%5s~M;99O<|Y9zomWTL z666lK^QW`)cXV_^Y05yQZH3IRCW%25BHAM$c0>w`x!jh^15Zp6xYb!LoQ zr+RukTw0X2mxN%K0%=8|JHiaA3pg5+GMfze%9o5^#upx0M?G9$+P^DTx7~qq9$Qoi zV$o)yy zuUq>3c{_q+HA5OhdN*@*RkxRuD>Bi{Ttv_hyaaB;XhB%mJ2Cb{yL;{Zu@l{N?!GKE7es6_9J{9 zO(tmc0ra2;@oC%SS-8|D=omQ$-Dj>S)Utkthh{ovD3I%k}HoranSepC_yco2Q8 zY{tAuPIhD{X`KbhQIr%!t+GeH%L%q&p z3P%<-S0YY2Emjc~Gb?!su85}h_qdu5XN2XJUM}X1k^!GbwuUPT(b$Ez#LkG6KEWQB z7R&IF4srHe$g2R-SB;inW9T{@+W+~wi7VQd?}7||zi!&V^~o0kM^aby7YE_-B63^d zf_uo8#&C77HBautt_YH%v6!Q>H?}(0@4pv>cM6_7dHJ)5JdyV0Phi!)vz}dv{*n;t zf(+#Hdr=f8DbJqbMez)(n>@QT+amJ7g&w6vZ-vG^H1v~aZqG~u!1D(O+jVAG0EQ*aIsr*bsBdbD`)i^FNJ z&B@yxqPFCRGT#}@dmu-{0vp47xk(`xNM6E=7QZ5{tg6}#zFrd8Pb_bFg7XP{FsYP8 zbvWqG6#jfg*4gvY9!gJxJ3l2UjP}+#QMB(*(?Y&Q4PO`EknE&Cb~Yb@lCbk;-KY)n zzbjS~W5KZ3FV%y>S#$9Sqi$FIBCw`GfPDP|G=|y32VV-g@a1D&@%_oAbB@cAUx#aZ zlAPTJ{iz#Qda8(aNZE&0q+8r3&z_Ln)b=5a%U|OEcc3h1f&8?{b8ErEbilrun}mh3 z$1o^$-XzIiH|iGoJA`w`o|?w3m*NX|sd$`Mt+f*!hyJvQ2fS*&!SYn^On-M|pHGlu z4SC5bM7f6BAkUhGuN*w`97LLkbCx=p@K5RL2p>YpDtf{WTD|d3ucb6iVZ-*DRtoEA zCC5(x)&e=giR_id>5bE^l%Mxx>0@FskpCD4oq@%-Fg$8IcdRwkfn;DsjoX(v;mt3d z_4Mnf#Ft4x!bY!7Hz?RRMq9;5FzugD(sbt4up~6j?-or+ch~y_PqrM2hhTToJjR_~ z)E1idgt7EW>G*9%Q^K;o_#uFjX!V2pwfpgi>}J&p_^QlZki!@#dkvR`p?bckC`J*g z=%3PkFT3HAX2Q+dShHUbb1?ZcK8U7oaufLTCB#1W{=~k0Jabgv>q|H+GU=f-y|{p4 zwN|AE+YbCgx=7vlXE?@gkXW9PaqbO#GB=4$o0FkNT#EI?aLVd2(qnPK$Yh%YD%v(mdwn}bgsxyIBI^)tY?&G zi^2JfClZ@4b{xFjyTY?D61w@*ez2@5rWLpG#34id?>>oPg{`4F-l`7Lg@D@Hc}On} zx%BO4MsLYosLGACJ-d?ifZ35r^t*}wde>AAWO*J-X%jvD+gL9`u`r=kP zyeJ%FqqKfz8e_3K(M1RmB?gIYi{W7Z<THP2ihue0mbpu5n(x_l|e1tw(q!#m5lmef6ktqIb${ zV+ee#XRU}_dDDUiV@opHZ@EbQ<9qIZJMDsZDkW0^t3#j`S)G#>N^ZBs8k+FJhAfu< z%u!$%dyP3*_+jUvCf-%{x#MyDAK?#iPfE<(@Q0H7;a125eD%I(+!x1f;Sy`e<9>nm zQH4czZDQmW7^n>jL)@P@aAuAF$;I7JZE5a8~AJI5CNDqyf$gjloKR7C?OPt9yeH}n5 zNF8Vhmd%1O>T4EZD&0%Dt7YWNImmEV{7QF(dy!>q5k>Kh&Xy8hcBMUvVV~Xn8O&%{ z&q=JCYw#KlwM8%cu-rNadu(P~i3bM<_a{3!J*;vZhR6dln6#eW0^0kN)Vv3!bqM`w z{@j*eyzz=743dgFPY`Cx3|>ata;;_hQ3RJd+kU}~p~aphRx`03B>g4*~f%hUV+#D9rYRbsGD?jkB^$3XcgB|3N1L& zrmk9&Dg450mAd=Q_p?gIy5Zx7vRL?*rpNq76_rysFo)z)tp0B;7lSb9G5wX1vC9Lc z5Q8tb-alolVNWFsxO_=12o}X(>@Mwz1mkYh1##(qQwN=7VKz?61kay8A9(94Ky(4V zq6qd2+4a20Z0QRrmp6C?4;%U?@MatfXnkj&U6bP_&2Ny}BF%4{QhNx*Tabik9Y-~Z z@0WV6XD}aI(%pN}oW$X~Qo_R#+1$@J8(31?zM`#e`#(0f<-AZ^={^NgH#lc?oi(Mu zMk|#KR^Q;V@?&(sh5)D;-fu)rx%gXZ1&5)MR+Mhssy+W>V%S|PRNyTAd}74<(#J>H zR(1BfM%eIv0+ngHH6(i`?-%_4!6PpK*0X)79SX0X$`lv_q>9(E2kkkP;?c@rW2E^Q zs<;`9dg|lDMNECFrD3jTM^Mn-C$44}9d9Kc z#>*k&e#25;D^%82^1d@Yt{Y91MbEu0C}-;HR4+IaCeZ`l?)Q8M2~&E^FvJ?EBJJ(% zz1>tCW-E~FB}DI}z#+fUo+=kQME^=eH>^%V8w)dh*ugPFdhMUi3R2Cg}Zak4!k_8YW(JcR-)hY8C zXja}R7@%Q0&IzQTk@M|)2ViZDNCDRLNI)*lH%SDa^2TG4;%jE4n`8`aQAA$0SPH2@ z)2eWZuP26+uGq+m8F0fZn)X^|bNe z#f{qYZS!(CdBdM$N2(JH_a^b#R2=>yVf%JI_ieRFB{w&|o9txwMrVxv+n78*aXFGb z>Rkj2yq-ED<)A46T9CL^$iPynv`FoEhUM10@J+UZ@+*@_gyboQ>HY9CiwTUo7OM=w zd~$N)1@6U8H#Zu(wGLa_(Esx%h@*pmm5Y9OX@CY`3kPYPQx@z8yAgtm(+agDU%4?c zy8pR4SYbu8vY?JX6HgVq7|f=?w(%`m-C+a@E{euXo>XrGmkmFGzktI*rj*8D z)O|CHKXEzH{~iS+6)%ybRD|JRQ6j<+u_+=SgnJP%K+4$st+~XCVcAjI9e5`RYq$n{ zzy!X9Nv7>T4}}BZpSj9G9|(4ei-}Du<_IZw+CB`?fd$w^;=j8?vlp(#JOWiHaXJjB0Q00RHJ@sG6N#y^H7t^&V} z;VrDI4?75G$q5W9mV=J2iP24NHJy&d|HWHva>FaS#3AO?+ohh1__FMx;?`f{HG3v0 ztiO^Wanb>U4m9eLhoc_2B(ca@YdnHMB*~aYO+AE(&qh@?WukLbf_y z>*3?Xt-lxr?#}y%kTv+l8;!q?Hq8XSU+1E8x~o@9$)zO2z9K#(t`vPDri`mKhv|sh z{KREcy`#pnV>cTT7dm7M9B@9qJRt3lfo(C`CNkIq@>|2<(yn!AmVN?ST zbX_`JjtWa3&N*U{K7FYX8})*D#2@KBae` zhKS~s!r%SrXdhCsv~sF}7?ocyS?afya6%rDBu6g^b2j#TOGp^1zrMR}|70Z>CeYq- z1o|-=FBKlu{@;pm@QQJ_^!&hzi;0Z_Ho){x3O1KQ#TYk=rAt9`YKC0Y^}8GWIN{QW znYJyVTrmNvl!L=YS1G8BAxGmMUPi+Q7yb0XfG`l+L1NQVSbe^BICYrD;^(rke{jWCEZOtVv3xFze!=Z&(7}!)EcN;v0Dbit?RJ6bOr;N$ z=nk8}H<kCEE+IK3z<+3mkn4q!O7TMWpKShWWWM)X*)m6k%3luF6c>zOsFccvfLWf zH+mNkh!H@vR#~oe=ek}W3!71z$Dlj0c(%S|sJr>rvw!x;oCek+8f8s!U{DmfHcNpO z9>(IKOMfJwv?ey`V2ysSx2Npeh_x#bMh)Ngdj$al;5~R7Ac5R2?*f{hI|?{*$0qU- zY$6}ME%OGh^zA^z9zJUs-?a4ni8cw_{cYED*8x{bWg!Fn9)n;E9@B+t;#k}-2_j@# zg#b%R(5_SJAOtfgFCBZc`n<&z6)%nOIu@*yo!a% zpLg#36KBN$01W{b;qWN`Tp(T#jh%;Zp_zpS64lvBVY2B#UK)p`B4Oo)IO3Z&D6<3S zfF?ZdeNEnzE{}#gyuv)>;z6V{!#bx)` zY;hL*f(WVD*D9A4$WbRKF2vf;MoZVdhfWbWhr{+Db5@M^A4wrFReuWWimA4qp`GgoL2`W4WPUL5A=y3Y3P z%G?8lLUhqo@wJW8VDT`j&%YY7xh51NpVYlsrk_i4J|pLO(}(b8_>%U2M`$iVRDc-n zQiOdJbroQ%*vhN{!{pL~N|cfGooK_jTJCA3g_qs4c#6a&_{&$OoSQr_+-O^mKP=Fu zGObEx`7Qyu{nHTGNj(XSX*NPtAILL(0%8Jh)dQh+rtra({;{W2=f4W?Qr3qHi*G6B zOEj7%nw^sPy^@05$lOCjAI)?%B%&#cZ~nC|=g1r!9W@C8T0iUc%T*ne z)&u$n>Ue3FN|hv+VtA+WW)odO-sdtDcHfJ7s&|YCPfWaVHpTGN46V7Lx@feE#Od%0XwiZy40plD%{xl+K04*se zw@X4&*si2Z_0+FU&1AstR)7!Th(fdaOlsWh`d!y=+3m!QC$Zlkg8gnz!}_B7`+wSz z&kD?6{zPnE3uo~Tv8mLP%RaNt2hcCJBq=0T>%MW~Q@Tpt2pPP1?KcywH>in5@ zx+5;xu-ltFfo5vLU;2>r$-KCHjwGR&1XZ0YNyrXXAUK!FLM_7mV&^;;X^*YH(FLRr z`0Jjg7wiq2bisa`CG%o9i)o1`uG?oFjU_Zrv1S^ipz$G-lc^X@~6*)#%nn+RbgksJfl{w=k31(q>7a!PCMp5YY{+Neh~mo zG-3dd!0cy`F!nWR?=9f_KP$X?Lz&cLGm_ohy-|u!VhS1HG~e7~xKpYOh=GmiiU;nu zrZ5tWfan3kp-q_vO)}vY6a$19Q6UL0r znJ+iSHN-&w@vDEZ0V%~?(XBr|jz&vrBNLOngULxtH(Rp&U*rMY42n;05F11xh?k;n_DX2$4|vWIkXnbwfC z=ReH=(O~a;VEgVO?>qsP*#eOC9Y<_9Yt<6X}X{PyF7UXIA$f)>NR5P&4G_Ygq(9TwwQH*P>Rq>3T4I+t2X(b5ogXBAfNf!xiF#Gilm zp2h{&D4k!SkKz-SBa%F-ZoVN$7GX2o=(>vkE^j)BDSGXw?^%RS9F)d_4}PN+6MlI8*Uk7a28CZ)Gp*EK)`n5i z){aq=0SFSO-;sw$nAvJU-$S-cW?RSc7kjEBvWDr1zxb1J7i;!i+3PQwb=)www?7TZ zE~~u)vO>#55eLZW;)F(f0KFf8@$p)~llV{nO7K_Nq-+S^h%QV_CnXLi)p*Pq&`s!d zK2msiR;Hk_rO8`kqe_jfTmmv|$MMo0ll}mI)PO4!ikVd(ZThhi&4ZwK?tD-}noj}v zBJ?jH-%VS|=t)HuTk?J1XaDUjd_5p1kPZi6y#F6$lLeRQbj4hsr=hX z4tXkX2d5DeLMcAYTeYm|u(XvG5JpW}hcOs4#s8g#ihK%@hVz|kL=nfiBqJ{*E*WhC zht3mi$P3a(O5JiDq$Syu9p^HY&9~<#H89D8 zJm84@%TaL_BZ+qy8+T3_pG7Q%z80hnjN;j>S=&WZWF48PDD%55lVuC0%#r5(+S;WH zS7!HEzmn~)Ih`gE`faPRjPe^t%g=F ztpGVW=Cj5ZkpghCf~`ar0+j@A=?3(j@7*pq?|9)n*B4EQTA1xj<+|(Y72?m7F%&&& zdO44owDBPT(8~RO=dT-K4#Ja@^4_0v$O3kn73p6$s?mCmVDUZ+Xl@QcpR6R3B$=am z%>`r9r2Z79Q#RNK?>~lwk^nQlR=Hr-ji$Ss3ltbmB)x@0{VzHL-rxVO(++@Yr@Iu2 zTEX)_9sVM>cX$|xuqz~Y8F-(n;KLAfi*63M7mh&gsPR>N0pd9h!0bm%nA?Lr zS#iEmG|wQd^BSDMk0k?G>S-uE$vtKEF8Dq}%vLD07zK4RLoS?%F1^oZZI$0W->7Z# z?v&|a`u#UD=_>i~`kzBGaPj!mYX5g?3RC4$5EV*j0sV)>H#+$G6!ci=6`)85LWR=FCp-NUff`;2zG9nU6F~ z;3ZyE*>*LvUgae+uMf}aV}V*?DCM>{o31+Sx~6+sz;TI(VmIpDrN3z+BUj`oGGgLP z>h9~MP}Pw#YwzfGP8wSkz`V#}--6}7S9yZvb{;SX?6PM_KuYpbi~*=teZr-ga2QqIz{QrEyZ@>eN*qmy;N@FCBbRNEeeoTmQyrX;+ zCkaJ&vOIbc^2BD6_H+Mrcl?Nt7O{xz9R_L0ZPV_u!sz+TKbXmhK)0QWoe-_HwtKJ@@7=L+ z+K8hhf=4vbdg3GqGN<;v-SMIzvX=Z`WUa_91Yf89^#`G(f-Eq>odB^p-Eqx}ENk#&MxJ+%~Ad2-*`1LNT>2INPw?*V3&kE;tt?rQyBw? zI+xJD04GTz1$7~KMnfpkPRW>f%n|0YCML@ODe`10;^DXX-|Hb*IE%_Vi#Pn9@#ufA z_8NY*1U%VseqYrSm?%>F@`laz+f?+2cIE4Jg6 z_VTcx|DSEA`g!R%RS$2dSRM|9VQClsW-G<~=j5T`pTbu-x6O`R z98b;}`rPM(2={YiytrqX+uh65f?%XiPp`;4CcMT*E*dQJ+if9^D>c_Dk8A(cE<#r=&!& z_`Z01=&MEE+2@yr!|#El=yM}v>i=?w^2E_FLPy(*4A9XmCNy>cBWdx3U>1RylsItO z4V8T$z3W-qqq*H`@}lYpfh=>C!tieKhoMGUi)EpWDr;yIL&fy};Y&l|)f^QE*k~4C zH>y`Iu%#S)z)YUqWO%el*Z)ME#p{1_8-^~6UF;kBTW zMQ!eXQuzkR#}j{qb(y9^Y!X7&T}}-4$%4w@w=;w+>Z%uifR9OoQ>P?0d9xpcwa>7kTv2U zT-F?3`Q`7xOR!gS@j>7In>_h){j#@@(ynYh;nB~}+N6qO(JO1xA z@59Pxc#&I~I64slNR?#hB-4XE>EFU@lUB*D)tu%uEa))B#eJ@ZOX0hIulfnDQz-y8 z`CX@(O%_VC{Ogh&ot``jlDL%R!f>-8yq~oLGxBO?+tQb5%k@a9zTs!+=NOwSVH-cR zqFo^jHeXDA_!rx$NzdP;>{-j5w3QUrR<;}=u2|FBJ;D#v{SK@Z6mjeV7_kFmWt95$ zeGaF{IU?U>?W`jzrG_9=9}yN*LKyzz))PLE+)_jc#4Rd$yFGol;NIk(qO1$5VXR)+ zxF7%f4=Q!NzR>DVXUB&nUT&>Nyf+5QRF+Z`X-bB*7=`|Go5D1&h~ zflKLw??kpiRm0h3|1GvySC2^#kcFz^5{79KKlq@`(leBa=_4CgV9sSHr{RIJ^KwR_ zY??M}-x^=MD+9`v@I3jue=OCn0kxno#6i>b(XKk_XTp_LpI}X*UA<#* zsgvq@yKTe_dTh>q1aeae@8yur08S(Q^8kXkP_ty48V$pX#y9)FQa~E7P7}GP_CbCm zc2dQxTeW(-~Y6}im24*XOC8ySfH*HMEnW3 z4CXp8iK(Nk<^D$g0kUW`8PXn2kdcDk-H@P0?G8?|YVlIFb?a>QunCx%B9TzsqQQ~HD!UO7zq^V!v9jho_FUob&Hxi ztU1nNOK)a!gkb-K4V^QVX05*>-^i|{b`hhvQLyj`E1vAnj0fbqqO%r z6Q;X1x0dL~GqMv%8QindZ4CZ%7pYQW~ z9)I*#Gjref-q(4Z*E#1c&rE0-_(4;_M(V7rgH_7H;ps1s%GBmU z{4a|X##j#XUF2n({v?ZUUAP5k>+)^F)7n-npbV3jAlY8V3*W=fwroDS$c&r$>8aH` zH+irV{RG3^F3oW2&E%5hXgMH9>$WlqX76Cm+iFmFC-DToTa`AcuN9S!SB+BT-IA#3P)JW1m~Cuwjs`Ep(wDXE4oYmt*aU z!Naz^lM}B)JFp7ejro7MU9#cI>wUoi{lylR2~s)3M!6a=_W~ITXCPd@U9W)qA5(mdOf zd3PntGPJyRX<9cgX?(9~TZB5FdEHW~gkJXY51}?s4ZT_VEdwOwD{T2E-B>oC8|_ZwsPNj=-q(-kwy%xX2K0~H z{*+W`-)V`7@c#Iuaef=?RR2O&x>W0A^xSwh5MsjTz(DVG-EoD@asu<>72A_h<39_# zawWVU<9t{r*e^u-5Q#SUI6dV#p$NYEGyiowT>>d*or=Ps!H$-3={bB|An$GPkP5F1 zTnu=ktmF|6E*>ZQvk^~DX(k!N`tiLut*?3FZhs$NUEa4ccDw66-~P;x+0b|<!ZN7Z%A`>2tN#CdoG>((QR~IV_Gj^Yh%!HdA~4C3jOXaqb6Ou z21T~Wmi9F6(_K0@KR@JDTh3-4mv2=T7&ML<+$4;b9SAtv*Uu`0>;VVZHB{4?aIl3J zL(rMfk?1V@l)fy{J5DhVlj&cWKJCcrpOAad(7mC6#%|Sn$VwMjtx6RDx1zbQ|Ngg8N&B56DGhu;dYg$Z{=YmCNn+?ceDclp65c_RnKs4*vefnhudSlrCy6-96vSB4_sFAj# zftzECwmNEOtED^NUt{ZDjT7^g>k1w<=af>+0)%NA;IPq6qx&ya7+QAu=pk8t>KTm` zEBj9J*2t|-(h)xc>Us*jHs)w9qmA>8@u21UqzKk*Ei#0kCeW6o z-2Q+Tvt25IUkb}-_LgD1_FUJ!U8@8OC^9(~Kd*0#zr*8IQkD)6Keb(XFai5*DYf~` z@U?-{)9X&BTf!^&@^rjmvea#9OE~m(D>qfM?CFT9Q4RxqhO0sA7S)=--^*Q=kNh7Y zq%2mu_d_#23d`+v`Ol263CZ<;D%D8Njj6L4T`S*^{!lPL@pXSm>2;~Da- zBX97TS{}exvSva@J5FJVCM$j4WDQuME`vTw>PWS0!;J7R+Kq zVUy6%#n5f7EV(}J#FhDpts;>=d6ow!yhJj8j>MJ@Wr_?x30buuutIG97L1A*QFT$c ziC5rBS;#qj=~yP-yWm-p(?llTwDuhS^f&<(9vA9@UhMH2-Fe_YAG$NvK6X{!mvPK~ zuEA&PA}meylmaIbbJXDOzuIn8cJNCV{tUA<$Vb?57JyAM`*GpEfMmFq>)6$E(9e1@W`l|R%-&}38#bl~levA#fx2wiBk^)mPj?<=S&|gv zQO)4*91$n08@W%2b|QxEiO0KxABAZC{^4BX^6r>Jm?{!`ZId9jjz<%pl(G5l));*`UU3KfnuXSDj2aP>{ zRIB$9pm7lj3*Xg)c1eG!cb+XGt&#?7yJ@C)(Ik)^OZ5><4u$VLCqZ#q2NMCt5 z6$|VN(RWM;5!JV?-h<JkEZ(SZF zC(6J+>A6Am9H7OlOFq6S62-2&z^Np=#xXsOq0WUKr zY_+Ob|CQd1*!Hirj5rn*=_bM5_zKmq6lG zn*&_=x%?ATxZ8ZTzd%biKY_qyNC#ZQ1vX+vc48N>aJXEjs{Y*3Op`Q7-oz8jyAh>d zNt_qvn`>q9aO~7xm{z`ree%lJ3YHCyC`q`-jUVCn*&NIml!uuMNm|~u3#AV?6kC+B z?qrT?xu2^mobSlzb&m(8jttB^je0mx;TT8}`_w(F11IKz83NLj@OmYDpCU^u?fD{) z&=$ptwVw#uohPb2_PrFX;X^I=MVXPDpqTuYhRa>f-=wy$y3)40-;#EUDYB1~V9t%$ z^^<7Zbs0{eB93Pcy)96%XsAi2^k`Gmnypd-&x4v9rAq<>a(pG|J#+Q>E$FvMLmy7T z5_06W=*ASUyPRfgCeiPIe{b47Hjqpb`9Xyl@$6*ntH@SV^bgH&Fk3L9L=6VQb)Uqa z33u#>ecDo&bK(h1WqSH)b_Th#Tvk&%$NXC@_pg5f-Ma#7q;&0QgtsFO~`V&{1b zbSP*X)jgLtd@9XdZ#2_BX4{X~pS8okF7c1xUhEV9>PZco>W-qz7YMD`+kCGULdK|^ zE7VwQ-at{%&fv`a+b&h`TjzxsyQX05UB~a0cuU-}{*%jR48J+yGWyl3Kdz5}U>;lE zgkba*yI5>xqIPz*Y!-P$#_mhHB!0Fpnv{$k-$xxjLAc`XdmHd1k$V@2QlblfJPrly z*~-4HVCq+?9vha>&I6aRGyq2VUon^L1a)g`-Xm*@bl2|hi2b|UmVYW|b+Gy?!aS-p z86a}Jep6Mf>>}n^*Oca@Xz}kxh)Y&pX$^CFAmi#$YVf57X^}uQD!IQSN&int=D> zJ>_|au3Be?hmPKK)1^JQ(O29eTf`>-x^jF2xYK6j_9d_qFkWHIan5=7EmDvZoQWz5 zZGb<{szHc9Nf@om)K_<=FuLR<&?5RKo3LONFQZ@?dyjemAe4$yDrnD zglU#XYo6|~L+YpF#?deK6S{8A*Ou;9G`cdC4S0U74EW18bc5~4>)<*}?Z!1Y)j;Ot zosEP!pc$O^wud(={WG%hY07IE^SwS-fGbvpP?;l8>H$;}urY2JF$u#$q}E*ZG%fR# z`p{xslcvG)kBS~B*^z6zVT@e}imYcz_8PRzM4GS52#ms5Jg9z~ME+uke`(Tq1w3_6 zxUa{HerS7!Wq&y(<9yyN@P^PrQT+6ij_qW3^Q)I53iIFCJE?MVyGLID!f?QHUi1tq z0)RNIMGO$2>S%3MlBc09l!6_(ECxXTU>$KjWdZX^3R~@3!SB zah5Za2$63;#y!Y}(wg1#shMePQTzfQfXyJ-Tf`R05KYcyvo8UW9-IWGWnzxR6Vj8_la;*-z5vWuwUe7@sKr#Tr51d z2PWn5h@|?QU3>k=s{pZ9+(}oye zc*95N_iLmtmu}H-t$smi49Y&ovX}@mKYt2*?C-i3Lh4*#q5YDg1Mh`j9ovRDf9&& zp_UMQh`|pC!|=}1uWoMK5RAjdTg3pXPCsYmRkWW}^m&)u-*c_st~gcss(`haA)xVw zAf=;s>$`Gq_`A}^MjY_BnCjktBNHY1*gzh(i0BFZ{Vg^F?Pbf`8_clvdZ)5(J4EWzAP}Ba5zX=S(2{gDugTQ3`%!q`h7kYSnwC`zEWeuFlODKiityMaM9u{Z%E@@y1jmZA#ⅅ8MglG&ER{i5lN315cO?EdHNLrg? zgxkP+ytd)OMWe7QvTf8yj4;V=?m172!BEt@6*TPUT4m3)yir}esnIodFGatGnsSfJ z**;;yw=1VCb2J|A7cBz-F5QFOQh2JDQFLarE>;4ZMzQ$s^)fOscIVv2-o{?ct3~Zv zy{0zU>3`+-PluS|ADraI9n~=3#Tvfx{pDr^5i$^-h5tL*CV@AeQFLxv4Y<$xI{9y< zZ}li*WIQ+XS!IK;?IVD0)C?pNBA(DMxqozMy1L#j+ba1Cd+2w&{^d-OEWSSHmNH>9 z%1Ldo(}5*>a8rjQF&@%Ka`-M|HM+m<^E#bJtVg&YM}uMb7UVJ|OVQI-zt-*BqQ zG&mq`Bn7EY;;+b%Obs9i{gC^%>kUz`{Qnc=ps7ra_UxEP$!?f&|5fHnU(rr?7?)D z$3m9e{&;Zu6yfa1ixTr;80IP7KLgkKCbgv1%f_weZK6b7tY+AS%fyjf6dR(wQa9TD zYG9`#!N4DqpMim|{uViKVf0B+Vmsr7p)Y+;*T~-2HFr!IOedrpiXXz+BDppd5BTf3 ztsg4U?0wR?9@~`iV*nwGmtYFGnq`X< zf?G%=o!t50?gk^qN#J(~!sxi=_yeg?Vio04*w<2iBT+NYX>V#CFuQGLsX^u8dPIkP zPraQK?ro`rqA4t7yUbGYk;pw6Z})Bv=!l-a5^R5Ra^TjoXI?=Qdup)rtyhwo<(c9_ zF>6P%-6Aqxb8gf?wY1z!4*hagIch)&A4treifFk=E9v@kRXyMm?V*~^LEu%Y%0u(| z52VvVF?P^D<|fG)_au(!iqo~1<5eF$Sc5?)*$4P3MAlSircZ|F+9T66-$)0VUD6>e zl2zlSl_QQ?>ULUA~H?QbWazYeh61%B!!u;c(cs`;J|l z=7?q+vo^T#kzddr>C;VZ5h*;De8^F2y{iA#9|(|5@zYh4^FZ-3r)xej=GghMN3K2Y z=(xE`TM%V8UHc4`6Cdhz4%i0OY^%DSguLUXQ?Y3LP+5x3jyN)-UDVhEC}AI5wImt; zHY|*=UW}^bS3va-@L$-fJz2P2LbCl)XybkY)p%2MjPJd-FzkdyWW~NBC@NlPJkz{v z+6k6#nif`E>>KCGaP34oY*c#nBFm#G8a0^px1S6mm6Cs+d}E8{J;DX=NEHb|{fZm0 z@Ors@ebTgbf^Jg&DzVS|h&Or)56$+;%&sh0)`&6VkS@QxQ=#6WxF5g+FWSr7Lp9uF zV#rc`yLe?f*u6oZoi3WpOkKFf^>lHb2GC6t!)dyGaQbK7&BNZ7oyP)hUX1Y(LdW-I z6LI2$i%+g!zsjT(5l}5ROLb)8`9kkldbklcq6tfLSrAyh#s(C1U2Sz9`h3#T9eX#Hryi1AU^!uv*&6I~qdM_B7-@`~8#O^jN&t7+S zTKI6;T$1@`Kky-;;$rU1*TdY;cUyg$JXalGc&3-Rh zJ&7kx=}~4lEx*%NUJA??g8eIeavDIDC7hTvojgRIT$=MlpU}ff0BTTTvjsZ0=wR)8 z?{xmc((XLburb0!&SA&fc%%46KU0e&QkA%_?9ZrZU%9Wt{*5DCUbqIBR%T#Ksp?)3 z%qL(XlnM!>F!=q@jE>x_P?EU=J!{G!BQq3k#mvFR%lJO2EU2M8egD?0r!2s*lL2Y} zdrmy`XvEarM&qTUz4c@>Zn}39Xi2h?n#)r3C4wosel_RUiL8$t;FSuga{9}-%FuOU z!R9L$Q!njtyY!^070-)|#E8My)w*~4k#hi%Y77)c5zfs6o(0zaj~nla0Vt&7bUqfD zrZmH~A50GOvk73qiyfXX6R9x3Qh)K=>#g^^D65<$5wbZjtrtWxfG4w1f<2CzsKj@e zvdsQ$$f6N=-%GJk~N7G(+-29R)Cbz8SIn_u|(VYVSAnlWZhPp8z6qm5=hvS$Y zULkbE?8HQ}vkwD!V*wW7BDBOGc|75qLVkyIWo~3<#nAT6?H_YSsvS+%l_X$}aUj7o z>A9&3f2i-`__#MiM#|ORNbK!HZ|N&jKNL<-pFkqAwuMJi=(jlv5zAN6EW`ex#;d^Z z<;gldpFcVD&mpfJ1d7><79BnCn~z8U*4qo0-{i@1$CCaw+<$T{29l1S2A|8n9ccx0!1Pyf;)aGWQ15lwEEyU35_Y zQS8y~9j9ZiByE-#BV7eknm>ba75<_d1^*% zB_xp#q`bpV1f9o6C(vbhN((A-K+f#~3EJtjWVhRm+g$1$f2scX!eZkfa%EIZd2ZVG z6sbBo@~`iwZQC4rH9w84rlHjd!|fHc9~12Il&?-FldyN50A`jzt~?_4`OWmc$qkgI zD_@7^L@cwg4WdL(sWrBYmkH;OjZGE^0*^iWZM3HBfYNw(hxh5>k@MH>AerLNqUg*Og9LiYmTgPw zX9IiqU)s?_obULF(#f~YeK#6P>;21x+cJ$KTL}|$xeG?i`zO;dAk0{Uj6GhT-p-=f zP2NJUcRJ{fZy=bbsN1Jk3q}(!&|Fkt_~GYdcBd7^JIt)Q!!7L8`3@so@|GM9b(D$+ zlD&69JhPnT>;xlr(W#x`JJvf*DPX(4^OQ%1{t@)Lkw5nc5zLVmRt|s+v zn(25v*1Z(c8RP@=3l_c6j{{=M$=*aO^ zPMUbbEKO7m2Q$4Xn>GIdwm#P_P4`or_w0+J+joK&qIP#uEiCo&RdOaP_7Z;PvfMh@ zsXUTn>ppdoEINmmq5T1BO&57*?QNLolW-8iz-jv7VAIgoV&o<<-vbD)--SD%FFOLd z>T$u+V>)4Dl6?A24xd1vgm}MovrQjf-@YH7cIk6tP^eq-xYFymnoSxcw}{lsbCP1g zE_sX|c_nq(+INR3iq+Oj^TwkjhbdOo}FmpPS2*#NGxNgl98|H0M*lu)Cu0TrA|*t=i`KIqoUl(Q7jN zb6!H-rO*!&_>-t)vG5jG>WR6z#O9O&IvA-4ho9g;as~hSnt!oF5 z6w(4pxz|WpO?HO<>sC_OB4MW)l`-E9DZJ$!=ytzO}fWXwnP>`8yWm5tYw`b1KDdg zp@oD;g===H+sj+^v6DCpEu7R?fh7>@pz>f74V5&#PvBN+95?28`mIdGR@f*L@j2%% z%;Rz5R>l#1U zYCS_5_)zUjgq#0SdO#)xEfYJ)JrHLXfe8^GK3F*CA(Y)jsSPJ{j&Ae!SeWN%Ev727 zxdd3Y0n^OBOtBSKdglEBL)i5=NdKfqK=1n~6LX`ja;#Tr!II$AAH{Z#sp%`rwNGT5 zvHT%(LJB+kD{5N}7c_Rk6}@tikIeq%@MqxX%$P!(238YD(H<_d;xxo*oMiv^1io>g zt5z&6`}cjci90q2r0hutQXr!UA~|4e*u=k81D(Cp7n{4LVCa+u0%-8Uha+sqI#Om~ z!&)KN(#Zone^~&@Ja{|l?X64Dxk)q>tLRv{=0|t$`Kdaj z#{AJr>{_BtpS|XEgTVJ4WMvBRk-(mk@ZYGdY1VwI z81;z(MBGV|2j*Cj%dvl8?b2{{B#e0B7&7wfv+>g`R2^Ai5C_WUx|CnTrHm+RFGXrt zs<~zBtk@?Niu%|o6IEL+y60Q>zJlv``ePCa07C%*O~lj?74|}&A0!uA)3V7ST8b_- z6CBP1;x+S@xTzgOY2#s%@=bhZ@i@BwmS)neQG&=9KUtRf^K=MvjC5JnqLqykCE_P0 zjf#V4SdH2#%2EuDb!>FLHK7j;nd6VLW|$3gJuegpEl3DZ`BpJU$<}}A(rW?<6OB@9 zKP9G3An?T5BztrLdlximA;{>Tr7GAeSU=^<*y;%RHj+7;v+tonyh(8d;Izn}2{oz& zW)fsZ9gHYpI?B|uekS3zHUue3mI zb7?0+&Zm>Kq(F>~%VYEn)0b32I3~O^?Wx-HI|Zu?1-OA2yfyJ;gWygLOeU;)vRm3u z5J4vDIQYztnEm=QauX2(WJO{yzI0HUFl+oO&isMf!Yh2pu@p}65)|0EdWRbg(@J6qo5_Els>#|_2a1p0&y&UP z8x#Z69q=d663NPPi>DHx3|QhJl5Ka$Cfqbvl*oRLYYXiH>g8*vriy!0XgmT~&jh3l z+!|~l=oCj<*PD>1EY*#+^a{rVk3T(66rJ^DxGt|~XTNnJf$vix1v1qdYu+d@Jn~bh z!7`a`y+IEcS#O*fSzA;I`e_T~XYzpW7alC%&?1nr);tSkNwO&J`JnX+7X1Q8fRh_d zx%)Xh_YjI3hwTCmGUeq_Z@H#ovkk_b(`osa$`aNmt`9A#t&<^jvuf z1E1DrW(%7PpAOQGwURz@luEW9-)L!`Jy*aC*4mcD?Si~mb=3Kn#M#1il9%`C0wkZ` zbpJ-qEPaOE5Y5iv_z%Wr{y4jh#U+o^KtP{pPCq-Qf&!=Uu)cEE(Iu9`uT#oHwHj+w z_R=kr7vmr~{^5sxXkj|WzNhAlXkW^oB4V)BZ{({~4ylOcM#O>DR)ZhD;RWwmf|(}y zDn)>%iwCE=*82>zP0db>I4jN#uxcYWod+<;#RtdMGPDpQW;riE;3cu``1toL|FaWa zK)MVA%ogXt3q55(Q&q+sjOG`?h=UJE9P;8i#gI*#f}@JbV(DuGEkee;La*9{p&Z?;~lE!&-kUFCtoDHY*MS zzj+S$L9+aTs(F^4ufZe6>SBg;m@>0&+kEZMFmD*~p~sx?rx=!>Ge;KYw<33y#*&77 zFZI`YE(Iz?+tH;Fq;y=MaSqT{Ayh*HFv0(z{_?Q+7@nE%p?S8%X6c!+y;!0NLXwJV8Co_}R3*7>n+oMsQpv8}8ZS-P@(Rg|gmxZHzf=nMOUAAY}AZGfWVzZjE@4$=7xkIrs8BE%606aVU%kxz_04ipig51k& z(>c9rJL2q%xvU%Zj#GR9C9)HLCR;#zQBB@x;e_9$ayn(JmSg_*0G?+wOF?&iu@}S{ zt$;TPf*Lj$3=d<}Q3o!Hq@3~lFxoiCyeEt}o3fihIn{x2s1)e2@3##&GYDq~YO|!q zUs0P-zy)+ohl-VQ`bhvUpC{-d$lkpML_M%Kl6@#_@A}w{jWCDsPa#cSbWA#C4Sf|*C*&Z{ zz?hOU7Cc`?>H$WGqITA2P~fYudnQHxB8^;0ZFKC;19F#~n_2P@{cE{Czq-#K5L_8| zc3aOEwq4%zL5>YU_mc9fc-p~{fBTWUkxTiZvxt9FOqC{s#TBp(#dWc+{Ee{dZ#B!g zHnaOJ8;KO1G;QU2ciodE+#Z$Wuz*Hc6NRO!AUMi|gov=>=cwcZeL&`>Jfn!35hV1J z;B2@0!bIR853w%T*m6)gQ?DPnQ)o6EtKaN3L;o?*q<83d&lG&U=A|6hcT?f0)4h6{ zGIZ0|!}-?*n{zr}-}cC}qWxEN%g60+{my)o^57{QEn(tSrmD7o)|r0+HVpQPopFu; z0<S}pW8W2vXzSxEqGD+qePj^x?R$e2LO&*ewsLo{+_Z)Wl|Z1K47j zsKoNRlX)h2z^ls_>IZ0!2X5t&irUs%RAO$Dr>0o$-D+$!Kb9puSgpoWza1jnX6(eG zTg-U z6|kf1atI!_>#@|=d01Ro@Rg)BD?mY3XBsG7U9%lmq>4;Gf&2k3_oyEOdEN&X6Hl5K zCz^hyt67G;IE&@w1n~%ji_{sob_ssP#Ke|qd!Xx?J&+|2K=^`WfwZ-zt|sklFouxC zXZeDgluD2a?Zd3e{MtE$gQfAY9eO@KLX;@8N`(?1-m`?AWp!a8bA%UN>QTntIcJX zvbY+C-GD&F?>E?jo$xhyKa@ps9$Dnwq>&)GB=W~2V3m)k;GNR$JoPRk%#f3#hgVdZ zhW3?cSQ*((Fog26jiEeNvum-6ID-fbfJ?q1ZU#)dgnJ^FCm`+sdP?g;d4VD$3XKx{ zs|Y4ePJp|93fpu)RL+#lIN9Ormd;<_5|oN!k5CENnpO>{60X;DN>vgHCX$QZYtgrj z*1{bEA1LKi8#U%oa!4W-4G+458~`5O4S1&tuyv>%H9DjLip7cC~RRS@HvdJ<|c z$TxEL=)r)XTfTgVxaG!gtZhLL`$#=gz1X=j|I@n~eHDUCW39r=o_ml@B z0cDx$5;3OA2l)&41kiKY^z7sO_U%1=)Ka4gV(P#(<^ z_zhThw=}tRG|2|1m4EP|p{Swfq#eNzDdi&QcVWwP+7920UQB*DpO0(tZHvLVMIGJl zdZ5;2J%a!N1lzxFwAkq05DPUg2*6SxcLRsSNI6dLiK0&JRuYAqwL}Z!YVJ$?mdnDF z82)J_t=jbY&le6Hq$Qs}@AOZGpB1}$Ah#i;&SzD1QQNwi6&1ddUf7UG0*@kX?E zDCbHypPZ9+H~KnDwBeOXZ-W-Y80wpoGB*A) z_;26Z`#s0tKrf~QBi2rl2=>;CS1w)rcD3-sB!8NI*1iQo59PJ>OLnqeV4iK7`RBi^ zFW{*6;nlD&cSunmU3v4JKj|K4xeN(q>H%;SsY8yDdw5BJ75q8>Ov)&D5OPZ`XiRHl z;)mAA0Woy6f!xCK(9H2rq?qzp83liZAIpBPl-dQ&$2=&H?Im~%g;vnIw1I+8q|kr! z36&^9}CMmR(U2rf|j12oG=vb%Ypsq8u9Kq}U*ANX*)9uK}fAi8;V_7Z;0_4*iydDxN-? zv?qJ=T*{MzL~-xUv{_Kh_q9#F{8gPV!yPUUS8pEq*=}2-#1d=sC_|U-rX~F0 zBLawgCWy#?#ax{~DAnDvh^`}wyUO`ioMK~jgh%L7^}#h?beSyvQ_g>+`2`}`-1h7# zg*?qJdm=53hwN8~B=^|LPmYtOVrQ(W{sNm4uofq=4P@dUA%$onWbw_m-KWia&n9iv zi)!9#OJ#^}eg8tE{wSb9(c0D^PS1 z9EBS5*ypSiVRS_G0v?$hyoZOS7hFWlp4qbYkf9Y&{%OzhsIdHskLptn96@k6@^K@U zszd8POehITDK+AyW#JKpnWY;ju#MC$JjB1Y*~(E6N%{p#kO+bVxG3X<34n3fW=k{A zCZt|KP%x^GQ9%mU)KE0{LA=vaZvRQbxSlK~eAkwWo2Z<{j5eS5NVTMe`m%re8%~7K zZLtU&b~YDN%~uA9wPf>x2=PI=MA6_oVe>Ek$s5&&Z=8vvF5EODP4Av(b|dlNgF1O8 zy83W0WRdzjz2iNA~t1piEqlyU&`$yZtqR`6X_PmuP>W+D|8iH;FQ zN{JuU#Tz9mV=4R_IewROL1|mK^`lLat#LcIBfggzM(iO$pQT*-c_ z94^LUWw#5B9~sp2W1p`c)Y(xfR<{O^9n4E6vDDw{#-R4UMBKo{>Hqlqn*a9rl_>+0 zS5MwJC~nCC`1X%VCyWFsiDX;bfAJQAUkU#105f_s5U-8rqO}n8fA1{b>Fr6Q|Ea(V z5B11Lo^ooWF?`^{-U#?iatokWI-e$632frzY?Yzzx(xJc@LFM4A~-eg!u|tl{)8Nx ztZLXsSC*68g%9TFu(f&J9nmc^9hgyy#uUOMJFCaifSaDcyQ&6=8e9=t zIFEAQ{EK{|73{($!a4=!wj4ABcQrUQp#+gGM?wEUp(w@+Fzi{!lt}|3`PM%&d-seeR zB$}BrFGD3R10CE>Hsb>;PrP}pd` zaY4}6+Wu(`#uAV+E5SV7VIT7ES#b(U0%%DgN1}USJH>)mm;CHPv>}B18&0F~Kj@1= z&^Jyo+z-E)GRT4U*7$8wJO1OibWg0Jw>C$%Ge|=YwV@Y1(4fR>cV#6aGtRoF@I`*w_V4;)V231NzNqb6g@jdpjmjv*<2j02yU$F8ZS$fTvCC`%|Yn#x< zXUnP&b!GLpOY-TY3d?<-Hhxom_LM9`JC9LEX2{t1P-Nj%nG+0Vq)vQwvO^}coPH-> zAo8w#s>Je^Yy*#PlK=XDxpVS~pFe-j#jN-(As&LRewOf(kN-aKF(H+s*{*!0xrlZw zchJu@XAvQWX7DI1E8?F}Wc8m46eT+C<0eXVB+Z^(g=Kl@FG-cn@u$suj)1V2(KNg_ zh29ws6&6(q~+sOAoHY^o86A<#n*?Pg2)cK$+y;cY$hJLq4)4V84=j+3ShSr##Tk5kgmxB zkW+8A1GtceEx~^Ebhwm36U?oA)h)!mt=eg0QE$D1QsLNZ_T3NH?=B&0j~#298!6iv zhc0|-{46*3`Rx&nKSXnf1&w-Rs>#PGAGuY@cBTU-j|Fxbn3z49S#6KBaP^Lx*AOXxIibr z!1ysMi(&kr!1wwQB5w`BDH2~>T4bI`T1}A2RM0zd7ikC&kuBRsB`Z2@J!Udm{AmSN zrr0k6_qCZL**=)xRW`MFu(OY=OT;3G8eF~ z2mmkXZ9X(sjuKmq+_<=LSjphB$~R1o^Yb=rO!j!(4ErIox^x55o{pXSE9X$!76^*$ zoKhlAX6y%n^U=C~@!vIlEgXQGD@>oOU=_(aXF-Sjas*$AKESfRzxQ8#3yOj|y0OCU z>6Z-0%LCcjla&7I+CXm&caKp@@jQ!5M`(_{CL=@4#JJ}cHeZw>^b6fpv269LSV?gV5Q{kk?4;;y9RIsy5vk%DIRiL(9xe1aA@4!VX zDh2}xgUd5X?6nji%&7-%QuyKSYA-Z{PwJijUQ}In+EJl|x@dF1P<5bPa5W3&&?^h$ zZCo8LepKo0a(Fsln*cHL;D(gu9MMkoiM0*n31u)jHqX5x^F95tnI&^}^yKx3YwEm@ zo8?EZ710ykx@19{=yz5IXb8w4yjdveWb{IVL6Z(Cs>!a_0X^1E27o!4e&b43+J*u2Gb(59k2uK0goLwhO{ujLS ziI9LA9`&x~Y$6JNX!aEXR``}LUI}Gr#=<^wBHmg%v<)zRWDVtq)kT$-P7iU1R)2XZ zi~bYhV@EZ`@prgK(cs{>2jn$pxg$<|KjJ7%26Km>%KcXh^bU@y@V_Lf@=j1x%R4{v zOcQn{I}!2W<~08FOVnoV>zOTH=+>v9!jFo|q)ucqIe!N4{U5_G`>>*sVD{8I~4FqyU8imZ**-Gy`~Xd z4w35GMf%7^i65HdX{Iz|f2Kg193#KhPIeR)-=eYx3Z!%RM=JjwLrdk^B#6rg!ym2w zPbFqYyO4>W_Z6PonAwiu7?!h=x%sR-T+_*xZOGh2wWhWr%}%2^$$ zQvACIB~pi=m|`hXIMvoq`TOCx=J_D2>pi6$NPy3&8#vy|oX)=kM0Z}$BR$r0G}MzOk-OqG+VmZtOZoj6x4(tLh|5h) zBv64Y{DPHsy&_H(5_l(&Y}FhVvr9m_*_Q~Zy-}V9+VmGnvndEjYW4qt4K~N&Y&6g| zfpz*V=A#^mVmuOAz)(KVI<%v5NY0%Goy!{9&o41upsPWk(yFuRP|A4q6NMnX%V~MT zi_Rb-Bno2kI+j0Cw`@ydy{e%ARS#Z%b6I%_yfo_ZKXr4BLVoHzBKJ^ZG z-2>2IzU)55@9C|?_P$ew^-7zEiAKG1XAi{!3h%1m#9s%^pGy6S9wKFYY4<$djeoJP z{GI}Vd%idY$4_fh(7NXm7#;cC!DS&-{tGr!Qze{^%bUx2jgG@-kMta^q-EwrKB}d8 z{%FT>rFk_bzW<{lc%eYlrsiYTZXGgzD1&lmRyp+c1O=0=zAX=KV62bx-a~JP{cPF4 zU$-XT#(9&T>l@bMu3nSr{)%-5lV+0t&bxip4DVJ~vlL$J2P6X~ zd{FS8vm{Lhrieul*7&(AgPuXhjpGila%6_?-+k#b)cdk#M1jB*nE>G6NGOr+Ek{`= z9b%S1`$`=g0CC$>0$Db;l_szReLYVmce*(()9%Zz1`*fNXhI*oRlerWHarD(v^W^c zuc1Vuw6Gbp7ZsoRH>QGt#&lv;5G~Ovt$%7VFd*-rN2>UjbOWBFGNGO`bru7CFB4tn zL`^?69Lj_g_TA&`9`dSI8s|)K|QM0 zybvV7!>xDY|6c6y;Q}qs`){1+WQu_5Dgd8Qe|q}}bxjH+joQQtqs1IVZn6{e7T{ia zF|=^xa%eWO%(x<7j*QZbcU_;aVaVP!arexOLOtoSNt*hvsRL%}%)jPetSich(`b-^ zMZ$PM9%s@%*jPVz0Z^W*cK_>G4f}+eEVX`HOaHg#!B`<4v;x}zDLMR*M27`kNfp!! zOfdt(>k-g>7jf^{Se@3$8<+;R*cYtw+wD_Z8Pl~!JDCUEPq{Ea*!J9`%ihyNJZ30i zmfve}S5<$Uso}_?SuI$ks|{-ddGLu9WR9`^9)Kdi@Vs;x#SY-xp}wHPU0|vEA7234 z@BN1z7OF=OOQtPF$4twn3!HTVlUVD_)ubMM7PEPoiC6lQgL2q9PK4~e8v-OuH%lie z?NgBLkIdPMG$QBq(>r^AOHB`|*1#*!2Z? zuU8H|FD`OBRu^(R?Z-Vhr0j;FLpS~a34KREnd}B=EYHS*>Hm+f%tgJt!4J8Q`qn^4 z9F=tO#JRJ}tzA`vx$nZ)O%wC?Uiv0+_nz}5Lj4ki*&=K&*#U`=rv z`Q@Q{+IhAj@6lrNK2B=8Yln!O2%zomfRehFT~;!O@(@Xy|1Jlw*uOB-M$#6K^)QBm z_7%#QVUDPwnW{iOV-grMQQU|3{=BQMh}c5(yMGdoQf*)k9-B zMQ(^GdJh+y)>qJprknS!%WxqM>HlHOP#7UVdy>%PW$!l72J`n-p7j(DBKoGxXWh(Y z>BFDZl|7knU_jg_SSbvFk8)39%2)Hu5W0}HKlh>EaqvFoXI&56Yy)3) zQkE4X^P0QnPn?iUUVHJZXzPp`s5uv?pG{K9IgGoHvcmlBxubi|iF7n{)mhenIcxGs zgr0OpQy#Y#u=5lOyiECfE_Sn?Fj1LyoRKcbTgX{p<T*v!CGkPc)pcA2D=4Ekp0Gb*wpy7S88C%Ywsbr?MI(3UdsCM?XJ1X%*hNjB)XqZ*W(qDdtSb z<3XN74ARXL3=c^bfW~F%NM^5*Zx92>Wq`&M625p~j$8mYwLbk%Kf)jbn#<2z$%vP5 zy#b>-tF-S2_AB4;R^K&^-1LJrUmi@9rB^FLF)-k&YHK8P+k@RCJ1qSTZ@=kHxA3l$ zmK_ZG)l6(nmCR1a8|;QF-B5e_ELnjJ1$m-;4UXX?WytF_wz7#&AjwZYTMVieLbq@R z3t-q|G4^BB#EpNu4uyfDebB+-uu_$9>y-dzB30Y9F=R zrW-Heqnj*InPTWHgR9v^R7~hokldh&h8=HDhMW(EFfim1*{)5Lc1-+eBVkK-2!u=N zuZKABgJs3I--NbjE;>Undg6uK`^U>AQ6V zhc!RhYgvrmeGNsftr+(C<_MtuV$`5RZTf#5r=DR?gWG->#})#=(td%C3`oO+2B7im zUqY}&a_QNTn?s+?=mNXiREN%x_=(H)L|DtYPY>SR3pQfBOel7G_jR_{!9`dSj8Up-`JgcB;=Oor)U=_EVjF3C5{Sqh8cq=~bRjoBpoc$kJCgtTyZGSpQ4= zYi$6b$-dGmuTDF&@amhV?cU05g(AZV&v2$4m&j_~GZk;&keSO(@LRESRZ&p`dV*6w z2$em~p*8yM6j;SYorw`M5K2mluJq7P5Yn$VtZj8DEs2Zk=O@4T&Q}>~f31Z{uk}`E z{Dp{KObh1kk~~MfLUod72{Pk6G@T$_0_N??lOrdR=Z;VV#m0l)&@hz{Z?)@sgImi-&i1@95g53rON83v!yVPDHRU*Mzc4yZ(-Fr z{8{WXmIJf7jeswk$;6s~Qac6QyM3W&`}m#gRt=rr95A+Ad&wSAgvXZ|F))rBJVJ5W1CsjN`QaOzct2ocq#0!v zmj#075)C!3oS>&N;aHS@<+c>RHL)8j^p)k(8#7$LEx!1g_1^02!4_qA=;uhKW=+ix zGX%+vBMiRiF^^jm{mdO(?GdWJ#unO#_F^7mhT8)s(z_WlwFyJ#Xh)k5+RG2f;LC*K**1dr`#}~6A=0B=I&V;%zDA1)d@G!X#Rng)7G*2k8Kg447r0ox> z5NK`d(H-afBwo9feDOUi>;BbPsu!2|=@g=3j*PY}@YrOb+SX6?#Yb2xaaK!?>SX1J z_!VsB`2n1=wwSftkydm!39|-1?c%Epx?TO<(#GO~I&{f4+)XwRk<7RQ1~5>QcKH|D z?!}j1ueO0Lk;FZ{k4FA_(S`Ot0w~tl&m0duID*f6RY#bkw||o;kZ# zISYNTb|{~|X$m$Q-Jv#uxyw)eM0gIv`V#wOAp&Vv@>X4_tSZ&L#juM@$S9 zx_X_tLh<_^-F;LAQ09s@sPb%PMTrcw*HUV0P=RYSlM&AXEOI&&R&YCm_S<7DRBx^L zA^R^iwW+LMk(r*$Pq-fKU5X@=mQ=`ErO30H@@&qqnI7zJcrbSh+H<V ze&7Uli0xj@WrW#&-9%*FP~kPYF_YYM_hs5~|ExMynQ%qvq`leRB6W0yhC@pCb8>_P zlf=F~WMv_u*-DV=UaVu#2rlzK{q8D95VwZrfV?gj@rSNWXFvktUq)V5+YrlxwX302ae(;aG4e>L-M@3J+-f3IT{b9l!kg*2M zC1+ND9}6m^()LE87Mt+^Q|)!y#suc&v26C=0W88%a{?)E8Yvo@kM&KNMaOst#|-_CbUTm}WS@-c>nRb;&z^ zYr)+IE$1=jov(CZ%3uR+`~NI>1&Gs6W(jaamjcN$a`2!*nO}l|b%?)Q%%UWzw>A`C zR@px(P*7j$TK?jbv*%x)e^|jcLsv}aF(Z0=7(%Oa7+1wY>{B>d+i&ZA$}k(qgZPZY z;VkW~8eWnU&HPIAbco?&tc2O1$6=7n{u|^Y*nXoac{o1W-6aXfy~KlNbJfLoq~6;+ zDYmnv--Fhqrl+UV#k@_(1=gWNtqhyVKN=9CZ-{Ohi>e=~bm4IKbhM%%W zW8oXE!rGpV7Wt(_^4nndH1_imheaWzDi|I})9ZVZ9>pN+P%dVc5wG`Ze*4`@rjn1^ z`ln(;vPBHQUb}y8S>=8q__r7g+=z$>!pReVB0@XKchAvyGjLQs-u>+w%`frV4FeIG zj=7n~hGrwx*&5aHy(7X$bDZ7YhcP%(*>G^lAYMK;qG~V8Jz@b7oNg;IA1z$9@TbzW z;@I51@Ekef#qbxnG$Y8Z%bm~ibZ=4#%yKr%#b)CDrfKN`ujIY?tA4h9)i~dZ4E;ZM znvb$n2)zn$Wx&zlW%mJZDh28ox$@%`w3i7YFepXUChw}$UXKI=-TM51`M#FH=tdr*mQ!c=aB1296Lu>iTTKZWss0f z5~ihdImPN$aTle_AdbYC^31}_^EK|9R&l#%3hbx;8vJ+Gp^tm{9JDILu*1PW!rh^Dn9p<)h#Sl4kKM%nm<+!ESSk* zC;lLNT$fgr-!+{aBsSx$41b}yy6o>r3F#1&iv3cfY2N<+`0qJ+>=&Qxs}JOEkD?^l-F5i`t5+zNuvJf z3Fh4$mNqiFXL-aq4U4K@Ae$fq-TDT`rvrx;gqx96w^*@s=mcthCaIyPe(w)6kI{EqV10tcShHU9eeAPs)s?6#vrq}>y3FeTJu$Udha+z zs7}rmA@yR(L&>35sNjQqrw}o^)UitMU!5g6nnG)(tgst!^`FKJEzI1(d@j_w@;^hr zgYxlIRYjho4U$bhczfq&YySCqCE(5_d>l(4tk1v9!V7PB%Vx{QO=G2NC@c1%3rEzw zN<6i?h;CJX>h)kn49Sr)g#Em6km6ESP`1qc5C3ZHizN>r>V-fSS=X1nT{+Thh@kC! z(H=PlqDt7V6gOYezXUK-dretz!1?IUD6&eL2b!4=9h+HUO&DYZKMM>|YhlEEg?q?S z^XT4$2Fd|zT=x3U#L1|F;-#`to-Y6hiYkWdO=rRC)meY72pIfl`3zEGDU8($iWR^K zI$nq80aSJII<;#W5Pj>^_T&013BJ*O89Uoq z5>;Paa^E}xar^r=!pexg&OTM8wluk4R~Ru=)Hgk`Y#i_$jk{jc8hx}?(dW*X!l4vs z6_%$s#duJJFmaFc-5#>v6Yea=I~)s_pXGS>Tkz?s+WS}>Qp<9MappMLXpkXpSM~SmH6u)`Z5>o02kJs;w@KhdiZ3}29y*xr|6tMo zBHzGic+b+dTd!xOJ;p{Rguh^corJ;K?R6daayQKm+0rf7|AXg0qs!R9eS7t4{G=fs z1$=?kK1Ih=gEkI>@jgXDWHZt*C7FUEWs|u^pE3Z``^K|1KEC^sbN*4nQUfRc_AyE0 zn)?RrGjgPkzfE~_s!rDB!fDsV+*|kEX4+DyS#8%!cshn;s8svwBXSsDGX2ZRa0={* z=`p1F{zD17*Rk>Uk_cw3t5j=9-d6$}MoM~z{v{t^M!g75-+o8_XkP@CZWUQ2z!^26 zCNOu~hgrrK)y>bgqb{`Q_1^zrG4;cGarP!nb4E~(ZKWc`LVeEq;IewVneLp^ZU2+% z95PgN*M5v7Q;ZlGvM#`&u2NdHm%&gZ{bZM5wBCp&?HeZhwU87wyT_z!n4z+1?=RvXZ^72d*%+R1s1$KbAFtR|= zw;MEq=O7pMIKpFwKH6$OOszJAf<_Z<1)36cB>D>|Z6$gJL~jH`n3MMou$#Si%rDAu z4pSkJspG|^CJ86vg6kkfXsA_`8@8iOryOe!Qhn8SV6}mPlof3=WJRVqAr_b;e->`Z zMR(p|K|$L0^6;u~USxg#B6-ZNc%E1dv*^P=|2k*^NOBni#G%9Y?##{=)8KZwh85OL zSBG9|gb|hdmY^gn(ziY&O5#@I?W)W;361Yb^VQNpz0A7&^(7HRAsUvw#)fvhocvja zLxV65J0_$>&cVRctJFsn^qLos^tG`+B0_gQ{NeOwKt-!C^gGFufdtPT*Vi>l#X1|V z2XxsAcixN)Ekq=a##_^=k_^BFH5_zpvPDRP>u6+3$}i&b zy0@FdzAHw?i9OqnlTts_w5D@Nd#eM)KKEuN#m{|AJyscxa}(eA?z4&4yvXo{OBS65 z-?gW;<+;+ntM}U_yTmHm6*2zj0Imj<&ZgE9Wj|gfsXhrVH-c0p$7HXnR8bxDYOi z=_r3FA~u`L&2;Vir8}P3)k|@c?sK1U@&iWo{HEXcoy>6wQSuJ+b4l%aTBuigs&k@Y<2c=S3Ef?p zH>ki4yDuXdo_eu>X1{E$g(Q-u#zVXN^&%70guoizo7x(kQ0OZ}H$O9UB}(FaX8Ct1 zFpx~}EbHf2r6V;x=@8GH$C2|6*?K~?LrtMYd^bw*WYXhA z_))@RMH;nZedW3+qfWbv<|_#BYOxX^rhbN+!za)|!|8K*LRs(R$O*2SDM{g9k7e{u zN4VIdi}e#0&h?sBxu$>Yy%)j(k1V2fuhp8r!}gfF@b;F?U`6}YnnMh1&sSU&lR^?# zu!61+lGsuFEfDraX3+$QZibCbKzc{75G^T7@WZSQ)j5898G1AOXB*H*TSd`f<`IK# zm1%&t?i|2Z-a&r!pJehzg@!awNp)R)aa?q_SqGrxE5u+T#f?K2;GAHV?O&>!W@Q*k)7=g2vDW+7K zbyY9i{|nOF*SbMYoRQSAbSH2y$bE5(@d6xKxcF#@TE~X#3o=;`0sc!RupdRmQsML? z&>SCwS{FOpSr+@6Uuz3m`hj}(^g`Jz|6?({!%WVJn$H|ugxW+x-GEA?J&U^ugj3Nb z;65~)W<}iH2PJ@st8LtLfSOLXYgj=9<;?ih7rq$bXW9J#!B8!Wu6#U`A$wlcoC*&` z_9Js~7%m79#+edeT&P`@_Ng@e&5J+pqpx%31tAF71)pcz~-yJ>P5yX(nuM4;bUHDa8E(~~l{j~JeCGkX>nHJDpgSf&bTHEf)qw8{Q~CBPEVen|MW2P3vmf`8X9-g|>>ddp zcgfjbl~(?3Wa*NzQH>4nsM$3}Ul>pX1xC0oF3TZXe7=V!9!n?WgvH|R zpbruczmB%z=zkZ>=1R|gXwGThLELqD5KCUhtiRGT*JwKIvzbzV%ZU!e!VcNHSSX3> zObH|oohc8nvQZ2}q??C}@>!fe3gH+HF@4(qWqi>;ag~md#D;cl8&gQb^?2a@5cikT z=7r78@&5gV3Ggc9f=<<8v~yz`NcEGvbX1V_`IL(&+Z>LB zM~$ok2qXzod@1$TEl*U~H$V5g$er{Uj^($sWb7Nr{gsIbE(`$LRGECTOraXiU%=uq z0zvpi1S%)RxTjzoVcR4#10)fs()4Mtsa@e?9j)Bk!LsYyXIZga2q7d%`vQE!V@<1Y zmkpH3LeXJNO9f7l>F84g;huc=4nk(UnU}RLZmYk2TtB#lv34K(?8~gyx-mN%g=U44 zOPdr_!j-;IEbe|l9-buuKEy^Q9MLjSKG$S6dz)!U_32{1)N}L)3+COmlg=nY1@od$ zJ<0z-B%sisAR1yh>z-RfQQb6M4i-d#vxvb~f69M{JLPZv1JSCh1$gQ*LxOF-tH9!k zbQ0ZW)S7)qCSF|=2`q_A3}OHBNBueZwTTz^ar~gz#2KA74&&D)KHt~m4F_nK<^*7_ z!!pN@xiGkq%>1N(rNxw$zu-=1t*IpAy$ z4~dD0w%9;E?(greVWZ3(o9ux`elM>Rek#0 zO=#-(4p5B+wFzlEU7^k{3EdL6sIp|K*>xrriI`}E8ze|z-$YpN`^_teL_7P`%e>IN z7tNiH619P+0Q1hBR|W#POOta)1|LkIRtgz zMJ9VOxXN#o)mlXS=u%`Q>~PBuKEmOWsIuQRp{y%!ty{fEyL0gV)$LQeL#pqX3L@SR zJ2Gb^E9+KVd?;joVOXlGie3?z6>(>u(i!(qGz(W( ze~^xj&IRF<98ypEis{Y_FoHn%C0bW(XeF#Lj=2WUEBqKNPPFppEH?_a3}-h906X}C zSYKcZFU`Om5YlWhh@ogzCn3NvuM~F9jOX|xe-X*!YL+#ceh_tJoHXz`aTnvSrOAZ| zOtdGz?QdT!oAJr3(XL2G(p%2X4{xEohU&vd_zQ(U%ihHOlKPWnb$&YYhx48?|R++>`5?sxvM?!;ru|9 zZ#nwuTK^S%ce<+ggdJBE&fRrXN7O!{nu`%q`M{2Ef_+IRad2cf01P9pST9AOK>y75c!9}~)Et^6$`&Nm{wzWcm4c0j9DF!xJTpGrMp3esI4D_iiDe`sswXSu{dQZE_`^A11 z?Z@Hw=65mVu^%X`>;$mciK}XiZ{xw7I_!t)S00^JuxdCXhIRO~S*lPS(S^je`DH4E zxbKNs8RL`N?gCQ@YSOU=>0FE#Ku#DRO7JA&fu-X8b;3!^#{=7`WsDXUxfUsE(FKSQ z&=N`A7IwLq%+vt(F;z+T=uZNl=@K4|E%p{p^o5(BGjsE|WOR`%8+XgGW8xJTFJc4L zVY#L`OdnSM{HyS$fX1)3_JuNNH1aDsDqi>CzCT5=kY5zV<~29bX)c^I8R5n&ymHkx zj(QC4t#mDK;2xi8O%V;C{HqDQeM64=b4@sa*N_K0a&ro4+8LY6cFHz< ze|!g}zF|tDrP=`+U7KwKl20gdW1%!iN>1=uxA|NZJ2peruBOj?RBPb~8G;s6xIi6- z?_odhafsxoxiBf zwZZ)c*)FLc0#wE~bXw0TPBYl+h9hs|DYr_B4LR_YL@S1hQs=p zNEh%_fUvWZCbJtaF#kP5=(O#{8|g&Kmz1&8{@Lufw^DhtvKx955~aqxi2C=)Z-!Kd z+m-u+#^U4(HYn6a1w652kO0bYBt&goyx(n?MR^kI+{Q?0Y{G~W2) z0dS3fuJ?SU(6ZDp=kUley%PK}K_;YQyK|U|?7t9SHiyIfpT4a_kUVIhH4PSaj@3mo z`z}|mHhx1Pq?@(3vTBb5HTXuFAzFZEt0D-fw_kd=XvwIUh3VXTm{wbDA~cESd5cI1 zd>6=&AvG3yu+)`9oxmfrDQ(1fzv(_0l?bp{a364dXLRRBI8kBv!KsL;brY)#E3`o{ z3TlWUsS0{Voci?6MejccG9x_KiqN>So*1{25r6BSl9jUyR}1TgXBLL7Pr6Wv~Nu47;fbiU7TbL}>qmtl36YSZ() zVf@nqW(As~#`@bIC+AxSw!O5Pocf&rYaCFm?Jd?XR)p#@{!|5^Ws@wd855)mI^8y{ zws+VvGXW6%xoj@JkGb=~%oJ~7m6+uhOv?bH+jJJ~eFgp+}~*^C+3>R-MY!IZQoabCh( zN(T+z@Oyc^C)WqQESmh{d!!T8zS(!wX=R#hEKxMXy(eg zZ+Cwm1a%?;RH$h2_ws|nRjn8ZY!>3gn+6Ep4xT|AeFox7!rac2Lw?jsz}JqPE?5JG zok0}q1P;cuzs%Yrze|&d$oTr<`Lx{fbq2OV=!3v-ODq(n?|WxuhtmwJBIoW^^FB+D z-?Ok9HBKc5@)L(W&vmI{prL?4^OE9TR)bELS=<>*w%&aKjzi*@;5#P3moG@dm{Eke zhE#Is;&=o|{2GWai}7LYEI+gmc^Kj4K7w7n)+9godg?yB2?xs}pF1<*!Sv?D~Uvbkgs9xx9s#6zBv9l@ox>d#H6eqw^KZO;Vg}h!q zI33^$4}yF*q+q{DsJsa(SsV!YQ#zi^IF9MQV6i{SiN4dWWCi%YQ+hNc1r!^+<(YnB zG62-D`M3w3Q2;@X{S`n`{QO>migDpz0FK`->sYDOESs6u>-~<}_XN_6><2g7U#XC{ z$#Ig;n{_yEMnlvx-lP*;ts#DHV0r8j518>~33?Ak#jocW>uk>6V||p7{4rov#RS9c zdPD6r`qF1om9r!zS4Jk1>7fn#GCnmD=JIt1Na`X)=*LP7R!3XATgk`;&U*P<(0d z9p<0T&eYqQ9jot39FxpfuPSPYlfQ$s-*;+c1KL+cHIVcG5`H~^Ryu1Hk7%Nf$TCwR!SzG31@NHpm`mcp8v!wyWM49TjTxASJ-8JP*MTHLC}hF==PUOh8kaaXeGFGd<|e29vSDaS ztPeu&zv0^wN}Hahi`$pcDs~FVt2F;K!q}q*Y@{7i#stWfU`u2La4aerBKhV`^zG~j zJWvtZpcHIP7x*tfLSQcng6D(`HVp4=LWp_0Xt=2wEHjK)!DSz_Z?5J@>awRyk?azj zU-kdSs~cp))*pfJ_q7u`IsCq8F|OShB~D56S(Mwwlt?{yURE7#eI&WcpVq(@9Fd~g zeUiD!a4w51Nj(YzLnau+O3MDub|?loF0=<#jLztAM>PruE7yNDD0L}y=Ayuc?^?Ni zf~%GK=iEhn2}xKp7GonJx!JpDmDsco$|$XtRdUDwbM9$9s7x9-of2nKNj~?b@UOKz z9{`=Irz^ba-c&1vSQxSh;I2`cKc8-4)aCy%#bam;3_8vSJ-jw`_}lyukEC~z00EbC zI*dU3F21A)dSZr{qA5QF+{a%D`h#?8o%M?)*hWxuqnQD(TpcmfNq&UN$BmB)0!r8) zxno@Q?$_D&*4(rW6b+?-Y^5|*P`DHmJ%pI<6*yP)o}2^?>d7P#bd2j=vvx2mfLW@R zQLD`%buR*}nzNYNf%68w-D$7%v|=bXg1mYrdZy~}(@RRZ-U+Gx=nmCjVxr5Ag# zLw3R29-MHJl|`mRxj#sv@EfyR#-q>BE-XFEENbV$#dWM?!VjU8~kKZsd@G=HPrI{HiqN&j<92*-3$^M*;n@rG*i! zvi#?j;lc5w>@+r!6*CVUrN9as=S3?(ZBT979$5R#ZpPm?2VjIyQcEFp9orGR>f;G? zK<~FiYY6ow-&}|v7k?+03TC++so$)2~rN``u z>N%j$AbNQLX_!evzG8abf=15260vIXdz7K^a$YS)iw{@x5<|Rr#ii|ov=LJ{eu>dZYe_ip$ZuzvRu1dpjQK1BvP zH~m#t=2_wy>9+YkdNF-z` zQ*#7=^r%R*pIi2AI`>n9>(QJVE1k8?Ilav<)NUjW^O$}^yZZ{_Uwn!4Fq1`aslX;Y zj`XDIm`E1sz|wShA=?a@ZGKDSMU#Z3$E!1nZ)g^Eg3ZDoSN6@RXrGVCHvMIauS7d> zuJltXf9)LdTWdF!n%-iA9b#2$W#i??K)zYho^((ZqluvhAr@{H{diy0%@-~VW zKYC|2Ma)2^=skdLT@ZVqJfiCDqS@~qIGexL(BKy6Aw9ch0hoHN&E+m3*uka9+AIh3gTWdSe~W({-&^oFw`!j7$DcsF$7`pO?kRMK<9h=SV?cmyJIe`$4|zoI(6u9#qY9zM?#zNe^!Dl2>Z^dH`>`wSY# ztU;V*+g0R0DH6EnJA$U{QL&T~&s{`smeC2I-5mzv=v$l@iF;yN0hMibU=CG^e>J;+9k`Si9PzLaj$>}QKI6lWmO_o+_( zmhxA*0|-Na`+*J1qEMIXZf9rb#;pcOw>EDeDjb!|GumQ2!1ac;YqU|X;F@l1_lemzTN0J|U zFJF(kO21aHg)*KfuKT=BA{VDkOvlx(b{f|A9D69_BHUm#S$F>~`Mt@GesjLp3;reY zP~q>6Tt;`XkjqV?i7lqPbWGh`y<7dq<}pDHl-dDA4QG6`QDq)+vq_&HfW!}P6Cp4d zt>Qnli5ri*I1ILEOGD~3Y!@2^Jmcy1xDXmKolC?at}_6;neEfca0rLHT}NLpoUYh` zDbCtfZnYN&>}m-(F{5d1=)bBuZ?OcP`GmsQV@kn%JMJUIep`Avon#8=ATpEo-@hg& z12f-)R=HCD%pUjvbWa|P!}u)=wInpZG*LHKrZDMeC>Qils^IyY)x;kDRs4c3!DDOG zAptSsf#1X>kSli|Qka@S)6O4un-2aKL?bcV;$*>KSxHovjrfZ^-+c#>;(42yj71K| zzRyFiLrwv$rPcNA{mtv=o(*JDA0kS93>OE0D{KMJzLk$cc_5dCLWnJcFJd6_>BpE< z?aW9;^!;arQcIjloW&YL+~MkNO&a>N=pmhg>{SM<@`a&VeUA`ay*P@R$_+WS2%r?_ zs&Z%c`>ie+%!I=Lz>$9$7a`-`hoc&*dl60^whsaQ;~9~@JYn1Oc_bmgVVyAzUOYgZ z#j{`#D_YZ)(wa5;qzR#zo4a|-ANJjBB90r4Iun3*BkMxw_Ti>SjhktsmR|BPCLt>9 zZ_3eQjweI*-8+HNt)$9^s|+10w@sU!PY{`#BnF!ULS=#{k0Zr5`yOS?p8PfWbKT`6 z@T+PeRJ4`fj5t8bMs)0>o9|C>mBTlfQ*nFG#Rri-Q7}E}+eaz`LmO!`Y_pHkoAruu z`&!5VNnA3IG$}Pz)V&pt&AF!$E{J-;or3vWv3&Sl&9KzG+ae73Zf}=aP*SCI1{?0T z9SAC)W(?DSKOkcmW$(K5Bl?c@(5#>J#j@eq#ctX~$TIjkl>Wrfv%Ey+bl1Z-v?NxJ zwZ9!ae-MsHPUx&_W22?9$mCE%&~lzVG?hDXM%~gXGk+Q!Jf0BspkMWxy;^!n<6JIrSYjv z6F%~$8)0^qbUho9Sdf97b_n({$;|XH9-RHrohHuPcro@03KEPFejN&q?&nJFoIQY; zSI#uL6>2^^yOR!51OLO65xGas55dPG;3=uQ35ZYW04#+~byXQf^7Vq`G z zKpxF`G*X(YOz2^@7i#D+s-~A1E;3&x%%qL5hkiy^JhYjJ74{hvVmAx*6BH`M`!qGC zO9pjEsR)A-n1`6KLACSL%FS_Kcm+?4*z-V?WAZPs?RkzoijIr~I+oh1^~T`q^dCFvG$Gbd8AnTYBjLKYUmayaQz#S1le7Q^Hyr#;X&h*1wDpm+gZC!rSKom zq|+o&UGpeXtlQ1;?@JukKG!8PGS1Io0z6O}ZeL&DsON^I0K+>Mxv#ohK+;ByAZ`Eb z2orY{j0Pa3edA(#-pJA0AaJ6h& z81Gl(pd#j~mrizktoid14K5ig7u8FvZmLLP%l@dl05IprCyqDB?mA2fc*6UB+49lb zZ8`V9epdo=OeZoiY%zw-w`8DNwTORV_>>3T{r)1-YsGSo0E2s>tix9OBqKFBjg#}G z`pgkCblKMYs!Z)r^(qT_c+}gLhR|gnq!1~Qr|~kt&2@_yswx{i$KEn`8J1W8BGljl zr@GEG#W(s#AKKyuqLp+cl1C}7%`m#-!$15XF{M(M*-fD%+i#mFbP35jlgN3{8#A-dmj&OQtG)!031jTwGMal=&YtPfq2AUWekP9J-JT(p099!L`+yen$ zVH1?kRrhV7(mGKkm_jPP_U@Xd;x=ppk}4WY0Rbr> z0MJM_;$GGxL*P68y%KBqHntF{>X&<{aeI4m6+{TQ%~Zp}v%Pujr)zg5mV;cFKqeA- zQm5`#Sd{B6Rc*4PS-rO(vf>YEdXmOK?>K@`L5}|9q}#t_IE%g+U<-1qw3mr5&v;2A zCQ}BEn9_u;;>n5N#dP0RhCF-_UplC+U(i~Zjh>U5+b8%@p3HK(R*IMQwE!uritb}< zF)AK2?+0@-aE3LYkg`B*&N&m~JWB9>(Z>`aqRwgioU)0w{U1K4?>-#i|ZfhNa9hV)2)(%ch zJMH1twoeZWwkE@I!dz$ma+;9GeACv>Ncupl@+gBSeU_uzfj!$+h&@EACkZG_vwLGA z(?^;rcJu1$5H~xI@6lHIYC-$+b&hF1p`AoAOKqw{t0Fu#X`OGt$)7Q!nmJ=&)xjq@ zHoxT4pcYKSPT5(4yzIuQ^S*N2NJpR4v0?rB-^JuaXNLis?E(l>Jo8mUw(gsFLLOy? zEszHWGaCn|lw$LSwoj{G7Uq(zK0W^VVWu#ms8BMRlF2z%-g`fOXmndgC(na8fc)s` zz$GAoxP+l|+T_S4$r1sLwkV77ew1Gug*`|HiE*?FGLm1q; z^p0A0eqqbmk3?|!CB9DBN1Zof6d7+ zJSn!`VD~tVaqy<*Mw^8dM5v3Bvj2VdVFb=)U3L2eDM3@>n(P z?Rr_=I17+r4fE{>1LBQG0&o97nef67n-aNnVP<{dd6*B!Q344 zZbsAof&jw+;CLeK2d87t9s~YZ5?6Qwf&{NPEBN+)LbjOcZRXNcR&h)x`TtdpI+b!>$E~h0o1L*2OddpR9!Gw~-E^Cj(7i69S<66ak$)AYMv|xG+;uR(`;h zGIV3}?+Qxdjz)s;s}jHY{JPmeo@-tN$H@hxaV@)}K?y~ts~E6H(F|SlsN5oH8g7*h zGiC!8c1doE3U|D}Vul1yPmXuCk*hmyU4MG2ml#V0+(G5I+`L_=3cD$%$I=@*8m-LU-!fn&-sZO1%ls63+w}AiAK`Jv z>`q~ztr&&(gCkFpci+*1Ekdv*MhBCzGfPBj9dM|YEjZk(tWBuz4?MGeq+*)t>Q=z6UXF_w z{QDUT4^JQ8J%hW;d2xGB>Fl4Y-bRT!ttP2GE5jYoI1e(eVK0&V5W+>zludt=nf|UN zi1IV;MK$Fy%$yw<oGeW?JIGjmfGLH$Y;l|T0p1V!N*Jvu zHSAG0WpwPip0vm7%VRq8$2O2>P5b!WBfTz*6dZ4Wd6O9Y(8A;nOuG((y?F`ac_u2( z#~17CoTK)1G<~~Z4jXlout{e&nZbDHyHf(=a?OtaJ(2Q(!g#)Ugw-QQ?A?mN#yN%T zBtJ`sA6Lpg`k>Pi8a7GssiY$eG0Be8LCoQL{GDqi-;j0pLmT!Z)szldvbN7GVcu*S zzb1rEq|M)1qa7rM*I8!<#w7FnQ?{v^? z0`MlS3+`#ZB5$DT4+`7e-Hlp_2G0`*F@STbRJ|!tk3cC~1T%NR-p4s=sTT+RqsMjF zyrp-Jv?CD4Y3N&Zb1gr=%`MFR8;|r)uxQ6*X{OpEhQ~+tu}^n8Wijiy`pSMw0uKNi zSNX^Z1y;WirM0o_x%zft0U2GcLm_2BS`b{Z>g|9VOVr%QF*R?pTpiJsEbj4jLVAyd zTA;x15=f~b0^(e*Vo;Tn;WTJSxpI9LmL($Lxob<^S!k7mGhnnVNnAC*g!$ms0#Q|q zs=25I0<>fUw_&+KU`}5P9wlmjRWdMYh%Np6n?AAHQ;JzG?s(Z9UR`pNh79Nzk~DF+ zX~jy>>f-2bl?drlM8 z3NfIQnrT@pLmv+QA6efWPv!sqe;mh3_RcOj5>Ya;4hhN13dtx*_TJ-=kX_kZQDkPz zIw}#e_dK%au@1*L&iUP^cfH?zf1iK)tHv=t|>-9mMT!;;Vg|svSzWkN7q#t$c4N$Q;tl3EYwef_4q>GO<#I89VhY;`X*hz$n*GZ%f+;uViG z?uLlxD1OIeid}0r9%Ssoc7@vJjZIsZlU9zvYpjhYiOrzD5sq3OC zpf-X;Nb!DLpxqX^zDIK%=46-Z3%i-bac`RIBS5*wcw5Pu>G|kF>TQP$dGRYh#1hwD z{|cbbTOKL>Gb1-;X6?vWLC+KJ_^Ij?KzJ7eZ?^8XNgoYU9^z&>d zsIjX*uOK`#Wu!`>L@y!=XpQcW+mBaRjm|XrB@etLdr}Ob57e7EkE;7a*t7=M#XFL6 za;KHHk-rBNTjp-gS^;ehKNv>K>+_jPQ45J%4><1HyKJ?;T9#~k_23?xD}B&@Wp{%H z($hU+nWR?g!9dsJkgVz(J_Yrdns+m~9V_gQ7Sb`&F4wZZ!k}##j$>O{4{?avCbCZfyW zO$)m7LE=P?$CXHDU_RUD+sYwT;nKI7 zSs_XTv!BuxpJ!7(b~uYfsgzt~mj5(vf2r~`LHwpePs!o2A3zEr@#sxo8HEe8>V||d zBiz0@e&6}p*}!6jsm}I0bN9Mc2(c#jg@;Nu6!Kv&4&P8-UcQ-00WJIO%4OuUn;^jU z;I3r=T3KQtiMQ7&x32eVtB`mCe)9ws^7u%2P`B%Xc}=Qc&O^{FmS^{~Rho}^s`B+H z=1_T);9LRK?{$Vx22!5m)Er8aoPOA8&{7fyt`t@~Vw%gtx~+g3qs8LFR%(2Uny28A6dFYnNQgcUa>Sq=%alFh&8#@1o_qgwve* zVFimnUtL{4aHP6s?FB%bu2SP=e*VGqXC8iuZ-JOc{5%Lx0g|VvyWkdh&FD^Gkc!0N zhoolXvp6GC8wj?Y+V;r*EN+<1ac`-+!8Mqb@Nz)=OqV?4gxhR^t7*+^+AfxxVt(n{ z+fkk|-xSGqmkZa@Q%`;;r`-Z|? z0fR6b@l%pTwK*@xY+(MwBUwf^z+F*~piC64BWTrz}-HS1-XF-IA%?Zs_#F8 zcmUuEZ6Of>YIJOe$&{V;3vIBw7|jSGPeS6cvTMdj96Y~pI-z7InGW;(DhFqaiTTO9@KWvQi9__j0btLZ9 zAa~-Po%^sDFfme4@Yiq}r`BgnYK2eTwCjg9_zC4V{{&_GTm-!qHGVR6JXDjw;}GzF z6lXA{xo1+tQM{9vwb1&sRXPdGDHbEMbnwh}t+%tvcw5p4J4r#hEpDl=A{;Mjc%0)T zsG}v<$^HhdcE)5IJ^iBWK{7?Zn)vb%c!5eIj4 zbT}CGO*u)Od@^LuIC@_2{=AP2-O99NglFudj{!T}0e8wtTQcB@F9QW6$J!0Ye`T+U zXDx84b$!hD#4YzSyZLy~!IIZuFa3%eU zG4eg5?}sZ6Yj29P^-PcXG*8%VzLL$0!oL?c(!oQ+G!kORsa+lsf5YER>PX83R4LgF zgPNQJ#Bo#)MXU%J9k?RWD;c>|as5b5p>xAwau=X5XbERX`_ZHB8_XSNDe`s?n(e>) zGF$G%n6o+W{6A-@4hsIK0*J%jpB#Y*G^B48eQD(CDZR5oBl-P=)r7fH^PLf?!aK6V zwkIM35?l*I6p@;^H}JIDNs-fF*IFN?k?kj(M)QKM%%?dSkf1d$Nly2z(>)oq8z}0H zH?Qa{x&36#W@y04!9zx@x7un@ob$&)V8#f~0n1|jF0kFs4aZ{ND1~QjWHToIY5)LY zrgKDCj@dFCx&-w$QMi=CqD*=`$NqC~2k366pPXl#>Y7A=iQD}f`)+B-pS@LIW_M?9 zlBS_)(vGz!L$#P`?<3Hvonw@B1uJ244y)M?0)z0-hq++sJ0GZ+{oiiH;lFi&wy(C! z0Bv9z^M;`4@)USP)7dhg@K5K&U&|7&-@I0Sk>I+ZH75_xEn>qh9qmc%aA@NEKBsVBgUuK zC=b{w-0oU|)~tAVI zyJ3BAB}%rsjz7qZ?x_XCWe6!_u-{e_3u68Asso0IvwKdxq1lN#%4w>J zi>}P;$JZ>58(ZAjsmSJl6BWUTe`0eGEf3f_yS#H6vx;UJWO7CCK!{)4C}`C$j5gNj|k znb$4QRurEE3tPEe!JzG-a0DmvXePO zSD#Q-qOAjTMm|=aBSnvwHoEbgyVIz@J$hT*legak-hhb}e#%cm2$nR2 zV9A{kc)WT$np=5coPQIskbGMO@Fn2NxPv$@SJZdG6}jV;+%(cH+*RFQ(+DjsJlman zy`D(yN?8MCtjWD3w}Q|jQccb$}BDW%M$zZZnri2+5ls)@@(wQD`jt_GpTKL_^CO&SSCcHbfMX#JXYFI^*947 zPh&S-G=l*C@`E5CU1$m7ao(Q&oSmY7)ZZ#5_fEyYzLsFJwJ%GfErFeRN@7lUbUrL| z$6;gQSNsI91LJvT+$Zb0>g<4g8T{B!U05lfKmoSRH^pB^^8sJ3{8PzVq0NeypMF5k zU3qOqksdq{>AUjm3O~dZx^vS6C$ldgCWszl?xd8-sJ;-kPnISB*-f=L*8XggOx$?u zg%B-QovSjBbj}%sShZv~r?`*6PiiQW;nee<-=+y4}S#}q_BgXIJoSOf$YbE7vXt4;Np zrKzZf6Ny0aES8(-cqmnIGMg&ieYWryBZ0VTB=4<*@auP4NdIk&q(Mt(OLPm|Yl za!0OpC9sA#tk>OsaCSx0;!$5r6naw ztzLBo>#LKaxxsO=yWe%yGilL`A|6E#TK! z+1VRQlo*D?(k0-mlRM+`OMT8kVB*-%ZGv}Aj1u^j!wu*~>L<-T+u?6sX!3C}lQte- zk(6_=iwXsQ0JbRvJDwMnk!c99w~s~uD_4vMB=m~-ft-*|z~$*g4g;pgG~Ap1m@@Fx zWS)8IKSN6`^vVQ8hv^Oc+O(Rt7!U%wVsGP+Y6fyS%GG+v+dIdVfCXPzAV~~li+3m5 ztFQmbE)(#2#Oi@k$1#zUS6ijD_yYsa{+BHZAw+^zAEI3bc(h0qm?|pNf?oS}Km#OG zrOfCKn_-CVO;}DXu|5YE#d8I2o>}vUxYlv&>=+I28WY>a1;uI)HUM_IvpF;Ln4ROT zf!=1rpKihNFUo=R@sD-pT!EOm%%ncl43f;aem^;|A#s3`b6vjeAzO!M-gwc`-Kj~{ zBX)tq64*kJl#TrgW4o%hTY3x$P01nD6a6s2#MmwM$vyX5PU|YngU*wXGK*?f?#Eg$~^OWW3I@of-=XVuu-b%A1Z|nqY_2 z;~jD&=QnB#WGU>;RwFq(I< z34K1fCMwf9F}G%k(&?~2EY&)W*-_z0ReS$;7+I1)zz`)M zpAF{5ZHLPMJhYU z;GE*@hM1NM{G{L94dL$!Y-h6A9K9W=I6AYb`Y=v{(tpyLQz^^Aibea(q()R*TU|-m zozpyr!|-BZ_Dn+$*2|vq2Y@ghHo!-`WjVtU-bab(SJp2*2i-}$UP9^qnF_OIFS~-< zYj^VS!)Wu}vn6!LDIt!HJ1SU-@ce>z8f4cT4R9V@O^Xg9)4`VpjsXm*~@%l^Ux;Rf#Zck`BNXu0Y(!C zj%Z}UAmD00nsOS%Uull)dU(fZgJ$bo>3Oa`8h~Wt)EM?v(ndlTS1p0|E9Pg>=&>58 zghD~%R;YpqZAw;F;M(lx5b_wkVbnd+ER+6A-SYj^1XUgNGn0I~ES|f|5emjyPIW)S z0z8i6)BZt&h(qQxih4HbFYa6~jyeKbc_`QEdLD@9SBGButjw|b^l*oQjDk<7Nig08IK zb`ATVGzK%LP+>9aFM0hr8t+m`uNr?h&8o3Rp$T&ql||K}7GgobFhCViaDH~+F#yC- zt>7T3&_PZ*feTKTyd6vlF~JmEA1f+*>CCE4ex}5N^$4o)YuxX&3T$P0(IS!+kan^J z_p>v#1J8bWELml|S02YAQe-&yVew+kipZr~H-I@yc$=8#rZ-8L<_nDx&Qv3dJDwUX z!)@=h1`~R2M{$J8bM^1O&Gy2oxe1T;K?NA{iv_eYuhpLyc3%xu%z`dVc}Z}%cHGHQ<7P!Q|e?dwnSpL!AUf!B^!?#^Q#W!Ry+7ofwPZ1mZq z(Id0{htmX1W?2cAYWZo_lOtT#+Us-nlP$=CGK|Ri4x0Xh>(|iN9y1 z=9y26A4Y}ViRi9Fxzm{>J`YM>GX1D|$4BY9xJrY{oY2~Z&};B{Zq9Pp!pox`8e#0C z-h~@fohA74(#ws!{7kIe4v6XUX<)9bd)g66Bz%^Y4p0~OF+rY;l$v&7T<3~4y!bv> zR$r#LblZcVgy2lq!ff+>yuR4qCcljQa03x|dTcG7`CHcxh#POtGKt6ymNd_0qF7Wf zBj_KC8{jl!zZ>0neDp19n3sD?HC=|WM3!}cK4zCnu6Uoj*hbV1<#F2BD)@A~y%@VXx+u}Hcn=_s-({PxzmMZ^xJ1SV zoZMY*FarYvO_@z8Lr2ep)%HgIL7rhYa~#X&&V8oYSw zA4m{3{hw1Vb~~26K^xro&e7i9eg^SqK0i}kG3z(!_~E?sjJlSWIWXJqKiHAWTG*SpPcCMD`kEc1gx`R^YkYWz zEN4vEIkj@&e4tC!(_~x`-K$w6CU%X7U2Y z)Y}T5stEyoSsB{H{+xfST3tov~6@lO}2gx#N(rHXiOAHT!dp6FiV8V)B4{L_P_% zmX0rPa^-{1xG6|#uEGo+!v)QAOjRe|jg2ICcXU!|Cr+LMbLHlhJ)ErR*P9*z$NLlt zmYjAUbljq004ZyOco?HJovV7M*Wb2nF8vT2D;3kGi%F)6Kr#TVW>}zTHnUQxoGmD0CY9J`|d%8@}n;_co2q zWr98`R_c@PQbMi}x3bWo4XZj{it6qYj+o*XvNoS4>rF;7WNn;vA*|A!3H}Wh-uk@n z*hV0S+XnX;K;BOoz?&*9_{NnM25s4^^QUt|>R!()^Z6#G3OmL{CU^-IG_M7_a~B+& zCrV;ouC1ljbK(K=ygqAE_-}ewnH2&&t0enS7}I4i0wJgNvCf|P$`|DHku`K`HfDa2=n@DCg8MRi_)vpMR2Mxy4PE2Qe! zD||kNXy=0WeU(43v%md9Hg9Zu#CP%d%C67gk_#pfXs8lf>M=betm(}0fdDKq0{26# z_c?J!Cgo-~*=wswLXkR|W8d+rDdV00`22Ouv=_Hod9bmB!=D$I4r@7DZX7e+0tO!9 zR{0d}A6^K#yRx@ykotO4(WUJsmFvN)d-o-wZ(wcDSUS`8jO-JSAMa4y@MK4fDP`(P zzxQ2})ofiauWKj9{Rm$Yw^?g=?`oO(Vf|T^I+-A+o1#F`>tn59d=FtgVJAV=y;G&` z0GMvtEeil5;e$Ln8-41(UeMl2kYLk%vPl?0+Egg_;g)494o5FsvdeZKP;&&fjw7o{ z|B+e%Z|)8Ts?=>@p|hr!nYXgV=ZjI4Cp#$E>+g^6r7Nd3<>-t=G%B5IyZUI{e{49G zqnIXEB=M@5Ndf1J#l5YWcLG=A4ufF8S{z5Kz-uM?Ni{{%mr);=l0=473h#cIc{K3> zZ-VUw_Ng5^HgWQhs5tQU@qv-YBej9`R$a^|lknX<*+sSVXue8M0#EPBJ6_Liwl*8l z_zoD#!l%WIXJZ$jm?|zUu0LdeP&8IW*(|39&QzKGnem$6--u{ZGtHt#Hro*h)?lu zXGKo-4Hv1WP*VLj;uA6UwGSV*6ro%PRbwR{@tXoCOb=OFTB4ru-|Id!rP5Y6LF*-D zy|t0qDSVPo$ffyoj#CIZV?l3VsPRYye$F^xxv~Z78_fwlCWbwW!nYCR2nx0_+@tg3C_UDMVa2Br=X3hfP}^Cp4Yg=#OK}K zKYVY`V9jEKD!UrCbSX6Xym2T-cg}!n;?;o{mM|zWj0P@D|FO-rQ zKt#ApEh#AX%_f%9!G6`I*K=bSnMIhQ%W5&BOMntzVr*eS;WR;FgM)+k`#+Vze*z&V zkU^I-R|!Nwy<~>eeQ~hJqa2|DdpX15kD=6U73Du;T|VarycBP^n#IZeIJ&H3S9#@oec~poZELqX$DAc>XZyuIqd^GK0Jq~0kI=d zA7gMo8%zmkEdnqMh)tkp?V0I;Tm3`>aU3^~dXw zlhdd3=iygnUgYu#GRhxln}4D?Gokczq?T;RjCk0=fUHy18$lt!-q!%sNxee7No^+N$9d?Es*``)0UJ4SC&FNY0pf z_MlbGdUy$|F}YDvJ9GTCkZbsNKj3DL5;=BGBx8xI;n)=A0d0j6MP7Mi6MQdk@Tux2Qy`oI_&*%EQ0bE?|R>P$rDhcFa8O?JIK zPOpFDa?-L*+Q7RrCg#y5z$l0d>n@+OYo3g>-Z*x&`Jj5|=*UOYaJer6;FAbdtt0O? zrFGUE?!XeUG}G8wMgeTs%+r;3uUU;Nq5EuU{h-g&UOBKhdS`;J=m!~xn*ztv_p@dD zR)tR!P=~5kX)FRsx9)uyuu?0dh%Ht7`PTM@e#Cq!z2ts;O;L)tQ1ipDiWqbGz@o_p z^D=UKR#`S7HAt4vQtD(_SeWyj_av~#tJKlb9>-s5Ykuzx_E1ZNl4)~f=zG$*;-y=T z2ozmFva9az<{2&63fQ?(Q8{IPx@t1LuFcxP-LXVctWh3AwazVTt2)w^*Zn-#eB`bD zSHoAusjOBK5(>uQPGj=ijdOH3jqG?(<5#C{*JQ?Lt~@zow=Ii4Al$Vr!#+Cf-gx)A z`_h(>b@7?*6bYM8%628gGW^rwWoG$mK_eCk`}B&llStfwHf12*{5spmTeNH$4{gCY z@Yuwr*k@%m;T<60bw9z6^WpWi@Bu^qe-g;YAzI+VjgsuZaGA=^G*I{KLy@rIjSpWb zFQNsCp2T;S$VaJtZ<(waRu8y7^X;>YhsWp zM)mKgCeE@K;J4vQSV z&-(Gl5AJCp>K*2-`U|4i;u3p8xo6(isu-38>cY zml1Eo&FBBKJpour?}q&nggpFiGM%m+YX`ng8P+uRnJiMyWcv*_AZ8KAB$w;rfmN8C z<-2EB6TqZO>A~P{*<);wYqZgxQS8E*syOXvGkGxF@s(scud0uv?T)fQ z(DGrwM7lvpitUG~6!*}kZUpBn9PuP`5^nMK@($xI^0Q~axP5qU>L~uF{R_<9&m z({}$$WuD1y-QzMVb3jLPk`~bDJNkw(Dv-6cKUb4uzD= z-w?i0NZ2K}AbT}Zi^uOZ32xmSxJw+6(3j%a!~Tdy-@RxVx6YUw2|V6JX+mSJNclfl zF~SD#eo+lnB=ZpHLl{)E+`sI^-V1Vn!6#Ml_W4aH*Pe(++sNI`M=5L3?X1z0;CJeE zJiX5Mp6JH*=R9W0t(1@>>1y=lP^F=yJil6JxU~I}EpTsBx?rJ5LbCbQ zuLBmmX1MO&!E}khx=+#hCesIB53`IWwqyFtR{AUv7vJ{Q^dn1S0@*^UOmRwctFy&> zd={(J@avBzmu$MbyamRMt_$kfHY<*v)%%&nY4hUDH=$k)$8LHlUG0G3Kv#T~-vQjw z)hXbsNIg?~b-jRw)ir5Q(gfwM+Zk+0haf z+4ER%>T8RnKAoJ-(s&tu&-iZ@A?^J|d z6md=9C4am*v2r=aa&a?~37bc($n#wQ<8UGXL+!RtrRXGSj-2INJ#+3J=}e6nOC}G8 zN~lvCS@rxoq7w$CLg-wx!%V%ymw>~xhUw4cADX*$A}D~{21F$!Y61aHwpdL!QcrsN zl~$s5kk%7HWHkZ43%mOcwlk3RcbKGQ*}K(Fxput)rpE0zH0vY(EyY=blQZ`odG#hD z)~{&r6XkSE(^csqsaMm>2c%xsT2&g_Nab1bTY%fIoNHatDY@C@Ei~v@19|F?szU6SWRS)uDXqNY!48RlAb;S*ijqus; zp;bteR835>3BXML2CewOM<^q3M*ubU`}gnI-oS&(vf=GF|JJB-inGOH_dc1xb|iqR zWgrcNy?1*8)vAlAaiBE%K3Q>5Ygy-#Wf$>FqL|Kvgb&6H?iQC*Z|PN)xZJhH#d#=a z@s9O0oea6Lg}submzNZ{iZ*_okZ$6G*h5YO!dE=7c4=YA9g$y%1xjkVl#|1DShEjM zH3(sS?uRfB3mhW5Wrm} zrY>KpBxM&CC;s5Ie_{o}upN{vdb8x<_$5iiQN49`z`+Zz`&E`yLAim;X&}$HAfKmT zkO2Dgdno95mWMH~h2c4);H=MigT8hyzl|4g;dU7F;p^X>w!fa0zf{^rf?>~ z0w{=F_R}ru{g5i@&xwC%R-!-1x|(k6pSb5_)$f`zyErIvSCs{z`iVvU4x_znFKti!!av6BkRX_=+kEc;*`_rla zB`g4ruCJGT3XVTTrlh3Yj>1>PNIy?sV%Yo*=qaBIOY87_?P04yx6TV?_{~K? zOHEo3|2EA2JAMPYZM!H<{|!s-$r>l5{19icxV`Wf-{<0I>{v&H4FZaCy$B6Ludz{v zRH!!HV#JGP?5(L!Zp#}NlOODgWqjO+yo~+LasPYxH+ht2KjdfCFQr(oovP3?vkFK^5FvPJ4^LD=DpYQi4tUXuY1;erJaBQ79 zHcp(>mKvoD+)bq5SX9siR>(%CL??*D>Snn%p}NfGO4(RY^puLI+j$Pw)NZLb5bKo{s|0L~ z-A3R~;QHMg0bHSgESOM&N&@oF4|8gkPF-nVM=sQ;d}wcS{{!iW-)yQ``D6t#xlh(O zRF0Z@O>0uMz9g)u{P))ptV5lH2(gC8I5i(FDRG5Gp1bgBydKgxJy5gBfK(#D7NzZU zatG}S^z#KL*Do5=K*F7hk(`mbdgI1XoM!8*-};#UzNtEG@Nki#`7)GfV;VlfW^)=` zBaAjK5>gx@wf_D!B!2C6xBK^K4%x|+#?P@5N7tlfWo6xWJD~Wz^cnPfFF($Ixt4!j z9%x^1$on56XZB0Irm^kw-*rd1YVO;(*LbB21@7OPJspo%WO676#~oUMws(zP#+shG+$ns0IC3W z_{kYU>N5<_6=j>*0d}r-?8U+--eXfy2M+opoYL|=I932TMp=&k#tzJ^72OtRJ8BVOvTYPh;@EE=LJLeOk`y?d|Dd9%fWlhON^LnB^6x0LyZqz@imyogJ`$C@Lr9Z4o)ZQz>NCavG$$@e2#r3 z4I=}I5KgV>wl)~_Ja7gLQGju0c1{h%cV&6c`doWWv$>q*=ZLc8J{hBiKXNK?zx2Nr zz!pph;BLU2OaZTv>Pzj(VpSp2&OWNCF<~>NgL!nezhxEgj;&2 zl>z@V#>sykFCnFL?|(j)J3SFr|FFa`n@KbhC2pZB7 z#3>qIn&~mG_Vki=p8_x&CFeD4V7MvgJlk^G7H;(apFxr+7Gc0+1KfI6$@aeF+d7DJ~_-A|H=0?Da#&^Cqb=!=fVz>giW5nw=jWQBS%L^t1EZ@ zCm9;qlG{($@0W3T&l17ownc5pWhfM8Mwn-fLtb7H|IYl)8@QikEc_Le+s60x?&B*m z5kObB5{BD}gGr7l84~vP{N)C~3V;xhBWd%=^j0&KBw3T3-HU`;hqWA3OWW~<8nl-M zfYn-BI0_?g`3$_;&Exw<(G{QM|8)Kq28x9NF-F$>r@_BO)t^T*i-U1bX01<)zC_uE zR@8qEQQ#cm$YbXIUPVO?z7KI$pw@r=-V{V@>dC9Hn==1QBVy_b;#*jR+&f*$AwCl?o&G?2Uk4=*Ej zFK^Yvw*HTO9n!XRBWe++o3)4O!OC9PC=_l_<$M(W8(Akk`zv5?nJifb^rH3N?Hhio zo$=nNmSEz_QFHj|XF!vQEcdqPyZz_4|M_GBH)k)KA9XGRlTJD;3*y1c#?ZWkeaQM* z^`Bf04#Z)ARgrE4rMmlk8E5F=NpaW8xKNd3)-orW$m+kh(W12jQbQ7oi z)=#qbmhkplt}u`FC0sV9sdnb5$E!zX_xlA{4wW&j0*DCm`=1;Sh_sB1xiH@C89Z93;8d)EUk=lPNIZ`o3H`Vd+Ig`=CV}#?PAXvzWk{x96fn z0(rYh<>?PJ>Hd8v@c8=*vm+)>P1k@i2>yMaKw2nihLV6Z;wcdc*E2{8=xNh(FkEe3 zq_pc;ISw&}`?lqKx<4vIa67!xu|P}G$c3MDyg?u^InS?uM6Zzys0QM9ChW>g-ypzA zkOUSfvhTTWq{_>TJ{+kpgwX{@>P5ptiJ1NTO5)8 z8BiLUY_!*AJ$V386^TicK@z0qOPWP#Ea5?}!$_&fQ zOcRKuR^tLX*&CM(ahYftiNg!a=uU|He)2nU2(~iX@Yo|foZp906;o=d%aK09YEW7_ z-yX*;XE#z@?zZ&fQ?2fYX!T8@-$(K5Jo+AkyOM+(944x4B%2NR&avFFJY^9_br5UtzSX5@gmYYm@ z@S$jtqFn18bXQr0IYhQ=+2~ZDB_DRW3d=*B+3q`-*1P$i!GVIG(AMp=vBQ#^_mNxp z(;4Iz#_~&9jZ}}7oW?R;_x8&h?b0N326NJq4~>W^TeI^!o4=G5G{|9ff|`NN5+?ns zL@IWva(*@PXPmVGQ#rgIOY*nnoqNDDy$hd2uMT>wBgzg>YT&BV2U{k1ah1(1j_v0` z@o;6~SUGW=!+j!oa9ko_2^G75?VolPmWk=Pb-h{k=phZga( z88Rp7QzbHkpYG!aug9e^DF63Bi|1#CeAW^CpakO9DTT!p$yhuT8Aq10^cl2O@Zl-2RXr`+zCPj#_FqXs}W2{Qvn2Y{BmNsG45? zB{BF_rVgT$u0 zE8o6|@C>uOK1Ba}!V zx!M$9J1B7#_JSs90cKlucib?T&HqQpLE9YV1?v{gh2NWKEt9FX8;3DePnCL5Z=k)Flp=?-i$<5H4zc z`?2ZZ+p~Y8FYr;m3Vn2(u5Z`Av6#S}zkpQpZ|vNP0DY^I-oa$HXzg+ajQC7%wldRN zfOAL!UwFtuphqqR41v|3He4cQF5;UU9M~lti-k<HSTs^#>-Tf|C2&~#m%6WZAy1jz!Q_-IbpZP z8ht8}UG13lz+N-7+01+RlE)6OT^3px7fn@1|_b7^{bhPet}< z_)77(<^>8-qQ2X(n4faVhm@T0@Z{5HFSWs~EDXtV@7IAMbVUP6;v8^%l3PZ#wOZ-* z*Vk4lRj6OYpAZ_$*`t|tYKmLar&&{5{d+5cst)rQTn`n8>Xi+0zXc6YbTPMgzewFg z23F=+`8=FXXF6b*CDVN$v3|6iy;TSFSYh$qrbhKDcT^U9l zj}3g#zty{k*>s8S+>t|cng#3@Rz`z}njy{*?90mV6_Mkvv=iL9pb0ttHf$7;TxkX1 z-klTGb`2~-Mxx6~+{b-KiFd3XG`p?+6-0PMorB#Q@TY_CH5)En#5WrmHqj;@Fvi1A zeGpO@wuYIPOgRY&02e-U+j7!$LZ#5mS72R3MJS^gfheL5`kQV_n{8}KXaj)V%4b~As zFrQ7yZal}~{ELX@8c#V?2LlM@)g(|;VvcBjEuTJ=`WkOem{DL!+7Lr!U;F!mGm_^~ z+V^T?%bz+8noq9{ybcq16Gzd^fS2`skac)@6|;8X8l6Q19epZ@l^3@1ES!x2XLNA4 z_FI8#x5sq7hXVr83D;_5$sU!*Ye}zyx1wMC?Q{DSgrUx#fM?_Fj@{syA2x2yL^J{S zPPLkQ#O+9E9a^H*USdriL6rGHDt$B!vu~t7^)@_e=(<|SVd!MenX48AP(Z$4WoC9_ zeN;I;hEAr{ZvB^gK*1AWfI~5H0a{Y#2UBjn9`7;3JDrI5leeufemoZol*pDlVTSHP z3#8@6kxsJwUFg9(;)>Xm!{nsFC<7}Xwv_?o=eP)$>vvvj>yw z=YS7{pIOg(u@mJ%G0G^TM@L6>l)?_{_e`(yLxmX%h*D zMJS13@e!}HFR{?GNtq;%=4#zUgfFP^$g|Ax1<`vC&qIPbwGNo}3>ZM?=Evk6r|J&S zi$UD-za)A$kcqu)8)1mG z{FI*zS4{wM6S3;RP-!$0&8!6*;>|%T%HJxZt}cmap#~4vD0Pkx22gBbPo~=2iEMFa zSN<~qRz>jf54?e)>3%j;Gc6C1_YO0C|CDQDt7+bE({$0($tizZ)xn2L?@6_ zR3$`yiwH?E%X*^k*^oQ=z!1GA|E&fXHPR=rIEGq4%0=SGvror2Y%k#d`aPmx5@~7a zdkmPa1d-<`6M%& zp9rn|?C(5SRowEcasXoE$)s`=GvJk9wPt|2VX31T2F}6x3#(&IMqZND*a1muBh9?X zX_HSLo?$y$a;qFx^U1W|YAd%)Gaf|AEHqZ*{PW96FF*&nO-@c?c6t5=K_z@2f$8<^ zY}d|9NRviy7sF$61>@bV$B3*VeDg4DX3qScxVTL~5Go^T?}aG+th- z2`EduJx~ZcSssR;yX%oW&ze|$TF?;>HGHp~Eq?$w&SAD?d#s$$|4F@l*T7}X$7>}7 zRvPwxrPaLO5X-qYiQ7{P^4Ui2GDbq&DJ3Yu`)8zfMi1{>HEq`+uR1bJ4x!#n0D6_M8Zs_# z3mc%u30aK|avL-!XI&?{^%v4OXUr4OzaL*|-HV&M5GPx)SUqYMWw@Ex;%DHx^&FOD zncjYHD@AiYbGx1O(rsKW>Eg}cid)6bqA}!r!G{?x#)c?^k+q_uv%Xh3ha^A^{%wnpRPY({1LqK{NQy>!UjUc8f7x2` zgyLiGpsKlFO75ee2#drn3Glyna)PvUP}e(t6P z(8^W6g23+fzT5gZQQ^L-Yg#^P;QK8FTZAe)*|CKS6(I>8a2aoN+XEkYf2jAF!Zi3! zjS($tF@bu(ypeC>`IZtF;jz`F6A-Y7ZUQBuZxp&q4zHb9cc*!1`T3p9xL9`nWhNVr z!2lf=fCA>;1E&E|yfmrHqB#XnUCu28b*4#eZ{lLL(42#`ui?BO&uZj|d_Fh!Bw8g$ zn@2uezsJz@^XM(T{!CEw+EyG*eaF`FuTN%C zOZg)khBpDobCl(3ud$bhr>EdmuQ^l^Cic|y2m>LM+gsZGYKUAeJE5YUX9}j^JDoojv<}Cm&t+agmp?JE0%d#fo}m_cYogpjn5&egilTvDFz-Df}1i zB4)bXfn$dqb!cCa13DdCgMNehaa&${n5Mw&bxeKfNmHq%e{T_H@WB!H3QgFK2gNpB zP<;xkez-y-Lr(0^P^G!YH~WLut`0=mPXbVN64iv6Nd`s=eUQ;?V((+QU0&B4SF3*{Pm$AVrq;v&)c>VLy_UCe45VEsI@ZWM2TaB# zRU6XaLx0^H=0)Z!$rIu`3*s{Z!W7pU@6aHvX*vUuzME+!B5H}k_gFD)3=f;nI zi1|B!@iO%p;L{!JSEI~vyUByf_{HY=;RuAK##-h!06XFwxYi?xl}oWStJ*P{OcVe~ z_v(y8!+BaLQB`(D(XrL0ReKMn$R)8mU2@$q$Pq; zbZq-$IkP4V(`m}e<)cwnZLrjiA-X0@VY~Gi5-PKX20#Eag!JOw1br%7Rr}`(v@d!u zCo@&wE1SwM=zt~$K!eJ**9GAv!}Cogn9(d0X~BwPkU4gaWh?WVRcE3N?C%_R_D)Vw z(YmJTJ_0~fhItqHPqoIFGQYE2!~?aSRa{vjcDWhy5>oT zGOMFTWfL`aLx-!QL(9r?~D6y9Uhq=af8z!rqg#p zXk%gE-;=@G>MUv7p@P#ni@zP*$YQwA0Dlc21`%pV;p!_F@xI(^eA5&SZ{rU?^Wj}! z6Y%C^eMYilc_~MAwqV`h=I0;WA)MqJ^$IvyJ-O0)*RuLYjTL1TWd|(NbhIZ;nOop( z`4bc=fsxaeI@zc!vvYFFetFRKSMjef2_#oIzzPIxZ4oB0sxKOzX4Wltz#G@LD2Qr5 zm9o~xF;EU*_!O`}IigC{sU%1^$$B@>Fa_H0*>*1Amc^7tnKxcPpr8zZTme`6(0@J| zXfBE;0)lcuv%tqq05V8P2B^)Nhq~qdR|1KCfe>(GeuFaNc)T~zvma>o)FZv;sVD@D zynx%jpd8m<{zI zz44BQcmN85TNhy2plu`Nt$b;sKELSBpW)my@*ZnL{lFaD|7-8c-;zw*wh@(1yH+~o zQd6mwOU~P(B4CS|mX=v+F44&NRvMbQpcpDmU!|BhndzGgrsa}~;RGs*v>~aLX|A9$ zxrCyC3y6ZiciVh3@BH@t1LJY%FM8{e94DY4JQ} zYS0fcOC|N!{@iq*a@H$Qe9ONriBWJrhLhC?o5K2)!=~i)0hGh-mMd~RkqdIGCB(fU zy5*IvHssJ&gxudt>g(3w2{)axskJ_#h96qTc~<{c!`n^f zg+SOfdm8=UI!4%}d%RkXd}yWU1H66h)eDTsQr!qkcZE^zbI#F$k(dn7l7z}@YSv1+ zIcEYw{HJjfg()x7R@zQ&o;LdJ2vi6Fkl?OHM-Ga!%w}co(6=I5LZ>n{9pr~6!z|S$ zq_VfE7##n|{H(t$wPI-D`~L#((@V(MZ>p6Eb8k%4{lIGT;hZ9cg%~HhcbDCd%0RbM zs?uZG1wSL{Z0f+NzDiO?w9~XT^dWptKJ@M~0(@5*az*ZgabU465JN9eFY7vD8Wdz_ zlAIonnlivB;uDXov3sIgoKx2>G6a;@?v0qg;r`RnZ{4wMw2%}(e*c8k`R7sNT@>H} zfUU~mHR~8!4rJTHVlT=v3wz2kx&95Nz?@Tj8)s5E}t{|AFA=d_Y zOTqb{ATx>U``k~NJ2hYk3r#Gn1}|1Xj}jq!9%;{k(?9!WZt1z#{OATvapC-}#$LWi zi2R>~v0v6A<|?Eg)Ye#VyRyr7RJ$N4vFEFfmb1jHF(yZN^rc!ULDen>KWu(D9Z5!P ze(qg(G2HmSqyi2B&W`vo@N=3l?+dXbWn-`1LrY1^_mSilpKLLxQp}@s?=Tqw6Do5Pui*IhPZtaT|GAE&MF$;(4s9Bt5f+vbITElRv3( ze&@3GgY%ltiz;PZXq||TeA+sP9bc(#*G<2ck&zF3W?0$Bxit`EwvZb7jke;810>h3 zb}}!oS_xUbJ^$_PWrSlJ-;v4qq!@|L9uM#ALcMu|+|fni+AqPpu+CtjBrs#Y1jKVU zEc6L$d!2l-MgMi5&7?{Dfxj)qn;mIZudn7I6V$88%05A!PtCQTGSxXKMGh;qXa|fE zJBUmhM!}@e#A?s%bajm+=Ka1WxHZWaj;k#XT{T#;bH9c5zA8txVHEz(EeE*PP9eD9 z<2|evdxmVLj_n@`lp>6@ zy_ZTczm54_lGjPwPaq$dF1HdIks&Mp;%bge$QZnnp${}#&Z3)z95ei@b9;c=kJpY- z$G#RZbgyTi3&d4=3%+gXOSp|g^~^%K1id>re4gTka;7m@WA}bFo`GUbT8-n19VVdO}IkuW(H_iil_S}@$xy(Q*fCcNaD60 zxqsWK5lESLWnKgy^ci@da#k9^aW5)oLzbFxlUVBA&UM~79PF7=rW@Ot`>9(Gju3N{A4%EK0dPuz{=J_LUv|Pe^*x3eq_ExMNjB3?{$+xH^_Y z;e5pH)*~Lo@y=;b=P$Iqp9KR|j(>D-kaI4WeI&&HPFRtbZBMiQ^PwE`pF$Z7#(@UF zP2~&InXDTNx3`4)H2mD8yHl{Jk(|C(VA2vwY}3IRqo*qy9HvN7a!$$hlZqjmb6tZy zp1fLd^be5LmcI`_d3@@A`jLDS!b0qXVvP%y>+DfL86Ie=*TZ)PL??Lk^F};4=dwv; zPRBV>*)f&NE0vtjYHw@vs9l(Dk*g-}ARSciwv!f)E361d_9y<;9b7)PBw$3dh`AZi zAY4)BVh3t>;gR=s)nZW3PT_3bOLDK)eTZT^*m%P!HdC!FvK=Z=_iA>Bg!`SsC|P3u zz+oMr^PUcTebccFK>bqp475+?5RUC{Y7klp^p=Q;ZM+c8Zq6wBtH*5c=QHlp7wZS%6AszeebN>>_2^H7uuK@g%1{vF}DT>U{h`}c+u5ubXcFMH)fZ6-l z!y=qVN>jqgj)3T!mALcM;1!8}PDcMCU6<9?l#euNff${zE=b0d%;TcPFfw`y>zjLg#_WgnwatH|t}Y&WrR32m5W_AWNa`OqIc{ zW{_mX(Ck1psRCgMhJ*hXhcAG1ocb_kuY)%9rlYzq8h$K;X}=5m+8CYpJ4Yw6zLi%S zpu}dkAc_hVv>NfWy9eLsQ-6OzoBl{WAkRi|U;anmJ5dFwz(C9~-A(!Vfw z(E!S5ua;@}(q5GrIc6|PAOSPg{il$s$UBI}tk5xuP-VedGyZd}xqXvWvU_`{;Cf0> z5fN79T(#iq-q$RLb(of0ZA0lfepj^!a2-6 zv{v^7r2J*xmj&XVgZ>Wd=RqwGGe1`-Svll~bz(-y7*N1ooU5J*aY@&5ea5ss6n(a? z`N9l?w~=^1g2wLDVRD5ovqLc^Z#YRDFR+QYV4emH*fzOpzer3>Pudh??f``be>dD3 z)xB}1O6bZpnt=j(m92Fxq0dz89n>B05xx10QDL-YDz&e>h_u@9+RG)Pv4{2IYNiMy z8auH}j+fW*;q%Ymtbq+KI_r4gxGUeYJ>hq~vbe!N3%NntH+Dyh7I70!cu(qE_`Vp; z07NvH4Q2s#9;mKj;>umoviK|H+#CbgGq`D+QxI*$r6&D`yf%-M^{H;6gi4*j3?c9c z8$}NK?0I4%b?c`p2;SvL3*xY`0fe_KIZqPm`M%{DCrPUt{bS|zlhbHBNlUe7zcK}E z$L2zIl+z#Z!thJW!}{G&JAC@Pg`H(}GLM_m;uV}C9Yt(vF+F0Dy7{`k zY&v=ZZf?8^qSD>~2iP#{qQK632aMplZye6Q3X>dctS@JHSz2)zJaqXvFEZlr>9$oY z^&9^4pN`1EJcEw_wi@P{zJqQX470?WZTB*5Y7F!3#xJO^z|Gw@)bFoY5#daTP5OgI zcbKI$Ok(|9g_%#If*$3ga=U0_n%|#}eWwyeW~(19Te+!xF*(rd=LU(nM15;<7Z&oA zrqIw#r7}&_qgCdvS7+!|3?8w7JNRtHQ$~8Yyw(xC+n=- z7SQBo3+)tbg2NJn^=lukNOCkiEsgt~4tCrZ{aSnrHRMk@_?1^whFrEn3mT1NSC9B&c-(JrWu@FUhSNf+(>-_%kX#@LYnzq`^M#XX}(*!_LZCY za24(5Y$WH^=;GY^#0c{Y4{_!GPvm_bd#&6ypUpfwu%|+=UEe^Q+oe$7cXnyF@O67L3%SKO#rdayD^4^vH2hG{w%vp|_*jKf4 z=jb?40UP4S+Mi~(Uz(^cvgVB+r+Rt|;wnFRYcz(i=&Q14Ok=V-tTPw4%v&;ZrxI#w z6&rvLjj#yzBr5~N*7o09CkIE=>EWwo`ceL*@Y=504RB*xY#SY{)p3Gvn9zBL_FCN0 zl^axu8p~su8HpiDNi{%5ojAv1{0?t7*mflF9&Y_x4#)X(jyLl~c+s6*I1G7{zBI;tH*_ z94)o##4$cU4ohj~e#C^E><)3E`d;ftdwTQZpDmp)9)n5^+h%BE?)8LI2A`L!zjTBL zPYE&+#0&jDFc&4Tg}VC}E@4ZGyWbiK2dvn6Mpu!cQT_^6!RG!7)fE>V>?PNFm?vc5 z>A8gcW=5Xm2#LEW_;XgMQ$=Y-#lc|zs2}}2ny_4Kb%D@Vrtu6rOmUe!ph7;;L`XHi zXcDHc;OYbIk44?|A9-=Ml{Xap)^{jb5$Kl?v`CIT`bDXV*x{h+UARtzOd}#US>a%X zOdU`5^_P@lkQxB*B<&RQB?FgJOH2-~rMnXf_{5%~s&OlUM^i30FeOM{`XOXs)3_BU zEAyNr%bz8RJ=Cvw8y=)3p z`K|i!j$l~LqQ)kabHK}7WeyB$x*({t#cQWf98qh&X{R*Y--9)~g)?XCL>&z;v9#hY zTFY?DV&1fPE&*z}6Ki`Y5#(-eVYB;OzZjPSDnN%ArA8D>wODpQT4Jt}ah556JE+G_! z_P0uQ!qDhR94VdpAqajIOl4~>oTaQ8H5yXaTZUOb%cRAkWYV?KSNlTqgSM=Wgf)JP zz=?Q5f5zPEVO!NbOCbqEwP^Ff_O_`gdm67#U{Mp^_bKcq2IoO%zcJb(M5z`cjv1Ck z+!awNRhwjj6CQqu+xC#{UWo^3+h?6ymzq3r?3JV}<|u_9x=MWAm`1AqAnOsJ*@)^4 zr|`FkZlg{Cd!#Chmhn=_ZQe;~-DTUOv>)Tbmh0{z_42vWa|vNUO% z_5KA1xNHBgw0zjUH|s5xg$b4k z@Koa#-AFizrr6h2#$k*41tm7_jp$yL4X*DZcklq!u+>9E0WnhcOFPn7Vh^ao@~tno z@RwY)*+8&|Hpdq)`a=L*Teuw;_B@u;o!a!YaOO@bs-?*gqpm?nRkXl~mKFfF z+OVzE%RlC`M5-+KM_GXZ@9b;=2C(sq+R&Ko_RzZ%5P~kDieK3yzV4BN*{$E%KY;4k z)s?*vacHYN~u+?SoI`e@S2!9Co!cdvz;@N@{yj`0-9^8osR(V7PR-O&gM)x3owqs5oJpIwc zgY`#VzjI$V>YYDrIr8D;0JK<10@ycefw z;;oV(!gUR*xBg%xTl-#d>u(5}#jFrLKo}q0b{IuuZhuO7n++ zo@9)d#`(AT$mbW5g;c;&z>1_2Nk%;L?TIhfeK%PYp>5N<5wdihxw4-qvVsN6t@bol zDFgi~t`B&ZU3ek!#fXVE5Ao$7AwI+@amT_m2SclwQE{cLcv3kwhokq+!S%>Fe_*(Z z75)vhq@YqZqa~Hf$0S?T@nr_%mV%*aT${~4)6|(P@Bq_Q!VC4tZa`7?ra`4?oV+wSr2`TVSUmKS_>V@3%0*S#!+L=3f@oF=4k9U9xv0p1;Fx&}V;X2J~h zcz^}G3|;s8JyEFR*LB*fPUm+?f+ofnBQ5uK%NrwA+RV_~h<6-mw_wU?NGRI!zNTh% z&>ty6x8&gW75gdW)?p->&%?{*brS|k@b|(>&<^nyO55Pi_q*eK)=J*Uunw2cw--p%E!VXuDa? ztZ$HPKJ6$Sh7!UrpxVBLFSnpZOw$(ftvg!Nk1LVfL+FL(u zh1Abu(oCSmgqQ2IrE;Zz2f2DAD%T4XO6tU&)2IB}vV3{^xpz1MYFEPy_09RP2QvmA zIqw<(UaCnCs!mFX$+3sjnV*(O5)y`jW!*wzF-l^K`Bxgap+0Ej z@c^nf{Ic`6I5#9bcE7fwiiP8JZ9dr3FsD~SBiW_`8{UgFt*{$@qj#E)90JYra>Zs3 z$sCTuzOye2GdTO;4@;wgJK@!ij-|c--insluCR}{#q=D6Xz#nL6;`rkc*UzLTR%Y{ zN2YK;Zcz4YY=+|(0_?E=#~3U@I1fIyRiBF zIeWj=id+b|L;kSMs>NMfeB^(={IdrC;NYJy_$L+olL`OdOqgH0OpSa?FTRhwb<|%A Pe7HEdAEg|=c=LY&YVNkY literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..13b35eba55c6dabc3aac36f33d859266c18fa0d0 GIT binary patch literal 5680 zcmaiYXH?Tqu=Xz`p-L#B_gI#0we$cm_HcmYFP$?wjD#BaCN4mzC5#`>w9y6=ThxrYZc0WPXprg zYjB`UsV}0=eUtY$(P6YW}npdd;%9pi?zS3k-nqCob zSX_AQEf|=wYT3r?f!*Yt)ar^;l3Sro{z(7deUBPd2~(SzZ-s@0r&~Km2S?8r##9-< z)2UOSVaHqq6}%sA9Ww;V2LG=PnNAh6mA2iWOuV7T_lRDR z&N8-eN=U)-T|;wo^Wv=34wtV0g}sAAe}`Ph@~!|<;z7*K8(qkX0}o=!(+N*UWrkEja*$_H6mhK1u{P!AC39} z|3+Z(mAOq#XRYS)TLoHv<)d%$$I@+x+2)V{@o~~J-!YUI-Q9%!Ldi4Op&Lw&B>jj* zwAgC#Y>gbIqv!d|J5f!$dbCXoq(l3GR(S>(rtZ~Z*agXMMKN!@mWT_vmCbSd3dUUm z4M&+gz?@^#RRGal%G3dDvj7C5QTb@9+!MG+>0dcjtZEB45c+qx*c?)d<%htn1o!#1 zpIGonh>P1LHu3s)fGFF-qS}AXjW|M*2Xjkh7(~r(lN=o#mBD9?jt74=Rz85I4Nfx_ z7Z)q?!};>IUjMNM6ee2Thq7))a>My?iWFxQ&}WvsFP5LP+iGz+QiYek+K1`bZiTV- zHHYng?ct@Uw5!gquJ(tEv1wTrRR7cemI>aSzLI^$PxW`wL_zt@RSfZ1M3c2sbebM* ze0=;sy^!90gL~YKISz*x;*^~hcCoO&CRD)zjT(A2b_uRue=QXFe5|!cf0z1m!iwv5GUnLw9Dr*Ux z)3Lc!J@Ei;&&yxGpf2kn@2wJ2?t6~obUg;?tBiD#uo$SkFIasu+^~h33W~`r82rSa ztyE;ehFjC2hjpJ-e__EH&z?!~>UBb=&%DS>NT)1O3Isn-!SElBV2!~m6v0$vx^a<@ISutdTk1@?;i z<8w#b-%|a#?e5(n@7>M|v<<0Kpg?BiHYMRe!3Z{wYc2hN{2`6(;q`9BtXIhVq6t~KMH~J0~XtUuT06hL8c1BYZWhN zk4F2I;|za*R{ToHH2L?MfRAm5(i1Ijw;f+0&J}pZ=A0;A4M`|10ZskA!a4VibFKn^ zdVH4OlsFV{R}vFlD~aA4xxSCTTMW@Gws4bFWI@xume%smAnuJ0b91QIF?ZV!%VSRJ zO7FmG!swKO{xuH{DYZ^##gGrXsUwYfD0dxXX3>QmD&`mSi;k)YvEQX?UyfIjQeIm! z0ME3gmQ`qRZ;{qYOWt}$-mW*>D~SPZKOgP)T-Sg%d;cw^#$>3A9I(%#vsTRQe%moT zU`geRJ16l>FV^HKX1GG7fR9AT((jaVb~E|0(c-WYQscVl(z?W!rJp`etF$dBXP|EG z=WXbcZ8mI)WBN>3<@%4eD597FD5nlZajwh8(c$lum>yP)F}=(D5g1-WVZRc)(!E3} z-6jy(x$OZOwE=~{EQS(Tp`yV2&t;KBpG*XWX!yG+>tc4aoxbXi7u@O*8WWFOxUjcq z^uV_|*818$+@_{|d~VOP{NcNi+FpJ9)aA2So<7sB%j`$Prje&auIiTBb{oD7q~3g0 z>QNIwcz(V-y{Ona?L&=JaV5`o71nIsWUMA~HOdCs10H+Irew#Kr(2cn>orG2J!jvP zqcVX0OiF}c<)+5&p}a>_Uuv)L_j}nqnJ5a?RPBNi8k$R~zpZ33AA4=xJ@Z($s3pG9 zkURJY5ZI=cZGRt_;`hs$kE@B0FrRx(6K{`i1^*TY;Vn?|IAv9|NrN*KnJqO|8$e1& zb?OgMV&q5|w7PNlHLHF) zB+AK#?EtCgCvwvZ6*u|TDhJcCO+%I^@Td8CR}+nz;OZ*4Dn?mSi97m*CXXc=};!P`B?}X`F-B5v-%ACa8fo0W++j&ztmqK z;&A)cT4ob9&MxpQU41agyMU8jFq~RzXOAsy>}hBQdFVL%aTn~M>5t9go2j$i9=(rZ zADmVj;Qntcr3NIPPTggpUxL_z#5~C!Gk2Rk^3jSiDqsbpOXf^f&|h^jT4|l2ehPat zb$<*B+x^qO8Po2+DAmrQ$Zqc`1%?gp*mDk>ERf6I|42^tjR6>}4`F_Mo^N(~Spjcg z_uY$}zui*PuDJjrpP0Pd+x^5ds3TG#f?57dFL{auS_W8|G*o}gcnsKYjS6*t8VI<) zcjqTzW(Hk*t-Qhq`Xe+x%}sxXRerScbPGv8hlJ;CnU-!Nl=# zR=iTFf9`EItr9iAlAGi}i&~nJ-&+)Y| zMZigh{LXe)uR+4D_Yb+1?I93mHQ5{pId2Fq%DBr7`?ipi;CT!Q&|EO3gH~7g?8>~l zT@%*5BbetH)~%TrAF1!-!=)`FIS{^EVA4WlXYtEy^|@y@yr!C~gX+cp2;|O4x1_Ol z4fPOE^nj(}KPQasY#U{m)}TZt1C5O}vz`A|1J!-D)bR%^+=J-yJsQXDzFiqb+PT0! zIaDWWU(AfOKlSBMS};3xBN*1F2j1-_=%o($ETm8@oR_NvtMDVIv_k zlnNBiHU&h8425{MCa=`vb2YP5KM7**!{1O>5Khzu+5OVGY;V=Vl+24fOE;tMfujoF z0M``}MNnTg3f%Uy6hZi$#g%PUA_-W>uVCYpE*1j>U8cYP6m(>KAVCmbsDf39Lqv0^ zt}V6FWjOU@AbruB7MH2XqtnwiXS2scgjVMH&aF~AIduh#^aT1>*V>-st8%=Kk*{bL zzbQcK(l2~)*A8gvfX=RPsNnjfkRZ@3DZ*ff5rmx{@iYJV+a@&++}ZW+za2fU>&(4y`6wgMpQGG5Ah(9oGcJ^P(H< zvYn5JE$2B`Z7F6ihy>_49!6}(-)oZ(zryIXt=*a$bpIw^k?>RJ2 zQYr>-D#T`2ZWDU$pM89Cl+C<;J!EzHwn(NNnWpYFqDDZ_*FZ{9KQRcSrl5T>dj+eA zi|okW;6)6LR5zebZJtZ%6Gx8^=2d9>_670!8Qm$wd+?zc4RAfV!ZZ$jV0qrv(D`db zm_T*KGCh3CJGb(*X6nXzh!h9@BZ-NO8py|wG8Qv^N*g?kouH4%QkPU~Vizh-D3<@% zGomx%q42B7B}?MVdv1DFb!axQ73AUxqr!yTyFlp%Z1IAgG49usqaEbI_RnbweR;Xs zpJq7GKL_iqi8Md?f>cR?^0CA+Uk(#mTlGdZbuC*$PrdB$+EGiW**=$A3X&^lM^K2s zzwc3LtEs5|ho z2>U(-GL`}eNgL-nv3h7E<*<>C%O^=mmmX0`jQb6$mP7jUKaY4je&dCG{x$`0=_s$+ zSpgn!8f~ya&U@c%{HyrmiW2&Wzc#Sw@+14sCpTWReYpF9EQ|7vF*g|sqG3hx67g}9 zwUj5QP2Q-(KxovRtL|-62_QsHLD4Mu&qS|iDp%!rs(~ah8FcrGb?Uv^Qub5ZT_kn%I^U2rxo1DDpmN@8uejxik`DK2~IDi1d?%~pR7i#KTS zA78XRx<(RYO0_uKnw~vBKi9zX8VnjZEi?vD?YAw}y+)wIjIVg&5(=%rjx3xQ_vGCy z*&$A+bT#9%ZjI;0w(k$|*x{I1c!ECMus|TEA#QE%#&LxfGvijl7Ih!B2 z6((F_gwkV;+oSKrtr&pX&fKo3s3`TG@ye+k3Ov)<#J|p8?vKh@<$YE@YIU1~@7{f+ zydTna#zv?)6&s=1gqH<-piG>E6XW8ZI7&b@-+Yk0Oan_CW!~Q2R{QvMm8_W1IV8<+ zQTyy=(Wf*qcQubRK)$B;QF}Y>V6d_NM#=-ydM?%EPo$Q+jkf}*UrzR?Nsf?~pzIj$ z<$wN;7c!WDZ(G_7N@YgZ``l;_eAd3+;omNjlpfn;0(B7L)^;;1SsI6Le+c^ULe;O@ zl+Z@OOAr4$a;=I~R0w4jO`*PKBp?3K+uJ+Tu8^%i<_~bU!p%so z^sjol^slR`W@jiqn!M~eClIIl+`A5%lGT{z^mRbpv}~AyO%R*jmG_Wrng{B9TwIuS z0!@fsM~!57K1l0%{yy(#no}roy#r!?0wm~HT!vLDfEBs9x#`9yCKgufm0MjVRfZ=f z4*ZRc2Lgr(P+j2zQE_JzYmP0*;trl7{*N341Cq}%^M^VC3gKG-hY zmPT>ECyrhIoFhnMB^qpdbiuI}pk{qPbK^}0?Rf7^{98+95zNq6!RuV_zAe&nDk0;f zez~oXlE5%ve^TmBEt*x_X#fs(-En$jXr-R4sb$b~`nS=iOy|OVrph(U&cVS!IhmZ~ zKIRA9X%Wp1J=vTvHZ~SDe_JXOe9*fa zgEPf;gD^|qE=dl>Qkx3(80#SE7oxXQ(n4qQ#by{uppSKoDbaq`U+fRqk0BwI>IXV3 zD#K%ASkzd7u>@|pA=)Z>rQr@dLH}*r7r0ng zxa^eME+l*s7{5TNu!+bD{Pp@2)v%g6^>yj{XP&mShhg9GszNu4ITW=XCIUp2Xro&1 zg_D=J3r)6hp$8+94?D$Yn2@Kp-3LDsci)<-H!wCeQt$e9Jk)K86hvV^*Nj-Ea*o;G zsuhRw$H{$o>8qByz1V!(yV{p_0X?Kmy%g#1oSmlHsw;FQ%j9S#}ha zm0Nx09@jmOtP8Q+onN^BAgd8QI^(y!n;-APUpo5WVdmp8!`yKTlF>cqn>ag`4;o>i zl!M0G-(S*fm6VjYy}J}0nX7nJ$h`|b&KuW4d&W5IhbR;-)*9Y0(Jj|@j`$xoPQ=Cl literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3f5fa40fb3d1e0710331a48de5d256da3f275d GIT binary patch literal 520 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uuz(rC1}QWNE&K#jR^;j87-Auq zoUlN^K{r-Q+XN;zI ze|?*NFmgt#V#GwrSWaz^2G&@SBmck6ZcIFMww~vE<1E?M2#KUn1CzsB6D2+0SuRV@ zV2kK5HvIGB{HX-hQzs0*AB%5$9RJ@a;)Ahq#p$GSP91^&hi#6sg*;a~dt}4AclK>h z_3MoPRQ{i;==;*1S-mY<(JFzhAxMI&<61&m$J0NDHdJ3tYx~j0%M-uN6Zl8~_0DOkGXc0001@sz3l12C6Xg{AT~( zm6w64BA|AX`Ve)YY-glyudNN>MAfkXz-T7`_`fEolM;0T0BA)(02-OaW z0*cW7Z~ec94o8&g0D$N>b!COu{=m}^%oXZ4?T8ZyPZuGGBPBA7pbQMoV5HYhiT?%! zcae~`(QAN4&}-=#2f5fkn!SWGWmSeCISBcS=1-U|MEoKq=k?_x3apK>9((R zuu$9X?^8?@(a{qMS%J8SJPq))v}Q-ZyDm6Gbie0m92=`YlwnQPQP1kGSm(N2UJ3P6 z^{p-u)SSCTW~c1rw;cM)-uL2{->wCn2{#%;AtCQ!m%AakVs1K#v@(*-6QavyY&v&*wO_rCJXJuq$c$7ZjsW+pJo-$L^@!7X04CvaOpPyfw|FKvu;e(&Iw>Tbg zL}#8e^?X%TReXTt>gsBByt0kSU20oQx*~P=4`&tcZ7N6t-6LiK{LxX*p6}9c<0Pu^ zLx1w_P4P2V>bX=`F%v$#{sUDdF|;rbI{p#ZW`00Bgh(eB(nOIhy8W9T>3aQ=k8Z9% zB+TusFABF~J?N~fAd}1Rme=@4+1=M{^P`~se7}e3;mY0!%#MJf!XSrUC{0uZqMAd7%q zQY#$A>q}noIB4g54Ue)x>ofVm3DKBbUmS4Z-bm7KdKsUixva)1*&z5rgAG2gxG+_x zqT-KNY4g7eM!?>==;uD9Y4iI(Hu$pl8!LrK_Zb}5nv(XKW{9R144E!cFf36p{i|8pRL~p`_^iNo z{mf7y`#hejw#^#7oKPlN_Td{psNpNnM?{7{R-ICBtYxk>?3}OTH_8WkfaTLw)ZRTfxjW+0>gMe zpKg~`Bc$Y>^VX;ks^J0oKhB#6Ukt{oQhN+o2FKGZx}~j`cQB%vVsMFnm~R_1Y&Ml? zwFfb~d|dW~UktY@?zkau>Owe zRroi(<)c4Ux&wJfY=3I=vg)uh;sL(IYY9r$WK1$F;jYqq1>xT{LCkIMb3t2jN8d`9 z=4(v-z7vHucc_fjkpS}mGC{ND+J-hc_0Ix4kT^~{-2n|;Jmn|Xf9wGudDk7bi*?^+ z7fku8z*mbkGm&xf&lmu#=b5mp{X(AwtLTf!N`7FmOmX=4xwbD=fEo8CaB1d1=$|)+ z+Dlf^GzGOdlqTO8EwO?8;r+b;gkaF^$;+#~2_YYVH!hD6r;PaWdm#V=BJ1gH9ZK_9 zrAiIC-)z)hRq6i5+$JVmR!m4P>3yJ%lH)O&wtCyum3A*})*fHODD2nq!1@M>t@Za+ zH6{(Vf>_7!I-APmpsGLYpl7jww@s5hHOj5LCQXh)YAp+y{gG(0UMm(Ur z3o3n36oFwCkn+H*GZ-c6$Y!5r3z*@z0`NrB2C^q#LkOuooUM8Oek2KBk}o1PU8&2L z4iNkb5CqJWs58aR394iCU^ImDqV;q_Pp?pl=RB2372(Io^GA^+oKguO1(x$0<7w3z z)j{vnqEB679Rz4i4t;8|&Zg77UrklxY9@GDq(ZphH6=sW`;@uIt5B?7Oi?A0-BL}(#1&R;>2aFdq+E{jsvpNHjLx2t{@g1}c~DQcPNmVmy| zNMO@ewD^+T!|!DCOf}s9dLJU}(KZy@Jc&2Nq3^;vHTs}Hgcp`cw&gd7#N}nAFe3cM1TF%vKbKSffd&~FG9y$gLyr{#to)nxz5cCASEzQ}gz8O)phtHuKOW6p z@EQF(R>j%~P63Wfosrz8p(F=D|Mff~chUGn(<=CQbSiZ{t!e zeDU-pPsLgtc#d`3PYr$i*AaT!zF#23htIG&?QfcUk+@k$LZI}v+js|yuGmE!PvAV3 ztzh90rK-0L6P}s?1QH`Ot@ilbgMBzWIs zIs6K<_NL$O4lwR%zH4oJ+}JJp-bL6~%k&p)NGDMNZX7)0kni&%^sH|T?A)`z z=adV?!qnWx^B$|LD3BaA(G=ePL1+}8iu^SnnD;VE1@VLHMVdSN9$d)R(Wk{JEOp(P zm3LtAL$b^*JsQ0W&eLaoYag~=fRRdI>#FaELCO7L>zXe6w*nxN$Iy*Q*ftHUX0+N- zU>{D_;RRVPbQ?U+$^%{lhOMKyE5>$?U1aEPist+r)b47_LehJGTu>TcgZe&J{ z{q&D{^Ps~z7|zj~rpoh2I_{gAYNoCIJmio3B}$!5vTF*h$Q*vFj~qbo%bJCCRy509 zHTdDh_HYH8Zb9`}D5;;J9fkWOQi%Y$B1!b9+ESj+B@dtAztlY2O3NE<6HFiqOF&p_ zW-K`KiY@RPSY-p9Q99}Hcd05DT79_pfb{BV7r~?9pWh=;mcKBLTen%THFPo2NN~Nf zriOtFnqx}rtO|A6k!r6 zf-z?y-UD{dT0kT9FJ`-oWuPHbo+3wBS(}?2ql(+e@VTExmfnB*liCb zmeI+v5*+W_L;&kQN^ChW{jE0Mw#0Tfs}`9bk3&7UjxP^Ke(%eJu2{VnW?tu7Iqecm zB5|=-QdzK$=h50~{X3*w4%o1FS_u(dG2s&427$lJ?6bkLet}yYXCy)u_Io1&g^c#( z-$yYmSpxz{>BL;~c+~sxJIe1$7eZI_9t`eB^Pr0)5CuA}w;;7#RvPq|H6!byRzIJG ziQ7a4y_vhj(AL`8PhIm9edCv|%TX#f50lt8+&V+D4<}IA@S@#f4xId80oH$!_!q?@ zFRGGg2mTv&@76P7aTI{)Hu%>3QS_d)pQ%g8BYi58K~m-Ov^7r8BhX7YC1D3vwz&N8{?H*_U7DI?CI)+et?q|eGu>42NJ?K4SY zD?kc>h@%4IqNYuQ8m10+8xr2HYg2qFNdJl=Tmp&ybF>1>pqVfa%SsV*BY$d6<@iJA ziyvKnZ(~F9xQNokBgMci#pnZ}Igh0@S~cYcU_2Jfuf|d3tuH?ZSSYBfM(Y3-JBsC|S9c;# zyIMkPxgrq};0T09pjj#X?W^TFCMf1-9P{)g88;NDI+S4DXe>7d3Mb~i-h&S|Jy{J< zq3736$bH?@{!amD!1Ys-X)9V=#Z={fzsjVYMX5BG6%}tkzwC#1nQLj1y1f#}8**4Y zAvDZHw8)N)8~oWC88CgzbwOrL9HFbk4}h85^ptuu7A+uc#$f^9`EWv1Vr{5+@~@Uv z#B<;-nt;)!k|fRIg;2DZ(A2M2aC65kOIov|?Mhi1Sl7YOU4c$T(DoRQIGY`ycfkn% zViHzL;E*A{`&L?GP06Foa38+QNGA zw3+Wqs(@q+H{XLJbwZzE(omw%9~LPZfYB|NF5%j%E5kr_xE0u;i?IOIchn~VjeDZ) zAqsqhP0vu2&Tbz3IgJvMpKbThC-@=nk)!|?MIPP>MggZg{cUcKsP8|N#cG5 zUXMXxcXBF9`p>09IR?x$Ry3;q@x*%}G#lnB1}r#!WL88I@uvm}X98cZ8KO&cqT1p> z+gT=IxPsq%n4GWgh-Bk8E4!~`r@t>DaQKsjDqYc&h$p~TCh8_Mck5UB84u6Jl@kUZCU9BA-S!*bf>ZotFX9?a_^y%)yH~rsAz0M5#^Di80_tgoKw(egN z`)#(MqAI&A84J#Z<|4`Co8`iY+Cv&iboMJ^f9ROUK0Lm$;-T*c;TCTED_0|qfhlcS zv;BD*$Zko#nWPL}2K8T-?4}p{u)4xon!v_(yVW8VMpxg4Kh^J6WM{IlD{s?%XRT8P|yCU`R&6gwB~ zg}{At!iWCzOH37!ytcPeC`(({ovP7M5Y@bYYMZ}P2Z3=Y_hT)4DRk}wfeIo%q*M9UvXYJq!-@Ly79m5aLD{hf@BzQB>FdQ4mw z6$@vzSKF^Gnzc9vbccii)==~9H#KW<6)Uy1wb~auBn6s`ct!ZEos`WK8e2%<00b%# zY9Nvnmj@V^K(a_38dw-S*;G-(i(ETuIwyirs?$FFW@|66a38k+a%GLmucL%Wc8qk3 z?h_4!?4Y-xt)ry)>J`SuY**fuq2>u+)VZ+_1Egzctb*xJ6+7q`K$^f~r|!i?(07CD zH!)C_uerf-AHNa?6Y61D_MjGu*|wcO+ZMOo4q2bWpvjEWK9yASk%)QhwZS%N2_F4& z16D18>e%Q1mZb`R;vW{+IUoKE`y3(7p zplg5cBB)dtf^SdLd4n60oWie|(ZjgZa6L*VKq02Aij+?Qfr#1z#fwh92aV-HGd^_w zsucG24j8b|pk>BO7k8dS86>f-jBP^Sa}SF{YNn=^NU9mLOdKcAstv&GV>r zLxKHPkFxpvE8^r@MSF6UA}cG`#yFL8;kA7ccH9D=BGBtW2;H>C`FjnF^P}(G{wU;G z!LXLCbPfsGeLCQ{Ep$^~)@?v`q(uI`CxBY44osPcq@(rR-633!qa zsyb>?v%@X+e|Mg`+kRL*(;X>^BNZz{_kw5+K;w?#pReiw7eU8_Z^hhJ&fj80XQkuU z39?-z)6Fy$I`bEiMheS(iB6uLmiMd1i)cbK*9iPpl+h4x9ch7x- z1h4H;W_G?|)i`z??KNJVwgfuAM=7&Apd3vm#AT8uzQZ!NII}}@!j)eIfn53h{NmN7 zAKG6SnKP%^k&R~m5#@_4B@V?hYyHkm>0SQ@PPiw*@Tp@UhP-?w@jW?nxXuCipMW=L zH*5l*d@+jXm0tIMP_ec6Jcy6$w(gKK@xBX8@%oPaSyG;13qkFb*LuVx3{AgIyy&n3 z@R2_DcEn|75_?-v5_o~%xEt~ONB>M~tpL!nOVBLPN&e5bn5>+7o0?Nm|EGJ5 zmUbF{u|Qn?cu5}n4@9}g(G1JxtzkKv(tqwm_?1`?YSVA2IS4WI+*(2D*wh&6MIEhw z+B+2U<&E&|YA=3>?^i6)@n1&&;WGHF-pqi_sN&^C9xoxME5UgorQ_hh1__zzR#zVC zOQt4q6>ME^iPJ37*(kg4^=EFqyKH@6HEHXy79oLj{vFqZGY?sVjk!BX^h$SFJlJnv z5uw~2jLpA)|0=tp>qG*tuLru?-u`khGG2)o{+iDx&nC}eWj3^zx|T`xn5SuR;Aw8U z`p&>dJw`F17@J8YAuW4=;leBE%qagVTG5SZdh&d)(#ZhowZ|cvWvGMMrfVsbg>_~! z19fRz8CSJdrD|Rl)w!uznBF&2-dg{>y4l+6(L(vzbLA0Bk&`=;oQQ>(M8G=3kto_) zP8HD*n4?MySO2YrG6fwSrVmnesW+D&fxjfEmp=tPd?RKLZJcH&K(-S+x)2~QZ$c(> zru?MND7_HPZJVF%wX(49H)+~!7*!I8w72v&{b={#l9yz+S_aVPc_So%iF8>$XD1q1 zFtucO=rBj0Ctmi0{njN8l@}!LX}@dwl>3yMxZ;7 z0Ff2oh8L)YuaAGOuZ5`-p%Z4H@H$;_XRJQ|&(MhO78E|nyFa158gAxG^SP(vGi^+< zChY}o(_=ci3Wta#|K6MVljNe0T$%Q5ylx-v`R)r8;3+VUpp-)7T`-Y&{Zk z*)1*2MW+_eOJtF5tCMDV`}jg-R(_IzeE9|MBKl;a7&(pCLz}5<Zf+)T7bgNUQ_!gZtMlw=8doE}#W+`Xp~1DlE=d5SPT?ymu!r4z%&#A-@x^=QfvDkfx5-jz+h zoZ1OK)2|}_+UI)i9%8sJ9X<7AA?g&_Wd7g#rttHZE;J*7!e5B^zdb%jBj&dUDg4&B zMMYrJ$Z%t!5z6=pMGuO-VF~2dwjoXY+kvR>`N7UYfIBMZGP|C7*O=tU z2Tg_xi#Q3S=1|=WRfZD;HT<1D?GMR%5kI^KWwGrC@P2@R>mDT^3qsmbBiJc21kip~ zZp<7;^w{R;JqZ)C4z-^wL=&dBYj9WJBh&rd^A^n@07qM$c+kGv^f+~mU5_*|eePF| z3wDo-qaoRjmIw<2DjMTG4$HP{z54_te_{W^gu8$r=q0JgowzgQPct2JNtWPUsjF8R zvit&V8$(;7a_m%%9TqPkCXYUp&k*MRcwr*24>hR! z$4c#E=PVE=P4MLTUBM z7#*RDe0}=B)(3cvNpOmWa*eH#2HR?NVqXdJ=hq);MGD07JIQQ7Y0#iD!$C+mk7x&B zMwkS@H%>|fmSu#+ zI!}Sb(%o29Vkp_Th>&&!k7O>Ba#Om~B_J{pT7BHHd8(Ede(l`7O#`_}19hr_?~JP9 z`q(`<)y>%)x;O7)#-wfCP{?llFMoH!)ZomgsOYFvZ1DxrlYhkWRw#E-#Qf*z@Y-EQ z1~?_=c@M4DO@8AzZ2hKvw8CgitzI9yFd&N1-{|vP#4IqYb*#S0e3hrjsEGlnc4xwk z4o!0rxpUt8j&`mJ8?+P8G{m^jbk)bo_UPM+ifW*y-A*et`#_Ja_3nYyRa9fAG1Xr5 z>#AM_@PY|*u)DGRWJihZvgEh#{*joJN28uN7;i5{kJ*Gb-TERfN{ERe_~$Es~NJCpdKLRvdj4658uYYx{ng7I<6j~w@p%F<7a(Ssib|j z51;=Py(Nu*#hnLx@w&8X%=jrADn3TW>kplnb zYbFIWWVQXN7%Cwn6KnR)kYePEBmvM45I)UJb$)ninpdYg3a5N6pm_7Q+9>!_^xy?k za8@tJ@OOs-pRAAfT>Nc2x=>sZUs2!9Dwa%TTmDggH4fq(x^MW>mcRyJINlAqK$YQCMgR8`>6=Sg$ zFnJZsA8xUBXIN3i70Q%8px@yQPMgVP=>xcPI38jNJK<=6hC={a07+n@R|$bnhB)X$ z(Zc%tadp70vBTnW{OUIjTMe38F}JIH$#A}PB&RosPyFZMD}q}5W%$rh>5#U;m`z2K zc(&WRxx7DQLM-+--^w*EWAIS%bi>h587qkwu|H=hma3T^bGD&Z!`u(RKLeNZ&pI=q$|HOcji(0P1QC!YkAp*u z3%S$kumxR}jU<@6`;*-9=5-&LYRA<~uFrwO3U0k*4|xUTp4ZY7;Zbjx|uw&BWU$zK(w55pWa~#=f$c zNDW0O68N!xCy>G}(CX=;8hJLxAKn@Aj(dbZxO8a$+L$jK8$N-h@4$i8)WqD_%Snh4 zR?{O%k}>lr>w$b$g=VP8mckcCrjnp>uQl5F_6dPM8FWRqs}h`DpfCv20uZhyY~tr8 zkAYW4#yM;*je)n=EAb(q@5BWD8b1_--m$Q-3wbh1hM{8ihq7UUQfg@)l06}y+#=$( z$x>oVYJ47zAC^>HLRE-!HitjUixP6!R98WU+h>zct7g4eD;Mj#FL*a!VW!v-@b(Jv zj@@xM5noCp5%Vk3vY{tyI#oyDV7<$`KG`tktVyC&0DqxA#>V;-3oH%NW|Q&=UQ&zU zXNIT67J4D%5R1k#bW0F}TD`hlW7b)-=-%X4;UxQ*u4bK$mTAp%y&-(?{sXF%e_VH6 zTkt(X)SSN|;8q@8XX6qfR;*$r#HbIrvOj*-5ND8RCrcw4u8D$LXm5zlj@E5<3S0R# z??=E$p{tOk96$SloZ~ARe5`J=dB|Nj?u|zy2r(-*(q^@YwZiTF@QzQyPx_l=IDKa) zqD@0?IHJqSqZ_5`)81?4^~`yiGh6>7?|dKa8!e|}5@&qV!Iu9<@G?E}Vx9EzomB3t zEbMEm$TKGwkHDpirp;FZD#6P5qIlQJ8}rf;lHoz#h4TFFPYmS3+8(13_Mx2`?^=8S z|0)0&dQLJTU6{b%*yrpQe#OKKCrL8}YKw+<#|m`SkgeoN69TzIBQOl_Yg)W*w?NW) z*WxhEp$zQBBazJSE6ygu@O^!@Fr46j=|K`Mmb~xbggw7<)BuC@cT@Bwb^k?o-A zKX^9AyqR?zBtW5UA#siILztgOp?r4qgC`9jYJG_fxlsVSugGprremg-W(K0{O!Nw-DN%=FYCyfYA3&p*K>+|Q}s4rx#CQK zNj^U;sLM#q8}#|PeC$p&jAjqMu(lkp-_50Y&n=qF9`a3`Pr9f;b`-~YZ+Bb0r~c+V z*JJ&|^T{}IHkwjNAaM^V*IQ;rk^hnnA@~?YL}7~^St}XfHf6OMMCd9!vhk#gRA*{L zp?&63axj|Si%^NW05#87zpU_>QpFNb+I00v@cHwvdBn+Un)n2Egdt~LcWOeBW4Okm zD$-e~RD+W|UB;KQ;a7GOU&%p*efGu2$@wR74+&iP8|6#_fmnh^WcJLs)rtz{46);F z4v0OL{ZP9550>2%FE(;SbM*#sqMl*UXOb>ch`fJ|(*bOZ9=EB1+V4fkQ)hjsm3-u^Pk-4ji_uDDHdD>84tER!MvbH`*tG zzvbhBR@}Yd`azQGavooV=<WbvWLlO#x`hyO34mKcxrGv=`{ssnP=0Be5#1B;Co9 zh{TR>tjW2Ny$ZxJpYeg57#0`GP#jxDCU0!H15nL@@G*HLQcRdcsUO3sO9xvtmUcc{F*>FQZcZ5bgwaS^k-j5mmt zI7Z{Xnoml|A(&_{imAjK!kf5>g(oDqDI4C{;Bv162k8sFNr;!qPa2LPh>=1n z=^_9)TsLDvTqK7&*Vfm5k;VXjBW^qN3Tl&}K=X5)oXJs$z3gk0_+7`mJvz{pK|FVs zHw!k&7xVjvY;|(Py<;J{)b#Yjj*LZO7x|~pO4^MJ2LqK3X;Irb%nf}L|gck zE#55_BNsy6m+W{e zo!P59DDo*s@VIi+S|v93PwY6d?CE=S&!JLXwE9{i)DMO*_X90;n2*mPDrL%{iqN!?%-_95J^L z=l<*{em(6|h7DR4+4G3Wr;4*}yrBkbe3}=p7sOW1xj!EZVKSMSd;QPw>uhKK z#>MlS@RB@-`ULv|#zI5GytO{=zp*R__uK~R6&p$q{Y{iNkg61yAgB8C^oy&``{~FK z8hE}H&nIihSozKrOONe5Hu?0Zy04U#0$fB7C6y~?8{or}KNvP)an=QP&W80mj&8WL zEZQF&*FhoMMG6tOjeiCIV;T{I>jhi9hiUwz?bkX3NS-k5eWKy)Mo_orMEg4sV6R6X&i-Q%JG;Esl+kLpn@Bsls9O|i9z`tKB^~1D5)RIBB&J<6T@a4$pUvh$IR$%ubH)joi z!7>ON0DPwx=>0DA>Bb^c?L8N0BBrMl#oDB+GOXJh;Y&6I)#GRy$W5xK%a;KS8BrER zX)M>Rdoc*bqP*L9DDA3lF%U8Yzb6RyIsW@}IKq^i7v&{LeIc=*ZHIbO68x=d=+0T( zev=DT9f|x!IWZNTB#N7}V4;9#V$%Wo0%g>*!MdLOEU>My0^gni9ocID{$g9ytD!gy zKRWT`DVN(lcYjR|(}f0?zgBa3SwunLfAhx><%u0uFkrdyqlh8_g zDKt#R6rA2(Vm2LW_>3lBNYKG_F{TEnnKWGGC15y&OebIRhFL4TeMR*v9i0wPoK#H< zu4){s4K&K)K(9~jgGm;H7lS7y_RYfS;&!Oj5*eqbvEcW^a*i67nevzOZxN6F+K~A%TYEtsAVsR z@J=1hc#Dgs7J2^FL|qV&#WBFQyDtEQ2kPO7m2`)WFhqAob)Y>@{crkil6w9VoA?M6 zADGq*#-hyEVhDG5MQj677XmcWY1_-UO40QEP&+D)rZoYv^1B_^w7zAvWGw&pQyCyx zD|ga$w!ODOxxGf_Qq%V9Z7Q2pFiUOIK818AGeZ-~*R zI1O|SSc=3Z?#61Rd|AXx2)K|F@Z1@x!hBBMhAqiU)J=U|Y)T$h3D?ZPPQgkSosnN! zIqw-t$0fqsOlgw3TlHJF*t$Q@bg$9}A3X=cS@-yU3_vNG_!#9}7=q7!LZ?-%U26W4 z$d>_}*s1>Ac%3uFR;tnl*fNlylJ)}r2^Q3&@+is3BIv<}x>-^_ng;jhdaM}6Sg3?p z0jS|b%QyScy3OQ(V*~l~bK>VC{9@FMuW_JUZO?y(V?LKWD6(MXzh}M3r3{7b4eB(#`(q1m{>Be%_<9jw8HO!x#yF6vez$c#kR+}s zZO-_;25Sxngd(}){zv?ccbLqRAlo;yog>4LH&uZUK1n>x?u49C)Y&2evH5Zgt~666 z_2_z|H5AO5Iqxv_Bn~*y1qzRPcob<+Otod5Xd2&z=C;u+F}zBB@b^UdGdUz|s!H}M zXG%KiLzn3G?FZgdY&3pV$nSeY?ZbU^jhLz9!t0K?ep}EFNqR1@E!f*n>x*!uO*~JF zW9UXWrVgbX1n#76_;&0S7z}(5n-bqnII}_iDsNqfmye@)kRk`w~1 z6j4h4BxcPe6}v)xGm%=z2#tB#^KwbgMTl2I*$9eY|EWAHFc3tO48Xo5rW z5oHD!G4kb?MdrOHV=A+8ThlIqL8Uu+7{G@ zb)cGBm|S^Eh5= z^E^SZ=yeC;6nNCdztw&TdnIz}^Of@Ke*@vjt)0g>Y!4AJvWiL~e7+9#Ibhe)> ziNwh>gWZL@FlWc)wzihocz+%+@*euwXhW%Hb>l7tf8aJe5_ZSH1w-uG|B;9qpcBP0 zM`r1Hu#htOl)4Cl1c7oY^t0e4Jh$-I(}M5kzWqh{F=g&IM#JiC`NDSd@BCKX#y<P@Gwl$3a3w z6<(b|K(X5FIR22M)sy$4jY*F4tT{?wZRI+KkZFb<@j@_C316lu1hq2hA|1wCmR+S@ zRN)YNNE{}i_H`_h&VUT5=Y(lN%m?%QX;6$*1P}K-PcPx>*S55v)qZ@r&Vcic-sjkm z! z=nfW&X`}iAqa_H$H%z3Tyz5&P3%+;93_0b;zxLs)t#B|up}JyV$W4~`8E@+BHQ+!y zuIo-jW!~)MN$2eHwyx-{fyGjAWJ(l8TZtUp?wZWBZ%}krT{f*^fqUh+ywHifw)_F> zp76_kj_B&zFmv$FsPm|L7%x-j!WP>_P6dHnUTv!9ZWrrmAUteBa`rT7$2ixO;ga8U z3!91micm}{!Btk+I%pMgcKs?H4`i+=w0@Ws-CS&n^=2hFTQ#QeOmSz6ttIkzmh^`A zYPq)G1l3h(E$mkyr{mvz*MP`x+PULBn%CDhltKkNo6Uqg!vJ#DA@BIYr9TQ`18Un2 zv$}BYzOQuay9}w(?JV63F$H6WmlYPPpH=R|CPb%C@BCv|&Q|&IcW7*LX?Q%epS z`=CPx{1HnJ9_46^=0VmNb>8JvMw-@&+V8SDLRYsa>hZXEeRbtf5eJ>0@Ds47zIY{N z42EOP9J8G@MXXdeiPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$^8f$?lu1NER9Fe^SItioK@|V(ZWmgL zZT;XwPgVuWM>O%^|Dc$VK;n&?9!&g5)aVsG8cjs5UbtxVVnQNOV~7Mrg3+jnU;rhE z6fhW6P)R>_eXrXo-RW*y6RQ_qcb^s1wTu$TwriZ`=JUws>vRi}5x}MW1MR#7p|gIWJlaLK;~xaN}b< z<-@=RX-%1mt`^O0o^~2=CD7pJ<<$Rp-oUL-7PuG>do^5W_Mk#unlP}6I@6NPxY`Q} zuXJF}!0l)vwPNAW;@5DjPRj?*rZxl zwn;A(cFV!xe^CUu+6SrN?xe#mz?&%N9QHf~=KyK%DoB8HKC)=w=3E?1Bqj9RMJs3U z5am3Uv`@+{jgqO^f}Lx_Jp~CoP3N4AMZr~4&d)T`R?`(M{W5WWJV^z~2B|-oih@h^ zD#DuzGbl(P5>()u*YGo*Och=oRr~3P1wOlKqI)udc$|)(bacG5>~p(y>?{JD7nQf_ z*`T^YL06-O>T(s$bi5v~_fWMfnE7Vn%2*tqV|?~m;wSJEVGkNMD>+xCu#um(7}0so zSEu7?_=Q64Q5D+fz~T=Rr=G_!L*P|(-iOK*@X8r{-?oBlnxMNNgCVCN9Y~ocu+?XA zjjovJ9F1W$Nf!{AEv%W~8oahwM}4Ruc+SLs>_I_*uBxdcn1gQ^2F8a*vGjgAXYyh? zWCE@c5R=tbD(F4nL9NS?$PN1V_2*WR?gjv3)4MQeizuH`;sqrhgykEzj z593&TGlm3h`sIXy_U<7(dpRXGgp0TB{>s?}D{fwLe>IV~exweOfH!qM@CV5kib!YA z6O0gvJi_0J8IdEvyP#;PtqP*=;$iI2t(xG2YI-e!)~kaUn~b{6(&n zp)?iJ`z2)Xh%sCV@BkU`XL%_|FnCA?cVv@h*-FOZhY5erbGh)%Q!Av#fJM3Csc_g zC2I6x%$)80`Tkz#KRA!h1FzY`?0es3t!rKDT5EjPe6B=BLPr7s0GW!if;Ip^!AmGW zL;$`Vdre+|FA!I4r6)keFvAx3M#1`}ijBHDzy)3t0gwjl|qC2YB`SSxFKHr(oY#H$)x{L$LL zBdLKTlsOrmb>T0wd=&6l3+_Te>1!j0OU8%b%N342^opKmT)gni(wV($s(>V-fUv@0p8!f`=>PxC|9=nu ze{ToBBj8b<{PLfXV$h8YPgA~E!_sF9bl;QOF{o6t&JdsX?}rW!_&d`#wlB6T_h;Xf zl{4Tz5>qjF4kZgjO7ZiLPRz_~U@k5%?=30+nxEh9?s78gZ07YHB`FV`4%hlQlMJe@J`+e(qzy+h(9yY^ckv_* zb_E6o4p)ZaWfraIoB2)U7_@l(J0O%jm+Or>8}zSSTkM$ASG^w3F|I? z$+eHt7T~04(_WfKh27zqS$6* zzyy-ZyqvSIZ0!kkSvHknm_P*{5TKLQs8S6M=ONuKAUJWtpxbL#2(_huvY(v~Y%%#~ zYgsq$JbLLprKkV)32`liIT$KKEqs$iYxjFlHiRNvBhxbDg*3@Qefw4UM$>i${R5uB zhvTgmqQsKA{vrKN;TSJU2$f9q=y{$oH{<)woSeV>fkIz6D8@KB zf4M%v%f5U2?<8B(xn}xV+gWP?t&oiapJhJbfa;agtz-YM7=hrSuxl8lAc3GgFna#7 zNjX7;`d?oD`#AK+fQ=ZXqfIZFEk{ApzjJF0=yO~Yj{7oQfXl+6v!wNnoqwEvrs81a zGC?yXeSD2NV!ejp{LdZGEtd1TJ)3g{P6j#2jLR`cpo;YX}~_gU&Gd<+~SUJVh+$7S%`zLy^QqndN<_9 zrLwnXrLvW+ew9zX2)5qw7)zIYawgMrh`{_|(nx%u-ur1B7YcLp&WFa24gAuw~& zKJD3~^`Vp_SR$WGGBaMnttT)#fCc^+P$@UHIyBu+TRJWbcw4`CYL@SVGh!X&y%!x~ zaO*m-bTadEcEL6V6*{>irB8qT5Tqd54TC4`h`PVcd^AM6^Qf=GS->x%N70SY-u?qr>o2*OV7LQ=j)pQGv%4~z zz?X;qv*l$QSNjOuQZ>&WZs2^@G^Qas`T8iM{b19dS>DaXX~=jd4B2u`P;B}JjRBi# z_a@&Z5ev1-VphmKlZEZZd2-Lsw!+1S60YwW6@>+NQ=E5PZ+OUEXjgUaXL-E0fo(E* zsjQ{s>n33o#VZm0e%H{`KJi@2ghl8g>a~`?mFjw+$zlt|VJhSU@Y%0TWs>cnD&61fW4e0vFSaXZa4-c}U{4QR8U z;GV3^@(?Dk5uc@RT|+5C8-24->1snH6-?(nwXSnPcLn#X_}y3XS)MI_?zQ$ZAuyg+ z-pjqsw}|hg{$~f0FzmmbZzFC0He_*Vx|_uLc!Ffeb8#+@m#Z^AYcWcZF(^Os8&Z4g zG)y{$_pgrv#=_rV^D|Y<_b@ICleUv>c<0HzJDOsgJb#Rd-Vt@+EBDPyq7dUM9O{Yp zuGUrO?ma2wpuJuwl1M=*+tb|qx7Doj?!F-3Z>Dq_ihFP=d@_JO;vF{iu-6MWYn#=2 zRX6W=`Q`q-+q@Db|6_a1#8B|#%hskH82lS|9`im0UOJn?N#S;Y0$%xZw3*jR(1h5s z?-7D1tnIafviko>q6$UyqVDq1o@cwyCb*})l~x<@s$5D6N=-Uo1yc49p)xMzxwnuZ zHt!(hu-Ek;Fv4MyNTgbW%rPF*dB=;@r3YnrlFV{#-*gKS_qA(G-~TAlZ@Ti~Yxw;k za1EYyX_Up|`rpbZ0&Iv#$;eC|c0r4XGaQ-1mw@M_4p3vKIIpKs49a8Ns#ni)G314Z z8$Ei?AhiT5dQGWUYdCS|IC7r z=-8ol>V?u!n%F*J^^PZ(ONT&$Ph;r6X;pj|03HlDY6r~0g~X#zuzVU%a&!fs_f|m?qYvg^Z{y?9Qh7Rn?T*F%7lUtA6U&={HzhYEzA`knx1VH> z{tqv?p@I(&ObD5L4|YJV$QM>Nh-X3cx{I&!$FoPC_2iIEJfPk-$;4wz>adRu@n`_y z_R6aN|MDHdK;+IJmyw(hMoDCFCQ(6?hCAG5&7p{y->0Uckv# zvooVuu04$+pqof777ftk<#42@KQ((5DPcSMQyzGOJ{e9H$a9<2Qi_oHjl{#=FUL9d z+~0^2`tcvmp0hENwfHR`Ce|<1S@p;MNGInXCtHnrDPXCKmMTZQ{HVm_cZ>@?Wa6}O zHsJc7wE)mc@1OR2DWY%ZIPK1J2p6XDO$ar`$RXkbW}=@rFZ(t85AS>>U0!yt9f49^ zA9@pc0P#k;>+o5bJfx0t)Lq#v4`OcQn~av__dZ-RYOYu}F#pdsl31C^+Qgro}$q~5A<*c|kypzd} ziYGZ~?}5o`S5lw^B{O@laad9M_DuJle- z*9C7o=CJh#QL=V^sFlJ0c?BaB#4bV^T(DS6&Ne&DBM_3E$S^S13qC$7_Z?GYXTpR@wqr70wu$7+qvf-SEUa5mdHvFbu^7ew!Z1a^ zo}xKOuT*gtGws-a{Tx}{#(>G~Y_h&5P@Q8&p!{*s37^QX_Ibx<6XU*AtDOIvk|^{~ zPlS}&DM5$Ffyu-T&0|KS;Wnaqw{9DB&B3}vcO14wn;)O_e@2*9B&0I_ zZz{}CMxx`hv-XouY>^$Y@J(_INeM>lIQI@I>dBAqq1)}?Xmx(qRuX^i4IV%=MF306 z9g)i*79pP%_7Ex?m6ag-4Tlm=Z;?DQDyC-NpUIb#_^~V_tsL<~5<&;Gf2N+p?(msn zzUD~g>OoW@O}y0@Z;RN)wjam`CipmT&O7a|YljZqU=U86 zedayEdY)2F#BJ6xvmW8K&ffdS*0!%N<%RB!2~PAT4AD*$W7yzHbX#Eja9%3aD+Ah2 zf#T;XJW-GMxpE=d4Y>}jE=#U`IqgSoWcuvgaWQ9j1CKzG zDkoMDDT)B;Byl3R2PtC`ip=yGybfzmVNEx{xi_1|Cbqj>=FxQc{g`xj6fIfy`D8fA z##!-H_e6o0>6Su&$H2kQTujtbtyNFeKc}2=|4IfLTnye#@$Au7Kv4)dnA;-fz@D_8 z)>irG$)dkBY~zX zC!ZXLy*L3xr6cb70QqfN#Q>lFIc<>}>la4@3%7#>a1$PU&O^&VszpxLC%*!m-cO{B z-Y}rQr4$84(hvy#R69H{H zJ*O#uJh)TF6fbXy;fZkk%X=CjsTK}o5N1a`d7kgYYZLPxsHx%9*_XN8VWXEkVJZ%A z1A+5(B;0^{T4aPYr8%i@i32h)_)|q?9vws)r+=5u)1YNftF5mknwfd*%jXA2TeP}Z zQ!m?xJ3?9LpPM?_A3$hQ1QxNbR&}^m z!F999s?p^ak#C4NM_x2p9FoXWJ$>r?lJ)2bG)sX{gExgLA2s5RwHV!h6!C~d_H||J z>9{E{mEv{Z1z~65Vix@dqM4ZqiU|!)eWX$mwS5mLSufxbpBqqS!jShq1bmwCR6 z4uBri7ezMeS6ycaXPVu(i2up$L; zjpMtB`k~WaNrdgM_R=e#SN?Oa*u%nQy01?()h4A(jyfeNfx;5o+kX?maO4#1A^L}0 zYNyIh@QVXIFiS0*tE}2SWTrWNP3pH}1Vz1;E{@JbbgDFM-_Mky^7gH}LEhl~Ve5PexgbIyZ(IN%PqcaV@*_`ZFb=`EjspSz%5m2E34BVT)d=LGyHVz@-e%9Ova*{5@RD;7=Ebkc2GP%pIP^P7KzKapnh`UpH?@h z$RBpD*{b?vhohOKf-JG3?A|AX|2pQ?(>dwIbWhZ38GbTm4AImRNdv_&<99ySX;kJ| zo|5YgbHZC#HYgjBZrvGAT4NZYbp}qkVSa;C-LGsR26Co+i_HM&{awuO9l)Ml{G8zD zs$M8R`r+>PT#Rg!J(K6T4xHq7+tscU(}N$HY;Yz*cUObX7J7h0#u)S7b~t^Oj}TBF zuzsugnst;F#^1jm>22*AC$heublWtaQyM6RuaquFd8V#hJ60Z3j7@bAs&?dD#*>H0SJaDwp%U~27>zdtn+ z|8sZzklZy$%S|+^ie&P6++>zbrq&?+{Yy11Y>@_ce@vU4ZulS@6yziG6;iu3Iu`M= zf3rcWG<+3F`K|*(`0mE<$89F@jSq;j=W#E>(R}2drCB7D*0-|D;S;(;TwzIJkGs|q z2qH{m_zZ+el`b;Bv-#bQ>}*VPYC|7`rgBFf2oivXS^>v<&HHTypvd4|-zn|=h=TG{ z05TH2+{T%EnADO>3i|CB zCu60#qk`}GW{n4l-E$VrqgZGbI zbQW690KgZt4U3F^5@bdO1!xu~p@7Y~*_FfWg2CdvED5P5#w#V46LH`<&V0{t&Ml~4 zHNi7lIa+#i+^Z6EnxO7KJQw)wD)4~&S-Ki8)3=jpqxmx6c&zU&<&h%*c$I(5{1HZT zc9WE}ijcWJiVa^Q^xC|WX0habl89qycOyeViIbi(LFsEY_8a|+X^+%Qv+W4vzj>`y zpuRnjc-eHNkvXvI_f{=*FX=OKQzT?bck#2*qoKTHmDe>CDb&3AngA1O)1b}QJ1Tun z_<@yVEM>qG7664Pa@dzL@;DEh`#?yM+M|_fQS<7yv|i*pw)|Z8)9IR+QB7N3v3K(wv4OY*TXnH&X0nQB}?|h2XQeGL^q~N7N zDFa@x0E(UyN7k9g%IFq7Sf+EAfE#K%%#`)!90_)Dmy3Bll&e1vHQyPA87TaF(xbqMpDntVp?;8*$87STop$!EAnGhZ?>mqPJ(X zFsr336p3P{PpZCGn&^LP(JjnBbl_3P3Kcq+m}xVFMVr1zdCPJMDIV_ki#c=vvTwbU z*gKtfic&{<5ozL6Vfpx>o2Tts?3fkhWnJD&^$&+Mh5WGGyO7fG@6WDE`tEe(8<;+q z@Ld~g08XDzF8xtmpIj`#q^(Ty{Hq>t*v`pedHnuj(0%L(%sjkwp%s}wMd!a<*L~9T z9MM@s)Km~ogxlqEhIw5(lc46gCPsSosUFsgGDr8H{mj%OzJz{N#;bQ;KkV+ZWA1(9 zu0PXzyh+C<4OBYQ0v3z~Lr;=C@qmt8===Ov2lJ1=DeLfq*#jgT{YQCuwz?j{&3o_6 zsqp2Z_q-YWJg?C6=!Or|b@(zxTlg$ng2eUQzuC<+o)k<6^9ju_Z*#x+oioZ5T8Z_L zz9^A1h2eFS0O5muq8;LuDKwOv4A9pxmOjgb6L*i!-(0`Ie^d5Fsgspon%X|7 zC{RRXEmYn!5zP9XjG*{pLa)!2;PJB2<-tH@R7+E1cRo=Wz_5Ko8h8bB$QU%t9#vol zAoq?C$~~AsYC|AQQ)>>7BJ@{Cal)ZpqE=gjT+Juf!RD-;U0mbV1ED5PbvFD6M=qj1 zZ{QERT5@(&LQ~1X9xSf&@%r|3`S#ZCE=sWD`D4YQZ`MR`G&s>lN{y2+HqCfvgcw3E z-}Kp(dfGG?V|97kAHQX+OcKCZS`Q%}HD6u*e$~Ki&Vx53&FC!x94xJd4F2l^qQeFO z?&JdmgrdVjroKNJx64C!H&Vncr^w zzR#XI}Dn&o8jB~_YlVM^+#0W(G1LZH5K^|uYT@KSR z^Y5>^*Bc45E1({~EJB(t@4n9gb-eT#s@@7)J^^<_VV`Pm!h7av8XH6^5zO zOcQBhTGr;|MbRsgxCW69w{bl4EW#A~);L?d4*y#j8Ne=Z@fmJP0k4{_cQ~KA|Y#_#BuUiYx8y*za3_6Y}c=GSe7(2|KAfhdzud!Zq&}j)=o4 z7R|&&oX7~e@~HmyOOsCCwy`AR+deNjZ3bf6ijI_*tKP*_5JP3;0d;L_p(c>W1b%sG zJ*$wcO$ng^aW0E(5ldckV9unU7}OB7s?Wx(761?1^&8tA5y0_(ieV>(x-e@}1`lWC z-YH~G$D>#ud!SxK2_Iw{K%92=+{4yb-_XC>ji&j7)1ofp(OGa4jjF;Hd*`6YQL+Jf zffg+6CPc8F@EDPN{Kn96yip;?g@)qgkPo^nVKFqY?8!=h$G$V=<>%5J&iVjwR!7H0 z$@QL|_Q81I;Bnq8-5JyNRv$Y>`sWl{qhq>u+X|)@cMlsG!{*lu?*H`Tp|!uv z9oEPU1jUEj@ueBr}%Y)7Luyi)REaJV>eQ{+uy4uh0ep0){t;OU8D*RZ& zE-Z-&=BrWQLAD^A&qut&4{ZfhqK1ZQB0fACP)=zgx(0(o-`U62EzTkBkG@mXqbjXm z>w`HNeQM?Is&4xq@BB(K;wv5nI6EXas)XXAkUuf}5uSrZLYxRCQPefn-1^#OCd4aO zzF=dQ*CREEyWf@n6h7(uXLNgJIwGp#Xrsj6S<^bzQ7N0B0N{XlT;`=m9Olg<>KL}9 zlp>EKTx-h|%d1Ncqa=wnQEuE;sIO-f#%Bs?g4}&xS?$9MG?n$isHky0caj za8W+B^ERK#&h?(x)7LLpOqApV5F>sqB`sntV%SV>Q1;ax67qs+WcssfFeF3Xk=e4^ zjR2^(%K1oBq%0%Rf!y&WT;lu2Co(rHi|r1_uW)n{<7fGc-c=ft7Z0Q}r4W$o$@tQF#i?jDBwZ8h+=SC}3?anUp3mtRVv9l#H?-UD;HjTF zQ*>|}e=6gDrgI9p%c&4iMUkQa4zziS$bO&i#DI$Wu$7dz7-}XLk%!US^XUIFf2obO zFCTjVEtkvYSKWB;<0C;_B{HHs~ax_48^Cml*mjfBC5*7^HJZiLDir(3k&BerVIZF8zF;0q80eX8c zPN4tc+Dc5DqEAq$Y3B3R&XPZ=AQfFMXv#!RQnGecJONe0H;+!f^h5x0wS<+%;D}MpUbTNUBA}S2n&U59-_5HKr{L^jPsV8B^%NaH|tUr)mq=qCBv_- ziZ1xUp(ZzxUYTCF@C}To;u60?RIfTGS?#JnB8S8@j`TKPkAa)$My+6ziGaBcA@){d z91)%+v2_ba7gNecdj^8*I4#<11l!{XKl6s0zkXfJPxhP+@b+5ev{a>p*W-3*25c&} zmCf{g9mPWVQ$?Sp*4V|lT@~>RR)9iNdN^7KT@>*MU3&v^3e?=NTbG9!h6C|9zO097 zN{Qs6YwR-5$)~ z`b~qs`a1Dbx8P>%V=1XGjBptMf%P~sl1qbHVm1HYpY|-Z^Dar8^HqjIw}xaeRlsYa zJ_@Apy-??`gxPmb`m`0`z`#G7*_C}qiSZe~l2z65tE~IwMw$1|-u&t|z-8SxliH00 zlh1#kuqB56s+E&PWQ7Nz17?c}pN+A@-c^xLqh(j;mS|?>(Pf7(?qd z5q@jkc^nA&!K-}-1P=Ry0yyze0W!+h^iW}7jzC1{?|rEFFWbE^Yu7Y}t?jmP-D$f+ zmqFT7nTl0HL|4jwGm7w@a>9 zKD)V~+g~ysmei$OT5}%$&LK8?ib|8aY|>W3;P+0B;=oD=?1rg+PxKcP(d;OEzq1CKA&y#boc51P^ZJPPS)z5 zAZ)dd2$glGQXFj$`XBBJyl2y-aoBA8121JC9&~|_nY>nkmW>TLi%mWdn-^Jks-Jv| zSR*wij;A3Fcy8KsDjQ15?Z9oOj|Qw2;jgJiq>dxG(2I2RE- z$As!#zSFIskebqU2bnoM^N<4VWD2#>!;saPSsY8OaCCQqkCMdje$C?Sp%V}f2~tG5 z0whMYk6tcaABwu*x)ak@n4sMElGPX1_lmv@bgdI2jPdD|2-<~Jf`L`@>Lj7{<-uLQ zE3S_#3e10q-ra=vaDQ42QUY^@edh>tnTtpBiiDVUk5+Po@%RmuTntOlE29I4MeJI?;`7;{3e4Qst#i-RH6s;>e(Sc+ubF2_gwf5Qi%P!aa89fx6^{~A*&B4Q zKTF|Kx^NkiWx=RDhe<{PWXMQ;2)=SC=yZC&mh?T&CvFVz?5cW~ritRjG2?I0Av_cI z)=s!@MXpXbarYm>Kj0wOxl=eFMgSMc?62U#2gM^li@wKPK9^;;0_h7B>F>0>I3P`{ zr^ygPYp~WVm?Qbp6O3*O2)(`y)x>%ZXtztz zMAcwKDr=TCMY!S-MJ8|2MJCVNUBI0BkJV6?(!~W!_dC{TS=eh}t#X+2D>Kp&)ZN~q zvg!ogxUXu^y(P*;Q+y_rDoGeSCYxkaGPldDDx)k;ocJvvGO#1YKoQLHUf2h_pjm&1 zqh&!_KFH03FcJvSdfgUYMp=5EpigZ*8}7N_W%Ms^WSQ4hH`9>3061OEcxmf~TcYn5_oHtscWn zo5!ayj<_fZ)vHu3!A!7M;4y1QIr8YGy$P2qDD_4+T8^=^dB6uNsz|D>p~4pF3Nrb6 zcpRK*($<~JUqOya#M1=#IhOZ zG)W+rJS-x(6EoVz)P zsSo>JtnChdj9^);su%SkFG~_7JPM zEDz3gk2T7Y%x>1tWyia|op(ilEzvAujW?Xwlw>J6d7yEi8E zv30riR|a_MM%ZZX&n!qm0{2agq(s?x9E@=*tyT$nND+{Djpm7Rsy!+c$j+wqMwTOF zZL8BQ|I`<^bGW)5apO{lh(Asqen?_U`$_n0-Ob~Yd%^89oEe%9yGumQ_8Be+l2k+n zCxT%s?bMpv|AdWP7M1LQwLm|x+igA~;+iK-*+tClF&ueX_V}>=4gvZ01xpubQWXD_ zi?Un>&3=$fu)dgk-Z;0Ll}HK5_YM->l^Czrd0^cJ))(DwL2g3aZuza7ga9^|mT_70 z))}A}r1#-(9cxtn<9jGRwOB4hb9kK@YCgjfOM-90I$8@l=H^`K$cyhe2mTM|FY9vW znH~h)I<_aa#V1xmhk?Ng@$Jw-s%a!$BI4Us+Df+?J&gKAF-M`v}j`OWKP3>6`X`tEmhe#y*(Xm$_^Ybbs=%;L7h zp7q^C*qM}Krqsinq|WolR99>_!GL#Z71Hhz|IwQQv<>Ds09B?Je(lhI1(FInO8mc} zl$RyKCUmfku+Cd^8s0|t+e}5g7M{ZPJQH=UB3(~U&(w#Bz#@DTDHy>_UaS~AtN>4O zJ-I#U@R($fgupHebcpuEBX`SZ>kN!rW$#9>s{^3`86ZRQRtYTY)hiFm_9wU3c`SC8 z-5M%g)h}3Pt|wyj#F%}pGC@VL`9&>9P+_UbudCkS%y2w&*o})hBplrB*@Z?gel5q+ z%|*59(sR9GMk3xME}wd%&k?7~J)OL`rK#4d-haC7uaU8-L@?$K6(r<0e<;y83rK&` z3Q!1rD9WkcB8WBQ|WT|$u^lkr0UL4WH4EQTJyk@5gzHb18cOte4w zS`fLv8q;PvAZyY;*Go3Qw1~5#gP0D0ERla6M6#{; zr1l?bR}Nh+OC7)4bfAs(0ZD(axaw6j9v`^jh5>*Eo&$dAnt?c|Y*ckEORIiJXfGcM zEo`bmIq6rJm`XhkXR-^3d8^RTK2;nmVetHfUNugJG(4XLOu>HJA;0EWb~?&|0abr6 zxqVp@p=b3MN^|~?djPe!=eex(u!x>RYFAj|*T$cTi*Sd3Bme7Pri1tkK9N`KtRmXf zZYNBNtik97ct1R^vamQBfo9ZUR@k*LhIg8OR9d_{iv#t)LQV91^5}K5u{eyxwOFoU zHMVq$C>tfa@uNDW^_>EmO~WYQd(@!nKmAvSSIb&hPO|}g-3985t?|R&WZXvxS}Kt2i^eRe>WHb_;-K5cM4=@AN1>E&1c$k!w4O*oscx(f=<1K6l#8Exi)U(ZiZ zdr#YTP6?m1e1dOKysUjQ^>-MR={OuD00g6+(a^cvcmn#A_%Fh3Of%(qP5nvjS1=(> z|Ld8{u%(J}%2SY~+$4pjy{()5HN2MYUjg1X9umxOMFFPdM+IwOVEs4Z(olynvT%G) zt9|#VR}%O2@f6=+6uvbZv{3U)l;C{tuc zZ{K$rut=eS%3_~fQv^@$HV6#9)K9>|0qD$EV2$G^XUNBLM|5-ZmFF!KV)$4l^KVj@ zZ4fI}Knv*K%zPqK77}B-h_V{66VrmoZP2>@^euu8Rc}#qwRwt5uEBWcJJE5*5rT2t zA4Jpx`QQ~1Sh_n_a9x%Il!t1&B~J6p54zxAJx`REov${jeuL8h8x-z=?qwMAmPK5i z_*ES)BW(NZluu#Bmn1-NUKQip_X&_WzJy~J`WYxEJQ&Gu7DD< z&F9urE;}8S{x4{yB zaq~1Zrz%8)<`prSQv$eu5@1RY2WLu=waPTrn`WK%;G5(jt^FeM;gOdvXQjYhax~_> z{bS_`;t#$RYMu-;_Dd&o+LD<5Afg6v{NK?0d8dD5ohAN?QoocETBj?y{MB)jQ%UQ}#t3j&iL!qr@#6JEajR3@^k5wgLfI9S9dT2^f`2wd z%I#Q*@Ctk@w=(u)@QC}yBvUP&fFRR-uYKJ){Wp3&$s(o~W7OzgsUIPx0|ph2L1(r*_Pa@T@mcH^JxBjh09#fgo|W#gG7}|)k&uD1iZxb0 z@|Y)W79SKj9sS&EhmTD;uI#)FE6VwQ*YAr&foK$RI5H8_ripb$^=;U%gWbrrk4!5P zXDcyscEZoSH~n6VJu8$^6LE6)>+=o#Q-~*jmob^@191+Ot1w454e3)WMliLtY6~^w zW|n#R@~{5K#P+(w+XC%(+UcOrk|yzkEes=!qW%imu6>zjdb!B#`efaliKtN}_c!Jp zfyZa`n+Nx8;*AquvMT2;c8fnYszdDA*0(R`bsof1W<#O{v%O!1IO4WZe=>XBu_D%d zOwWDaEtX%@B>4V%f1+dKqcXT>m2!|&?}(GK8e&R=&w?V`*Vj)sCetWp9lr@@{xe6a zE)JL&;p}OnOO}Nw?vFyoccXT*z*?r}E8{uPtd;4<(hmX;d$rqJhEF}I+kD+m(ke;J z7Cm$W*CSdcD=RYEBhedg>tuT{PHqwCdDP*NkHv4rvQTXkzEn*Mb0oJz&+WfWIOS4@ zzpPJ|e%a-PIwOaOC7uQcHQ-q(SE(e@fj+7oC@34wzaBNaP;cw&gm{Z8yYX?V(lIv5 zKbg*zo1m5aGA4^lwJ|bAU=j3*d8S{vp!~fLFcK8s6%Ng55_qW_d*3R%e=34aDZPfD z&Le39j|ahp6E7B0*9OVdeMNrTErFatiE+=Z!XZ^tv0y%zZKXRTBuPyP&C{5(H?t)S zKV24_-TKpOmCPzU&by8R1Q5HY^@IDoeDA9MbgizgQ*F1Er~HVmvSU>vx}pZVQ&tr| zOtZl8vfY2#L<)gZ=ba&wG~EI*Vd?}lRMCf+!b5CDz$8~be-HKMo5omk$w7p4`Mym*IR8WiTz4^kKcUo^8Hkcsu14u z`Pkg`#-Y^A%CqJ0O@UF|caAulf68@(zhqp~YjzInh7qSN7Ov%Aj(Qz%{3zW|xubJ- ztNE_u_MO7Q_585r;xD?e=Er}@U1G@BKW5v$UM((eByhH2p!^g9W}99OD8VV@7d{#H zv)Eam+^K(5>-Ot~U!R$Um3prQmM)7DyK=iM%vy>BRX4#aH7*oCMmz07YB(EL!^%F7?CA#>zXqiYDhS;e?LYPTf(bte6B ztrfvDXYG*T;ExK-w?Knt{jNv)>KMk*sM^ngZ-WiUN;=0Ev^GIDMs=AyLg2V@3R z7ugNc45;4!RPxvzoT}3NCMeK$7j#q3r_xV(@t@OPRyoKBzHJ#IepkDsm$EJRxL)A* zf{_GQYttu^OXr$jHQn}zs$Eh|s|Z!r?Yi+bS-bi+PE*lH zo|6ztu6$r_?|B~S#m>imI!kQP9`6X426uHRri!wGcK;J;`%sFM(D#*Le~W*t2uH`Q z(HEO9-c_`mhA@4QhbW+tgtt9Pzx=_*3Kh~TB$SKmU4yx-Ay&)n%PZPKg#rD4H{%Ke zdMY@rf5EAFfqtrf?Vmk&N(_d-<=bvfOdPrYwY*;5%j@O6@O#Qj7LJTk-x3LN+dEKy+X z>~U8j3Ql`exr1jR>+S4nEy+4c2f{-Q!3_9)yY758tLGg7k^=nt<6h$YE$ltA+13S<}uOg#XHe6 zZHKdNsAnMQ_RIuB;mdoZ%RWpandzLR-BnjN2j@lkBbBd+?i ze*!5mC}!Qj(Q!rTu`KrRRqp22c=hF6<^v&iCDB`n7mHl;vdclcer%;{;=kA(PwdGG zdX#BWoC!leBC4);^J^tPkPbIe<)~nYb6R3u{HvC!NOQa?DC^Q`|_@ zcz;rk`a!4rSLAS>_=b@g?Yab4%=J3Cc7pRv8?_rHMl_aK*HSPU%0pG2Fyhef_biA!aW|-(( z*RIdG&Lmk(=(nk28Q1k1Oa$8Oa-phG%Mc6dT3>JIylcMMIc{&FsBYBD^n@#~>C?HG z*1&FpYVvXOU@~r2(BUa+KZv;tZ15#RewooEM0LFb>guQN;Z0EBFMFMZ=-m$a3;gVD z)2EBD4+*=6ZF?+)P`z@DOT;azK0Q4p4>NfwDR#Pd;no|{q_qB!zk1O8QojE;>zhPu z1Q=1z^0MYHo1*``H3ex|bW-Zy==5J4fE2;g6sq6YcXMYK5i|S^9(OSw#v!3^!EB<% zZF~J~CleS`V-peStyf*I%1^R88D;+8{{qN6-t!@gTARDg^w2`uSzFZbPQ!)q^oC}m zPo8VOQxq2BaIN`pAVFGu8!{p3}(+iZ`f4ck2ygVpEZMQW38nLpj3NQx+&sAkb8`}P3- zc>N*k6AG?r}bfO6_vccTuKX+*- z7W4Q#2``P0jIHYs)F>uG#AM#I6W2)!Nu2nD5{CRV_PmkDS2ditmbd#pggqEgAo%5oC?|CP zGa0CV)wA*ko!xC7pZYkqo{10CN_e00FX5SjWkI3?@XG}}bze!(&+k2$C-C`6temSk z_YyYpB^wh3woo`B zrMSTd4T?(X-jh`FeO76C(3xsOm9s2BP_b%ospg^!#*2*o9N;tf4(X9$qc_d(()yz5 zDk@1}u_Xd+86vy5RBs?LQCuYKCGPS;E4uFOi@V%1JTK&|eRf~lp$AV#;*#O}iRI2=i3rFL8{ zA^ptDZ0l6k-mq=hUJ0x$Y@J>UNfz~I5l63H(`~*v;qX`Z{zwsQQD-!wp0D&hyB8&Z z7$R07gIKGJ^%AvQ{4KM0edM39iFRx=P^6`!<1(s0t|JbB2tXs_B_IH9#ajH0C=-n+ z`nz`fKMBKLlf?2AC+|83M+0rqR%uhNGD;uKA6jOjp7YDe^4%0fRB<^bcjlS2KF~F; zu09wh1x0&4pG&76M;x8$u`b134t=dEPBn6PV|X29<#T4F1mxGF*HOgiWU8tN@cguI z_F@o+XL7FJztR63wC|j4x_DANzcX94r7Iz-O2x$({&qd*mdLG=-Rv)uZ}UlMR+F&q zU}=lkfb0p1>1Ho){o$@}mSKIV;h*$AND7~Dl)QzpFBlSM99Kx+F7GsVK5xcR? z_4Q(Z%cgk8ST}U;;=!LwyZVu^S$>B-Waeik%wzcKTIqeX=0FP(TGQ=nxi=dsS5BYF zl@?}NT!Y!Iyos^@v7XWXA{_bV~1lxz7gC?xuXxy0_?GaN!AhRRM5>)^t%&ODd;@HN5L{MD3 zc>i2keQZVm#?NrDwbfd}_<*5^U&w0zv~n-y8=GGN-!=_`FU^cM8oVCWRFxw?BM^YD zi=Vxz4q|jwPTg+?q7_XI)-S@gQkh>w0ZUB}a{^ z_i;`Y(~fvpI!vmW*A^|P7(6+@C4UeL2WATf{P1?H5rk`5{TL zcf!CgP6Mi{MvjZS)rfo7JLDZK7M7ANd$3`{j9baD*7{#Zu-33fOYUzjvtKzR2)_T1I1s7fe&z|=)QkX;=`zX8!Byw-veM#yr;|wjO^II>!B*B z0+w%;0(=*G3V@88t!}~zx)&do(uF=073Yeh*fEhZb3Vn>t!m(9p~Y_FdV3IgR)9eT z)~e9xpI%2deTWyHlXA(7srrfc_`7ACm!R>SoIgkuF8 z!wkOhrixFy9y@)GdxAntd!!7@=L_tFD2T5OdSUO)I%yj02le`qeQ=yKq$g^h)NG;# za(0J@#VBi^5YI|QI=rq{KlxwGabZJ0dKmfWDROkcM}lUN$@DV`K7fU?8CP2H23QPi zG?YF*=Vn=kTK*#Y_{AQN&oLju|0#E=fx%YVh>S{puu&K$b;BN*jIo@VYhqPiJPzzM>#kxoy0vW9i;ne2_BIG0zyRFp<3M(iY(%*M_>q0ulV2K}Tg zkG{EWKS{i%4DUuHi%DVKy%e+Q!~Uf`>>F6NgD{{I8~nO4!VgOvtFOc7(O)X`|7n*f zxBa4CJ-v9fUUH+`7sPVvpM_C*udZ@OTGTzx56QM5y~OlrZc&w9=)B?nmd@keRn+^= zvm~4sa5987LFDnU{(N|N zJAR8H@}p1fC+H(yTI4n#%~TbImMpuqYn9cQ<0QQ%=PzZItLkC*ef9WJUvfITKWh#D zc#__8`4am9%#NslIUw+<82#SR8AYG|woLfBg#!-&dqq}@P>|I0%lbdy0lSMmNe+}o zj0zZuFr6Wb?Y{Qy-S=|r`bdrDmhnmvkRnkdn`YCleU>Q$=je}LGhh>_QAj6aa_0Oc z%Swsmui;IRx7bN*=AAS@5yW&Y2hy;3&|HAiA8}!HT6!Z!RVn~MZg`RmI6&%#tBZDx zfD+y@Z~NWlk*4l13vmt3AK2wP!fQlnBbECL>?p)F?T)<`w&QN>cP_V>r7UTcsTaaP zTOb$f!P@zf$6>890NVKbIkG8rE?9!Y97sMSZjfF?A zYR8lp`LMoz~O?iaZN;gcX;LC-%Ia*R%A&SLx!YIf29?P+=XAAojK8!^OU*@?R&DK!#G_lsn!#;S375uZ&B0HH1|BO0R90$U>qs zSvHv>H~mAgNCcjo-e+;RjY6B9NCbQrZ|BHjTkehaU<9CSkdd>Vl*ifA2LNOP&R2Qdy3k3-TQ+ zbq=#vI43x`s=%~cGyN&y4Y!FxhwgDe@i6uv8^BLL&3z*SO=D0aLjih?gY4-9uWp5or)H+v~w6n5X#F-I52z=Z_p4JB(;M| zeaVFhuR2|3UD2MzVc~^nSoD2(dD#uL_1PdnIxeA{V5n`#3xf1Zx@4lw(DsQ&H$h zw#%3O<1173hjg2_nhKi!d1ej=h7y`hVjCNB6|HTnx>SWuCE-kgTnfT+YGX4_Lun({ zDv2`>d3vrS)tTf7ps_vvh!Cx^e1BFuWnEAh0(7fkNk|-3oU|iRWdsC6U)?Raft~HN z;^$U}vZK5O8|LV$>6X5T(uYkblv{zwPxnQBh(BQ5tA~J!vGiAMYP^_ki~pkIxDfOZ zUJDwq%O~WueeV6%uN<54&u*c&E4y431cklBNrb06zGOOy4XNT~JS-q(s6@)F@ovbe ze`fial(O4(-su%6@@1+V0MsdLLMyE8;)nou(7}czU(5ASaZYDT(kUZ0L(&g$nF^n9 z9-Pi`ZZLX&)^*M6As4_2Mmc9S7OT)F8KkL2NJ)KJcnCuWU=Wy402A&45#Q9Id~BBH z0cY*xlv!uXzKrXLH!xQu(OtJvEj|0-DmRj1vjFz{c*I4$Pe(+_V|^b~S!0xm{8lq= zZv)@NlcyL3Xdz+*|L137F7y6L-2VsrKw=q^S>F6i%<{Fr8zk06$Ay-(!L$fY@7mcng!2}L0t zgi|KxfB63Xtk_Q8#ZPipQ@!zgjdpEIbK_?q17Hoi4Eiyun$hrc>T(7pOLVLQE=lgGwA+A308p& z7@=09(|$>eLy5gLe{*|3b(M;1n;C^~v?o88jYib48eR4$QGsBFzd}3QuwO^_XE(=B zq+hMi0UFC|dB{LCwch7;zYT=NK})O%sgi0k#yV;My@24^B1+CuZmYOh0^b)5Ba_)) zC%i#_Iev&nsu%I|1N5=MVc#PrlunKAs&hY|3s5;@}`>sB>}gzxuB zB=2vrRyB3uiyW(hkDUNe1@&(b`;>ZvGgw|@s{zVC#_`HXIN_^J@Etb zA7A+F?ot37T{<-vTy8h&b3e+WKHE1oh;pUQrN4yRRrx?mT_9jRa2i4l1fUnLW^Cbl z!I1>VzyFe?VELWWhM?@?t-YPZkD-Qjo@bC2(o#ZtZmr{KZsdFWItV`rs$gp{724@C zL8K5}E0+DHcWcL^{BGei4>@J-3%a#$y6;I}=upc};-NDv-z#kPX26ylOpH)Ov1uU{ zkLj6oiH6l_s+B~_z;|Jc2oi?naS7#3H63~~lWj4rUnd=fCnKdkik<@R&kch9q##G{ z4u!%=rlM~Yp3jk*t8}1B`Sv6<%Z^}~1e@aq zg|JQ`QO2pSjAm-g*?IrNc$^~sIrNBo2$m|Sxanr?Mfs>2@Auu49 zGXlsS<9XS1&8h(dD*Hl&5HBDG!^pJ*lkau_Ur+7`7z;rcs$hT4we?3bT=7Fe<>{5( z2m2(c+hUz2BTHM8dCe*Z3XX&Av;b~a=$6EF>&^E8%nyxO@m_n!q&XD^A{SRjRZQ0L~qDeC=j&0$j6=LNIz@`ni^>ch|sv}^6 zlm>?28yPl@WmDPR?Y-A9X{U9Dv_IsbXJnzKCjkRksLOg#42uG2mE_acbTQ4)J|1V>%U@K(FP3AYhL0U zdeOCPN1qLv!|#c=p!_+%VNV(GHt`RuLRV^vz<5tt-r)yOK**kUWPspVAf|}ZL{LS= z@k(@@!P&W!>wwe`x{+GrFSWhHov7hu?{KuuT%kl#WO@*WX$i_@retlhQBj++SVNCx z5$78LxP>Z=^aJ)D280r_jj=zFfMJFXCIe^B{~V@d1rl_F(qo&AB4bC-vYL>x2jSKX zpuTG-6kgp3e^T&+dtV*i6a~)v@n?n*MffN59y}<0djUX zt27R+SE#hp8bzc#;rk$jw3r4)Q@eI$*`_)=Pvge8@8|8>H3X)<9YX6cXa=ii#Le;(qKm@%0-7$>2ShnYc`j#zJ7gu_FE^?uAkL|H)UIH#gPu^40!6^J=^ zr`}iwa^!4tzW~vOMZAaKF>*8A{^8m$i(VK)>?=#l`xrVe>wseSvM_aF zATNkY>kM_P3?1kE`uIq#mvr-wuTgUH0N<&JhF=(E9%^NS*HLm!4GZ4_XI zL=R5tlG5Mk_1rPfg)sk^llFuKPMPBhuU|L5q#yP_mzxp1o&pAzi-X31sgFpIHn@($ z_>=`AB5(8tP6p2zS5VEvH5J$M` z_much3>S7t3Yo`Yx!>83-hW9LYzDKP?mKdkD#QAK8*M((sx{eBQdrR<^3ZhFP81+& zBnJMUefQyNBji~$5d88Wfw1Lv59aJN9t2!pABLg;ewJ#LXL-10;QcJl+Y4Mtngb)k6JZlCf)3uD_u)J3sYyN;NN5hNbg$%W!i-GK%e&!Us)2IExWSss$YG(hm3kJ-h%yD z>8q^n$+4I(_y_mbT{du4P%h1j3oSpjhY97{+IZ`aA4ug!vNJ6*p?<2H(2w+GD3j$I z1TUXGyNzdf>_yB3grP~FZUs<2Quw;eEi*7s(-MiIkQ%@J^+WGdQvYSUN+TRiD-xto zJ=OUU+kxGYc!HCLNbCvR4lGTp~#L;DFzGd-#gJe*xf(P3hDQz|y)?b9mwU3WUVnpcqXM<@w%r-k*Wr^gzAv)8T^sqA=Ye z!7qy&exJmAcAt~CwS#@yNmjr8*T*!A6w4~E*ibaLRs0CFo(;R3=ODhDt6zWNodmo0 zXx&bT$6&+5c>a|WJ)F4G-^GjY0H#*tY=UNyYr_q5fsrcjk(c^~e*7Lf`!Jd`)p412 zn|^*hV= zFI4UbwA%X@smDd$cQOiMC%jfitTxTb+#`9`G=2rJDfK!E=5ra|So>lc{X1$~w28i+ z4p&cTGwZ#5VueiXS9O8#;RR$yg7tL9!^)Sz&pZYIzlSh}0}V{LxL$Cu%B4U5_}k}- zm~|CsD<076x@<>m=6w6N?WaThIBP`!u{-;WF)xc=2otx*lwf|5+MkdJePjh(B z9SH+%cHGCMAXNxB{_3^otDWdsV7Ob6n{0 z+&!(;iaHOX__5z_$Qk{%xYV%Ig@7iokGBwR`3642ZP#H#v9QGbWl8<|MS*=@qO@Uj z6+SZ_v9`1paUe5tFN~v(b#J3a_Lx0+;r9giZIx-A5TxdbG>xi#AZ5_z1V}B^n)sxT zz49}eK7EWb6wR!6-qQOrHQHkUvshvq%=G2d&@(#XM*Am1;WbnJ{X_!a{ZkphD$^TQ z=Iskb&}=lBm(RHiwJoGg`*NiQ6#RB$T#LF+>#ef;Jne&MxKPX!#r`&TVEFsp2jnNx>dClzpcPy&G&13a_<0qaR3i+k212~hoQ z8nMk{JP-t04I{GW5gUBqcJW-jSMrlw}>p)ptx?WKuCUV77taMiV zHok9V=6yv+Uts@fMY&A}amC=!Yj}eL@=e%XJ#%?agkt1jWF+10{(E9mHLDa>Ll7Vj zG=3cp%ljIB-6pC}6&`xJ*6WCP|IlglLWJ^?yviI8Ve)?V_i4%n;olzny62_`-|IGi z^=}p_O>Z8M;c4|RExu70E7ePW(HWVS&E$+LL6xSQgB`QfMQJ|4pCTFowA39p5P-|$ zUtM_H2HnP8_RoS~Vwk(FhbG zH41licj%=0a;Ln2STFBvU}Ne&O&%8bYKj!h1FA#sNM`232fX|U3QPp#3C?mN2;hE9 z;)!@5ixSPl<89^7gwhHc2YAX1KJK$#*3`KOMIQ253q7-*RJ5k)zp9GBO|Ga~X*^}US5oN@aG&waHV%vi~r{t^`ptTxb zL}q1W8S7*>7oWwvgV4uFLZ(@k`R*=LO_|Gu`prs~!WQXj-NLIa^2(7IHg>BG^N zc|i{-^=&Cek9dkJFQys|sjG9i>LLz|;yCv{^1i%c*h>8zF91kLvS9HBQi~ZU!JL`B zK8N+U0fr1*6??Ium)AF!6tc1eGhXIYL6IRT7rmKp7+>?%5Pa6zC5)KY$ycF0ZJ`G5nEQDG100U-jLkH8^UE4g6wq?sg%pP=-$&G#bcN`^?w3a6 z((s$6eRKcSEIslW-kk5Qi|5Mg-(xdLF}PxxVh$PuO}#aR6pW1kV4Af!Bqh*btXNNZ z>-4(IUl+L4dw+3LcpGut=qB45O+W)Q5?*zZ2A6rJcg`qkSvWA!j^r2mqKuCm6`Py? z@^T#Ux04HemPGd!Hs7NkZdVn1}8_j`o?)*OKZGS!`ff)gF zG?v-lj$wWNWCcw2Mg2o18D~1?3_b0XzdiKBNkYSDpcv@&kp0POmweJE2ZkIQ3B!a! zIgIoE+Xv?;34kyo^QYjZk+tEqZvq^#QG(OzX4~X+KtsoQoddTWUR(yo8R+ObEF1j<-syWOb>)JQ&Zbdu(sctU%Mt zW&YR0{ttY2TTXYZ?~WNU&cES1Z2q(7SrWDh``!J(JM+Nk$!hu&Y;(7E`ZNKTe0w+% zJc?Qnw2B+%UR}0;cB0Rufa(7-3FF}?629@LgTiEC&2uyL6NxexOp?AKT^aAx3gi(W zao>r>MPw0eQ3>IV02uLsC@>yK_epX6GRg4{NEL2wPPF9=*L2RV3yyK8DhuEK>rmmV z`&Q~#c`lgR&93TdOCja|ewOXmPNRh7!&dMT(1ett#iDr8HZW~VqWW@7fe9B6;7S+? zbC`d4@MEau&mKlOPKd>*10q0c{~^baw6!a*w^sY#0Xim{oOsiXiDOhbG&kl3c$$n1 zMRrD83&QucDSEcV*7LIp8VTA@F<%qe+_c`L;6on(>SjAU^}5c9!BCffT>$VQhe=)z z8(=Ej{5>jhmjB3{xDfj2R@VmHQ!CqjlO4KnuOmvHy3K#po$yp_V;p_MKjh1`(rzj6 zHW956k1yvntz{_g?Xbs`avK(IjlTnsu%htO;D7 z?J#x^EzuvVn&NA=!MEj7cwe5A-Z$Zk2LBZH$~%E* zf`((xH0?`}hs|HA%mtwfOEsZJxxrennkTYcwP#FKO5%Lpc^JXhSpV|ZH$Wr;`}`_( zIP==gd3LYyVtwD|*ZJGi{7~x8{=^bGVqu0RJ`n_BZH9+}kz%-4ZRsImi@rx%=ZEKs zcPnUXo6hbJV>fH;@1|bAHIe0ijYI*&kdT|HkDS$9No9 zCHo=*HWb~U+Dtzxr+Esao}6@|;Pf+E$ay0$kQp#s{wlw+7aIKbMdf`OqhoG*;Tco0 zjrP}VQG#Y2cJuqoJg&5({)S(BA}q9T1lGeWRyu=Je|)I!6a+aj!IP^1({)ZYe&x6w zt3a)Dq^TB+A7CdB0-}#z2Ur$W&h3YVw8==!xONy$uQmDWh-@15iEOt!q2m&?ZLA|w z8loSb(0}7y6Xu0?M5Uf4>VZGluB`wMf2oh;m)ghxVda>3m}4%V)r^0nVQ5V6f3>*) z0&VN!N0~GC^P}vj$`EDMZEmVV;N&RISY2C;$0;2(<{Lt&PKzqRByQdiEHGAbwtbS zPj`Da5%U6k1oEtVzI}QNw;!hT6F+~|@=c@$C4NtO@=xgP?|5MyZAyuCzcvq4rdAv@C06%gZ`9%I);R6UGiGJobfux+<0DLS&|MSG4UH z_~o{^^9>ixMg~mY!-@Fai{xaE4^;qy9iZN15Gbn5ZqHWf>Jc5Rv6(#n8`1NcCsdmG zab*dSXVPaE?)wCalD;$ivF%@nB#7D`@YG04p6ed9m}4iJW|pfVMLE<-c{=-8$e?cH zUdU#mCj4gb zZKA^b9p*9S(}8@tw~1RNPHr7tQr;P+-)D8|sq=*o)G%RGqt> zzP5yf`pVxb)I51D_G~Xp^GNK zVI6sAX)a9s)e{8N3?35YA6aQTXuyszK3ah~CemzA&CII#8F&F#KN41~8I^&_%}6MCNb{W87qAF`zj_Y^szhb> z3p3}KbOxotY|(lD=;)`fYE_*{S}x;f^SW#)SU&5X#o|-R|trpa|L5PS5aa0 zTHw8%SDSVtU4?vyrhnq+^@dgFS)|(y{~(4j%3UEiO-rBM9%`)8(dh33pMLiuurNY# z#10AsQ7%*0Cu_DSAU}P;X(JwA64~Q_^R%d_zSm^6Aux?Pn70PM>9EvLeOX z&w9c)pGmcL22;MO3C_B>=NC0RJpMp8?#ZUf=GWRvy z6RHq3B}=MGVg?9@iKFBpsvnkVh3{Vpp=`CcD=u~@ql{my|6?3ssi3mCOPnjI&E}VC zc@X+Yl>;;DNo0W0`0th!X{?luDhOC{E8N=?!w}K1{V=)+1={m(f`Oc|N=07>}3;z{-(A zm{JL=j?Sro5iecmE2-pWlRf(r%|HEQ7kgwQ9+kt=NBhtQI7OwcZ#3%$Uf%^r2nhjY zoQ08MfC%_X{O9~WcirMZMhn#z^ux4Erx-tf-6bHD)9eH&^L>^jvAd^9A^DCDs?0;k zkm7LE*KjP6`2d17MrQaaLqd_Rka}J$csvUec#hw78<=s(hyR>065~YCVCA9+#Q+; za(*L0IEw!r5P|@-;x33L$Lv9 zcuN8YG&g{<(SeJG18~(b!5yywSqQiLAX0;---;}mF5&b4lg|T?LwKREa{9YX_-zL@ZE?Zqi@HxK^2KO1>0LATu{te=T zprmHtY)bDVfxI1S}KBE7V zznP7KQ8HekWU#W6mw`dr-boV}pMQR==&5=Q5T=_q091jfc;R*jX#&=MQ%~@E@9^?`$v48ks<>(fI(F6L(5ppKy|$HWng*bKOb(4|cMUB&z$#ob#XV z5-mg)gmFIybZf=znm3ZPyUO^GJfxt0kmHjaTZ|sthsxXw&}Y)fOUSg=JhRSR^UjZ- zhqqb}Wsyw4zdnj6@#BAJa#-PdI4_dgafFXh85DsEQ_cT+5)XpZq$fZlBA_9UsE9r6 zEFec5?uqN@QhJ^IzwZrwl-5J`CmVPv{(YDTqEqWR^dI;5hXc~cxP%B3v&~s0`Ct89 z@S`i~a^c%V^N81dDT*ItFS*&IN;@O$EgzX0e7x&}TD=!zS}hTpezBLS>mdX(5< z)8DEI(-o_D)c-UX@dA1MuJ*yc>Hf4|`*B2S_O>w*-tbUwtiu`;W(Ud{HTty@(&x(T(F&;M zJ=?H>6`B7nf-90e8V`WSVp|0oEKB-P2M{}4ZDawzvM&a!y>`Y#jCsD%T_l``@ah(I2nJs~Q|%uSKu@k!m~*8B*IoA{*TgtF<(5sHCGG;n@NE%~Xt(G$^&<87u;}Na zx-8cq0g`uA(&RBFo=-4Y1GUZ<``Zw{xL4jfHkZw~%~wvtGueszcXt)_QwH8g!; z%s&3kSa~R$dO$-%L-)c@_hi7&>{6L_M>OZFkUQu;{sL_bUMStNrt{{&O(Wn~*zPOk zB>dnfszb29NSTf2pqIs68k|p-UrSrxgLHqi?3N-UFa!LHy9n1)=s>`yS+J{MEzS@ zNlfGtpma7kG&LR3JE@wB%rFA*h~~KitlO=IP)ZjN6dQLM6qsry zHkB#cyNh#n`)}bCrN1My*;k)^@>e4gJ`LJK?2)Pwp?4Tl4)4FA0(tvY+#1jOUM)xw zlMz4x-f@g^+yKUN`?Vu)|AwujArnM~Pa@y*Q9S8eS(u{-S%(Z5=R~pRl5ZGDjdqH% zC8rW&{##wOpU_oTIG4WXMk4&%2t1;lWcW5&!yxmOT*!hBcKyTqEcNoO+R2;Q?Yj+W z1-Y4?59fijz4(MIDwGe4-baYf08UCs;r|YefD-Md2ST;=cxwpgW=tR76-dQVAhn^= zG9Wk5lQk%jIR@KNU!UMp6@BfU;r+;y4VQ)D2!Il9HX%yW-9nOzV+m$YKzVaO`B8S7t z$!S2Mz`xw>V(RjE`0>bQp<0y&h~Y=M#jpy!#=dE>`=e_AjSZq6u!Dy1xJf~-7|0F! zPR9|n`e_7D2DIV2H(CESQ}hA>U>n|6`%z?YKEA~)BOVY%y=jPV zT=44R!L?J)736X#csn|lfBJ)o8ixaZclguWgrGO<`TN2FMfO}7;5}d+BlK0yTSH3* z4!=;5rOh85&2|x=46hkNaz?)U8&=bcfh=N_#8BNpZ2v$aVBo;sk^*X`v;4-LU;D>! zM*h12MxXIQy)SfAqE4;jY)wgnppazZkdNNVVF;(PLf^qK$FgY9+VFyBKE7UC|f z`R|?&egV11K3s$rJ6!GvoeW=jV*!-e(wA;x(2=d0E_e_%0x--0o8#~m^H1%AH5Z^B zn!TNPn927*bvaf0pt}zhK0o^V@WlGwwKo(*nQ|Q~4_;>~-8y20`HP>@UJa)3nEnGG z5Hwhs|FcmFG16ZVNb5hL`2Gc1{zWIMM{_OiKewV!hCi}U!VuE?s9wU-QbZ!)+Y^tS zGzp5OSi5iq6hmEr$w}&9DFgoB+i*`q`8TBi^MVS{SKEb8Aw%@K7@XCo(De2A`6%mf&a2#~y1N)+kJLD$1HCP!22)(U}xo2|j?WRzt(11j8Z_*v;P$R+Ug*Gy3VxV4K; zGGUGabnW*`Z}~`ydXL-l9e=GC$pY#z|63vy>E*m=$=j}iWP{sRTh0%H54`t>2xYH% zsk+M&u&pNgMCM@3e)Xc?jBWX-TIR_cQ1Z!RW7!B zBjZX=+^3}?SE)B+$EP+0oi1Fp5blDT?*}nsP>filqXH{ms zxU<$hetC`u)Wi+x|EKL-`y^#aQX+sDYIa{M;V%LqLrOk~lR>u0Q!+pyQSU4zY`?E^ z|5@)C)w6G_=i5YYC5SE_u(7hDNYr}uKT|@DSqF%S++lTIbIk^$a>{~0IH8KNFEy%+ zW#$&!ynpgNJh>6uR~?2c)ZMW+h0OKu231(7L_vETPaR+(P)Zy%0~yGm>E9?@@x!Jy z3PYgS}Q@b}x}E#F27@F+j}0=&Ql4gES&f8acMrPAVlVs9$97`FR))R5wI zc&}KFI1UIewh>3PkhnB7u zS3AT8_*|nexznG|Z*DU0c!K@jsI4J)5#DyNi#|e#`l1Vv1`1)*NVcy0LZ``aL0n8B zecupJ(rhq3u8bW0NIRhKYq$v1li+jp*4hfAd&wxYDE8vn1TQ7S@bTM|I2Ob z8vMOIxA7&_j{AKmD+O@EyXT`|dElt0pED^@IV0m)RPBUs*5jW60>>w1!@_G3aBKzG z_f(KfAPBk}-jQtR*Sroq!*3rbQ_m27e+YdzQjUb<_*k8vc_C)y!@cj5E>NxUhPu&g z@Z2<~esU`)ih+4opWe+K7sbN9n*9@n>#@n3*o z?xoROgDuvhq>jJ;Ve{6i<3roQNfgo5^4Q4(|GNExO2Dr7GjgA2zWuKp_K)K0R(6lv z!l$!zW-+T6mb3gQaAFviTQi{|*t%>{(mhTdy+y;Re4qT@kccy#{b z&zWy~kLO@>*WPj2k#H)|7L&gAJ37DmHQAme#@m;(Y8Nu^`D5vf8sZFW#+lA2!HK=( zJ)#hO6JD*`o~&c*&46d}g=Qj@SsoB5ikC z^1V8E+&<-OzuS_C`p5<<(A6fB`LXT(!kV^0_~hL6PpW4={l%|#xgdh?5EIk~lu8{D z2hiyhv3Yxij_#$Wu>P@7SYsl`-~3;}Ktx{34_NL^Kwin&=?!HDv3elQDbcU*qyYpN z(#yw~f1vFGK-t%CC-qa-4FYHbA^h>bag-I&*qaxwn?Qv|idE$<>1H|Gr6JtUu(he2$eg!N z@HTF@dG1)*y;4fxe)4_ZkpaBHH9hXp9p4|gLrRQyuevRd@gSS}JhRnWqrvm|U@>qM z=yl7RQROTKwQtzP3!zUF)_6Ld#NGA6v~2{J9Dd`h6{%+XsU#qGLh%`fB1Hc?wfayK zN`H4BpDp)npVQuu$DVW1qsBS&AJ2eP%6Qw>;k{)Z$8%HL=Q4(a$Ng2_vHw&vA!1L+9zc8vaX2GtqJ{L-;gvF0IR$em zMQ8@{Qp3+3Quk)TJ$?I<8KmwzD*7#(q<@Mc`dchngW}cRG14(Z6K7{T|LhFXwhqUQ;BET;cYqPcAcMgt6M$V9$(?jHo@Sud$an$U&5F zZ1QNh^ztt)E*d#Ij;<43oSKKnd+WNr$_r}+s_O_x6DZSB10*5Q{ourqq>mTl| zx4y^(cy+9;t@R=*j>3_dmm_m)$k$#937V(sllby&5)Xex^UD-|m|q<(jEd#@DV(of zAd7sSdmS*zUDqJ9|K%O2J2OfdUiK{{b{PCy)pi<;hp~7v1CQj&4-10 zgO<3dqhYH1#-Fa}Q{pjql5>>P6gZH21zLfxZ4$SK4T@7b!|`nWF9b*84Bq8&Eht;9 z*P72x&NUCZ7*@B$`FtE=hz5b}S`|c6Ey+j@D1ZibjJaRlR;{cxAWv z?Nqa>QqV*H-*zzaPvpLMHt~nl(x6?vrPpR?zn7~wow?oj*1TKmx4j71>$hvtC$DLD zUrz0^tiP0792U&dxJxNv@r}Elsjn^aSLUu=9#mD{&9n8|ayIL$!H3s>%KEvbchBFW z%cd?VU83mGF#Dar9*s~w&AnmQRQIOvR+uWsuZ?+|a=TzApXO@q^(r%8=}iv#wCnFq z=K9}JbqU@k99Q%j-}NNk+qLCP)jXfmOO|)@?mHcnynd6({mJisP1_}u7k)|eYHXWK z63eQ)E$ufFi!3CWUY2gw%e>omCv}qEX66aH-k&35f9`Q@Us|NPetVqe8=dX*VxJdn ze`q7b=Dn(UA(2sf&g)cOmQFhNJ#<-aMELJZbA#@to>25@kbW<)&!X01 z%NMJt>1ST)tyX)h@?`DxhbgCHr>S4wv}WC&Nw-!{+Z7$2D}74QAcXTvip=M0%Tp_N zor=k`)t|ra^ySr-+(|R9mB(E=`MX#y(wSw)$!iymzB;^c*>%&^*7HxTnRga=soSZT zdDl+9s;r!v8hk6POtzBaig4pRp7eWF(<8gufvNHPu6xs-=e{;mnHzJyGKE+8L0j}; z@%8-e^UCL5HhMiR>sD3Rve&yVZ#{Q1*CO8c+qSr^Z#CN;)(X5>tGG5yUw3<+CfhaL z%bP;hZ?jvgJU67BWyiy74_)6r)_nSxttxn0`0?HE^5(uydHVgP+HE$V?Lv)Leti43 zWA|;f-RqX``95>)^P-fw!Vi{3KNsII-*5f){gdxqd%gVdB1sOBNe=nEW%;i~g_P8J w!5uhoe-Jcg1nPN%MiEAtgE$;km@@t6ukO)1^!cY^83Pb_y85}Sb4q9e0FIsP9{>OV literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1632cfddf3d9dade342351e627a0a75609fb46 GIT binary patch literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/AppInfo.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 000000000000..62772134902e --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = pipeline_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.pipelineExample + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2026 com.example. All rights reserved. diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Debug.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 000000000000..36b0fd9464f4 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Release.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 000000000000..dff4f49561c8 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Warnings.xcconfig b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 000000000000..42bcbf4780b1 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/DebugProfile.entitlements b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 000000000000..dddb8a30c851 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Info.plist b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Info.plist new file mode 100644 index 000000000000..4789daa6a443 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/MainFlutterWindow.swift b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 000000000000..3cc05eb23491 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Release.entitlements b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Release.entitlements new file mode 100644 index 000000000000..852fa1a4728a --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/RunnerTests/RunnerTests.swift b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000000..4fc85d1c0db6 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,10 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml new file mode 100644 index 000000000000..9aea3d7d2c58 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -0,0 +1,111 @@ +name: pipeline_example +description: "A new Flutter project." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: ^3.10.0-290.4.beta + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + cloud_firestore: + path: .. + firebase_core: ^4.4.0 + flutter: + sdk: flutter + http: ^1.0.0 + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + +dependency_overrides: + _flutterfire_internals: + path: ../../../_flutterfire_internals + cloud_firestore: + path: .. + cloud_firestore_platform_interface: + path: ../../cloud_firestore_platform_interface + cloud_firestore_web: + path: ../../cloud_firestore_web + firebase_core: + path: ../../../firebase_core/firebase_core + firebase_core_platform_interface: + path: ../../../firebase_core/firebase_core_platform_interface + firebase_core_web: + path: ../../../firebase_core/firebase_core_web + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/test/widget_test.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/test/widget_test.dart new file mode 100644 index 000000000000..7cae948eade1 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/test/widget_test.dart @@ -0,0 +1,34 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:pipeline_example/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const PipelineExampleApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/test_driver/integration_test.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/test_driver/integration_test.dart new file mode 100644 index 000000000000..5366642ffab1 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/web/favicon.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-192.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 zcmZ`-2T+sGz6~)*FVZ`aW+(v>MIm&M-g^@e2u-B-DoB?qO+b1Tq<5uCCv>ESfRum& zp%X;f!~1{tzL__3=gjVJ=j=J>+nMj%ncXj1Q(b|Ckbw{Y0FWpt%4y%$uD=Z*c-x~o zE;IoE;xa#7Ll5nj-e4CuXB&G*IM~D21rCP$*xLXAK8rIMCSHuSu%bL&S3)8YI~vyp@KBu9Ph7R_pvKQ@xv>NQ`dZp(u{Z8K3yOB zn7-AR+d2JkW)KiGx0hosml;+eCXp6+w%@STjFY*CJ?udJ64&{BCbuebcuH;}(($@@ znNlgBA@ZXB)mcl9nbX#F!f_5Z=W>0kh|UVWnf!At4V*LQP%*gPdCXd6P@J4Td;!Ur z<2ZLmwr(NG`u#gDEMP19UcSzRTL@HsK+PnIXbVBT@oHm53DZr?~V(0{rsalAfwgo zEh=GviaqkF;}F_5-yA!1u3!gxaR&Mj)hLuj5Q-N-@Lra{%<4ONja8pycD90&>yMB` zchhd>0CsH`^|&TstH-8+R`CfoWqmTTF_0?zDOY`E`b)cVi!$4xA@oO;SyOjJyP^_j zx^@Gdf+w|FW@DMdOi8=4+LJl$#@R&&=UM`)G!y%6ZzQLoSL%*KE8IO0~&5XYR9 z&N)?goEiWA(YoRfT{06&D6Yuu@Qt&XVbuW@COb;>SP9~aRc+z`m`80pB2o%`#{xD@ zI3RAlukL5L>px6b?QW1Ac_0>ew%NM!XB2(H+1Y3AJC?C?O`GGs`331Nd4ZvG~bMo{lh~GeL zSL|tT*fF-HXxXYtfu5z+T5Mx9OdP7J4g%@oeC2FaWO1D{=NvL|DNZ}GO?O3`+H*SI z=grGv=7dL{+oY0eJFGO!Qe(e2F?CHW(i!!XkGo2tUvsQ)I9ev`H&=;`N%Z{L zO?vV%rDv$y(@1Yj@xfr7Kzr<~0{^T8wM80xf7IGQF_S-2c0)0D6b0~yD7BsCy+(zL z#N~%&e4iAwi4F$&dI7x6cE|B{f@lY5epaDh=2-(4N05VO~A zQT3hanGy_&p+7Fb^I#ewGsjyCEUmSCaP6JDB*=_()FgQ(-pZ28-{qx~2foO4%pM9e z*_63RT8XjgiaWY|*xydf;8MKLd{HnfZ2kM%iq}fstImB-K6A79B~YoPVa@tYN@T_$ zea+9)<%?=Fl!kd(Y!G(-o}ko28hg2!MR-o5BEa_72uj7Mrc&{lRh3u2%Y=Xk9^-qa zBPWaD=2qcuJ&@Tf6ue&)4_V*45=zWk@Z}Q?f5)*z)-+E|-yC4fs5CE6L_PH3=zI8p z*Z3!it{1e5_^(sF*v=0{`U9C741&lub89gdhKp|Y8CeC{_{wYK-LSbp{h)b~9^j!s z7e?Y{Z3pZv0J)(VL=g>l;<}xk=T*O5YR|hg0eg4u98f2IrA-MY+StQIuK-(*J6TRR z|IM(%uI~?`wsfyO6Tgmsy1b3a)j6M&-jgUjVg+mP*oTKdHg?5E`!r`7AE_#?Fc)&a z08KCq>Gc=ne{PCbRvs6gVW|tKdcE1#7C4e`M|j$C5EYZ~Y=jUtc zj`+?p4ba3uy7><7wIokM79jPza``{Lx0)zGWg;FW1^NKY+GpEi=rHJ+fVRGfXO zPHV52k?jxei_!YYAw1HIz}y8ZMwdZqU%ESwMn7~t zdI5%B;U7RF=jzRz^NuY9nM)&<%M>x>0(e$GpU9th%rHiZsIT>_qp%V~ILlyt^V`=d z!1+DX@ah?RnB$X!0xpTA0}lN@9V-ePx>wQ?-xrJr^qDlw?#O(RsXeAvM%}rg0NT#t z!CsT;-vB=B87ShG`GwO;OEbeL;a}LIu=&@9cb~Rsx(ZPNQ!NT7H{@j0e(DiLea>QD zPmpe90gEKHEZ8oQ@6%E7k-Ptn#z)b9NbD@_GTxEhbS+}Bb74WUaRy{w;E|MgDAvHw zL)ycgM7mB?XVh^OzbC?LKFMotw3r@i&VdUV%^Efdib)3@soX%vWCbnOyt@Y4swW925@bt45y0HY3YI~BnnzZYrinFy;L?2D3BAL`UQ zEj))+f>H7~g8*VuWQ83EtGcx`hun$QvuurSMg3l4IP8Fe`#C|N6mbYJ=n;+}EQm;< z!!N=5j1aAr_uEnnzrEV%_E|JpTb#1p1*}5!Ce!R@d$EtMR~%9# zd;h8=QGT)KMW2IKu_fA_>p_und#-;Q)p%%l0XZOXQicfX8M~7?8}@U^ihu;mizj)t zgV7wk%n-UOb z#!P5q?Ex+*Kx@*p`o$q8FWL*E^$&1*!gpv?Za$YO~{BHeGY*5%4HXUKa_A~~^d z=E*gf6&+LFF^`j4$T~dR)%{I)T?>@Ma?D!gi9I^HqvjPc3-v~=qpX1Mne@*rzT&Xw zQ9DXsSV@PqpEJO-g4A&L{F&;K6W60D!_vs?Vx!?w27XbEuJJP&);)^+VF1nHqHBWu z^>kI$M9yfOY8~|hZ9WB!q-9u&mKhEcRjlf2nm_@s;0D#c|@ED7NZE% zzR;>P5B{o4fzlfsn3CkBK&`OSb-YNrqx@N#4CK!>bQ(V(D#9|l!e9(%sz~PYk@8zt zPN9oK78&-IL_F zhsk1$6p;GqFbtB^ZHHP+cjMvA0(LqlskbdYE_rda>gvQLTiqOQ1~*7lg%z*&p`Ry& zRcG^DbbPj_jOKHTr8uk^15Boj6>hA2S-QY(W-6!FIq8h$<>MI>PYYRenQDBamO#Fv zAH5&ImqKBDn0v5kb|8i0wFhUBJTpT!rB-`zK)^SNnRmLraZcPYK7b{I@+}wXVdW-{Ps17qdRA3JatEd?rPV z4@}(DAMf5EqXCr4-B+~H1P#;t@O}B)tIJ(W6$LrK&0plTmnPpb1TKn3?f?Kk``?D+ zQ!MFqOX7JbsXfQrz`-M@hq7xlfNz;_B{^wbpG8des56x(Q)H)5eLeDwCrVR}hzr~= zM{yXR6IM?kXxauLza#@#u?Y|o;904HCqF<8yT~~c-xyRc0-vxofnxG^(x%>bj5r}N zyFT+xnn-?B`ohA>{+ZZQem=*Xpqz{=j8i2TAC#x-m;;mo{{sLB_z(UoAqD=A#*juZ zCv=J~i*O8;F}A^Wf#+zx;~3B{57xtoxC&j^ie^?**T`WT2OPRtC`xj~+3Kprn=rVM zVJ|h5ux%S{dO}!mq93}P+h36mZ5aZg1-?vhL$ke1d52qIiXSE(llCr5i=QUS?LIjc zV$4q=-)aaR4wsrQv}^shL5u%6;`uiSEs<1nG^?$kl$^6DL z43CjY`M*p}ew}}3rXc7Xck@k41jx}c;NgEIhKZ*jsBRZUP-x2cm;F1<5$jefl|ppO zmZd%%?gMJ^g9=RZ^#8Mf5aWNVhjAS^|DQO+q$)oeob_&ZLFL(zur$)); zU19yRm)z<4&4-M}7!9+^Wl}Uk?`S$#V2%pQ*SIH5KI-mn%i;Z7-)m$mN9CnI$G7?# zo`zVrUwoSL&_dJ92YhX5TKqaRkfPgC4=Q&=K+;_aDs&OU0&{WFH}kKX6uNQC6%oUH z2DZa1s3%Vtk|bglbxep-w)PbFG!J17`<$g8lVhqD2w;Z0zGsh-r zxZ13G$G<48leNqR!DCVt9)@}(zMI5w6Wo=N zpP1*3DI;~h2WDWgcKn*f!+ORD)f$DZFwgKBafEZmeXQMAsq9sxP9A)7zOYnkHT9JU zRA`umgmP9d6=PHmFIgx=0$(sjb>+0CHG)K@cPG{IxaJ&Ueo8)0RWgV9+gO7+Bl1(F z7!BslJ2MP*PWJ;x)QXbR$6jEr5q3 z(3}F@YO_P1NyTdEXRLU6fp?9V2-S=E+YaeLL{Y)W%6`k7$(EW8EZSA*(+;e5@jgD^I zaJQ2|oCM1n!A&-8`;#RDcZyk*+RPkn_r8?Ak@agHiSp*qFNX)&i21HE?yuZ;-C<3C zwJGd1lx5UzViP7sZJ&|LqH*mryb}y|%AOw+v)yc`qM)03qyyrqhX?ub`Cjwx2PrR! z)_z>5*!*$x1=Qa-0uE7jy0z`>|Ni#X+uV|%_81F7)b+nf%iz=`fF4g5UfHS_?PHbr zB;0$bK@=di?f`dS(j{l3-tSCfp~zUuva+=EWxJcRfp(<$@vd(GigM&~vaYZ0c#BTs z3ijkxMl=vw5AS&DcXQ%eeKt!uKvh2l3W?&3=dBHU=Gz?O!40S&&~ei2vg**c$o;i89~6DVns zG>9a*`k5)NI9|?W!@9>rzJ;9EJ=YlJTx1r1BA?H`LWijk(rTax9(OAu;q4_wTj-yj z1%W4GW&K4T=uEGb+E!>W0SD_C0RR91 literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-512.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 zcmd5=2T+s!lYZ%-(h(2@5fr2dC?F^$C=i-}R6$UX8af(!je;W5yC_|HmujSgN*6?W z3knF*TL1$|?oD*=zPbBVex*RUIKsL<(&Rj9%^UD2IK3W?2j>D?eWQgvS-HLymHo9%~|N2Q{~j za?*X-{b9JRowv_*Mh|;*-kPFn>PI;r<#kFaxFqbn?aq|PduQg=2Q;~Qc}#z)_T%x9 zE|0!a70`58wjREmAH38H1)#gof)U3g9FZ^ zF7&-0^Hy{4XHWLoC*hOG(dg~2g6&?-wqcpf{ z&3=o8vw7lMi22jCG9RQbv8H}`+}9^zSk`nlR8?Z&G2dlDy$4#+WOlg;VHqzuE=fM@ z?OI6HEJH4&tA?FVG}9>jAnq_^tlw8NbjNhfqk2rQr?h(F&WiKy03Sn=-;ZJRh~JrD zbt)zLbnabttEZ>zUiu`N*u4sfQaLE8-WDn@tHp50uD(^r-}UsUUu)`!Rl1PozAc!a z?uj|2QDQ%oV-jxUJmJycySBINSKdX{kDYRS=+`HgR2GO19fg&lZKyBFbbXhQV~v~L za^U944F1_GtuFXtvDdDNDvp<`fqy);>Vw=ncy!NB85Tw{&sT5&Ox%-p%8fTS;OzlRBwErvO+ROe?{%q-Zge=%Up|D4L#>4K@Ke=x%?*^_^P*KD zgXueMiS63!sEw@fNLB-i^F|@Oib+S4bcy{eu&e}Xvb^(mA!=U=Xr3||IpV~3K zQWzEsUeX_qBe6fky#M zzOJm5b+l;~>=sdp%i}}0h zO?B?i*W;Ndn02Y0GUUPxERG`3Bjtj!NroLoYtyVdLtl?SE*CYpf4|_${ku2s`*_)k zN=a}V8_2R5QANlxsq!1BkT6$4>9=-Ix4As@FSS;1q^#TXPrBsw>hJ}$jZ{kUHoP+H zvoYiR39gX}2OHIBYCa~6ERRPJ#V}RIIZakUmuIoLF*{sO8rAUEB9|+A#C|@kw5>u0 zBd=F!4I)Be8ycH*)X1-VPiZ+Ts8_GB;YW&ZFFUo|Sw|x~ZajLsp+_3gv((Q#N>?Jz zFBf`~p_#^${zhPIIJY~yo!7$-xi2LK%3&RkFg}Ax)3+dFCjGgKv^1;lUzQlPo^E{K zmCnrwJ)NuSaJEmueEPO@(_6h3f5mFffhkU9r8A8(JC5eOkux{gPmx_$Uv&|hyj)gN zd>JP8l2U&81@1Hc>#*su2xd{)T`Yw< zN$dSLUN}dfx)Fu`NcY}TuZ)SdviT{JHaiYgP4~@`x{&h*Hd>c3K_To9BnQi@;tuoL z%PYQo&{|IsM)_>BrF1oB~+`2_uZQ48z9!)mtUR zdfKE+b*w8cPu;F6RYJiYyV;PRBbThqHBEu_(U{(gGtjM}Zi$pL8Whx}<JwE3RM0F8x7%!!s)UJVq|TVd#hf1zVLya$;mYp(^oZQ2>=ZXU1c$}f zm|7kfk>=4KoQoQ!2&SOW5|JP1)%#55C$M(u4%SP~tHa&M+=;YsW=v(Old9L3(j)`u z2?#fK&1vtS?G6aOt@E`gZ9*qCmyvc>Ma@Q8^I4y~f3gs7*d=ATlP>1S zyF=k&6p2;7dn^8?+!wZO5r~B+;@KXFEn^&C=6ma1J7Au6y29iMIxd7#iW%=iUzq&C=$aPLa^Q zncia$@TIy6UT@69=nbty5epP>*fVW@5qbUcb2~Gg75dNd{COFLdiz3}kODn^U*=@E z0*$7u7Rl2u)=%fk4m8EK1ctR!6%Ve`e!O20L$0LkM#f+)n9h^dn{n`T*^~d+l*Qlx z$;JC0P9+en2Wlxjwq#z^a6pdnD6fJM!GV7_%8%c)kc5LZs_G^qvw)&J#6WSp< zmsd~1-(GrgjC56Pdf6#!dt^y8Rg}!#UXf)W%~PeU+kU`FeSZHk)%sFv++#Dujk-~m zFHvVJC}UBn2jN& zs!@nZ?e(iyZPNo`p1i#~wsv9l@#Z|ag3JR>0#u1iW9M1RK1iF6-RbJ4KYg?B`dET9 zyR~DjZ>%_vWYm*Z9_+^~hJ_|SNTzBKx=U0l9 z9x(J96b{`R)UVQ$I`wTJ@$_}`)_DyUNOso6=WOmQKI1e`oyYy1C&%AQU<0-`(ow)1 zT}gYdwWdm4wW6|K)LcfMe&psE0XGhMy&xS`@vLi|1#Za{D6l@#D!?nW87wcscUZgELT{Cz**^;Zb~7 z(~WFRO`~!WvyZAW-8v!6n&j*PLm9NlN}BuUN}@E^TX*4Or#dMMF?V9KBeLSiLO4?B zcE3WNIa-H{ThrlCoN=XjOGk1dT=xwwrmt<1a)mrRzg{35`@C!T?&_;Q4Ce=5=>z^*zE_c(0*vWo2_#TD<2)pLXV$FlwP}Ik74IdDQU@yhkCr5h zn5aa>B7PWy5NQ!vf7@p_qtC*{dZ8zLS;JetPkHi>IvPjtJ#ThGQD|Lq#@vE2xdl%`x4A8xOln}BiQ92Po zW;0%A?I5CQ_O`@Ad=`2BLPPbBuPUp@Hb%a_OOI}y{Rwa<#h z5^6M}s7VzE)2&I*33pA>e71d78QpF>sNK;?lj^Kl#wU7G++`N_oL4QPd-iPqBhhs| z(uVM}$ItF-onXuuXO}o$t)emBO3Hjfyil@*+GF;9j?`&67GBM;TGkLHi>@)rkS4Nj zAEk;u)`jc4C$qN6WV2dVd#q}2X6nKt&X*}I@jP%Srs%%DS92lpDY^K*Sx4`l;aql$ zt*-V{U&$DM>pdO?%jt$t=vg5|p+Rw?SPaLW zB6nvZ69$ne4Z(s$3=Rf&RX8L9PWMV*S0@R zuIk&ba#s6sxVZ51^4Kon46X^9`?DC9mEhWB3f+o4#2EXFqy0(UTc>GU| zGCJmI|Dn-dX#7|_6(fT)>&YQ0H&&JX3cTvAq(a@ydM4>5Njnuere{J8p;3?1az60* z$1E7Yyxt^ytULeokgDnRVKQw9vzHg1>X@@jM$n$HBlveIrKP5-GJq%iWH#odVwV6cF^kKX(@#%%uQVb>#T6L^mC@)%SMd4DF? zVky!~ge27>cpUP1Vi}Z32lbLV+CQy+T5Wdmva6Fg^lKb!zrg|HPU=5Qu}k;4GVH+x z%;&pN1LOce0w@9i1Mo-Y|7|z}fbch@BPp2{&R-5{GLoeu8@limQmFF zaJRR|^;kW_nw~0V^ zfTnR!Ni*;-%oSHG1yItARs~uxra|O?YJxBzLjpeE-=~TO3Dn`JL5Gz;F~O1u3|FE- zvK2Vve`ylc`a}G`gpHg58Cqc9fMoy1L}7x7T>%~b&irrNMo?np3`q;d3d;zTK>nrK zOjPS{@&74-fA7j)8uT9~*g23uGnxwIVj9HorzUX#s0pcp2?GH6i}~+kv9fWChtPa_ z@T3m+$0pbjdQw7jcnHn;Pi85hk_u2-1^}c)LNvjdam8K-XJ+KgKQ%!?2n_!#{$H|| zLO=%;hRo6EDmnOBKCL9Cg~ETU##@u^W_5joZ%Et%X_n##%JDOcsO=0VL|Lkk!VdRJ z^|~2pB@PUspT?NOeO?=0Vb+fAGc!j%Ufn-cB`s2A~W{Zj{`wqWq_-w0wr@6VrM zbzni@8c>WS!7c&|ZR$cQ;`niRw{4kG#e z70e!uX8VmP23SuJ*)#(&R=;SxGAvq|&>geL&!5Z7@0Z(No*W561n#u$Uc`f9pD70# z=sKOSK|bF~#khTTn)B28h^a1{;>EaRnHj~>i=Fnr3+Fa4 z`^+O5_itS#7kPd20rq66_wH`%?HNzWk@XFK0n;Z@Cx{kx==2L22zWH$Yg?7 zvDj|u{{+NR3JvUH({;b*$b(U5U z7(lF!1bz2%06+|-v(D?2KgwNw7( zJB#Tz+ZRi&U$i?f34m7>uTzO#+E5cbaiQ&L}UxyOQq~afbNB4EI{E04ZWg53w0A{O%qo=lF8d zf~ktGvIgf-a~zQoWf>loF7pOodrd0a2|BzwwPDV}ShauTK8*fmF6NRbO>Iw9zZU}u zw8Ya}?seBnEGQDmH#XpUUkj}N49tP<2jYwTFp!P+&Fd(%Z#yo80|5@zN(D{_pNow*&4%ql zW~&yp@scb-+Qj-EmErY+Tu=dUmf@*BoXY2&oKT8U?8?s1d}4a`Aq>7SV800m$FE~? zjmz(LY+Xx9sDX$;vU`xgw*jLw7dWOnWWCO8o|;}f>cu0Q&`0I{YudMn;P;L3R-uz# zfns_mZED_IakFBPP2r_S8XM$X)@O-xVKi4`7373Jkd5{2$M#%cRhWer3M(vr{S6>h zj{givZJ3(`yFL@``(afn&~iNx@B1|-qfYiZu?-_&Z8+R~v`d6R-}EX9IVXWO-!hL5 z*k6T#^2zAXdardU3Ao~I)4DGdAv2bx{4nOK`20rJo>rmk3S2ZDu}))8Z1m}CKigf0 z3L`3Y`{huj`xj9@`$xTZzZc3je?n^yG<8sw$`Y%}9mUsjUR%T!?k^(q)6FH6Af^b6 zlPg~IEwg0y;`t9y;#D+uz!oE4VP&Je!<#q*F?m5L5?J3i@!0J6q#eu z!RRU`-)HeqGi_UJZ(n~|PSNsv+Wgl{P-TvaUQ9j?ZCtvb^37U$sFpBrkT{7Jpd?HpIvj2!}RIq zH{9~+gErN2+}J`>Jvng2hwM`=PLNkc7pkjblKW|+Fk9rc)G1R>Ww>RC=r-|!m-u7( zc(a$9NG}w#PjWNMS~)o=i~WA&4L(YIW25@AL9+H9!?3Y}sv#MOdY{bb9j>p`{?O(P zIvb`n?_(gP2w3P#&91JX*md+bBEr%xUHMVqfB;(f?OPtMnAZ#rm5q5mh;a2f_si2_ z3oXWB?{NF(JtkAn6F(O{z@b76OIqMC$&oJ_&S|YbFJ*)3qVX_uNf5b8(!vGX19hsG z(OP>RmZp29KH9Ge2kKjKigUmOe^K_!UXP`von)PR8Qz$%=EmOB9xS(ZxE_tnyzo}7 z=6~$~9k0M~v}`w={AeqF?_)9q{m8K#6M{a&(;u;O41j)I$^T?lx5(zlebpY@NT&#N zR+1bB)-1-xj}R8uwqwf=iP1GbxBjneCC%UrSdSxK1vM^i9;bUkS#iRZw2H>rS<2<$ zNT3|sDH>{tXb=zq7XZi*K?#Zsa1h1{h5!Tq_YbKFm_*=A5-<~j63he;4`77!|LBlo zR^~tR3yxcU=gDFbshyF6>o0bdp$qmHS7D}m3;^QZq9kBBU|9$N-~oU?G5;jyFR7>z hN`IR97YZXIo@y!QgFWddJ3|0`sjFx!m))><{BI=FK%f8s literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-maskable-192.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 zcmdT|`#%%j|KDb2V@0DPm$^(Lx5}lO%Yv(=e*7hl@QqKS50#~#^IQPxBmuh|i9sXnt4ch@VT0F7% zMtrs@KWIOo+QV@lSs66A>2pz6-`9Jk=0vv&u?)^F@HZ)-6HT=B7LF;rdj zskUyBfbojcX#CS>WrIWo9D=DIwcXM8=I5D{SGf$~=gh-$LwY?*)cD%38%sCc?5OsX z-XfkyL-1`VavZ?>(pI-xp-kYq=1hsnyP^TLb%0vKRSo^~r{x?ISLY1i7KjSp z*0h&jG(Rkkq2+G_6eS>n&6>&Xk+ngOMcYrk<8KrukQHzfx675^^s$~<@d$9X{VBbg z2Fd4Z%g`!-P}d#`?B4#S-9x*eNlOVRnDrn#jY@~$jfQ-~3Od;A;x-BI1BEDdvr`pI z#D)d)!2_`GiZOUu1crb!hqH=ezs0qk<_xDm_Kkw?r*?0C3|Io6>$!kyDl;eH=aqg$B zsH_|ZD?jP2dc=)|L>DZmGyYKa06~5?C2Lc0#D%62p(YS;%_DRCB1k(+eLGXVMe+=4 zkKiJ%!N6^mxqM=wq`0+yoE#VHF%R<{mMamR9o_1JH8jfnJ?NPLs$9U!9!dq8 z0B{dI2!M|sYGH&9TAY34OlpIsQ4i5bnbG>?cWwat1I13|r|_inLE?FS@Hxdxn_YZN z3jfUO*X9Q@?HZ>Q{W0z60!bbGh557XIKu1?)u|cf%go`pwo}CD=0tau-}t@R2OrSH zQzZr%JfYa`>2!g??76=GJ$%ECbQh7Q2wLRp9QoyiRHP7VE^>JHm>9EqR3<$Y=Z1K^SHuwxCy-5@z3 zVM{XNNm}yM*pRdLKp??+_2&!bp#`=(Lh1vR{~j%n;cJv~9lXeMv)@}Odta)RnK|6* zC+IVSWumLo%{6bLDpn)Gz>6r&;Qs0^+Sz_yx_KNz9Dlt^ax`4>;EWrIT#(lJ_40<= z750fHZ7hI{}%%5`;lwkI4<_FJw@!U^vW;igL0k+mK)-j zYuCK#mCDK3F|SC}tC2>m$ZCqNB7ac-0UFBJ|8RxmG@4a4qdjvMzzS&h9pQmu^x&*= zGvapd1#K%Da&)8f?<9WN`2H^qpd@{7In6DNM&916TRqtF4;3`R|Nhwbw=(4|^Io@T zIjoR?tB8d*sO>PX4vaIHF|W;WVl6L1JvSmStgnRQq zTX4(>1f^5QOAH{=18Q2Vc1JI{V=yOr7yZJf4Vpfo zeHXdhBe{PyY;)yF;=ycMW@Kb>t;yE>;f79~AlJ8k`xWucCxJfsXf2P72bAavWL1G#W z;o%kdH(mYCM{$~yw4({KatNGim49O2HY6O07$B`*K7}MvgI=4x=SKdKVb8C$eJseA$tmSFOztFd*3W`J`yIB_~}k%Sd_bPBK8LxH)?8#jM{^%J_0|L z!gFI|68)G}ex5`Xh{5pB%GtlJ{Z5em*e0sH+sU1UVl7<5%Bq+YrHWL7?X?3LBi1R@_)F-_OqI1Zv`L zb6^Lq#H^2@d_(Z4E6xA9Z4o3kvf78ZDz!5W1#Mp|E;rvJz&4qj2pXVxKB8Vg0}ek%4erou@QM&2t7Cn5GwYqy%{>jI z)4;3SAgqVi#b{kqX#$Mt6L8NhZYgonb7>+r#BHje)bvaZ2c0nAvrN3gez+dNXaV;A zmyR0z@9h4@6~rJik-=2M-T+d`t&@YWhsoP_XP-NsVO}wmo!nR~QVWU?nVlQjNfgcTzE-PkfIX5G z1?&MwaeuzhF=u)X%Vpg_e@>d2yZwxl6-r3OMqDn8_6m^4z3zG##cK0Fsgq8fcvmhu z{73jseR%X%$85H^jRAcrhd&k!i^xL9FrS7qw2$&gwAS8AfAk#g_E_tP;x66fS`Mn@SNVrcn_N;EQm z`Mt3Z%rw%hDqTH-s~6SrIL$hIPKL5^7ejkLTBr46;pHTQDdoErS(B>``t;+1+M zvU&Se9@T_BeK;A^p|n^krIR+6rH~BjvRIugf`&EuX9u69`9C?9ANVL8l(rY6#mu^i z=*5Q)-%o*tWl`#b8p*ZH0I}hn#gV%|jt6V_JanDGuekR*-wF`u;amTCpGG|1;4A5$ zYbHF{?G1vv5;8Ph5%kEW)t|am2_4ik!`7q{ymfHoe^Z99c|$;FAL+NbxE-_zheYbV z3hb0`uZGTsgA5TG(X|GVDSJyJxsyR7V5PS_WSnYgwc_D60m7u*x4b2D79r5UgtL18 zcCHWk+K6N1Pg2c;0#r-)XpwGX?|Iv)^CLWqwF=a}fXUSM?n6E;cCeW5ER^om#{)Jr zJR81pkK?VoFm@N-s%hd7@hBS0xuCD0-UDVLDDkl7Ck=BAj*^ps`393}AJ+Ruq@fl9 z%R(&?5Nc3lnEKGaYMLmRzKXow1+Gh|O-LG7XiNxkG^uyv zpAtLINwMK}IWK65hOw&O>~EJ}x@lDBtB`yKeV1%GtY4PzT%@~wa1VgZn7QRwc7C)_ zpEF~upeDRg_<#w=dLQ)E?AzXUQpbKXYxkp>;c@aOr6A|dHA?KaZkL0svwB^U#zmx0 zzW4^&G!w7YeRxt<9;d@8H=u(j{6+Uj5AuTluvZZD4b+#+6Rp?(yJ`BC9EW9!b&KdPvzJYe5l7 zMJ9aC@S;sA0{F0XyVY{}FzW0Vh)0mPf_BX82E+CD&)wf2!x@{RO~XBYu80TONl3e+ zA7W$ra6LcDW_j4s-`3tI^VhG*sa5lLc+V6ONf=hO@q4|p`CinYqk1Ko*MbZ6_M05k zSwSwkvu;`|I*_Vl=zPd|dVD0lh&Ha)CSJJvV{AEdF{^Kn_Yfsd!{Pc1GNgw}(^~%)jk5~0L~ms|Rez1fiK~s5t(p1ci5Gq$JC#^JrXf?8 z-Y-Zi_Hvi>oBzV8DSRG!7dm|%IlZg3^0{5~;>)8-+Nk&EhAd(}s^7%MuU}lphNW9Q zT)DPo(ob{tB7_?u;4-qGDo!sh&7gHaJfkh43QwL|bbFVi@+oy;i;M zM&CP^v~lx1U`pi9PmSr&Mc<%HAq0DGH?Ft95)WY`P?~7O z`O^Nr{Py9M#Ls4Y7OM?e%Y*Mvrme%=DwQaye^Qut_1pOMrg^!5u(f9p(D%MR%1K>% zRGw%=dYvw@)o}Fw@tOtPjz`45mfpn;OT&V(;z75J*<$52{sB65$gDjwX3Xa!x_wE- z!#RpwHM#WrO*|~f7z}(}o7US(+0FYLM}6de>gQdtPazXz?OcNv4R^oYLJ_BQOd_l172oSK$6!1r@g+B@0ofJ4*{>_AIxfe-#xp>(1 z@Y3Nfd>fmqvjL;?+DmZk*KsfXJf<%~(gcLwEez%>1c6XSboURUh&k=B)MS>6kw9bY z{7vdev7;A}5fy*ZE23DS{J?8at~xwVk`pEwP5^k?XMQ7u64;KmFJ#POzdG#np~F&H ze-BUh@g54)dsS%nkBb}+GuUEKU~pHcYIg4vSo$J(J|U36bs0Use+3A&IMcR%6@jv$ z=+QI+@wW@?iu}Hpyzlvj-EYeop{f65GX0O%>w#0t|V z1-svWk`hU~m`|O$kw5?Yn5UhI%9P-<45A(v0ld1n+%Ziq&TVpBcV9n}L9Tus-TI)f zd_(g+nYCDR@+wYNQm1GwxhUN4tGMLCzDzPqY$~`l<47{+l<{FZ$L6(>J)|}!bi<)| zE35dl{a2)&leQ@LlDxLQOfUDS`;+ZQ4ozrleQwaR-K|@9T{#hB5Z^t#8 zC-d_G;B4;F#8A2EBL58s$zF-=SCr`P#z zNCTnHF&|X@q>SkAoYu>&s9v@zCpv9lLSH-UZzfhJh`EZA{X#%nqw@@aW^vPcfQrlPs(qQxmC|4tp^&sHy!H!2FH5eC{M@g;ElWNzlb-+ zxpfc0m4<}L){4|RZ>KReag2j%Ot_UKkgpJN!7Y_y3;Ssz{9 z!K3isRtaFtQII5^6}cm9RZd5nTp9psk&u1C(BY`(_tolBwzV_@0F*m%3G%Y?2utyS zY`xM0iDRT)yTyYukFeGQ&W@ReM+ADG1xu@ruq&^GK35`+2r}b^V!m1(VgH|QhIPDE X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-maskable-512.png b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 zcmeFZ_gj-)&^4Nb2tlbLMU<{!p(#yjqEe+=0IA_oih%ScH9@5#MNp&}Y#;;(h=A0@ zh7{>lT2MkSQ344eAvrhici!td|HJuyvJm#Y_w1Q9Yu3!26dNlO-oxUDK_C#XnW^Co z5C{VN6#{~B0)K2j7}*1Xq(Nqemv23A-6&=ZpEijkVnSwVGqLv40?n0=p;k3-U5e5+ z+z3>aS`u9DS=!wg8ROu?X4TFoW6CFLL&{GzoVT)ldhLekLM|+j3tIxRd|*5=c{=s&*vfPdBr(Fyj(v@%eQj1Soy7m4^@VRl1~@-PV7y+c!xz$8436WBn$t{=}mEdK#k`aystimGgI{(IBx$!pAwFoE9Y`^t^;> zKAD)C(Dl^s%`?q5$P|fZf8Xymrtu^Pv(7D`rn>Z-w$Ahs!z9!94WNVxrJuXfHAaxg zC6s@|Z1$7R$(!#t%Jb{{s6(Y?NoQXDYq)!}X@jKPhe`{9KQ@sAU8y-5`xt?S9$jKH zoi}6m5PcG*^{kjvt+kwPpyQzVg4o)a>;LK`aaN2x4@itBD3Aq?yWTM20VRn1rrd+2 zKO=P0rMjEGq_UqpMa`~7B|p?xAN1SCoCp}QxAv8O`jLJ5CVh@umR%c%i^)6!o+~`F zaalSTQcl5iwOLC&H)efzd{8(88mo`GI(56T<(&p7>Qd^;R1hn1Y~jN~tApaL8>##U zd65bo8)79CplWxr#z4!6HvLz&N7_5AN#x;kLG?zQ(#p|lj<8VUlKY=Aw!ATqeL-VG z42gA!^cMNPj>(`ZMEbCrnkg*QTsn*u(nQPWI9pA{MQ=IsPTzd7q5E#7+z>Ch=fx$~ z;J|?(5jTo5UWGvsJa(Sx0?S#56+8SD!I^tftyeh_{5_31l6&Hywtn`bbqYDqGZXI( zCG7hBgvksX2ak8+)hB4jnxlO@A32C_RM&g&qDSb~3kM&)@A_j1*oTO@nicGUyv+%^ z=vB)4(q!ykzT==Z)3*3{atJ5}2PV*?Uw+HhN&+RvKvZL3p9E?gHjv{6zM!A|z|UHK z-r6jeLxbGn0D@q5aBzlco|nG2tr}N@m;CJX(4#Cn&p&sLKwzLFx1A5izu?X_X4x8r@K*d~7>t1~ zDW1Mv5O&WOxbzFC`DQ6yNJ(^u9vJdj$fl2dq`!Yba_0^vQHXV)vqv1gssZYzBct!j zHr9>ydtM8wIs}HI4=E}qAkv|BPWzh3^_yLH(|kdb?x56^BlDC)diWyPd*|f!`^12_U>TD^^94OCN0lVv~Sgvs94ecpE^}VY$w`qr_>Ue zTfH~;C<3H<0dS5Rkf_f@1x$Gms}gK#&k()IC0zb^QbR!YLoll)c$Agfi6MKI0dP_L z=Uou&u~~^2onea2%XZ@>`0x^L8CK6=I{ge;|HXMj)-@o~h&O{CuuwBX8pVqjJ*o}5 z#8&oF_p=uSo~8vn?R0!AMWvcbZmsrj{ZswRt(aEdbi~;HeVqIe)-6*1L%5u$Gbs}| zjFh?KL&U(rC2izSGtwP5FnsR@6$-1toz?RvLD^k~h9NfZgzHE7m!!7s6(;)RKo2z} zB$Ci@h({l?arO+vF;s35h=|WpefaOtKVx>l399}EsX@Oe3>>4MPy%h&^3N_`UTAHJ zI$u(|TYC~E4)|JwkWW3F!Tib=NzjHs5ii2uj0^m|Qlh-2VnB#+X~RZ|`SA*}}&8j9IDv?F;(Y^1=Z0?wWz;ikB zewU>MAXDi~O7a~?jx1x=&8GcR-fTp>{2Q`7#BE#N6D@FCp`?ht-<1|y(NArxE_WIu zP+GuG=Qq>SHWtS2M>34xwEw^uvo4|9)4s|Ac=ud?nHQ>ax@LvBqusFcjH0}{T3ZPQ zLO1l<@B_d-(IS682}5KA&qT1+{3jxKolW+1zL4inqBS-D>BohA!K5++41tM@ z@xe<-qz27}LnV#5lk&iC40M||JRmZ*A##K3+!j93eouU8@q-`W0r%7N`V$cR&JV;iX(@cS{#*5Q>~4BEDA)EikLSP@>Oo&Bt1Z~&0d5)COI%3$cLB_M?dK# z{yv2OqW!al-#AEs&QFd;WL5zCcp)JmCKJEdNsJlL9K@MnPegK23?G|O%v`@N{rIRa zi^7a}WBCD77@VQ-z_v{ZdRsWYrYgC$<^gRQwMCi6);%R~uIi31OMS}=gUTE(GKmCI z$zM>mytL{uNN+a&S38^ez(UT=iSw=l2f+a4)DyCA1Cs_N-r?Q@$3KTYosY!;pzQ0k zzh1G|kWCJjc(oZVBji@kN%)UBw(s{KaYGy=i{g3{)Z+&H8t2`^IuLLKWT6lL<-C(! zSF9K4xd-|VO;4}$s?Z7J_dYqD#Mt)WCDnsR{Kpjq275uUq6`v0y*!PHyS(}Zmv)_{>Vose9-$h8P0|y;YG)Bo}$(3Z%+Gs0RBmFiW!^5tBmDK-g zfe5%B*27ib+7|A*Fx5e)2%kIxh7xWoc3pZcXS2zik!63lAG1;sC1ja>BqH7D zODdi5lKW$$AFvxgC-l-)!c+9@YMC7a`w?G(P#MeEQ5xID#<}W$3bSmJ`8V*x2^3qz zVe<^^_8GHqYGF$nIQm0Xq2kAgYtm#UC1A(=&85w;rmg#v906 zT;RyMgbMpYOmS&S9c38^40oUp?!}#_84`aEVw;T;r%gTZkWeU;;FwM@0y0adt{-OK z(vGnPSlR=Nv2OUN!2=xazlnHPM9EWxXg2EKf0kI{iQb#FoP>xCB<)QY>OAM$Dcdbm zU6dU|%Mo(~avBYSjRc13@|s>axhrPl@Sr81{RSZUdz4(=|82XEbV*JAX6Lfbgqgz584lYgi0 z2-E{0XCVON$wHfvaLs;=dqhQJ&6aLn$D#0i(FkAVrXG9LGm3pSTf&f~RQb6|1_;W> z?n-;&hrq*~L=(;u#jS`*Yvh@3hU-33y_Kv1nxqrsf>pHVF&|OKkoC)4DWK%I!yq?P z=vXo8*_1iEWo8xCa{HJ4tzxOmqS0&$q+>LroMKI*V-rxhOc%3Y!)Y|N6p4PLE>Yek>Y(^KRECg8<|%g*nQib_Yc#A5q8Io z6Ig&V>k|~>B6KE%h4reAo*DfOH)_01tE0nWOxX0*YTJgyw7moaI^7gW*WBAeiLbD?FV9GSB zPv3`SX*^GRBM;zledO`!EbdBO_J@fEy)B{-XUTVQv}Qf~PSDpK9+@I`7G7|>Dgbbu z_7sX9%spVo$%qwRwgzq7!_N;#Td08m5HV#?^dF-EV1o)Q=Oa+rs2xH#g;ykLbwtCh znUnA^dW!XjspJ;otq$yV@I^s9Up(5k7rqhQd@OLMyyxVLj_+$#Vc*}Usevp^I(^vH zmDgHc0VMme|K&X?9&lkN{yq_(If)O`oUPW8X}1R5pSVBpfJe0t{sPA(F#`eONTh_) zxeLqHMfJX#?P(@6w4CqRE@Eiza; z;^5)Kk=^5)KDvd9Q<`=sJU8rjjxPmtWMTmzcH={o$U)j=QBuHarp?=}c??!`3d=H$nrJMyr3L-& zA#m?t(NqLM?I3mGgWA_C+0}BWy3-Gj7bR+d+U?n*mN$%5P`ugrB{PeV>jDUn;eVc- zzeMB1mI4?fVJatrNyq|+zn=!AiN~<}eoM#4uSx^K?Iw>P2*r=k`$<3kT00BE_1c(02MRz4(Hq`L^M&xt!pV2 zn+#U3@j~PUR>xIy+P>51iPayk-mqIK_5rlQMSe5&tDkKJk_$i(X&;K(11YGpEc-K= zq4Ln%^j>Zi_+Ae9eYEq_<`D+ddb8_aY!N;)(&EHFAk@Ekg&41ABmOXfWTo)Z&KotA zh*jgDGFYQ^y=m)<_LCWB+v48DTJw*5dwMm_YP0*_{@HANValf?kV-Ic3xsC}#x2h8 z`q5}d8IRmqWk%gR)s~M}(Qas5+`np^jW^oEd-pzERRPMXj$kS17g?H#4^trtKtq;C?;c ztd|%|WP2w2Nzg@)^V}!Gv++QF2!@FP9~DFVISRW6S?eP{H;;8EH;{>X_}NGj^0cg@ z!2@A>-CTcoN02^r6@c~^QUa={0xwK0v4i-tQ9wQq^=q*-{;zJ{Qe%7Qd!&X2>rV@4 z&wznCz*63_vw4>ZF8~%QCM?=vfzW0r_4O^>UA@otm_!N%mH)!ERy&b!n3*E*@?9d^ zu}s^By@FAhG(%?xgJMuMzuJw2&@$-oK>n z=UF}rt%vuaP9fzIFCYN-1&b#r^Cl6RDFIWsEsM|ROf`E?O(cy{BPO2Ie~kT+^kI^i zp>Kbc@C?}3vy-$ZFVX#-cx)Xj&G^ibX{pWggtr(%^?HeQL@Z( zM-430g<{>vT*)jK4aY9(a{lSy{8vxLbP~n1MXwM527ne#SHCC^F_2@o`>c>>KCq9c(4c$VSyMl*y3Nq1s+!DF| z^?d9PipQN(mw^j~{wJ^VOXDCaL$UtwwTpyv8IAwGOg<|NSghkAR1GSNLZ1JwdGJYm zP}t<=5=sNNUEjc=g(y)1n5)ynX(_$1-uGuDR*6Y^Wgg(LT)Jp><5X|}bt z_qMa&QP?l_n+iVS>v%s2Li_;AIeC=Ca^v1jX4*gvB$?H?2%ndnqOaK5-J%7a} zIF{qYa&NfVY}(fmS0OmXA70{znljBOiv5Yod!vFU{D~*3B3Ka{P8?^ zfhlF6o7aNT$qi8(w<}OPw5fqA7HUje*r*Oa(YV%*l0|9FP9KW@U&{VSW{&b0?@y)M zs%4k1Ax;TGYuZ9l;vP5@?3oQsp3)rjBeBvQQ>^B;z5pc=(yHhHtq6|0m(h4envn_j787fizY@V`o(!SSyE7vlMT zbo=Z1c=atz*G!kwzGB;*uPL$Ei|EbZLh8o+1BUMOpnU(uX&OG1MV@|!&HOOeU#t^x zr9=w2ow!SsTuJWT7%Wmt14U_M*3XiWBWHxqCVZI0_g0`}*^&yEG9RK9fHK8e+S^m? zfCNn$JTswUVbiC#>|=wS{t>-MI1aYPLtzO5y|LJ9nm>L6*wpr_m!)A2Fb1RceX&*|5|MwrvOk4+!0p99B9AgP*9D{Yt|x=X}O% zgIG$MrTB=n-!q%ROT|SzH#A$Xm;|ym)0>1KR}Yl0hr-KO&qMrV+0Ej3d@?FcgZ+B3 ztEk16g#2)@x=(ko8k7^Tq$*5pfZHC@O@}`SmzT1(V@x&NkZNM2F#Q-Go7-uf_zKC( zB(lHZ=3@dHaCOf6C!6i8rDL%~XM@rVTJbZL09?ht@r^Z_6x}}atLjvH^4Vk#Ibf(^LiBJFqorm?A=lE zzFmwvp4bT@Nv2V>YQT92X;t9<2s|Ru5#w?wCvlhcHLcsq0TaFLKy(?nzezJ>CECqj zggrI~Hd4LudM(m{L@ezfnpELsRFVFw>fx;CqZtie`$BXRn#Ns%AdoE$-Pf~{9A8rV zf7FbgpKmVzmvn-z(g+&+-ID=v`;6=)itq8oM*+Uz**SMm_{%eP_c0{<%1JGiZS19o z@Gj7$Se~0lsu}w!%;L%~mIAO;AY-2i`9A*ZfFs=X!LTd6nWOZ7BZH2M{l2*I>Xu)0 z`<=;ObglnXcVk!T>e$H?El}ra0WmPZ$YAN0#$?|1v26^(quQre8;k20*dpd4N{i=b zuN=y}_ew9SlE~R{2+Rh^7%PA1H5X(p8%0TpJ=cqa$65XL)$#ign-y!qij3;2>j}I; ziO@O|aYfn&up5F`YtjGw68rD3{OSGNYmBnl?zdwY$=RFsegTZ=kkzRQ`r7ZjQP!H( zp4>)&zf<*N!tI00xzm-ME_a{_I!TbDCr;8E;kCH4LlL-tqLxDuBn-+xgPk37S&S2^ z2QZumkIimwz!c@!r0)j3*(jPIs*V!iLTRl0Cpt_UVNUgGZzdvs0(-yUghJfKr7;=h zD~y?OJ-bWJg;VdZ^r@vlDoeGV&8^--!t1AsIMZ5S440HCVr%uk- z2wV>!W1WCvFB~p$P$$_}|H5>uBeAe>`N1FI8AxM|pq%oNs;ED8x+tb44E) zTj{^fbh@eLi%5AqT?;d>Es5D*Fi{Bpk)q$^iF!!U`r2hHAO_?#!aYmf>G+jHsES4W zgpTKY59d?hsb~F0WE&dUp6lPt;Pm zcbTUqRryw^%{ViNW%Z(o8}dd00H(H-MmQmOiTq{}_rnwOr*Ybo7*}3W-qBT!#s0Ie z-s<1rvvJx_W;ViUD`04%1pra*Yw0BcGe)fDKUK8aF#BwBwMPU;9`!6E(~!043?SZx z13K%z@$$#2%2ovVlgFIPp7Q6(vO)ud)=*%ZSucL2Dh~K4B|%q4KnSpj#n@(0B})!9 z8p*hY@5)NDn^&Pmo;|!>erSYg`LkO?0FB@PLqRvc>4IsUM5O&>rRv|IBRxi(RX(gJ ztQ2;??L~&Mv;aVr5Q@(?y^DGo%pO^~zijld41aA0KKsy_6FeHIn?fNHP-z>$OoWer zjZ5hFQTy*-f7KENRiCE$ZOp4|+Wah|2=n@|W=o}bFM}Y@0e62+_|#fND5cwa3;P{^pEzlJbF1Yq^}>=wy8^^^$I2M_MH(4Dw{F6hm+vrWV5!q;oX z;tTNhz5`-V={ew|bD$?qcF^WPR{L(E%~XG8eJx(DoGzt2G{l8r!QPJ>kpHeOvCv#w zr=SSwMDaUX^*~v%6K%O~i)<^6`{go>a3IdfZ8hFmz&;Y@P%ZygShQZ2DSHd`m5AR= zx$wWU06;GYwXOf(%MFyj{8rPFXD};JCe85Bdp4$YJ2$TzZ7Gr#+SwCvBI1o$QP0(c zy`P51FEBV2HTisM3bHqpmECT@H!Y2-bv2*SoSPoO?wLe{M#zDTy@ujAZ!Izzky~3k zRA1RQIIoC*Mej1PH!sUgtkR0VCNMX(_!b65mo66iM*KQ7xT8t2eev$v#&YdUXKwGm z7okYAqYF&bveHeu6M5p9xheRCTiU8PFeb1_Rht0VVSbm%|1cOVobc8mvqcw!RjrMRM#~=7xibH&Fa5Imc|lZ{eC|R__)OrFg4@X_ ze+kk*_sDNG5^ELmHnZ7Ue?)#6!O)#Nv*Dl2mr#2)w{#i-;}0*_h4A%HidnmclH#;Q zmQbq+P4DS%3}PpPm7K_K3d2s#k~x+PlTul7+kIKol0@`YN1NG=+&PYTS->AdzPv!> zQvzT=)9se*Jr1Yq+C{wbK82gAX`NkbXFZ)4==j4t51{|-v!!$H8@WKA={d>CWRW+g z*`L>9rRucS`vbXu0rzA1#AQ(W?6)}1+oJSF=80Kf_2r~Qm-EJ6bbB3k`80rCv(0d` zvCf3;L2ovYG_TES%6vSuoKfIHC6w;V31!oqHM8-I8AFzcd^+_86!EcCOX|Ta9k1!s z_Vh(EGIIsI3fb&dF$9V8v(sTBC%!#<&KIGF;R+;MyC0~}$gC}}= zR`DbUVc&Bx`lYykFZ4{R{xRaUQkWCGCQlEc;!mf=+nOk$RUg*7 z;kP7CVLEc$CA7@6VFpsp3_t~m)W0aPxjsA3e5U%SfY{tp5BV5jH-5n?YX7*+U+Zs%LGR>U- z!x4Y_|4{gx?ZPJobISy991O znrmrC3otC;#4^&Rg_iK}XH(XX+eUHN0@Oe06hJk}F?`$)KmH^eWz@@N%wEc)%>?Ft z#9QAroDeyfztQ5Qe{m*#R#T%-h*&XvSEn@N$hYRTCMXS|EPwzF3IIysD2waj`vQD{ zv_#^Pgr?s~I*NE=acf@dWVRNWTr(GN0wrL)Z2=`Dr>}&ZDNX|+^Anl{Di%v1Id$_p zK5_H5`RDjJx`BW7hc85|> zHMMsWJ4KTMRHGu+vy*kBEMjz*^K8VtU=bXJYdhdZ-?jTXa$&n)C?QQIZ7ln$qbGlr zS*TYE+ppOrI@AoPP=VI-OXm}FzgXRL)OPvR$a_=SsC<3Jb+>5makX|U!}3lx4tX&L z^C<{9TggZNoeX!P1jX_K5HkEVnQ#s2&c#umzV6s2U-Q;({l+j^?hi7JnQ7&&*oOy9 z(|0asVTWUCiCnjcOnB2pN0DpuTglKq;&SFOQ3pUdye*eT<2()7WKbXp1qq9=bhMWlF-7BHT|i3TEIT77AcjD(v=I207wi-=vyiw5mxgPdTVUC z&h^FEUrXwWs9en2C{ywZp;nvS(Mb$8sBEh-*_d-OEm%~p1b2EpcwUdf<~zmJmaSTO zSX&&GGCEz-M^)G$fBvLC2q@wM$;n4jp+mt0MJFLuJ%c`tSp8$xuP|G81GEd2ci$|M z4XmH{5$j?rqDWoL4vs!}W&!?!rtj=6WKJcE>)?NVske(p;|#>vL|M_$as=mi-n-()a*OU3Okmk0wC<9y7t^D(er-&jEEak2!NnDiOQ99Wx8{S8}=Ng!e0tzj*#T)+%7;aM$ z&H}|o|J1p{IK0Q7JggAwipvHvko6>Epmh4RFRUr}$*2K4dz85o7|3#Bec9SQ4Y*;> zXWjT~f+d)dp_J`sV*!w>B%)#GI_;USp7?0810&3S=WntGZ)+tzhZ+!|=XlQ&@G@~3 z-dw@I1>9n1{+!x^Hz|xC+P#Ab`E@=vY?3%Bc!Po~e&&&)Qp85!I|U<-fCXy*wMa&t zgDk!l;gk;$taOCV$&60z+}_$ykz=Ea*)wJQ3-M|p*EK(cvtIre0Pta~(95J7zoxBN zS(yE^3?>88AL0Wfuou$BM{lR1hkrRibz=+I9ccwd`ZC*{NNqL)3pCcw^ygMmrG^Yp zn5f}Xf>%gncC=Yq96;rnfp4FQL#{!Y*->e82rHgY4Zwy{`JH}b9*qr^VA{%~Z}jtp z_t$PlS6}5{NtTqXHN?uI8ut8rOaD#F1C^ls73S=b_yI#iZDOGz3#^L@YheGd>L;<( z)U=iYj;`{>VDNzIxcjbTk-X3keXR8Xbc`A$o5# zKGSk-7YcoBYuAFFSCjGi;7b<;n-*`USs)IX z=0q6WZ=L!)PkYtZE-6)azhXV|+?IVGTOmMCHjhkBjfy@k1>?yFO3u!)@cl{fFAXnRYsWk)kpT?X{_$J=|?g@Q}+kFw|%n!;Zo}|HE@j=SFMvT8v`6Y zNO;tXN^036nOB2%=KzxB?n~NQ1K8IO*UE{;Xy;N^ZNI#P+hRZOaHATz9(=)w=QwV# z`z3+P>9b?l-@$@P3<;w@O1BdKh+H;jo#_%rr!ute{|YX4g5}n?O7Mq^01S5;+lABE+7`&_?mR_z7k|Ja#8h{!~j)| zbBX;*fsbUak_!kXU%HfJ2J+G7;inu#uRjMb|8a){=^))y236LDZ$$q3LRlat1D)%7K0!q5hT5V1j3qHc7MG9 z_)Q=yQ>rs>3%l=vu$#VVd$&IgO}Za#?aN!xY>-<3PhzS&q!N<=1Q7VJBfHjug^4|) z*fW^;%3}P7X#W3d;tUs3;`O&>;NKZBMR8au6>7?QriJ@gBaorz-+`pUWOP73DJL=M z(33uT6Gz@Sv40F6bN|H=lpcO z^AJl}&=TIjdevuDQ!w0K*6oZ2JBOhb31q!XDArFyKpz!I$p4|;c}@^bX{>AXdt7Bm zaLTk?c%h@%xq02reu~;t@$bv`b3i(P=g}~ywgSFpM;}b$zAD+=I!7`V~}ARB(Wx0C(EAq@?GuxOL9X+ffbkn3+Op0*80TqmpAq~EXmv%cq36celXmRz z%0(!oMp&2?`W)ALA&#|fu)MFp{V~~zIIixOxY^YtO5^FSox8v$#d0*{qk0Z)pNTt0QVZ^$`4vImEB>;Lo2!7K05TpY-sl#sWBz_W-aDIV`Ksabi zvpa#93Svo!70W*Ydh)Qzm{0?CU`y;T^ITg-J9nfWeZ-sbw)G@W?$Eomf%Bg2frfh5 zRm1{|E0+(4zXy){$}uC3%Y-mSA2-^I>Tw|gQx|7TDli_hB>``)Q^aZ`LJC2V3U$SABP}T)%}9g2pF9dT}aC~!rFFgkl1J$ z`^z{Arn3On-m%}r}TGF8KQe*OjSJ=T|caa_E;v89A{t@$yT^(G9=N9F?^kT*#s3qhJq!IH5|AhnqFd z0B&^gm3w;YbMNUKU>naBAO@fbz zqw=n!@--}o5;k6DvTW9pw)IJVz;X}ncbPVrmH>4x);8cx;q3UyiML1PWp%bxSiS|^ zC5!kc4qw%NSOGQ*Kcd#&$30=lDvs#*4W4q0u8E02U)7d=!W7+NouEyuF1dyH$D@G& zaFaxo9Ex|ZXA5y{eZT*i*dP~INSMAi@mvEX@q5i<&o&#sM}Df?Og8n8Ku4vOux=T% zeuw~z1hR}ZNwTn8KsQHKLwe2>p^K`YWUJEdVEl|mO21Bov!D0D$qPoOv=vJJ`)|%_ z>l%`eexY7t{BlVKP!`a^U@nM?#9OC*t76My_E_<16vCz1x_#82qj2PkWiMWgF8bM9 z(1t4VdHcJ;B~;Q%x01k_gQ0>u2*OjuEWNOGX#4}+N?Gb5;+NQMqp}Puqw2HnkYuKA zzKFWGHc&K>gwVgI1Sc9OT1s6fq=>$gZU!!xsilA$fF`kLdGoX*^t}ao@+^WBpk>`8 z4v_~gK|c2rCq#DZ+H)$3v~Hoi=)=1D==e3P zpKrRQ+>O^cyTuWJ%2}__0Z9SM_z9rptd*;-9uC1tDw4+A!=+K%8~M&+Zk#13hY$Y$ zo-8$*8dD5@}XDi19RjK6T^J~DIXbF5w&l?JLHMrf0 zLv0{7*G!==o|B%$V!a=EtVHdMwXLtmO~vl}P6;S(R2Q>*kTJK~!}gloxj)m|_LYK{ zl(f1cB=EON&wVFwK?MGn^nWuh@f95SHatPs(jcwSY#Dnl1@_gkOJ5=f`%s$ZHljRH0 z+c%lrb=Gi&N&1>^L_}#m>=U=(oT^vTA&3!xXNyqi$pdW1BDJ#^{h|2tZc{t^vag3& zAD7*8C`chNF|27itjBUo^CCDyEpJLX3&u+(L;YeeMwnXEoyN(ytoEabcl$lSgx~Ltatn}b$@j_yyMrBb03)shJE*$;Mw=;mZd&8e>IzE+4WIoH zCSZE7WthNUL$|Y#m!Hn?x7V1CK}V`KwW2D$-7&ODy5Cj;!_tTOOo1Mm%(RUt)#$@3 zhurA)t<7qik%%1Et+N1?R#hdBB#LdQ7{%-C zn$(`5e0eFh(#c*hvF>WT*07fk$N_631?W>kfjySN8^XC9diiOd#s?4tybICF;wBjp zIPzilX3{j%4u7blhq)tnaOBZ_`h_JqHXuI7SuIlNTgBk9{HIS&3|SEPfrvcE<@}E` zKk$y*nzsqZ{J{uWW9;#n=de&&h>m#A#q)#zRonr(?mDOYU&h&aQWD;?Z(22wY?t$U3qo`?{+amA$^TkxL+Ex2dh`q7iR&TPd0Ymwzo#b? zP$#t=elB5?k$#uE$K>C$YZbYUX_JgnXA`oF_Ifz4H7LEOW~{Gww&3s=wH4+j8*TU| zSX%LtJWqhr-xGNSe{;(16kxnak6RnZ{0qZ^kJI5X*It_YuynSpi(^-}Lolr{)#z_~ zw!(J-8%7Ybo^c3(mED`Xz8xecP35a6M8HarxRn%+NJBE;dw>>Y2T&;jzRd4FSDO3T zt*y+zXCtZQ0bP0yf6HRpD|WmzP;DR^-g^}{z~0x~z4j8m zucTe%k&S9Nt-?Jb^gYW1w6!Y3AUZ0Jcq;pJ)Exz%7k+mUOm6%ApjjSmflfKwBo6`B zhNb@$NHTJ>guaj9S{@DX)!6)b-Shav=DNKWy(V00k(D!v?PAR0f0vDNq*#mYmUp6> z76KxbFDw5U{{qx{BRj(>?|C`82ICKbfLxoldov-M?4Xl+3;I4GzLHyPOzYw7{WQST zPNYcx5onA%MAO9??41Po*1zW(Y%Zzn06-lUp{s<3!_9vv9HBjT02On0Hf$}NP;wF) zP<`2p3}A^~1YbvOh{ePMx$!JGUPX-tbBzp3mDZMY;}h;sQ->!p97GA)9a|tF(Gh{1$xk7 zUw?ELkT({Xw!KIr);kTRb1b|UL`r2_`a+&UFVCdJ)1T#fdh;71EQl9790Br0m_`$x z9|ZANuchFci8GNZ{XbP=+uXSJRe(;V5laQz$u18#?X*9}x7cIEbnr%<=1cX3EIu7$ zhHW6pe5M(&qEtsqRa>?)*{O;OJT+YUhG5{km|YI7I@JL_3Hwao9aXneiSA~a* z|Lp@c-oMNyeAEuUz{F?kuou3x#C*gU?lon!RC1s37gW^0Frc`lqQWH&(J4NoZg3m8 z;Lin#8Q+cFPD7MCzj}#|ws7b@?D9Q4dVjS4dpco=4yX5SSH=A@U@yqPdp@?g?qeia zH=Tt_9)G=6C2QIPsi-QipnK(mc0xXIN;j$WLf@n8eYvMk;*H-Q4tK%(3$CN}NGgO8n}fD~+>?<3UzvsrMf*J~%i;VKQHbF%TPalFi=#sgj)(P#SM^0Q=Tr>4kJVw8X3iWsP|e8tj}NjlMdWp z@2+M4HQu~3!=bZpjh;;DIDk&X}=c8~kn)FWWH z2KL1w^rA5&1@@^X%MjZ7;u(kH=YhH2pJPFQe=hn>tZd5RC5cfGYis8s9PKaxi*}-s6*W zRA^PwR=y^5Z){!(4D9-KC;0~;b*ploznFOaU`bJ_7U?qAi#mTo!&rIECRL$_y@yI27x2?W+zqDBD5~KCVYKFZLK+>ABC(Kj zeAll)KMgIlAG`r^rS{loBrGLtzhHY8$)<_S<(Dpkr(Ym@@vnQ&rS@FC*>2@XCH}M+an74WcRDcoQ+a3@A z9tYhl5$z7bMdTvD2r&jztBuo37?*k~wcU9GK2-)MTFS-lux-mIRYUuGUCI~V$?s#< z?1qAWb(?ZLm(N>%S%y10COdaq_Tm5c^%ooIxpR=`3e4C|@O5wY+eLik&XVi5oT7oe zmxH)Jd*5eo@!7t`x8!K=-+zJ-Sz)B_V$)s1pW~CDU$=q^&ABvf6S|?TOMB-RIm@CoFg>mjIQE)?+A1_3s6zmFU_oW&BqyMz1mY*IcP_2knjq5 zqw~JK(cVsmzc7*EvTT2rvpeqhg)W=%TOZ^>f`rD4|7Z5fq*2D^lpCttIg#ictgqZ$P@ru6P#f$x#KfnfTZj~LG6U_d-kE~`;kU_X)`H5so@?C zWmb!7x|xk@0L~0JFall*@ltyiL^)@3m4MqC7(7H0sH!WidId1#f#6R{Q&A!XzO1IAcIx;$k66dumt6lpUw@nL2MvqJ5^kbOVZ<^2jt5-njy|2@`07}0w z;M%I1$FCoLy`8xp8Tk)bFr;7aJeQ9KK6p=O$U0-&JYYy8woV*>b+FB?xLX`=pirYM z5K$BA(u)+jR{?O2r$c_Qvl?M{=Ar{yQ!UVsVn4k@0!b?_lA;dVz9uaQUgBH8Oz(Sb zrEs;&Ey>_ex8&!N{PmQjp+-Hlh|OA&wvDai#GpU=^-B70V0*LF=^bi+Nhe_o|azZ%~ZZ1$}LTmWt4aoB1 zPgccm$EwYU+jrdBaQFxQfn5gd(gM`Y*Ro1n&Zi?j=(>T3kmf94vdhf?AuS8>$Va#P zGL5F+VHpxdsCUa}+RqavXCobI-@B;WJbMphpK2%6t=XvKWWE|ruvREgM+|V=i6;;O zx$g=7^`$XWn0fu!gF=Xe9cMB8Z_SelD>&o&{1XFS`|nInK3BXlaeD*rc;R-#osyIS zWv&>~^TLIyBB6oDX+#>3<_0+2C4u2zK^wmHXXDD9_)kmLYJ!0SzM|%G9{pi)`X$uf zW}|%%#LgyK7m(4{V&?x_0KEDq56tk|0YNY~B(Sr|>WVz-pO3A##}$JCT}5P7DY+@W z#gJv>pA5>$|E3WO2tV7G^SuymB?tY`ooKcN3!vaQMnBNk-WATF{-$#}FyzgtJ8M^; zUK6KWSG)}6**+rZ&?o@PK3??uN{Q)#+bDP9i1W&j)oaU5d0bIWJ_9T5ac!qc?x66Q z$KUSZ`nYY94qfN_dpTFr8OW~A?}LD;Yty-BA)-be5Z3S#t2Io%q+cAbnGj1t$|qFR z9o?8B7OA^KjCYL=-!p}w(dkC^G6Nd%_I=1))PC0w5}ZZGJxfK)jP4Fwa@b-SYBw?% zdz9B-<`*B2dOn(N;mcTm%Do)rIvfXRNFX&1h`?>Rzuj~Wx)$p13nrDlS8-jwq@e@n zNIj_|8or==8~1h*Ih?w*8K7rYkGlwlTWAwLKc5}~dfz3y`kM&^Q|@C%1VAp_$wnw6zG~W4O+^ z>i?NY?oXf^Puc~+fDM$VgRNBpOZj{2cMP~gCqWAX4 z7>%$ux8@a&_B(pt``KSt;r+sR-$N;jdpY>|pyvPiN)9ohd*>mVST3wMo)){`B(&eX z1?zZJ-4u9NZ|~j1rdZYq4R$?swf}<6(#ex%7r{kh%U@kT)&kWuAszS%oJts=*OcL9 zaZwK<5DZw%1IFHXgFplP6JiL^dk8+SgM$D?8X+gE4172hXh!WeqIO>}$I9?Nry$*S zQ#f)RuH{P7RwA3v9f<-w>{PSzom;>(i&^l{E0(&Xp4A-*q-@{W1oE3K;1zb{&n28dSC2$N+6auXe0}e4b z)KLJ?5c*>@9K#I^)W;uU_Z`enquTUxr>mNq z1{0_puF-M7j${rs!dxxo3EelGodF1TvjV;Zpo;s{5f1pyCuRp=HDZ?s#IA4f?h|-p zGd|Mq^4hDa@Bh!c4ZE?O&x&XZ_ptZGYK4$9F4~{%R!}G1leCBx`dtNUS|K zL-7J5s4W@%mhXg1!}a4PD%!t&Qn%f_oquRajn3@C*)`o&K9o7V6DwzVMEhjVdDJ1fjhr#@=lp#@4EBqi=CCQ>73>R(>QKPNM&_Jpe5G`n4wegeC`FYEPJ{|vwS>$-`fuRSp3927qOv|NC3T3G-0 zA{K`|+tQy1yqE$ShWt8ny&5~)%ITb@^+x$w0)f&om;P8B)@}=Wzy59BwUfZ1vqw87 za2lB8J(&*l#(V}Id8SyQ0C(2amzkz3EqG&Ed0Jq1)$|&>4_|NIe=5|n=3?siFV0fI z{As5DLW^gs|B-b4C;Hd(SM-S~GQhzb>HgF2|2Usww0nL^;x@1eaB)=+Clj+$fF@H( z-fqP??~QMT$KI-#m;QC*&6vkp&8699G3)Bq0*kFZXINw=b9OVaed(3(3kS|IZ)CM? zJdnW&%t8MveBuK21uiYj)_a{Fnw0OErMzMN?d$QoPwkhOwcP&p+t>P)4tHlYw-pPN z^oJ=uc$Sl>pv@fZH~ZqxSvdhF@F1s=oZawpr^-#l{IIOGG=T%QXjtwPhIg-F@k@uIlr?J->Ia zpEUQ*=4g|XYn4Gez&aHr*;t$u3oODPmc2Ku)2Og|xjc%w;q!Zz+zY)*3{7V8bK4;& zYV82FZ+8?v)`J|G1w4I0fWdKg|2b#iaazCv;|?(W-q}$o&Y}Q5d@BRk^jL7#{kbCK zSgkyu;=DV+or2)AxCBgq-nj5=@n^`%T#V+xBGEkW4lCqrE)LMv#f;AvD__cQ@Eg3`~x| zW+h9mofSXCq5|M)9|ez(#X?-sxB%Go8};sJ?2abp(Y!lyi>k)|{M*Z$c{e1-K4ky` MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/web/index.html b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/index.html new file mode 100644 index 000000000000..1088bdfe5d11 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + pipeline_example + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/web/manifest.json b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/manifest.json new file mode 100644 index 000000000000..17f17dafb5ed --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "pipeline_example", + "short_name": "pipeline_example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/.gitignore b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/.gitignore new file mode 100644 index 000000000000..d492d0d98c8f --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/CMakeLists.txt b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/CMakeLists.txt new file mode 100644 index 000000000000..0b27cba15e3a --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(pipeline_example LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "pipeline_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/flutter/CMakeLists.txt b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/flutter/CMakeLists.txt new file mode 100644 index 000000000000..903f4899d6fc --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/CMakeLists.txt b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/CMakeLists.txt new file mode 100644 index 000000000000..394917c053a0 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/Runner.rc b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/Runner.rc new file mode 100644 index 000000000000..c687adb36fc4 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "pipeline_example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "pipeline_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "pipeline_example.exe" "\0" + VALUE "ProductName", "pipeline_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.cpp b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.cpp new file mode 100644 index 000000000000..5ebed39dfc68 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.cpp @@ -0,0 +1,73 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { this->Show(); }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.h b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.h new file mode 100644 index 000000000000..7f8ccba43748 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/flutter_window.h @@ -0,0 +1,37 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/main.cpp b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/main.cpp new file mode 100644 index 000000000000..f465371f6806 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/main.cpp @@ -0,0 +1,46 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t* command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"pipeline_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/resource.h b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/resource.h new file mode 100644 index 000000000000..212b07c88aed --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/resource.h @@ -0,0 +1,20 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/resources/app_icon.ico b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 zcmeHQc|26z|35SKE&G-*mXah&B~fFkXr)DEO&hIfqby^T&>|8^_Ub8Vp#`BLl3lbZ zvPO!8k!2X>cg~Elr=IVxo~J*a`+9wR=A83c-k-DFd(XM&UI1VKCqM@V;DDtJ09WB} zRaHKiW(GT00brH|0EeTeKVbpbGZg?nK6-j827q-+NFM34gXjqWxJ*a#{b_apGN<-L_m3#8Z26atkEn& ze87Bvv^6vVmM+p+cQ~{u%=NJF>#(d;8{7Q{^rWKWNtf14H}>#&y7$lqmY6xmZryI& z($uy?c5-+cPnt2%)R&(KIWEXww>Cnz{OUpT>W$CbO$h1= z#4BPMkFG1Y)x}Ui+WXr?Z!w!t_hjRq8qTaWpu}FH{MsHlU{>;08goVLm{V<&`itk~ zE_Ys=D(hjiy+5=?=$HGii=Y5)jMe9|wWoD_K07(}edAxh`~LBorOJ!Cf@f{_gNCC| z%{*04ViE!#>@hc1t5bb+NO>ncf@@Dv01K!NxH$3Eg1%)|wLyMDF8^d44lV!_Sr}iEWefOaL z8f?ud3Q%Sen39u|%00W<#!E=-RpGa+H8}{ulxVl4mwpjaU+%2pzmi{3HM)%8vb*~-M9rPUAfGCSos8GUXp02|o~0BTV2l#`>>aFV&_P$ejS;nGwSVP8 zMbOaG7<7eKD>c12VdGH;?2@q7535sa7MN*L@&!m?L`ASG%boY7(&L5imY#EQ$KrBB z4@_tfP5m50(T--qv1BJcD&aiH#b-QC>8#7Fx@3yXlonJI#aEIi=8&ChiVpc#N=5le zM*?rDIdcpawoc5kizv$GEjnveyrp3sY>+5_R5;>`>erS%JolimF=A^EIsAK zsPoVyyUHCgf0aYr&alx`<)eb6Be$m&`JYSuBu=p8j%QlNNp$-5C{b4#RubPb|CAIS zGE=9OFLP7?Hgc{?k45)84biT0k&-C6C%Q}aI~q<(7BL`C#<6HyxaR%!dFx7*o^laG z=!GBF^cwK$IA(sn9y6>60Rw{mYRYkp%$jH z*xQM~+bp)G$_RhtFPYx2HTsWk80+p(uqv9@I9)y{b$7NK53rYL$ezbmRjdXS?V}fj zWxX_feWoLFNm3MG7pMUuFPs$qrQWO9!l2B(SIuy2}S|lHNbHzoE+M2|Zxhjq9+Ws8c{*}x^VAib7SbxJ*Q3EnY5lgI9 z=U^f3IW6T=TWaVj+2N%K3<%Un;CF(wUp`TC&Y|ZjyFu6co^uqDDB#EP?DV5v_dw~E zIRK*BoY9y-G_ToU2V_XCX4nJ32~`czdjT!zwme zGgJ0nOk3U4@IE5JwtM}pwimLjk{ln^*4HMU%Fl4~n(cnsLB}Ja-jUM>xIB%aY;Nq8 z)Fp8dv1tkqKanv<68o@cN|%thj$+f;zGSO7H#b+eMAV8xH$hLggtt?O?;oYEgbq@= zV(u9bbd12^%;?nyk6&$GPI%|+<_mEpJGNfl*`!KV;VfmZWw{n{rnZ51?}FDh8we_L z8OI9nE31skDqJ5Oa_ybn7|5@ui>aC`s34p4ZEu6-s!%{uU45$Zd1=p$^^dZBh zu<*pDDPLW+c>iWO$&Z_*{VSQKg7=YEpS3PssPn1U!lSm6eZIho*{@&20e4Y_lRklKDTUCKI%o4Pc<|G^Xgu$J^Q|B87U;`c1zGwf^-zH*VQ^x+i^OUWE0yd z;{FJq)2w!%`x7yg@>uGFFf-XJl4H`YtUG%0slGKOlXV`q?RP>AEWg#x!b{0RicxGhS!3$p7 zij;{gm!_u@D4$Ox%>>bPtLJ> zwKtYz?T_DR1jN>DkkfGU^<#6sGz|~p*I{y`aZ>^Di#TC|Z!7j_O1=Wo8thuit?WxR zh9_S>kw^{V^|g}HRUF=dcq>?q(pHxw!8rx4dC6vbQVmIhmICF#zU!HkHpQ>9S%Uo( zMw{eC+`&pb=GZRou|3;Po1}m46H6NGd$t<2mQh}kaK-WFfmj_66_17BX0|j-E2fe3Jat}ijpc53 zJV$$;PC<5aW`{*^Z6e5##^`Ed#a0nwJDT#Qq~^e8^JTA=z^Kl>La|(UQ!bI@#ge{Dzz@61p-I)kc2?ZxFt^QQ}f%ldLjO*GPj(5)V9IyuUakJX=~GnTgZ4$5!3E=V#t`yOG4U z(gphZB6u2zsj=qNFLYShhg$}lNpO`P9xOSnO*$@@UdMYES*{jJVj|9z-}F^riksLK zbsU+4-{281P9e2UjY6tse^&a)WM1MFw;p#_dHhWI7p&U*9TR0zKdVuQed%6{otTsq z$f~S!;wg#Bd9kez=Br{m|66Wv z#g1xMup<0)H;c2ZO6su_ii&m8j&+jJz4iKnGZ&wxoQX|5a>v&_e#6WA!MB_4asTxLRGQCC5cI(em z%$ZfeqP>!*q5kU>a+BO&ln=4Jm>Ef(QE8o&RgLkk%2}4Tf}U%IFP&uS7}&|Q-)`5< z+e>;s#4cJ-z%&-^&!xsYx777Wt(wZY9(3(avmr|gRe4cD+a8&!LY`1^T?7x{E<=kdY9NYw>A;FtTvQ=Y&1M%lyZPl$ss1oY^Sl8we}n}Aob#6 zl4jERwnt9BlSoWb@3HxYgga(752Vu6Y)k4yk9u~Kw>cA5&LHcrvn1Y-HoIuFWg~}4 zEw4bR`mXZQIyOAzo)FYqg?$5W<;^+XX%Uz61{-L6@eP|lLH%|w?g=rFc;OvEW;^qh z&iYXGhVt(G-q<+_j}CTbPS_=K>RKN0&;dubh0NxJyDOHFF;<1k!{k#7b{|Qok9hac z;gHz}6>H6C6RnB`Tt#oaSrX0p-j-oRJ;_WvS-qS--P*8}V943RT6kou-G=A+7QPGQ z!ze^UGxtW3FC0$|(lY9^L!Lx^?Q8cny(rR`es5U;-xBhphF%_WNu|aO<+e9%6LuZq zt(0PoagJG<%hyuf;te}n+qIl_Ej;czWdc{LX^pS>77s9t*2b4s5dvP_!L^3cwlc)E!(!kGrg~FescVT zZCLeua3f4;d;Tk4iXzt}g}O@nlK3?_o91_~@UMIl?@77Qc$IAlLE95#Z=TES>2E%z zxUKpK{_HvGF;5%Q7n&vA?`{%8ohlYT_?(3A$cZSi)MvIJygXD}TS-3UwyUxGLGiJP znblO~G|*uA^|ac8E-w#}uBtg|s_~s&t>-g0X%zIZ@;o_wNMr_;{KDg^O=rg`fhDZu zFp(VKd1Edj%F zWHPl+)FGj%J1BO3bOHVfH^3d1F{)*PL&sRX`~(-Zy3&9UQX)Z;c51tvaI2E*E7!)q zcz|{vpK7bjxix(k&6=OEIBJC!9lTkUbgg?4-yE{9+pFS)$Ar@vrIf`D0Bnsed(Cf? zObt2CJ>BKOl>q8PyFO6w)+6Iz`LW%T5^R`U_NIW0r1dWv6OY=TVF?N=EfA(k(~7VBW(S;Tu5m4Lg8emDG-(mOSSs=M9Q&N8jc^Y4&9RqIsk(yO_P(mcCr}rCs%1MW1VBrn=0-oQN(Xj!k%iKV zb%ricBF3G4S1;+8lzg5PbZ|$Se$)I=PwiK=cDpHYdov2QO1_a-*dL4KUi|g&oh>(* zq$<`dQ^fat`+VW?m)?_KLn&mp^-@d=&7yGDt<=XwZZC=1scwxO2^RRI7n@g-1o8ps z)&+et_~)vr8aIF1VY1Qrq~Xe``KJrQSnAZ{CSq3yP;V*JC;mmCT6oRLSs7=GA?@6g zUooM}@tKtx(^|aKK8vbaHlUQqwE0}>j&~YlN3H#vKGm@u)xxS?n9XrOWUfCRa< z`20Fld2f&;gg7zpo{Adh+mqNntMc-D$N^yWZAZRI+u1T1zWHPxk{+?vcS1D>08>@6 zLhE@`gt1Y9mAK6Z4p|u(5I%EkfU7rKFSM=E4?VG9tI;a*@?6!ey{lzN5=Y-!$WFSe z&2dtO>^0@V4WRc#L&P%R(?@KfSblMS+N+?xUN$u3K4Ys%OmEh+tq}fnU}i>6YHM?< zlnL2gl~sF!j!Y4E;j3eIU-lfa`RsOL*Tt<%EFC0gPzoHfNWAfKFIKZN8}w~(Yi~=q z>=VNLO2|CjkxP}RkutxjV#4fWYR1KNrPYq5ha9Wl+u>ipsk*I(HS@iLnmGH9MFlTU zaFZ*KSR0px>o+pL7BbhB2EC1%PJ{67_ z#kY&#O4@P=OV#-79y_W>Gv2dxL*@G7%LksNSqgId9v;2xJ zrh8uR!F-eU$NMx@S*+sk=C~Dxr9Qn7TfWnTupuHKuQ$;gGiBcU>GF5sWx(~4IP3`f zWE;YFO*?jGwYh%C3X<>RKHC-DZ!*r;cIr}GLOno^3U4tFSSoJp%oHPiSa%nh=Zgn% z14+8v@ygy0>UgEN1bczD6wK45%M>psM)y^)IfG*>3ItX|TzV*0i%@>L(VN!zdKb8S?Qf7BhjNpziA zR}?={-eu>9JDcl*R=OP9B8N$IcCETXah9SUDhr{yrld{G;PnCWRsPD7!eOOFBTWUQ=LrA_~)mFf&!zJX!Oc-_=kT<}m|K52 z)M=G#;p;Rdb@~h5D{q^K;^fX-m5V}L%!wVC2iZ1uu401Ll}#rocTeK|7FAeBRhNdQ zCc2d^aQnQp=MpOmak60N$OgS}a;p(l9CL`o4r(e-nN}mQ?M&isv-P&d$!8|1D1I(3-z!wi zTgoo)*Mv`gC?~bm?S|@}I|m-E2yqPEvYybiD5azInexpK8?9q*$9Yy9-t%5jU8~ym zgZDx>!@ujQ=|HJnwp^wv-FdD{RtzO9SnyfB{mH_(c!jHL*$>0o-(h(eqe*ZwF6Lvu z{7rkk%PEqaA>o+f{H02tzZ@TWy&su?VNw43! z-X+rN`6llvpUms3ZiSt)JMeztB~>9{J8SPmYs&qohxdYFi!ra8KR$35Zp9oR)eFC4 zE;P31#3V)n`w$fZ|4X-|%MX`xZDM~gJyl2W;O$H25*=+1S#%|53>|LyH za@yh+;325%Gq3;J&a)?%7X%t@WXcWL*BaaR*7UEZad4I8iDt7^R_Fd`XeUo256;sAo2F!HcIQKk;h})QxEsPE5BcKc7WyerTchgKmrfRX z!x#H_%cL#B9TWAqkA4I$R^8{%do3Y*&(;WFmJ zU7Dih{t1<{($VtJRl9|&EB?|cJ)xse!;}>6mSO$o5XIx@V|AA8ZcoD88ZM?C*;{|f zZVmf94_l1OmaICt`2sTyG!$^UeTHx9YuUP!omj(r|7zpm5475|yXI=rR>>fteLI+| z)MoiGho0oEt=*J(;?VY0QzwCqw@cVm?d7Y!z0A@u#H?sCJ*ecvyhj& z-F77lO;SH^dmf?L>3i>?Z*U}Em4ZYV_CjgfvzYsRZ+1B!Uo6H6mbS<-FFL`ytqvb& zE7+)2ahv-~dz(Hs+f})z{*4|{)b=2!RZK;PWwOnO=hG7xG`JU5>bAvUbdYd_CjvtHBHgtGdlO+s^9ca^Bv3`t@VRX2_AD$Ckg36OcQRF zXD6QtGfHdw*hx~V(MV-;;ZZF#dJ-piEF+s27z4X1qi5$!o~xBnvf=uopcn7ftfsZc zy@(PuOk`4GL_n(H9(E2)VUjqRCk9kR?w)v@xO6Jm_Mx})&WGEl=GS0#)0FAq^J*o! zAClhvoTsNP*-b~rN{8Yym3g{01}Ep^^Omf=SKqvN?{Q*C4HNNAcrowIa^mf+3PRy! z*_G-|3i8a;+q;iP@~Of_$(vtFkB8yOyWt2*K)vAn9El>=D;A$CEx6b*XF@4y_6M+2 zpeW`RHoI_p(B{%(&jTHI->hmNmZjHUj<@;7w0mx3&koy!2$@cfX{sN19Y}euYJFn& z1?)+?HCkD0MRI$~uB2UWri})0bru_B;klFdwsLc!ne4YUE;t41JqfG# zZJq6%vbsdx!wYeE<~?>o4V`A3?lN%MnKQ`z=uUivQN^vzJ|C;sdQ37Qn?;lpzg})y z)_2~rUdH}zNwX;Tp0tJ78+&I=IwOQ-fl30R79O8@?Ub8IIA(6I`yHn%lARVL`%b8+ z4$8D-|MZZWxc_)vu6@VZN!HsI$*2NOV&uMxBNzIbRgy%ob_ zhwEH{J9r$!dEix9XM7n&c{S(h>nGm?el;gaX0@|QnzFD@bne`el^CO$yXC?BDJ|Qg z+y$GRoR`?ST1z^e*>;!IS@5Ovb7*RlN>BV_UC!7E_F;N#ky%1J{+iixp(dUJj93aK zzHNN>R-oN7>kykHClPnoPTIj7zc6KM(Pnlb(|s??)SMb)4!sMHU^-ntJwY5Big7xv zb1Ew`Xj;|D2kzGja*C$eS44(d&RMU~c_Y14V9_TLTz0J#uHlsx`S6{nhsA0dWZ#cG zJ?`fO50E>*X4TQLv#nl%3GOk*UkAgt=IY+u0LNXqeln3Z zv$~&Li`ZJOKkFuS)dJRA>)b_Da%Q~axwA_8zNK{BH{#}#m}zGcuckz}riDE-z_Ms> zR8-EqAMcfyGJCtvTpaUVQtajhUS%c@Yj}&6Zz;-M7MZzqv3kA7{SuW$oW#=0az2wQ zg-WG@Vb4|D`pl~Il54N7Hmsauc_ne-a!o5#j3WaBBh@Wuefb!QJIOn5;d)%A#s+5% zuD$H=VNux9bE-}1&bcYGZ+>1Fo;3Z@e&zX^n!?JK*adSbONm$XW9z;Q^L>9U!}Toj2WdafJ%oL#h|yWWwyAGxzfrAWdDTtaKl zK4`5tDpPg5>z$MNv=X0LZ0d6l%D{(D8oT@+w0?ce$DZ6pv>{1&Ok67Ix1 zH}3=IEhPJEhItCC8E=`T`N5(k?G=B4+xzZ?<4!~ ze~z6Wk9!CHTI(0rLJ4{JU?E-puc;xusR?>G?;4vt;q~iI9=kDL=z0Rr%O$vU`30X$ zDZRFyZ`(omOy@u|i6h;wtJlP;+}$|Ak|k2dea7n?U1*$T!sXqqOjq^NxLPMmk~&qI zYg0W?yK8T(6+Ea+$YyspKK?kP$+B`~t3^Pib_`!6xCs32!i@pqXfFV6PmBIR<-QW= zN8L{pt0Vap0x`Gzn#E@zh@H)0FfVfA_Iu4fjYZ+umO1LXIbVc$pY+E234u)ttcrl$ z>s92z4vT%n6cMb>=XT6;l0+9e(|CZG)$@C7t7Z7Ez@a)h)!hyuV&B5K%%)P5?Lk|C zZZSVzdXp{@OXSP0hoU-gF8s8Um(#xzjP2Vem zec#-^JqTa&Y#QJ>-FBxd7tf`XB6e^JPUgagB8iBSEps;92KG`!#mvVcPQ5yNC-GEG zTiHEDYfH+0O15}r^+ z#jxj=@x8iNHWALe!P3R67TwmhItn**0JwnzSV2O&KE8KcT+0hWH^OPD1pwiuyx=b@ zNf5Jh0{9X)8;~Es)$t@%(3!OnbY+`@?i{mGX7Yy}8T_*0a6g;kaFPq;*=px5EhO{Cp%1kI<0?*|h8v!6WnO3cCJRF2-CRrU3JiLJnj@6;L)!0kWYAc_}F{2P))3HmCrz zQ&N&gE70;`!6*eJ4^1IR{f6j4(-l&X!tjHxkbHA^Zhrnhr9g{exN|xrS`5Pq=#Xf& zG%P=#ra-TyVFfgW%cZo5OSIwFL9WtXAlFOa+ubmI5t*3=g#Y zF%;70p5;{ZeFL}&}yOY1N1*Q;*<(kTB!7vM$QokF)yr2FlIU@$Ph58$Bz z0J?xQG=MlS4L6jA22eS42g|9*9pX@$#*sUeM(z+t?hr@r5J&D1rx}2pW&m*_`VDCW zUYY@v-;bAO0HqoAgbbiGGC<=ryf96}3pouhy3XJrX+!!u*O_>Si38V{uJmQ&USptX zKp#l(?>%^7;2%h(q@YWS#9;a!JhKlkR#Vd)ERILlgu!Hr@jA@V;sk4BJ-H#p*4EqC zDGjC*tl=@3Oi6)Bn^QwFpul18fpkbpg0+peH$xyPBqb%`$OUhPKyWb32o7clB*9Z< zN=i~NLjavrLtwgJ01bufP+>p-jR2I95|TpmKpQL2!oV>g(4RvS2pK4*ou%m(h6r3A zX#s&`9LU1ZG&;{CkOK!4fLDTnBys`M!vuz>Q&9OZ0hGQl!~!jSDg|~s*w52opC{sB ze|Cf2luD(*G13LcOAGA!s2FjSK8&IE5#W%J25w!vM0^VyQM!t)inj&RTiJ!wXzFgz z3^IqzB7I0L$llljsGq})thBy9UOyjtFO_*hYM_sgcMk>44jeH0V1FDyELc{S1F-;A zS;T^k^~4biG&V*Irq}O;e}j$$+E_#G?HKIn05iP3j|87TkGK~SqG!-KBg5+mN(aLm z8ybhIM`%C19UX$H$KY6JgXbY$0AT%rEpHC;u`rQ$Y=rxUdsc5*Kvc8jaYaO$^)cI6){P6K0r)I6DY4Wr4&B zLQUBraey#0HV|&c4v7PVo3n$zHj99(TZO^3?Ly%C4nYvJTL9eLBLHsM3WKKD>5!B` zQ=BsR3aR6PD(Fa>327E2HAu5TM~Wusc!)>~(gM)+3~m;92Jd;FnSib=M5d6;;5{%R zb4V7DEJ0V!CP-F*oU?gkc>ksUtAYP&V4ND5J>J2^jt*vcFflQWCrB&fLdT%O59PVJ zhid#toR=FNgD!q3&r8#wEBr`!wzvQu5zX?Q>nlSJ4i@WC*CN*-xU66F^V5crWevQ9gsq$I@z1o(a=k7LL~ z7m_~`o;_Ozha1$8Q}{WBehvAlO4EL60y5}8GDrZ< zXh&F}71JbW2A~8KfEWj&UWV#4+Z4p`b{uAj4&WC zha`}X@3~+Iz^WRlOHU&KngK>#j}+_o@LdBC1H-`gT+krWX3-;!)6?{FBp~%20a}FL zFP9%Emqcwa#(`=G>BBZ0qZDQhmZKJg_g8<=bBFKWr!dyg(YkpE+|R*SGpDVU!+VlU zFC54^DLv}`qa%49T>nNiA9Q7Ips#!Xx90tCU2gvK`(F+GPcL=J^>No{)~we#o@&mUb6c$ zCc*<|NJBk-#+{j9xkQ&ujB zI~`#kN~7W!f*-}wkG~Ld!JqZ@tK}eeSnsS5J1fMFXm|`LJx&}5`@dK3W^7#Wnm+_P zBZkp&j1fa2Y=eIjJ0}gh85jt43kaIXXv?xmo@eHrka!Z|vQv12HN#+!I5E z`(fbuW>gFiJL|uXJ!vKt#z3e3HlVdboH7;e#i3(2<)Fg-I@BR!qY#eof3MFZ&*Y@l zI|KJf&ge@p2Dq09Vu$$Qxb7!}{m-iRk@!)%KL)txi3;~Z4Pb}u@GsW;ELiWeG9V51 znX#}B&4Y2E7-H=OpNE@q{%hFLxwIpBF2t{vPREa8_{linXT;#1vMRWjOzLOP$-hf( z>=?$0;~~PnkqY;~K{EM6Vo-T(0K{A0}VUGmu*hR z{tw3hvBN%N3G3Yw`X5Te+F{J`(3w1s3-+1EbnFQKcrgrX1Jqvs@ADGe%M0s$EbK$$ zK)=y=upBc6SjGYAACCcI=Y*6Fi8_jgwZlLxD26fnQfJmb8^gHRN5(TemhX@0e=vr> zg`W}6U>x6VhoA3DqsGGD9uL1DhB3!OXO=k}59TqD@(0Nb{)Ut_luTioK_>7wjc!5C zIr@w}b`Fez3)0wQfKl&bae7;PcTA7%?f2xucM0G)wt_KO!Ewx>F~;=BI0j=Fb4>pp zv}0R^xM4eti~+^+gE$6b81p(kwzuDti(-K9bc|?+pJEl@H+jSYuxZQV8rl8 zjp@M{#%qItIUFN~KcO9Hed*`$5A-2~pAo~K&<-Q+`9`$CK>rzqAI4w~$F%vs9s{~x zg4BP%Gy*@m?;D6=SRX?888Q6peF@_4Z->8wAH~Cn!R$|Hhq2cIzFYqT_+cDourHbY z0qroxJnrZ4Gh+Ay+F`_c%+KRT>y3qw{)89?=hJ@=KO=@ep)aBJ$c!JHfBMJpsP*3G za7|)VJJ8B;4?n{~ldJF7%jmb`-ftIvNd~ekoufG(`K(3=LNc;HBY& z(lp#q8XAD#cIf}k49zX_i`*fO+#!zKA&%T3j@%)R+#yag067CU%yUEe47>wzGU8^` z1EXFT^@I!{J!F8!X?S6ph8J=gUi5tl93*W>7}_uR<2N2~e}FaG?}KPyugQ=-OGEZs z!GBoyYY+H*ANn4?Z)X4l+7H%`17i5~zRlRIX?t)6_eu=g2Q`3WBhxSUeea+M-S?RL zX9oBGKn%a!H+*hx4d2(I!gsi+@SQK%<{X22M~2tMulJoa)0*+z9=-YO+;DFEm5eE1U9b^B(Z}2^9!Qk`!A$wUE z7$Ar5?NRg2&G!AZqnmE64eh^Anss3i!{}%6@Et+4rr!=}!SBF8eZ2*J3ujCWbl;3; z48H~goPSv(8X61fKKdpP!Z7$88NL^Z?j`!^*I?-P4X^pMxyWz~@$(UeAcTSDd(`vO z{~rc;9|GfMJcApU3k}22a!&)k4{CU!e_ny^Y3cO;tOvOMKEyWz!vG(Kp*;hB?d|R3`2X~=5a6#^o5@qn?J-bI8Ppip{-yG z!k|VcGsq!jF~}7DMr49Wap-s&>o=U^T0!Lcy}!(bhtYsPQy z4|EJe{12QL#=c(suQ89Mhw9<`bui%nx7Nep`C&*M3~vMEACmcRYYRGtANq$F%zh&V zc)cEVeHz*Z1N)L7k-(k3np#{GcDh2Q@ya0YHl*n7fl*ZPAsbU-a94MYYtA#&!c`xGIaV;yzsmrjfieTEtqB_WgZp2*NplHx=$O{M~2#i_vJ{ps-NgK zQsxKK_CBM2PP_je+Xft`(vYfXXgIUr{=PA=7a8`2EHk)Ym2QKIforz# tySWtj{oF3N9@_;i*Fv5S)9x^z=nlWP>jpp-9)52ZmLVA=i*%6g{{fxOO~wEK literal 0 HcmV?d00001 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/runner.exe.manifest b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/runner.exe.manifest new file mode 100644 index 000000000000..153653e8d67f --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.cpp b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.cpp new file mode 100644 index 000000000000..f3c6a5e94098 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.cpp @@ -0,0 +1,69 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE* unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr) - + 1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, input_length, + utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.h b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.h new file mode 100644 index 000000000000..b2cf607427d7 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/utils.h @@ -0,0 +1,23 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.cpp b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.cpp new file mode 100644 index 000000000000..e25d13f9d076 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.cpp @@ -0,0 +1,284 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: +/// https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = + L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { return ShowWindow(window_handle_, SW_SHOWNORMAL); } + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = + RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, nullptr, + &light_mode, &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.h b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.h new file mode 100644 index 000000000000..190ad00d51e4 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/windows/runner/win32_window.h @@ -0,0 +1,104 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_aggregate_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_aggregate_test.dart new file mode 100644 index 000000000000..60c1ac3895ec --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_aggregate_test.dart @@ -0,0 +1,201 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './mock.dart'; + +void main() { + setupCloudFirestoreMocks(); + + setUpAll(() async { + await Firebase.initializeApp(); + }); + + group('PipelineAggregateFunction', () { + test('CountAll has name count_all and simple toMap', () { + final fn = CountAll(); + expect(fn.name, 'count_all'); + expect(fn.toMap(), {'name': 'count_all'}); + }); + + test('Count serializes with expression', () { + final fn = Count(Field('amount')); + expect(fn.toMap(), { + 'name': 'count', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'amount'}, + }, + }, + }); + }); + + test('Sum serializes with expression', () { + final fn = Sum(Field('total')); + expect(fn.toMap(), { + 'name': 'sum', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'total'}, + }, + }, + }); + }); + + test('Average serializes with expression', () { + final fn = Average(Field('score')); + expect(fn.toMap(), { + 'name': 'average', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'score'}, + }, + }, + }); + }); + + test('CountDistinct serializes with expression', () { + final fn = CountDistinct(Field('category')); + expect(fn.toMap(), { + 'name': 'count_distinct', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'category'}, + }, + }, + }); + }); + + test('Minimum serializes with expression', () { + final fn = Minimum(Field('price')); + expect(fn.toMap(), { + 'name': 'minimum', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'price'}, + }, + }, + }); + }); + + test('Maximum serializes with expression', () { + final fn = Maximum(Field('price')); + expect(fn.toMap(), { + 'name': 'maximum', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'price'}, + }, + }, + }); + }); + + test('First serializes with expression', () { + final fn = First(Field('rating')); + expect(fn.toMap(), { + 'name': 'first', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'rating'}, + }, + }, + }); + }); + + test('Last serializes with expression', () { + final fn = Last(Field('rating')); + expect(fn.toMap(), { + 'name': 'last', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'rating'}, + }, + }, + }); + }); + + test('ArrayAgg serializes with expression', () { + final fn = ArrayAgg(Field('tags')); + expect(fn.toMap(), { + 'name': 'array_agg', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'tags'}, + }, + }, + }); + }); + + test('ArrayAggDistinct serializes with expression', () { + final fn = ArrayAggDistinct(Field('tags')); + expect(fn.toMap(), { + 'name': 'array_agg_distinct', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'tags'}, + }, + }, + }); + }); + }); + + group('AliasedAggregateFunction', () { + test('toMap includes alias and aggregate_function', () { + final aliased = CountAll().as('totalCount'); + expect(aliased.alias, 'totalCount'); + final map = aliased.toMap(); + expect(map['name'], 'alias'); + expect(map['args']['alias'], 'totalCount'); + expect(map['args']['aggregate_function'], {'name': 'count_all'}); + }); + + test('wraps expression-based aggregate', () { + final aliased = Sum(Field('amount')).as('total'); + expect(aliased.alias, 'total'); + final map = aliased.toMap(); + expect(map['args']['aggregate_function']['name'], 'sum'); + }); + }); + + group('AggregateStageOptions', () { + test('toMap with accumulators only', () { + final options = AggregateStageOptions( + accumulators: [CountAll().as('count')], + ); + final map = options.toMap(); + expect(map['accumulators'], hasLength(1)); + expect(map.containsKey('groups'), isFalse); + }); + + test('toMap with accumulators and groups', () { + final options = AggregateStageOptions( + accumulators: [Sum(Field('x')).as('sumX')], + groups: [Field('category')], + ); + final map = options.toMap(); + expect(map['accumulators'], hasLength(1)); + expect(map['groups'], hasLength(1)); + }); + }); + + group('AggregateOptions', () { + test('toMap returns empty map', () { + final options = AggregateOptions(); + expect(options.toMap(), isEmpty); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_distance_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_distance_test.dart new file mode 100644 index 000000000000..b4d85b489ee5 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_distance_test.dart @@ -0,0 +1,29 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('DistanceMeasure', () { + test('cosine has expected name', () { + expect(DistanceMeasure.cosine.name, 'cosine'); + }); + + test('euclidean has expected name', () { + expect(DistanceMeasure.euclidean.name, 'euclidean'); + }); + + test('dotProduct has expected name', () { + expect(DistanceMeasure.dotProduct.name, 'dotProduct'); + }); + + test('has exactly three values', () { + expect(DistanceMeasure.values, hasLength(3)); + expect(DistanceMeasure.values, contains(DistanceMeasure.cosine)); + expect(DistanceMeasure.values, contains(DistanceMeasure.euclidean)); + expect(DistanceMeasure.values, contains(DistanceMeasure.dotProduct)); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_execute_options_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_execute_options_test.dart new file mode 100644 index 000000000000..cdd91f7b32c7 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_execute_options_test.dart @@ -0,0 +1,21 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('IndexMode', () { + test('recommended has expected name', () { + expect(IndexMode.recommended.name, 'recommended'); + }); + }); + + group('ExecuteOptions', () { + test('default indexMode is recommended', () { + const options = ExecuteOptions(); + expect(options.indexMode, IndexMode.recommended); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart new file mode 100644 index 000000000000..dbd4f1729424 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart @@ -0,0 +1,1027 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './mock.dart'; + +void main() { + setupCloudFirestoreMocks(); + + late FirebaseFirestore firestore; + + setUpAll(() async { + await Firebase.initializeApp(); + firestore = FirebaseFirestore.instance; + }); + + group('Field', () { + test('toMap returns field name structure', () { + final expr = Field('name'); + expect(expr.toMap(), { + 'name': 'field', + 'args': {'field': 'name'}, + }); + }); + + test('nested field path serializes correctly', () { + final expr = Field('user.profile.displayName'); + expect(expr.toMap()['args']['field'], 'user.profile.displayName'); + }); + }); + + group('Constant', () { + test('toMap for null', () { + final expr = Constant(null); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': null}, + }); + }); + + test('toMap for number', () { + final expr = Constant(42); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': 42}, + }); + }); + + test('toMap for double', () { + final expr = Constant(3.14); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': 3.14}, + }); + }); + + test('toMap for string', () { + final expr = Constant('hello'); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': 'hello'}, + }); + }); + + test('toMap for bool', () { + final expr = Constant(true); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': true}, + }); + }); + + test('toMap for DateTime', () { + final dt = DateTime.utc(2025, 1, 15); + final expr = Constant(dt); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': dt}, + }); + }); + + test('toMap for Timestamp', () { + final ts = Timestamp.fromDate(DateTime.utc(2025, 3, 10)); + final expr = Constant(ts); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': ts}, + }); + }); + + test('toMap for GeoPoint', () { + const gp = GeoPoint(52, 4); + final expr = Constant(gp); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': gp}, + }); + }); + + test('toMap for List (bytes)', () { + final bytes = [1, 2, 3]; + final expr = Constant(bytes); + expect( + expr.toMap(), + { + 'name': 'constant', + 'args': { + 'value': [1, 2, 3], + }, + }, + ); + }); + + test('toMap for Blob', () { + final blob = Blob(Uint8List.fromList([1, 2, 3])); + final expr = Constant(blob); + expect( + expr.toMap(), + { + 'name': 'constant', + 'args': { + 'value': blob, + }, + }, + ); + }); + + test('toMap for DocumentReference serializes path', () { + final ref = firestore.collection('users').doc('alice'); + final expr = Constant(ref); + expect(expr.toMap(), { + 'name': 'constant', + 'args': { + 'value': { + 'path': 'users/alice', + }, + }, + }); + }); + + test('toMap for VectorValue', () { + const vec = VectorValue([1.0, 2.0, 3.0]); + final expr = Constant(vec); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': vec}, + }); + }); + + test('throws ArgumentError for invalid value type', () { + expect( + () => Constant({'key': 'value'}), + throwsA( + isA().having( + (e) => e.message, + 'message', + allOf(contains('Constant value must be'), contains('Got:')), + ), + ), + ); + }); + + test('throws ArgumentError for List (not List)', () { + expect( + () => Constant(['a', 'b']), + throwsA( + isA().having( + (e) => e.message, + 'message', + contains('Got:'), + ), + ), + ); + }); + }); + + group('Expression static constructors', () { + test('Expression.field() returns Field with path', () { + final expr = Expression.field('amount'); + expect(expr, isA()); + expect(expr.toMap()['args']['field'], 'amount'); + }); + + test('Expression.constant() wraps value', () { + final expr = Expression.constant(100); + expect(expr.toMap(), { + 'name': 'constant', + 'args': {'value': 100}, + }); + }); + }); + + group('BooleanExpression from Field', () { + test('equal serializes correctly', () { + final expr = Field('age').equal(Constant(18)); + expect(expr.toMap(), { + 'name': 'equal', + 'args': { + 'left': { + 'name': 'field', + 'args': {'field': 'age'}, + }, + 'right': { + 'name': 'constant', + 'args': {'value': 18}, + }, + }, + }); + }); + + test('greaterThan serializes correctly', () { + final expr = Field('score').greaterThan(Constant(0)); + expect(expr.toMap(), { + 'name': 'greater_than', + 'args': { + 'left': { + 'name': 'field', + 'args': {'field': 'score'}, + }, + 'right': { + 'name': 'constant', + 'args': {'value': 0}, + }, + }, + }); + }); + + test('exists serializes correctly', () { + final expr = Field('email').exists(); + expect(expr.toMap(), { + 'name': 'exists', + 'args': { + 'expression': { + 'name': 'field', + 'args': {'field': 'email'}, + }, + }, + }); + }); + + test('notEqual serializes correctly', () { + final expr = Field('x').notEqual(Constant(0)); + expect(expr.toMap(), { + 'name': 'not_equal', + 'args': { + 'left': { + 'name': 'field', + 'args': {'field': 'x'}, + }, + 'right': { + 'name': 'constant', + 'args': {'value': 0}, + }, + }, + }); + }); + + test('lessThan serializes correctly', () { + final expr = Field('n').lessThan(Constant(10)); + expect(expr.toMap()['name'], 'less_than'); + expect(expr.toMap()['args']['left']['args']['field'], 'n'); + expect(expr.toMap()['args']['right']['args']['value'], 10); + }); + + test('lessThanOrEqual serializes correctly', () { + final expr = Field('n').lessThanOrEqual(Constant(5)); + expect(expr.toMap()['name'], 'less_than_or_equal'); + }); + + test('greaterThanOrEqual serializes correctly', () { + final expr = Field('n').greaterThanOrEqual(Constant(1)); + expect(expr.toMap()['name'], 'greater_than_or_equal'); + }); + }); + + group('Ordering from Expression', () { + test('ascending() returns Ordering with asc', () { + final ordering = Field('name').ascending(); + expect(ordering.direction, OrderDirection.asc); + expect(ordering.toMap()['order_direction'], 'asc'); + }); + + test('descending() returns Ordering with desc', () { + final ordering = Field('created').descending(); + expect(ordering.direction, OrderDirection.desc); + expect(ordering.toMap()['order_direction'], 'desc'); + }); + }); + + group('Aliased expression', () { + test('as() wraps expression with alias', () { + final aliased = Field('total').as('sumTotal'); + expect(aliased.toMap(), { + 'name': 'alias', + 'args': { + 'alias': 'sumTotal', + 'expression': { + 'name': 'field', + 'args': {'field': 'total'}, + }, + }, + }); + }); + }); + + group('Expression static boolean helpers', () { + test('Expression.equalStatic produces equal expression', () { + final expr = Expression.equalStatic( + Field('a'), + Constant(1), + ); + expect(expr.toMap()['name'], 'equal'); + }); + + test('Expression.not inverts boolean expression', () { + final inner = Field('active').equal(Constant(true)); + final expr = Expression.not(inner); + expect(expr.toMap(), { + 'name': 'not', + 'args': { + 'expression': { + 'name': 'equal', + 'args': { + 'left': { + 'name': 'field', + 'args': {'field': 'active'}, + }, + 'right': { + 'name': 'constant', + 'args': {'value': true}, + }, + }, + }, + }, + }); + }); + }); + + group('Logic expressions (and, or, xor)', () { + test('Expression.and serializes correctly', () { + final a = Field('a').equal(Constant(1)); + final b = Field('b').equal(Constant(2)); + final expr = Expression.and(a, b); + expect(expr.toMap()['name'], 'and'); + expect(expr.toMap()['args']['expressions'], hasLength(2)); + }); + + test('Expression.or serializes correctly', () { + final a = Field('x').greaterThan(Constant(0)); + final b = Field('y').lessThan(Constant(0)); + final expr = Expression.or(a, b); + expect(expr.toMap()['name'], 'or'); + expect(expr.toMap()['args']['expressions'], hasLength(2)); + }); + + test('Expression.xor serializes correctly', () { + final a = Field('p').equal(Constant(true)); + final b = Field('q').equal(Constant(true)); + final expr = Expression.xor(a, b); + expect(expr.toMap()['name'], 'xor'); + expect(expr.toMap()['args']['expressions'], hasLength(2)); + }); + }); + + group('Conditional expression', () { + test('Expression.conditional serializes correctly', () { + final cond = Field('flag').equal(Constant(true)); + final thenExpr = Constant('yes'); + final elseExpr = Constant('no'); + final expr = Expression.conditional(cond, thenExpr, elseExpr); + expect(expr.toMap(), { + 'name': 'conditional', + 'args': { + 'condition': cond.toMap(), + 'then': thenExpr.toMap(), + 'else': elseExpr.toMap(), + }, + }); + }); + }); + + group('ifAbsent and ifError', () { + test('ifAbsent serializes correctly', () { + final base = Field('optional'); + final fallback = Constant('default'); + final expr = base.ifAbsent(fallback); + expect(expr.toMap(), { + 'name': 'if_absent', + 'args': { + 'expression': base.toMap(), + 'else': fallback.toMap(), + }, + }); + }); + + test('Expression.ifAbsentValueStatic serializes correctly', () { + final expr = Expression.ifAbsentValueStatic(Field('a'), 0); + expect(expr.toMap()['name'], 'if_absent'); + }); + + test('ifError serializes correctly', () { + final base = Field('risky'); + final catchExpr = Constant('error'); + final expr = base.ifError(catchExpr); + expect(expr.toMap(), { + 'name': 'if_error', + 'args': { + 'expression': base.toMap(), + 'catch': catchExpr.toMap(), + }, + }); + }); + }); + + group('Presence and error checks', () { + test('Expression.isAbsentStatic serializes correctly', () { + final expr = Expression.isAbsentStatic(Field('maybe')); + expect(expr.toMap(), { + 'name': 'is_absent', + 'args': {'expression': Field('maybe').toMap()}, + }); + }); + + test('Expression.isErrorStatic serializes correctly', () { + final expr = Expression.isErrorStatic(Field('x')); + expect(expr.toMap(), { + 'name': 'is_error', + 'args': {'expression': Field('x').toMap()}, + }); + }); + + test('Expression.existsField serializes correctly', () { + final expr = Expression.existsField('email'); + expect(expr.toMap()['name'], 'exists'); + }); + }); + + group('String expressions', () { + test('concat serializes correctly', () { + final expr = Field('first').concat([Constant(' '), Field('last')]); + expect(expr.toMap(), { + 'name': 'concat', + 'args': { + 'expressions': [ + Field('first').toMap(), + Constant(' ').toMap(), + Field('last').toMap(), + ], + }, + }); + }); + + test('length serializes correctly', () { + final expr = Field('title').length(); + expect(expr.toMap(), { + 'name': 'length', + 'args': {'expression': Field('title').toMap()}, + }); + }); + + test('toLowerCase serializes correctly', () { + final expr = Field('name').toLowerCase(); + expect(expr.toMap()['name'], 'to_lower_case'); + expect(expr.toMap()['args']['expression']['args']['field'], 'name'); + }); + + test('toUpperCase serializes correctly', () { + final expr = Field('code').toUpperCase(); + expect(expr.toMap()['name'], 'to_upper_case'); + }); + + test('trim serializes correctly', () { + final expr = Field('input').trim(); + expect(expr.toMap(), { + 'name': 'trim', + 'args': {'expression': Field('input').toMap()}, + }); + }); + + test('substring serializes correctly', () { + final expr = Field('text').substring(Constant(0), Constant(5)); + expect(expr.toMap(), { + 'name': 'substring', + 'args': { + 'expression': Field('text').toMap(), + 'start': Constant(0).toMap(), + 'end': Constant(5).toMap(), + }, + }); + }); + + test('stringReplaceAll serializes correctly', () { + final expr = + Field('s').stringReplaceAll(Constant('old'), Constant('new')); + expect(expr.toMap(), { + 'name': 'string_replace_all', + 'args': { + 'expression': Field('s').toMap(), + 'find': Constant('old').toMap(), + 'replacement': Constant('new').toMap(), + }, + }); + }); + + test('split serializes correctly', () { + final expr = Field('csv').split(Constant(',')); + expect(expr.toMap()['name'], 'split'); + expect(expr.toMap()['args']['expression']['args']['field'], 'csv'); + expect(expr.toMap()['args']['delimiter']['args']['value'], ','); + }); + + test('join serializes correctly', () { + final arr = Expression.array([Field('a'), Field('b')]); + final expr = arr.join(Constant('-')); + expect(expr.toMap(), { + 'name': 'join', + 'args': { + 'expression': arr.toMap(), + 'delimiter': Constant('-').toMap(), + }, + }); + }); + }); + + group('Array expressions', () { + test('Expression.array serializes correctly', () { + final expr = Expression.array([Constant(1), Constant(2), Field('x')]); + expect(expr.toMap(), { + 'name': 'array', + 'args': { + 'elements': [ + Constant(1).toMap(), + Constant(2).toMap(), + Field('x').toMap(), + ], + }, + }); + }); + + test('arrayContainsValue serializes correctly', () { + final expr = Field('tags').arrayContainsValue(Constant('flutter')); + expect(expr.toMap(), { + 'name': 'array_contains', + 'args': { + 'array': Field('tags').toMap(), + 'element': Constant('flutter').toMap(), + }, + }); + }); + + test('arrayContainsAny serializes correctly', () { + final expr = + Field('tags').arrayContainsAny([Constant('a'), Constant('b')]); + expect(expr.toMap()['name'], 'array_contains_any'); + expect(expr.toMap()['args']['array']['args']['field'], 'tags'); + expect(expr.toMap()['args']['values'], hasLength(2)); + }); + + test('arrayContainsAll with list serializes correctly', () { + final expr = Field('tags').arrayContainsAll(['a', Constant('b')]); + expect(expr.toMap(), { + 'name': 'array_contains_all', + 'args': { + 'array': Field('tags').toMap(), + 'values': [ + Constant('a').toMap(), + Constant('b').toMap(), + ], + }, + }); + }); + + test('arrayContainsAllFrom with array expression serializes correctly', () { + final elements = Expression.array([Field('tag1'), Constant('tag2')]); + final expr = Field('tags').arrayContainsAllFrom(elements); + expect(expr.toMap(), { + 'name': 'array_contains_all', + 'args': { + 'array': Field('tags').toMap(), + 'array_expression': elements.toMap(), + }, + }); + }); + + test( + 'Expression.arrayContainsAllWithExpression(array, arrayExpression) serializes correctly', + () { + final arrayExpr = + Expression.array([Field('required'), Constant('admin')]); + final expr = Expression.arrayContainsAllWithExpression( + Field('permissions'), + arrayExpr, + ); + expect(expr.toMap(), { + 'name': 'array_contains_all', + 'args': { + 'array': Field('permissions').toMap(), + 'array_expression': arrayExpr.toMap(), + }, + }); + }); + + test('Expression.arrayContainsAllValues(array, list) serializes correctly', + () { + final expr = Expression.arrayContainsAllValues( + Field('tags'), + [Constant('flutter'), Constant('dart')], + ); + expect(expr.toMap()['name'], 'array_contains_all'); + expect(expr.toMap()['args']['values'], hasLength(2)); + }); + + test('Expression.arrayContainsAllField serializes correctly', () { + final required = Expression.array([Field('requiredPermissions')]); + final expr = Expression.arrayContainsAllField('permissions', required); + expect(expr.toMap(), { + 'name': 'array_contains_all', + 'args': { + 'array': Field('permissions').toMap(), + 'array_expression': required.toMap(), + }, + }); + }); + + test('arrayLength serializes correctly', () { + final expr = Field('items').arrayLength(); + expect(expr.toMap(), { + 'name': 'array_length', + 'args': {'expression': Field('items').toMap()}, + }); + }); + + test('arrayConcat serializes correctly', () { + final a = Expression.array([Constant(1)]); + final b = Expression.array([Constant(2)]); + final expr = a.arrayConcat(b); + expect(expr.toMap(), { + 'name': 'array_concat', + 'args': { + 'first': a.toMap(), + 'second': b.toMap(), + }, + }); + }); + + test('arraySum serializes correctly', () { + final expr = Field('values').arraySum(); + expect(expr.toMap()['name'], 'array_sum'); + expect(expr.toMap()['args']['expression']['args']['field'], 'values'); + }); + + test('arrayReverse serializes correctly', () { + final expr = Field('order').arrayReverse(); + expect(expr.toMap()['name'], 'array_reverse'); + expect(expr.toMap()['args']['expression']['args']['field'], 'order'); + }); + }); + + group('Numeric expressions', () { + test('add serializes correctly', () { + final expr = Field('a').add(Field('b')); + expect(expr.toMap(), { + 'name': 'add', + 'args': { + 'left': Field('a').toMap(), + 'right': Field('b').toMap(), + }, + }); + }); + + test('subtract serializes correctly', () { + final expr = Field('x').subtract(Constant(1)); + expect(expr.toMap()['name'], 'subtract'); + expect(expr.toMap()['args']['left']['args']['field'], 'x'); + expect(expr.toMap()['args']['right']['args']['value'], 1); + }); + + test('multiply serializes correctly', () { + final expr = Field('qty').multiply(Field('price')); + expect(expr.toMap()['name'], 'multiply'); + }); + + test('divide serializes correctly', () { + final expr = Field('total').divide(Constant(2)); + expect(expr.toMap()['name'], 'divide'); + }); + + test('modulo serializes correctly', () { + final expr = Field('n').modulo(Constant(10)); + expect(expr.toMap()['name'], 'modulo'); + }); + + test('abs serializes correctly', () { + final expr = Field('diff').abs(); + expect(expr.toMap()['name'], 'abs'); + }); + }); + + group('Structure (nullValue, map)', () { + test('Expression.nullValue serializes correctly', () { + final expr = Expression.nullValue(); + expect(expr.toMap(), { + 'name': 'null', + 'args': {'value': null}, + }); + }); + + test('Expression.map serializes correctly', () { + final expr = Expression.map({ + 'k1': Constant(1), + 'k2': Field('v'), + }); + expect(expr.toMap(), { + 'name': 'map', + 'args': { + 'data': { + 'k1': Constant(1).toMap(), + 'k2': Field('v').toMap(), + }, + }, + }); + }); + }); + + group('Timestamp expressions', () { + test('Expression.currentTimestamp serializes correctly', () { + final expr = Expression.currentTimestamp(); + final map = expr.toMap(); + expect(map['name'], 'current_timestamp'); + }); + + test('timestampAddLiteral serializes correctly', () { + final ts = Field('created'); + final expr = Expression.timestampAddLiteral(ts, 'day', 1); + expect(expr.toMap(), { + 'name': 'timestamp_add', + 'args': { + 'timestamp': ts.toMap(), + 'unit': 'day', + 'amount': Constant(1).toMap(), + }, + }); + }); + + test('timestampTruncate serializes correctly', () { + final expr = Expression.timestampTruncate(Field('ts'), 'day'); + expect(expr.toMap(), { + 'name': 'timestamp_truncate', + 'args': { + 'timestamp': Field('ts').toMap(), + 'unit': 'day', + }, + }); + }); + }); + + group('Document and equality helpers', () { + test('Expression.documentIdFromRef serializes correctly', () { + final ref = firestore.collection('users').doc('alice'); + final expr = Expression.documentIdFromRef(ref); + expect(expr.toMap(), { + 'name': 'document_id_from_ref', + 'args': {'doc_ref': 'users/alice'}, + }); + }); + + test('equalAny serializes correctly', () { + final expr = Expression.equalAny(Field('status'), ['a', 'b']); + expect(expr.toMap(), { + 'name': 'equal_any', + 'args': { + 'value': Field('status').toMap(), + 'values': [Constant('a').toMap(), Constant('b').toMap()], + }, + }); + }); + + test('notEqualAny serializes correctly', () { + final expr = Expression.notEqualAny(Field('role'), ['admin']); + expect(expr.toMap(), { + 'name': 'not_equal_any', + 'args': { + 'value': Field('role').toMap(), + 'values': [Constant('admin').toMap()], + }, + }); + }); + }); + + group('asBoolean', () { + test('asBoolean serializes correctly', () { + final expr = Field('flag').asBoolean(); + expect(expr.toMap(), { + 'name': 'as_boolean', + 'args': {'expression': Field('flag').toMap()}, + }); + }); + }); + + group('Map mapSet / mapEntries', () { + test('mapSet serializes map and key_values pairs', () { + final expr = Field('meta').mapSet('k', 1, ['k2', 2]); + expect(expr.toMap(), { + 'name': 'map_set', + 'args': { + 'map': Field('meta').toMap(), + 'key_values': [ + Constant('k').toMap(), + Constant(1).toMap(), + Constant('k2').toMap(), + Constant(2).toMap(), + ], + }, + }); + }); + + test('mapSet throws when key/value list has odd length', () { + expect( + () => Field('m').mapSet('a', 1, ['orphan']), + throwsA(isA()), + ); + }); + + test('mapEntries serializes correctly', () { + final expr = Field('m').mapEntries(); + expect(expr.toMap(), { + 'name': 'map_entries', + 'args': {'expression': Field('m').toMap()}, + }); + }); + }); + + group('Regex and extended string expressions', () { + test('regexFind serializes correctly', () { + final expr = Field('email').regexFind(r'\w+'); + expect(expr.toMap(), { + 'name': 'regex_find', + 'args': { + 'expression': Field('email').toMap(), + 'pattern': Constant(r'\w+').toMap(), + }, + }); + }); + + test('regexFindAll serializes correctly', () { + final expr = Field('text').regexFindAll('[a-z]+'); + expect(expr.toMap()['name'], 'regex_find_all'); + }); + + test('stringReplaceOne serializes correctly', () { + final expr = Field('s').stringReplaceOne(Constant('a'), Constant('b')); + expect(expr.toMap(), { + 'name': 'string_replace_one', + 'args': { + 'expression': Field('s').toMap(), + 'find': Constant('a').toMap(), + 'replacement': Constant('b').toMap(), + }, + }); + }); + + test('stringIndexOf serializes correctly', () { + final expr = Field('s').stringIndexOf('needle'); + expect(expr.toMap()['name'], 'string_index_of'); + expect(expr.toMap()['args']['search'], Constant('needle').toMap()); + }); + + test('stringRepeat serializes correctly', () { + final expr = Field('s').stringRepeat(3); + expect(expr.toMap(), { + 'name': 'string_repeat', + 'args': { + 'expression': Field('s').toMap(), + 'repetitions': Constant(3).toMap(), + }, + }); + }); + + test('ltrim without value serializes correctly', () { + final expr = Field('s').ltrim(); + expect(expr.toMap(), { + 'name': 'ltrim', + 'args': {'expression': Field('s').toMap()}, + }); + }); + + test('ltrim with value serializes correctly', () { + final expr = Field('s').ltrim('"'); + expect(expr.toMap()['args']['value'], Constant('"').toMap()); + }); + + test('rtrim serializes correctly', () { + expect(Field('s').rtrim().toMap()['name'], 'rtrim'); + }); + }); + + group('type / isType / trunc / rand', () { + test('type() serializes correctly', () { + final expr = Field('x').type(); + expect(expr.toMap(), { + 'name': 'type', + 'args': {'expression': Field('x').toMap()}, + }); + }); + + test('isType serializes correctly', () { + final expr = Field('n').isType(Type.int64); + expect(expr.toMap(), { + 'name': 'is_type', + 'args': { + 'expression': Field('n').toMap(), + 'type': 'int64', + }, + }); + }); + + test('Expression.isTypeStatic matches instance isType', () { + expect( + Expression.isTypeStatic(Field('n'), Type.float64).toMap(), + Field('n').isType(Type.float64).toMap(), + ); + }); + + test('trunc without decimals serializes correctly', () { + final expr = Field('pi').trunc(); + expect(expr.toMap(), { + 'name': 'trunc', + 'args': {'expression': Field('pi').toMap()}, + }); + }); + + test('trunc with decimals serializes correctly', () { + final expr = Field('pi').trunc(Constant(2)); + expect(expr.toMap()['args']['decimals'], Constant(2).toMap()); + }); + + test('Expression.rand serializes correctly', () { + expect(Expression.rand().toMap(), { + 'name': 'rand', + 'args': {}, + }); + }); + }); + + group('Array analytics expressions', () { + test('arrayFirst serializes correctly', () { + expect(Field('tags').arrayFirst().toMap()['name'], 'array_first'); + }); + + test('arrayFirstN serializes correctly', () { + final expr = Field('tags').arrayFirstN(2); + expect(expr.toMap(), { + 'name': 'array_first_n', + 'args': { + 'expression': Field('tags').toMap(), + 'n': Constant(2).toMap(), + }, + }); + }); + + test('arrayLast / arrayLastN serialize correctly', () { + expect(Field('tags').arrayLast().toMap()['name'], 'array_last'); + expect(Field('tags').arrayLastN(1).toMap()['name'], 'array_last_n'); + }); + + test('arrayMaximum / arrayMinimum serialize correctly', () { + expect(Field('nums').arrayMaximum().toMap()['name'], 'maximum'); + expect(Field('nums').arrayMinimum().toMap()['name'], 'minimum'); + }); + + test('arrayMaximumN / arrayMinimumN serialize correctly', () { + expect(Field('nums').arrayMaximumN(2).toMap()['name'], 'maximum_n'); + expect(Field('nums').arrayMinimumN(2).toMap()['name'], 'minimum_n'); + }); + + test('arrayIndexOf serializes occurrence first', () { + final expr = Field('tags').arrayIndexOf('x'); + expect(expr.toMap(), { + 'name': 'array_index_of', + 'args': { + 'expression': Field('tags').toMap(), + 'element': Constant('x').toMap(), + 'occurrence': Constant('first').toMap(), + }, + }); + }); + + test('arrayLastIndexOf serializes occurrence last', () { + final expr = Field('tags').arrayLastIndexOf('x'); + expect(expr.toMap()['args']['occurrence'], Constant('last').toMap()); + }); + + test('arrayIndexOfAll serializes correctly', () { + expect( + Field('tags').arrayIndexOfAll('a').toMap()['name'], + 'array_index_of_all', + ); + }); + }); + + group('Expression aggregate helpers', () { + test('first() returns First aggregate', () { + expect(Field('s').first().toMap()['name'], 'first'); + }); + + test('last() returns Last aggregate', () { + expect(Field('s').last().toMap()['name'], 'last'); + }); + + test('arrayAgg returns ArrayAgg', () { + expect(Field('t').arrayAgg().toMap()['name'], 'array_agg'); + }); + + test('arrayAggDistinct returns ArrayAggDistinct', () { + expect( + Field('t').arrayAggDistinct().toMap()['name'], + 'array_agg_distinct', + ); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_ordering_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_ordering_test.dart new file mode 100644 index 000000000000..ccfeac4b922d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_ordering_test.dart @@ -0,0 +1,62 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './mock.dart'; + +void main() { + setupCloudFirestoreMocks(); + + setUpAll(() async { + await Firebase.initializeApp(); + }); + + group('OrderDirection', () { + test('asc has expected name', () { + expect(OrderDirection.asc.name, 'asc'); + }); + + test('desc has expected name', () { + expect(OrderDirection.desc.name, 'desc'); + }); + }); + + group('Ordering', () { + test('toMap() serializes ascending order', () { + final ordering = Ordering(Field('name'), OrderDirection.asc); + expect(ordering.toMap(), { + 'expression': { + 'name': 'field', + 'args': {'field': 'name'}, + }, + 'order_direction': 'asc', + }); + }); + + test('toMap() serializes descending order', () { + final ordering = Ordering(Field('score'), OrderDirection.desc); + expect(ordering.toMap(), { + 'expression': { + 'name': 'field', + 'args': {'field': 'score'}, + }, + 'order_direction': 'desc', + }); + }); + + test('toMap() includes expression toMap() result', () { + final ordering = Ordering(Constant(42), OrderDirection.asc); + expect(ordering.toMap(), { + 'expression': { + 'name': 'constant', + 'args': {'value': 42}, + }, + 'order_direction': 'asc', + }); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_sample_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_sample_test.dart new file mode 100644 index 000000000000..6f4a9c13d927 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_sample_test.dart @@ -0,0 +1,56 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './mock.dart'; + +void main() { + setupCloudFirestoreMocks(); + + late FirebaseFirestore firestore; + + setUpAll(() async { + await Firebase.initializeApp(); + firestore = FirebaseFirestore.instance; + }); + + group('PipelineSample', () { + group('withSize()', () { + test('serializes as type size with value', () { + final pipeline = firestore + .pipeline() + .collection('users') + .sample(PipelineSample.withSize(100)); + final stage = pipeline.stages.last; + expect(stage['stage'], 'sample'); + expect(stage['args']['type'], 'size'); + expect(stage['args']['value'], 100); + }); + + test('accepts zero size', () { + final pipeline = firestore + .pipeline() + .collection('users') + .sample(PipelineSample.withSize(0)); + expect(pipeline.stages.last['args']['value'], 0); + }); + }); + + group('withPercentage()', () { + test('serializes as type percentage with value', () { + final pipeline = firestore + .pipeline() + .collection('users') + .sample(PipelineSample.withPercentage(0.6)); + final stage = pipeline.stages.last; + expect(stage['stage'], 'sample'); + expect(stage['args']['type'], 'percentage'); + expect(stage['args']['value'], 0.6); + }); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_snapshot_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_snapshot_test.dart new file mode 100644 index 000000000000..5d727129ab44 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_snapshot_test.dart @@ -0,0 +1,80 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './mock.dart'; + +void main() { + setupCloudFirestoreMocks(); + + late FirebaseFirestore firestore; + + setUpAll(() async { + await Firebase.initializeApp(); + firestore = FirebaseFirestore.instance; + }); + + group('PipelineResult', () { + test('stores and returns data via data()', () { + final data = {'name': 'Alice', 'score': 100}; + final result = PipelineResult(data: data); + expect(result.data(), data); + }); + + test('data() returns null when data is null', () { + final result = PipelineResult(); + expect(result.data(), isNull); + }); + + test('stores document reference when provided', () { + final docRef = firestore.collection('users').doc('123'); + final result = PipelineResult(document: docRef); + expect(result.document, docRef); + }); + + test('document is null for aggregate-only result', () { + final result = PipelineResult( + data: {'count': 42}, + ); + expect(result.document, isNull); + }); + + test('stores createTime and updateTime', () { + final create = DateTime(2026); + final update = DateTime(2026, 1, 2); + final result = PipelineResult( + createTime: create, + updateTime: update, + ); + expect(result.createTime, create); + expect(result.updateTime, update); + }); + + test('stores empty data map', () { + final result = PipelineResult(data: {}); + expect(result.data(), isEmpty); + expect(result.data(), isNotNull); + }); + + test('stores all fields together', () { + final docRef = firestore.collection('orders').doc('o1'); + final dateTime1 = DateTime(2026, 2); + final dateTime2 = DateTime(2026, 2, 2); + final data = {'total': 99.99}; + final result = PipelineResult( + document: docRef, + createTime: dateTime1, + updateTime: dateTime2, + data: data, + ); + expect(result.document, docRef); + expect(result.createTime, dateTime1); + expect(result.updateTime, dateTime2); + expect(result.data(), data); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_source_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_source_test.dart new file mode 100644 index 000000000000..a7279c1b1896 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_source_test.dart @@ -0,0 +1,155 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './mock.dart'; + +void main() { + setupCloudFirestoreMocks(); + + late FirebaseFirestore firestore; + + setUpAll(() async { + await Firebase.initializeApp(); + firestore = FirebaseFirestore.instance; + }); + + group('PipelineSource', () { + test('pipeline() returns a PipelineSource', () { + final source = firestore.pipeline(); + expect(source, isA()); + }); + + group('collection()', () { + test('creates pipeline with collection stage', () { + final pipeline = firestore.pipeline().collection('users'); + expect(pipeline.stages, hasLength(1)); + expect(pipeline.stages.first, { + 'stage': 'collection', + 'args': {'path': 'users'}, + }); + }); + + test('accepts nested collection path', () { + final pipeline = firestore.pipeline().collection('users/abc123/orders'); + expect(pipeline.stages.first['args'], {'path': 'users/abc123/orders'}); + }); + + test('throws on empty path', () { + expect( + () => firestore.pipeline().collection(''), + throwsArgumentError, + ); + }); + + test('throws on path containing double slash', () { + expect( + () => firestore.pipeline().collection('users//posts'), + throwsArgumentError, + ); + }); + }); + + group('collectionReference()', () { + test('creates pipeline from collection reference path', () { + final colRef = firestore.collection('products'); + final pipeline = firestore.pipeline().collectionReference(colRef); + expect(pipeline.stages, hasLength(1)); + expect(pipeline.stages.first, { + 'stage': 'collection', + 'args': {'path': 'products'}, + }); + }); + + test('uses path from nested collection reference', () { + final colRef = + firestore.collection('users').doc('u1').collection('posts'); + final pipeline = firestore.pipeline().collectionReference(colRef); + expect(pipeline.stages.first['args'], { + 'path': 'users/u1/posts', + }); + }); + }); + + group('collectionGroup()', () { + test('creates pipeline with collection_group stage', () { + final pipeline = firestore.pipeline().collectionGroup('posts'); + expect(pipeline.stages, hasLength(1)); + expect(pipeline.stages.first, { + 'stage': 'collection_group', + 'args': {'path': 'posts'}, + }); + }); + + test('throws on empty collection id', () { + expect( + () => firestore.pipeline().collectionGroup(''), + throwsArgumentError, + ); + }); + + test('throws when collection id contains slash', () { + expect( + () => firestore.pipeline().collectionGroup('users/posts'), + throwsArgumentError, + ); + }); + }); + + group('documents()', () { + test('creates pipeline with documents stage', () { + final docRef = firestore.collection('users').doc('123'); + final pipeline = firestore.pipeline().documents([docRef]); + expect(pipeline.stages, hasLength(1)); + expect(pipeline.stages.first['stage'], 'documents'); + expect( + (pipeline.stages.first['args'] as List).first, + {'path': 'users/123'}, + ); + }); + + test('supports multiple document references', () { + final refs = [ + firestore.collection('c').doc('1'), + firestore.collection('c').doc('2'), + ]; + final pipeline = firestore.pipeline().documents(refs); + final args = pipeline.stages.first['args'] as List; + expect(args, hasLength(2)); + }); + + test('throws on empty list', () { + expect( + () => firestore.pipeline().documents([]), + throwsArgumentError, + ); + }); + }); + + group('database()', () { + test('creates pipeline with database stage only', () { + final pipeline = firestore.pipeline().database(); + expect(pipeline.stages, hasLength(1)); + expect(pipeline.stages.first, {'stage': 'database'}); + }); + }); + + group('chaining from source', () { + test('returned pipeline accepts stage methods', () { + final pipeline = firestore + .pipeline() + .collection('users') + .where(Field('active').equal(Constant(true))) + .limit(5); + expect(pipeline.stages, hasLength(3)); + expect(pipeline.stages[0]['stage'], 'collection'); + expect(pipeline.stages[1]['stage'], 'where'); + expect(pipeline.stages[2]['stage'], 'limit'); + }); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart new file mode 100644 index 000000000000..876d53e368e2 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart @@ -0,0 +1,457 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import './mock.dart'; + +void main() { + setupCloudFirestoreMocks(); + + late FirebaseFirestore firestore; + + setUpAll(() async { + await Firebase.initializeApp(); + firestore = FirebaseFirestore.instance; + }); + + group('Pipeline stages serialization', () { + group('_CollectionPipelineStage', () { + test('serializes collection path correctly', () { + final pipeline = firestore.pipeline().collection('users'); + expect(pipeline.stages.first, { + 'stage': 'collection', + 'args': {'path': 'users'}, + }); + }); + + test('serializes nested collection path', () { + final pipeline = firestore.pipeline().collection('users/123/posts'); + expect(pipeline.stages.first, { + 'stage': 'collection', + 'args': {'path': 'users/123/posts'}, + }); + }); + + test('throws on empty collection path', () { + expect( + () => firestore.pipeline().collection(''), + throwsArgumentError, + ); + }); + + test('throws on collection path with double slashes', () { + expect( + () => firestore.pipeline().collection('users//posts'), + throwsArgumentError, + ); + }); + }); + + group('_CollectionGroupPipelineStage', () { + test('serializes collection group path correctly', () { + final pipeline = firestore.pipeline().collectionGroup('posts'); + expect(pipeline.stages.first, { + 'stage': 'collection_group', + 'args': {'path': 'posts'}, + }); + }); + + test('throws on empty collection group id', () { + expect( + () => firestore.pipeline().collectionGroup(''), + throwsArgumentError, + ); + }); + + test('throws on collection group id containing slash', () { + expect( + () => firestore.pipeline().collectionGroup('users/posts'), + throwsArgumentError, + ); + }); + }); + + group('_DatabasePipelineStage', () { + test('serializes database stage correctly', () { + final pipeline = firestore.pipeline().database(); + expect(pipeline.stages.first, {'stage': 'database'}); + }); + }); + + group('_DocumentsPipelineStage', () { + test('serializes document references', () { + final docRef = firestore.collection('users').doc('123'); + final pipeline = firestore.pipeline().documents([docRef]); + expect(pipeline.stages.first['stage'], 'documents'); + final args = pipeline.stages.first['args'] as List; + expect(args, hasLength(1)); + expect(args.first, {'path': 'users/123'}); + }); + + test('serializes multiple document references', () { + final ref1 = firestore.collection('users').doc('1'); + final ref2 = firestore.collection('users').doc('2'); + final pipeline = firestore.pipeline().documents([ref1, ref2]); + final args = pipeline.stages.first['args'] as List; + expect(args, hasLength(2)); + }); + + test('throws on empty documents list', () { + expect( + () => firestore.pipeline().documents([]), + throwsArgumentError, + ); + }); + }); + + group('_WhereStage', () { + test('serializes where stage with a field filter', () { + final pipeline = firestore + .pipeline() + .collection('users') + .where(Field('age').greaterThan(Constant(18))); + final whereStage = pipeline.stages.last; + expect(whereStage['stage'], 'where'); + expect(whereStage['args'], isA()); + expect(whereStage['args']['expression'], isNotNull); + }); + }); + + group('_SelectStage', () { + test('serializes select stage with fields', () { + final pipeline = firestore + .pipeline() + .collection('users') + .select(Field('name'), Field('age')); + final selectStage = pipeline.stages.last; + expect(selectStage['stage'], 'select'); + expect(selectStage['args']['expressions'], hasLength(2)); + }); + + test('serializes select stage with alias', () { + final pipeline = firestore + .pipeline() + .collection('users') + .select(Field('name').as('userName')); + final selectStage = pipeline.stages.last; + expect(selectStage['stage'], 'select'); + expect(selectStage['args']['expressions'], hasLength(1)); + }); + }); + + group('_AddFieldsStage', () { + test('serializes addFields stage', () { + final pipeline = firestore + .pipeline() + .collection('users') + .addFields(Field('score').as('totalScore')); + final stage = pipeline.stages.last; + expect(stage['stage'], 'add_fields'); + expect(stage['args']['expressions'], hasLength(1)); + }); + + test('serializes addFields with multiple fields', () { + final pipeline = firestore.pipeline().collection('users').addFields( + Field('a').as('x'), + Field('b').as('y'), + Field('c').as('z'), + ); + final stage = pipeline.stages.last; + expect(stage['stage'], 'add_fields'); + expect(stage['args']['expressions'], hasLength(3)); + }); + }); + + group('_LimitStage', () { + test('serializes limit stage', () { + final pipeline = firestore.pipeline().collection('users').limit(10); + final stage = pipeline.stages.last; + expect(stage, { + 'stage': 'limit', + 'args': {'limit': 10}, + }); + }); + }); + + group('_OffsetStage', () { + test('serializes offset stage', () { + final pipeline = firestore.pipeline().collection('users').offset(5); + final stage = pipeline.stages.last; + expect(stage, { + 'stage': 'offset', + 'args': {'offset': 5}, + }); + }); + }); + + group('_SortStage', () { + test('serializes sort stage ascending', () { + final pipeline = firestore + .pipeline() + .collection('users') + .sort(Ordering(Field('name'), OrderDirection.asc)); + final stage = pipeline.stages.last; + expect(stage['stage'], 'sort'); + final orderings = stage['args']['orderings'] as List; + expect(orderings, hasLength(1)); + expect(orderings.first['order_direction'], 'asc'); + }); + + test('serializes sort stage descending', () { + final pipeline = firestore + .pipeline() + .collection('users') + .sort(Ordering(Field('score'), OrderDirection.desc)); + final stage = pipeline.stages.last; + final orderings = stage['args']['orderings'] as List; + expect(orderings.first['order_direction'], 'desc'); + }); + + test('serializes multiple orderings', () { + final pipeline = firestore.pipeline().collection('users').sort( + Ordering(Field('lastName'), OrderDirection.asc), + Ordering(Field('firstName'), OrderDirection.asc), + ); + final stage = pipeline.stages.last; + expect( + stage['args']['orderings'] as List, + hasLength(2), + ); + }); + }); + + group('_AggregateStage', () { + test('serializes aggregate stage', () { + final pipeline = firestore + .pipeline() + .collection('orders') + .aggregate(CountAll().as('totalCount')); + final stage = pipeline.stages.last; + expect(stage['stage'], 'aggregate'); + expect( + stage['args']['aggregate_functions'], + hasLength(1), + ); + }); + + test('serializes multiple aggregate functions', () { + final pipeline = firestore.pipeline().collection('orders').aggregate( + CountAll().as('count'), + Sum(Field('amount')).as('total'), + ); + final stage = pipeline.stages.last; + expect( + stage['args']['aggregate_functions'] as List, + hasLength(2), + ); + }); + }); + + group('_AggregateStageWithOptions', () { + test('serializes aggregate stage with accumulators only', () { + final pipeline = + firestore.pipeline().collection('orders').aggregateWithOptions( + AggregateStageOptions( + accumulators: [CountAll().as('count')], + ), + ); + final stage = pipeline.stages.last; + expect(stage['stage'], 'aggregate_with_options'); + final aggregateStage = + stage['args']['aggregate_stage'] as Map; + expect(aggregateStage['accumulators'], hasLength(1)); + expect(aggregateStage.containsKey('groups'), isFalse); + }); + + test('serializes aggregate stage with accumulators and groups', () { + final pipeline = + firestore.pipeline().collection('orders').aggregateWithOptions( + AggregateStageOptions( + accumulators: [ + Sum(Field('amount')).as('total'), + CountAll().as('count'), + ], + groups: [Field('category')], + ), + ); + final stage = pipeline.stages.last; + expect(stage['stage'], 'aggregate_with_options'); + final aggregateStage = + stage['args']['aggregate_stage'] as Map; + expect(aggregateStage['accumulators'], hasLength(2)); + expect(aggregateStage['groups'], hasLength(1)); + }); + + test('includes options map in args', () { + final pipeline = + firestore.pipeline().collection('orders').aggregateWithOptions( + AggregateStageOptions( + accumulators: [CountAll().as('count')], + ), + ); + final stage = pipeline.stages.last; + expect(stage['args'].containsKey('options'), isTrue); + }); + }); + + group('_DistinctStage', () { + test('serializes distinct stage', () { + final pipeline = + firestore.pipeline().collection('users').distinct(Field('country')); + final stage = pipeline.stages.last; + expect(stage['stage'], 'distinct'); + expect(stage['args']['expressions'], hasLength(1)); + }); + }); + + group('_RemoveFieldsStage', () { + test('serializes removeFields stage', () { + final pipeline = firestore + .pipeline() + .collection('users') + .removeFields('password', 'secretToken'); + final stage = pipeline.stages.last; + expect(stage, { + 'stage': 'remove_fields', + 'args': { + 'field_paths': ['password', 'secretToken'], + }, + }); + }); + }); + + group('_ReplaceWithStage', () { + test('serializes replaceWith stage', () { + final pipeline = firestore + .pipeline() + .collection('users') + .replaceWith(Field('profile')); + final stage = pipeline.stages.last; + expect(stage['stage'], 'replace_with'); + expect(stage['args']['expression'], isNotNull); + }); + }); + + group('_SampleStage', () { + test('serializes sample with size', () { + final pipeline = firestore + .pipeline() + .collection('users') + .sample(PipelineSample.withSize(100)); + final stage = pipeline.stages.last; + expect(stage['stage'], 'sample'); + expect(stage['args']['type'], 'size'); + expect(stage['args']['value'], 100); + }); + + test('serializes sample with percentage', () { + final pipeline = firestore + .pipeline() + .collection('users') + .sample(PipelineSample.withPercentage(0.1)); + final stage = pipeline.stages.last; + expect(stage['stage'], 'sample'); + expect(stage['args']['type'], 'percentage'); + expect(stage['args']['value'], 0.1); + }); + }); + + group('_FindNearestStage', () { + test('serializes findNearest without limit', () { + final pipeline = firestore.pipeline().collection('items').findNearest( + Field('embedding'), + [0.1, 0.2, 0.3], + DistanceMeasure.cosine, + ); + final stage = pipeline.stages.last; + expect(stage['stage'], 'find_nearest'); + expect(stage['args']['vector_field'], 'embedding'); + expect(stage['args']['vector_value'], [0.1, 0.2, 0.3]); + expect(stage['args']['distance_measure'], 'cosine'); + expect(stage['args'].containsKey('limit'), isFalse); + }); + + test('serializes findNearest with limit', () { + final pipeline = firestore.pipeline().collection('items').findNearest( + Field('embedding'), + [0.1, 0.2, 0.3], + DistanceMeasure.euclidean, + limit: 5, + ); + final stage = pipeline.stages.last; + expect(stage['args']['limit'], 5); + expect(stage['args']['distance_measure'], 'euclidean'); + }); + + test('serializes findNearest with dotProduct distance', () { + final pipeline = firestore.pipeline().collection('items').findNearest( + Field('embedding'), + [1.0, 0.0], + DistanceMeasure.dotProduct, + ); + final stage = pipeline.stages.last; + expect(stage['args']['distance_measure'], 'dotProduct'); + }); + }); + + group('_UnionStage', () { + test('serializes union stage with nested pipeline stages', () { + final innerPipeline = firestore.pipeline().collection('archived_users'); + final pipeline = + firestore.pipeline().collection('users').union(innerPipeline); + final stage = pipeline.stages.last; + expect(stage['stage'], 'union'); + expect(stage['args']['pipeline'], isA()); + expect( + stage['args']['pipeline'] as List, + hasLength(1), + ); + }); + }); + + group('_UnnestStage', () { + test('serializes unnest stage without indexField', () { + final pipeline = firestore + .pipeline() + .collection('users') + .unnest(Field('tags').as('tag')); + final stage = pipeline.stages.last; + expect(stage['stage'], 'unnest'); + expect(stage['args']['expression'], isNotNull); + expect(stage['args'].containsKey('index_field'), isFalse); + }); + + test('serializes unnest stage with indexField', () { + final pipeline = firestore + .pipeline() + .collection('users') + .unnest(Field('tags').as('tag'), 'idx'); + final stage = pipeline.stages.last; + expect(stage['args']['index_field'], 'idx'); + }); + }); + + group('Stage chaining', () { + test('accumulates stages in order', () { + final pipeline = firestore + .pipeline() + .collection('users') + .where(Field('age').greaterThan(Constant(18))) + .select(Field('name')) + .limit(10) + .offset(0); + + expect(pipeline.stages, hasLength(5)); + expect(pipeline.stages[0]['stage'], 'collection'); + expect(pipeline.stages[1]['stage'], 'where'); + expect(pipeline.stages[2]['stage'], 'select'); + expect(pipeline.stages[3]['stage'], 'limit'); + expect(pipeline.stages[4]['stage'], 'offset'); + }); + }); + }); +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart index 9f9b8e7866e0..2e7e97bec179 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/cloud_firestore_platform_interface.dart @@ -29,6 +29,8 @@ export 'src/platform_interface/platform_interface_index_definitions.dart'; export 'src/platform_interface/platform_interface_load_bundle_task.dart'; export 'src/platform_interface/platform_interface_load_bundle_task_snapshot.dart'; export 'src/platform_interface/platform_interface_persistent_cache_index_manager.dart'; +export 'src/platform_interface/platform_interface_pipeline.dart'; +export 'src/platform_interface/platform_interface_pipeline_snapshot.dart'; export 'src/platform_interface/platform_interface_query.dart'; export 'src/platform_interface/platform_interface_query_snapshot.dart'; export 'src/platform_interface/platform_interface_transaction.dart'; diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart index 573e5a3c91b9..889ea4c5351b 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart @@ -15,6 +15,8 @@ import 'package:flutter/services.dart'; import 'method_channel_collection_reference.dart'; import 'method_channel_document_reference.dart'; +import 'method_channel_pipeline.dart'; +import 'method_channel_pipeline_snapshot.dart'; import 'method_channel_query.dart'; import 'method_channel_transaction.dart'; import 'method_channel_write_batch.dart'; @@ -350,4 +352,37 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { convertPlatformException(e, stack); } } + + @override + PipelinePlatform pipeline(List> initialStages) { + return MethodChannelPipeline(this, pigeonApp, stages: initialStages); + } + + @override + Future executePipeline( + List> stages, { + Map? options, + }) async { + try { + // Convert stages to Pigeon format (List?>) + final List?> pigeonStages = stages.map((stage) { + return stage.map(MapEntry.new); + }).toList(); + + // Convert options to Pigeon format (Map?) + final Map? pigeonOptions = options?.map( + MapEntry.new, + ); + + final PigeonPipelineSnapshot result = await pigeonChannel.executePipeline( + pigeonApp, + pigeonStages, + pigeonOptions, + ); + + return MethodChannelPipelineSnapshot(this, pigeonApp, result); + } catch (e, stack) { + convertPlatformException(e, stack); + } + } } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart new file mode 100644 index 000000000000..7e0b65e43c7d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline.dart @@ -0,0 +1,51 @@ +// ignore_for_file: require_trailing_commas, unnecessary_lambdas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; +import 'package:cloud_firestore_platform_interface/src/platform_interface/platform_interface_pipeline.dart' + as pipeline; + +/// An implementation of [PipelinePlatform] that uses [MethodChannel] to +/// communicate with Firebase plugins. +class MethodChannelPipeline extends pipeline.PipelinePlatform { + /// Create a [MethodChannelPipeline] from [stages] + MethodChannelPipeline( + FirebaseFirestorePlatform _firestore, + this.pigeonApp, { + List>? stages, + }) : super(_firestore, stages); + + final FirestorePigeonFirebaseApp pigeonApp; + + /// Creates a new instance of [MethodChannelPipeline], however overrides + /// any existing [stages]. + /// + /// This is in place to ensure that changes to a pipeline don't mutate + /// other pipelines. + MethodChannelPipeline _copyWithStages(List> newStages) { + return MethodChannelPipeline( + firestore, + pigeonApp, + stages: List.unmodifiable([ + ...stages, + ...newStages, + ]), + ); + } + + @override + pipeline.PipelinePlatform addStage(Map serializedStage) { + return _copyWithStages([serializedStage]); + } + + @override + Future execute({ + Map? options, + }) async { + return firestore.executePipeline(stages, options: options); + } +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart new file mode 100644 index 000000000000..c5f351ef88ed --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart @@ -0,0 +1,83 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; +import 'package:cloud_firestore_platform_interface/src/method_channel/method_channel_document_reference.dart'; + +/// An implementation of [PipelineSnapshotPlatform] that uses [MethodChannel] to +/// communicate with Firebase plugins. +class MethodChannelPipelineSnapshot extends PipelineSnapshotPlatform { + final List _results; + final DateTime _executionTime; + + /// Creates a [MethodChannelPipelineSnapshot] from the given [pigeonSnapshot] + MethodChannelPipelineSnapshot( + FirebaseFirestorePlatform firestore, + FirestorePigeonFirebaseApp pigeonApp, + PigeonPipelineSnapshot pigeonSnapshot, + ) : _results = pigeonSnapshot.results + .whereType() + .map((result) => MethodChannelPipelineResult( + firestore, + pigeonApp, + result.documentPath, + result.createTime != null + ? DateTime.fromMillisecondsSinceEpoch(result.createTime!) + : null, + result.updateTime != null + ? DateTime.fromMillisecondsSinceEpoch(result.updateTime!) + : null, + result.data?.cast(), + )) + .toList(), + _executionTime = DateTime.fromMillisecondsSinceEpoch( + pigeonSnapshot.executionTime, + ), + super(); + + @override + List get results => _results; + + @override + DateTime get executionTime => _executionTime; +} + +/// An implementation of [PipelineResultPlatform] that uses [MethodChannel] to +/// communicate with Firebase plugins. +class MethodChannelPipelineResult extends PipelineResultPlatform { + final DocumentReferencePlatform? _document; + final DateTime? _createTime; + final DateTime? _updateTime; + final Map? _data; + + MethodChannelPipelineResult( + FirebaseFirestorePlatform firestore, + FirestorePigeonFirebaseApp pigeonApp, + String? documentPath, + this._createTime, + this._updateTime, + Map? data, + ) : _document = (documentPath != null && documentPath.isNotEmpty) + ? MethodChannelDocumentReference( + firestore, + documentPath, + pigeonApp, + ) + : null, + _data = data, + super(); + + @override + DocumentReferencePlatform? get document => _document; + + @override + DateTime? get createTime => _createTime; + + @override + DateTime? get updateTime => _updateTime; + + @override + Map? get data => _data; +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart index 2420b2cfc4b4..662ed9358d9f 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -301,6 +301,69 @@ class PigeonQuerySnapshot { } } +class PigeonPipelineResult { + PigeonPipelineResult({ + this.documentPath, + this.createTime, + this.updateTime, + this.data, + }); + + String? documentPath; + + int? createTime; + + int? updateTime; + + /// All fields in the result (from PipelineResult.data() on Android). + Map? data; + + Object encode() { + return [ + documentPath, + createTime, + updateTime, + data, + ]; + } + + static PigeonPipelineResult decode(Object result) { + result as List; + return PigeonPipelineResult( + documentPath: result[0] as String?, + createTime: result[1] as int?, + updateTime: result[2] as int?, + data: (result[3] as Map?)?.cast(), + ); + } +} + +class PigeonPipelineSnapshot { + PigeonPipelineSnapshot({ + required this.results, + required this.executionTime, + }); + + List results; + + int executionTime; + + Object encode() { + return [ + results, + executionTime, + ]; + } + + static PigeonPipelineSnapshot decode(Object result) { + result as List; + return PigeonPipelineSnapshot( + results: (result[0] as List?)!.cast(), + executionTime: result[1]! as int, + ); + } +} + class PigeonGetOptions { PigeonGetOptions({ required this.source, @@ -586,18 +649,24 @@ class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec { } else if (value is PigeonGetOptions) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is PigeonQueryParameters) { + } else if (value is PigeonPipelineResult) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PigeonQuerySnapshot) { + } else if (value is PigeonPipelineSnapshot) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonSnapshotMetadata) { + } else if (value is PigeonQueryParameters) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonTransactionCommand) { + } else if (value is PigeonQuerySnapshot) { buffer.putUint8(140); writeValue(buffer, value.encode()); + } else if (value is PigeonSnapshotMetadata) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonTransactionCommand) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -625,12 +694,16 @@ class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec { case 136: return PigeonGetOptions.decode(readValue(buffer)!); case 137: - return PigeonQueryParameters.decode(readValue(buffer)!); + return PigeonPipelineResult.decode(readValue(buffer)!); case 138: - return PigeonQuerySnapshot.decode(readValue(buffer)!); + return PigeonPipelineSnapshot.decode(readValue(buffer)!); case 139: - return PigeonSnapshotMetadata.decode(readValue(buffer)!); + return PigeonQueryParameters.decode(readValue(buffer)!); case 140: + return PigeonQuerySnapshot.decode(readValue(buffer)!); + case 141: + return PigeonSnapshotMetadata.decode(readValue(buffer)!); + case 142: return PigeonTransactionCommand.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -1342,4 +1415,37 @@ class FirebaseFirestoreHostApi { return; } } + + Future executePipeline( + FirestorePigeonFirebaseApp arg_app, + List?> arg_stages, + Map? arg_options, + ) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline', + codec, + binaryMessenger: _binaryMessenger, + ); + final List? replyList = await channel + .send([arg_app, arg_stages, arg_options]) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as PigeonPipelineSnapshot?)!; + } + } } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart index 3faffc0a3778..ee9cd3a32478 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_firestore.dart @@ -243,6 +243,21 @@ abstract class FirebaseFirestorePlatform extends PlatformInterface { throw UnimplementedError('setLoggingEnabled() is not implemented'); } + /// Creates a pipeline platform instance with initial stages. + PipelinePlatform pipeline(List> initialStages) { + throw UnimplementedError('pipeline() is not implemented'); + } + + /// Executes a pipeline and returns the results. + /// + /// The [stages] parameter contains the serialized pipeline stages. + Future executePipeline( + List> stages, { + Map? options, + }) { + throw UnimplementedError('executePipeline() is not implemented'); + } + @override //ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) => diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart new file mode 100644 index 000000000000..2d0449ee4aef --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline.dart @@ -0,0 +1,54 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; +import 'package:meta/meta.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +/// Represents a pipeline for querying and transforming Firestore data. +@immutable +abstract class PipelinePlatform extends PlatformInterface { + /// Create a [PipelinePlatform] instance + PipelinePlatform(this.firestore, List>? stages) + : _stages = stages ?? [], + super(token: _token); + + static final Object _token = Object(); + + /// Throws an [AssertionError] if [instance] does not extend + /// [PipelinePlatform]. + /// + /// This is used by the app-facing [Pipeline] to ensure that + /// the object in which it's going to delegate calls has been + /// constructed properly. + static void verify(PipelinePlatform instance) { + PlatformInterface.verify(instance, _token); + } + + /// The [FirebaseFirestorePlatform] interface for this current pipeline. + final FirebaseFirestorePlatform firestore; + + /// Stores the pipeline stages. + final List> _stages; + + /// Exposes the [stages] on the pipeline delegate. + /// + /// This should only be used for testing to ensure that all + /// pipeline stages are correctly set on the underlying delegate + /// when being tested from a different package. + List> get stages { + return List.unmodifiable(_stages); + } + + /// Adds a serialized stage to the pipeline + PipelinePlatform addStage(Map serializedStage); + + /// Executes the pipeline and returns a snapshot of the results + Future execute({ + Map? options, + }); +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart new file mode 100644 index 000000000000..1946ce740712 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_pipeline_snapshot.dart @@ -0,0 +1,44 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import '../../cloud_firestore_platform_interface.dart'; +import 'platform_interface_document_reference.dart'; + +/// Platform interface for [PipelineSnapshot]. +abstract class PipelineSnapshotPlatform extends PlatformInterface { + /// Create an instance of [PipelineSnapshotPlatform]. + PipelineSnapshotPlatform() : super(token: _token); + + static final Object _token = Object(); + + /// The results of the pipeline execution + List get results; + + /// The execution time of the pipeline + DateTime get executionTime; +} + +/// Platform interface for [PipelineResult]. +abstract class PipelineResultPlatform extends PlatformInterface { + /// Create an instance of [PipelineResultPlatform]. + PipelineResultPlatform() : super(token: _token); + + static final Object _token = Object(); + + /// The document reference. Null for aggregate-only results (no document row). + DocumentReferencePlatform? get document; + + /// The creation time of the document + DateTime? get createTime; + + /// The update time of the document + DateTime? get updateTime; + + /// All fields in the result (from PipelineResult.data() on the native SDK). + /// Returns null if the result has no data. + Map? get data; +} diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh index f6f0a2d4aef5..e8950e42ef53 100755 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh @@ -15,7 +15,7 @@ sed -i '' 's/private static class FirebaseFirestoreHostApiCodec extends Standard echo "Android modification complete." # Fix iOS files -FILE_NAME="../../cloud_firestore/ios/Classes/FirestoreMessages.g.m" +FILE_NAME="../../cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m" sed -i '' '/#import "FirestoreMessages.g.h"/a\ #import "FLTFirebaseFirestoreReader.h"\ #import "FLTFirebaseFirestoreWriter.h" @@ -26,7 +26,7 @@ sed -i '' 's/(self\.newIndex \?: \[NSNull null\]),/(self.index ?: [NSNull null]) sed -i '' 's/@interface FirebaseFirestoreHostApiCodecReader : FlutterStandardReader/@interface FirebaseFirestoreHostApiCodecReader : FLTFirebaseFirestoreReader/' $FILE_NAME sed -i '' 's/@interface FirebaseFirestoreHostApiCodecWriter : FlutterStandardWriter/@interface FirebaseFirestoreHostApiCodecWriter : FLTFirebaseFirestoreWriter/' $FILE_NAME -FILE_NAME="../../cloud_firestore/ios/Classes/Public/FirestoreMessages.g.h" +FILE_NAME="../../cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h" sed -i '' 's/@property(nonatomic, strong) NSNumber \*newIndex;/@property(nonatomic, strong) NSNumber \*index;/' $FILE_NAME echo "iOS modification complete." diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart index 1c1bda0a1177..a84c58f7af56 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart @@ -118,6 +118,31 @@ class PigeonQuerySnapshot { final PigeonSnapshotMetadata metadata; } +class PigeonPipelineResult { + const PigeonPipelineResult({ + this.documentPath, + this.createTime, + this.updateTime, + this.data, + }); + + final String? documentPath; + final int? createTime; // Timestamp in milliseconds since epoch + final int? updateTime; // Timestamp in milliseconds since epoch + /// All fields in the result (from PipelineResult.data() on Android). + final Map? data; +} + +class PigeonPipelineSnapshot { + const PigeonPipelineSnapshot({ + required this.results, + required this.executionTime, + }); + + final List results; + final int executionTime; // Timestamp in milliseconds since epoch +} + /// An enumeration of firestore source types. enum Source { /// Causes Firestore to try to retrieve an up-to-date (server-retrieved) snapshot, but fall back to @@ -442,4 +467,11 @@ abstract class FirebaseFirestoreHostApi { FirestorePigeonFirebaseApp app, PersistenceCacheIndexManagerRequest request, ); + + @async + PigeonPipelineSnapshot executePipeline( + FirestorePigeonFirebaseApp app, + List?> stages, + Map? options, + ); } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart index 32d57ebdcb48..e9ed58eafc5c 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart @@ -7,12 +7,12 @@ // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Uint8List; - -import 'package:cloud_firestore_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:cloud_firestore_platform_interface/src/pigeon/messages.pigeon.dart'; + class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { const _TestFirebaseFirestoreHostApiCodec(); @override @@ -44,18 +44,24 @@ class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { } else if (value is PigeonGetOptions) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is PigeonQueryParameters) { + } else if (value is PigeonPipelineResult) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PigeonQuerySnapshot) { + } else if (value is PigeonPipelineSnapshot) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonSnapshotMetadata) { + } else if (value is PigeonQueryParameters) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonTransactionCommand) { + } else if (value is PigeonQuerySnapshot) { buffer.putUint8(140); writeValue(buffer, value.encode()); + } else if (value is PigeonSnapshotMetadata) { + buffer.putUint8(141); + writeValue(buffer, value.encode()); + } else if (value is PigeonTransactionCommand) { + buffer.putUint8(142); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -63,22 +69,40 @@ class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { - return switch (type) { - 128 => AggregateQuery.decode(readValue(buffer)!), - 129 => AggregateQueryResponse.decode(readValue(buffer)!), - 130 => DocumentReferenceRequest.decode(readValue(buffer)!), - 131 => FirestorePigeonFirebaseApp.decode(readValue(buffer)!), - 132 => PigeonDocumentChange.decode(readValue(buffer)!), - 133 => PigeonDocumentOption.decode(readValue(buffer)!), - 134 => PigeonDocumentSnapshot.decode(readValue(buffer)!), - 135 => PigeonFirebaseSettings.decode(readValue(buffer)!), - 136 => PigeonGetOptions.decode(readValue(buffer)!), - 137 => PigeonQueryParameters.decode(readValue(buffer)!), - 138 => PigeonQuerySnapshot.decode(readValue(buffer)!), - 139 => PigeonSnapshotMetadata.decode(readValue(buffer)!), - 140 => PigeonTransactionCommand.decode(readValue(buffer)!), - _ => super.readValueOfType(type, buffer) - }; + switch (type) { + case 128: + return AggregateQuery.decode(readValue(buffer)!); + case 129: + return AggregateQueryResponse.decode(readValue(buffer)!); + case 130: + return DocumentReferenceRequest.decode(readValue(buffer)!); + case 131: + return FirestorePigeonFirebaseApp.decode(readValue(buffer)!); + case 132: + return PigeonDocumentChange.decode(readValue(buffer)!); + case 133: + return PigeonDocumentOption.decode(readValue(buffer)!); + case 134: + return PigeonDocumentSnapshot.decode(readValue(buffer)!); + case 135: + return PigeonFirebaseSettings.decode(readValue(buffer)!); + case 136: + return PigeonGetOptions.decode(readValue(buffer)!); + case 137: + return PigeonPipelineResult.decode(readValue(buffer)!); + case 138: + return PigeonPipelineSnapshot.decode(readValue(buffer)!); + case 139: + return PigeonQueryParameters.decode(readValue(buffer)!); + case 140: + return PigeonQuerySnapshot.decode(readValue(buffer)!); + case 141: + return PigeonSnapshotMetadata.decode(readValue(buffer)!); + case 142: + return PigeonTransactionCommand.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } } } @@ -197,6 +221,12 @@ abstract class TestFirebaseFirestoreHostApi { PersistenceCacheIndexManagerRequest request, ); + Future executePipeline( + FirestorePigeonFirebaseApp app, + List?> stages, + Map? options, + ); + static void setup( TestFirebaseFirestoreHostApi? api, { BinaryMessenger? binaryMessenger, @@ -1088,5 +1118,43 @@ abstract class TestFirebaseFirestoreHostApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline', + codec, + binaryMessenger: binaryMessenger, + ); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(channel, + (Object? message) async { + assert( + message != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null.', + ); + final List args = (message as List?)!; + final FirestorePigeonFirebaseApp? arg_app = + (args[0] as FirestorePigeonFirebaseApp?); + assert( + arg_app != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null, expected non-null FirestorePigeonFirebaseApp.', + ); + final List?>? arg_stages = + (args[1] as List?)?.cast?>(); + assert( + arg_stages != null, + 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null, expected non-null List?>.', + ); + final Map? arg_options = + (args[2] as Map?)?.cast(); + final PigeonPipelineSnapshot output = + await api.executePipeline(arg_app!, arg_stages!, arg_options); + return [output]; + }); + } + } } } diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/cloud_firestore_web.dart b/packages/cloud_firestore/cloud_firestore_web/lib/cloud_firestore_web.dart index ff68541be65a..04d722e3decf 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/cloud_firestore_web.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/cloud_firestore_web.dart @@ -21,6 +21,9 @@ import 'src/collection_reference_web.dart'; import 'src/document_reference_web.dart'; import 'src/field_value_factory_web.dart'; import 'src/interop/firestore.dart' as firestore_interop; +import 'src/interop/firestore_interop.dart' as firestore_interop_js; +import 'src/pipeline_builder_web.dart'; +import 'src/pipeline_web.dart'; import 'src/query_web.dart'; import 'src/transaction_web.dart'; import 'src/write_batch_web.dart'; @@ -271,4 +274,48 @@ class FirebaseFirestoreWeb extends FirebaseFirestorePlatform { } _delegate.setLoggingEnabled(value); } + + @override + PipelinePlatform pipeline(List> initialStages) { + return PipelineWeb(this, _delegate, initialStages); + } + + @override + Future executePipeline( + List> stages, { + Map? options, + }) async { + final jsFirestore = _delegate.jsObject; + firestore_interop_js.PipelineJsImpl jsPipeline; + try { + jsPipeline = buildPipelineFromStages(jsFirestore, stages); + } catch (e, stack) { + // Let our Dart FirebaseException (e.g. unsupported expression) propagate + // so the user sees a clear message; the guard would cast it to JSError. + if (e is FirebaseException) { + Error.throwWithStackTrace(e, stack); + } + // JS or other errors: run through the guard to convert to FirebaseException. + return convertWebExceptions(() async { + Error.throwWithStackTrace(e, stack); + }); + } + + final dartPipeline = firestore_interop.Pipeline.getInstance(jsPipeline); + return convertWebExceptions(() async { + String? executeOptions; + if (options != null) { + executeOptions = options['indexMode'] as String; + } + final snapshot = await dartPipeline.execute(executeOptions); + + final results = snapshot.results + .map((r) => PipelineResultWeb(this, _delegate, r.jsObject)) + .toList(); + + final executionTime = snapshot.executionTime ?? DateTime.now(); + + return PipelineSnapshotWeb(results, executionTime); + }); + } } diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart index 6703d7738f14..9ed2cf332707 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore.dart @@ -1089,3 +1089,122 @@ class AggregateQuerySnapshot } } } + +// ============================================================================= +// Pipeline (global execute + snapshot/result wrappers) +// ============================================================================= + +/// Single result in a pipeline snapshot (document + data). +class PipelineResult + extends JsObjectWrapper { + static final _expando = Expando(); + + late final DocumentReference? _ref; + late final Map? _data; + late final DateTime? _createTime; + late final DateTime? _updateTime; + + static PipelineResult getInstance( + firestore_interop.PipelineResultJsImpl jsObject) { + return _expando[jsObject] ??= PipelineResult._fromJsObject(jsObject); + } + + PipelineResult._fromJsObject(firestore_interop.PipelineResultJsImpl jsObject) + : _ref = jsObject.ref != null + ? DocumentReference.getInstance(jsObject.ref!) + : null, + _data = _dataFromResult(jsObject), + _createTime = _timestampToDateTime(jsObject.createTime), + _updateTime = _timestampToDateTime(jsObject.updateTime), + super.fromJsObject(jsObject); + + static Map? _dataFromResult( + firestore_interop.PipelineResultJsImpl jsResult) { + final d = jsResult.data(); + if (d == null) return null; + final parsed = dartify(d); + return parsed != null + ? Map.from(parsed as Map) + : null; + } + + static DateTime? _timestampToDateTime(dynamic value) { + if (value == null) return null; + final d = dartify(value); + if (d == null) return null; + if (d is DateTime) return d; + if (d is Timestamp) return d.toDate(); + if (d is int) return DateTime.fromMillisecondsSinceEpoch(d); + return null; + } + + DocumentReference? get ref => _ref; + Map? get data => _data; + DateTime? get createTime => _createTime; + DateTime? get updateTime => _updateTime; +} + +/// Snapshot of pipeline execution results. +class PipelineSnapshot + extends JsObjectWrapper { + static final _expando = Expando(); + + late final List _results; + late final DateTime? _executionTime; + + static PipelineSnapshot getInstance( + firestore_interop.PipelineSnapshotJsImpl jsObject) { + return _expando[jsObject] ??= PipelineSnapshot._fromJsObject(jsObject); + } + + static List _buildResults( + firestore_interop.PipelineSnapshotJsImpl jsObject) { + final rawResults = jsObject.results.toDart; + return rawResults + .cast() + .map(PipelineResult.getInstance) + .toList(); + } + + PipelineSnapshot._fromJsObject( + firestore_interop.PipelineSnapshotJsImpl jsObject) + : _results = _buildResults(jsObject), + _executionTime = _executionTimeFromJs(jsObject.executionTime), + super.fromJsObject(jsObject); + + static DateTime? _executionTimeFromJs(dynamic value) { + if (value == null) return null; + final d = dartify(value); + if (d == null) return null; + if (d is DateTime) return d; + if (d is int) return DateTime.fromMillisecondsSinceEpoch(d); + return null; + } + + List get results => _results; + DateTime? get executionTime => _executionTime; +} + +/// Wraps a JS pipeline; use [execute] to run it via the global execute function. +class Pipeline extends JsObjectWrapper { + static final _expando = Expando(); + + static Pipeline getInstance(firestore_interop.PipelineJsImpl jsObject) { + return _expando[jsObject] ??= Pipeline._fromJsObject(jsObject); + } + + Pipeline._fromJsObject(firestore_interop.PipelineJsImpl jsObject) + : super.fromJsObject(jsObject); + + /// Runs this pipeline using the global JS SDK execute function. + Future execute(String? executeOptions) async { + final executeOptionsJs = firestore_interop.PipelineExecuteOptionsJsImpl(); + if (executeOptions != null) { + executeOptionsJs.indexMode = executeOptions.toJS; + } + executeOptionsJs.pipeline = jsObject as JSAny; + final snapshot = + await firestore_interop.pipelines.execute(executeOptionsJs).toDart; + return PipelineSnapshot.getInstance(snapshot); + } +} diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart index 85cc51fbffde..a4069ebab335 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart @@ -333,13 +333,200 @@ external JSObject get and; @staticInterop external WriteBatchJsImpl writeBatch(FirestoreJsImpl firestore); -@JS('Firestore') -@staticInterop -abstract class FirestoreJsImpl {} - -extension FirestoreJsImplExtension on FirestoreJsImpl { +extension type FirestoreJsImpl._(JSObject _) implements JSObject { external AppJsImpl get app; external JSString get type; + + /// Returns the pipeline source for building and executing pipelines. + external JSAny pipeline(); +} + +@JS() +@staticInterop +external PipelinesJsImpl get pipelines; + +/// Pipeline expression API — mirrors the Firebase JS SDK pipelines module. +/// Use these to build expressions for where(), sort(), addFields(), aggregate(), etc. +extension type PipelinesJsImpl._(JSObject _) implements JSObject { + external JSPromise execute( + PipelineExecuteOptionsJsImpl pipeline); + + // --- Expression builders --- + external ExpressionJsImpl field(JSString path); + external ExpressionJsImpl constant(JSAny? value); + + // --- Boolean / comparison --- + external JSAny equal(JSAny left, JSAny right); + external JSAny notEqual(JSAny left, JSAny right); + external JSAny greaterThan(JSAny left, JSAny right); + external JSAny greaterThanOrEqual(JSAny left, JSAny right); + external JSAny lessThan(JSAny left, JSAny right); + external JSAny lessThanOrEqual(JSAny left, JSAny right); + external JSAny and(JSAny a, JSAny b); + external JSAny or(JSAny a, JSAny b); + external JSAny xor(JSAny a, JSAny b); + external JSAny not(JSAny expr); + + // --- Existence / type checks --- + external JSAny exists(JSAny expr); + external JSAny isAbsent(JSAny expr); + external JSAny isError(JSAny expr); + + // --- Array --- + external JSAny arrayContains(JSAny array, JSAny element); + external JSAny arrayContainsAny(JSAny array, JSArray values); + external JSAny arrayContainsAll(JSAny array, JSAny valuesOrArray); + + // --- IN / NOT IN (boolean) --- + external JSAny equalAny(JSAny element, JSAny valuesArray); + external JSAny notEqualAny(JSAny element, JSAny valuesArray); + + // --- String / value expressions (global) --- + external ExpressionJsImpl split(JSAny expression, JSAny delimiter); + external ExpressionJsImpl join(JSAny arrayExpression, JSAny delimiter); + external ExpressionJsImpl substring( + JSAny input, JSAny position, JSAny length); + external ExpressionJsImpl stringReplaceAll( + JSAny expression, JSAny find, JSAny replacement); + external ExpressionJsImpl ifAbsent(JSAny expression, JSAny elseExpr); + external ExpressionJsImpl ifError(JSAny expression, JSAny catchExpr); + external ExpressionJsImpl conditional( + JSAny condition, JSAny thenExpr, JSAny elseExpr); + external ExpressionJsImpl documentId(JSAny path); + external ExpressionJsImpl collectionId(JSAny expression); + external ExpressionJsImpl mapGet(JSAny mapExpr, JSString key); + external ExpressionJsImpl mapKeys(JSAny mapExpr); + external ExpressionJsImpl mapValues(JSAny mapExpr); + external ExpressionJsImpl currentTimestamp(); + external ExpressionJsImpl timestampAdd( + JSAny timestamp, JSString unit, JSAny amount); + external ExpressionJsImpl timestampSubtract( + JSAny timestamp, JSString unit, JSAny amount); + external ExpressionJsImpl timestampTruncate(JSAny timestamp, JSString unit, + [JSString? timezone]); + external ExpressionJsImpl abs(JSAny expr); + external ExpressionJsImpl arrayLength(JSAny array); + external ExpressionJsImpl arraySum(JSAny expression); + external ExpressionJsImpl arrayConcat(JSAny first, JSAny second); + external ExpressionJsImpl array(JSArray elements); + external ExpressionJsImpl map(JSObject keyValuePairs); + external ExpressionJsImpl rand(); + + @JS('isType') + external JSAny isTypeExpr(JSAny expression, JSAny typeValue); + + // --- Ordering (for sort stage) --- + external JSAny ascending(JSAny expr); + external JSAny descending(JSAny expr); + + // --- Aggregates --- + external AggregateFunctionJsImpl sum(JSAny expr); + external AggregateFunctionJsImpl average(JSAny expr); + external AggregateFunctionJsImpl count(JSAny expr); + external AggregateFunctionJsImpl countDistinct(JSAny expr); + external AggregateFunctionJsImpl minimum(JSAny expr); + external AggregateFunctionJsImpl maximum(JSAny expr); + external AggregateFunctionJsImpl first(JSAny expr); + external AggregateFunctionJsImpl last(JSAny expr); + external AggregateFunctionJsImpl arrayAgg(JSAny expr); + external AggregateFunctionJsImpl arrayAggDistinct(JSAny expr); + external AggregateFunctionJsImpl countAll(); + + // --- Aliased (for select/addFields/aggregate output names) --- + external JSAny aliased(JSAny expr, JSString alias); +} + +/// Aggregate function (result of sum(), average(), count(), etc. on pipelines). +/// Has .as(alias) to create an aliased aggregate for accumulators. +extension type AggregateFunctionJsImpl._(JSObject _) implements JSObject { + @JS('as') + external JSAny asAlias(JSString alias); +} + +extension type ExpressionJsImpl._(JSObject _) implements JSObject { + @JS('as') + external JSAny asAlias(JSString alias); + + external ExpressionJsImpl add(JSAny right); + external ExpressionJsImpl subtract(JSAny right); + external ExpressionJsImpl multiply(JSAny right); + external ExpressionJsImpl divide(JSAny right); + @JS('mod') + external ExpressionJsImpl modulo(JSAny right); + external ExpressionJsImpl length(); + external ExpressionJsImpl concat(JSAny right); + external ExpressionJsImpl toLower(); + external ExpressionJsImpl toUpper(); + external ExpressionJsImpl trim(); + external ExpressionJsImpl arrayReverse(); + external ExpressionJsImpl asBoolean(); + external ExpressionJsImpl isError(); + external ExpressionJsImpl isAbsent(); + + external ExpressionJsImpl regexFind(JSAny pattern); + external ExpressionJsImpl regexFindAll(JSAny pattern); + external ExpressionJsImpl stringReplaceOne(JSAny find, JSAny replacement); + external ExpressionJsImpl stringIndexOf(JSAny search); + external ExpressionJsImpl stringRepeat(JSAny repetitions); + external ExpressionJsImpl ltrim([JSAny? valueToTrim]); + external ExpressionJsImpl rtrim([JSAny? valueToTrim]); + external ExpressionJsImpl type(); + external ExpressionJsImpl trunc([JSAny? decimals]); + external ExpressionJsImpl arrayFirst(); + external ExpressionJsImpl arrayFirstN(JSAny n); + external ExpressionJsImpl arrayLast(); + external ExpressionJsImpl arrayLastN(JSAny n); + external ExpressionJsImpl arrayMaximum(); + external ExpressionJsImpl arrayMaximumN(JSAny n); + external ExpressionJsImpl arrayMinimum(); + external ExpressionJsImpl arrayMinimumN(JSAny n); + external ExpressionJsImpl arrayIndexOf(JSAny element); + external ExpressionJsImpl arrayLastIndexOf(JSAny element); + external ExpressionJsImpl arrayIndexOfAll(JSAny element); + external ExpressionJsImpl mapSet(JSAny key, JSAny value); + external ExpressionJsImpl mapEntries(); +} + +extension type SelectableJsImpl._(JSObject _) implements JSObject { + @JS('as') + external JSAny asAlias(JSString alias); +} + +/// Aliased aggregate for use in aggregate() stage accumulators. +/// Mirrors Firebase JS SDK: constructor(aggregate, alias, _methodName?). +@JS('AliasedAggregate') +@staticInterop +abstract class AliasedAggregateJsImpl { + external factory AliasedAggregateJsImpl( + JSAny aggregate, + JSString alias, [ + JSString? methodName, + ]); +} + +/// Options for the aggregate() pipeline stage. +/// Mirrors Firebase JS SDK AggregateStageOptions: { accumulators, groups? }. +extension type AggregateStageOptionsJsImpl._(JSObject _) implements JSObject { + AggregateStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set accumulators(JSAny value); + // ignore: avoid_setters_without_getters + external set groups(JSAny value); +} + +extension type SelectStageOptionsJsImpl._(JSObject _) implements JSObject { + SelectStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set selections(JSArray value); +} + +extension type AddFieldsOptionsJsImpl._(JSObject _) implements JSObject { + AddFieldsOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set fields(JSAny value); } extension type WriteBatchJsImpl._(JSObject _) implements JSObject { @@ -1014,3 +1201,141 @@ extension type AggregateQuerySnapshotJsImpl._(JSObject _) implements JSObject { @JS() @staticInterop abstract class PersistentCacheIndexManager {} + +/// Entry point for defining the data source of a Firestore Pipeline. +/// Use .collection(), .collectionGroup(), .database(), or .documents(). +extension type PipelineSourceJsImpl._(JSObject _) implements JSObject { + /// Returns all documents from the entire collection (can be nested). + external PipelineJsImpl collection(JSString collectionPath); + + /// Returns all documents from a collection ID regardless of parent. + external PipelineJsImpl collectionGroup(JSString collectionId); + + /// Returns all documents from the entire database. + external PipelineJsImpl database(); + + /// Sets the pipeline source to the given document paths or references. + external PipelineJsImpl documents(JSArray docs); +} + +/// Pipeline returned by PipelineSource methods; chain stages and call execute(). +/// See: https://firebase.google.com/docs/reference/js/firestore_pipelines.pipeline +extension type PipelineJsImpl._(JSObject _) implements JSObject { + external PipelineJsImpl limit(JSNumber limit); + external PipelineJsImpl offset(JSNumber offset); + external PipelineJsImpl where(JSAny condition); + external PipelineJsImpl sort(JSAny orderingOrOptions); + external PipelineJsImpl addFields(JSAny fieldOrOptions); + external PipelineJsImpl select(JSAny selectionOrOptions); + external PipelineJsImpl distinct(JSAny groupOrOptions); + external PipelineJsImpl aggregate(AggregateStageOptionsJsImpl options); + external PipelineJsImpl sample(JSAny documentsOrOptions); + external PipelineJsImpl unnest(JSAny selectableOrOptions); + external PipelineJsImpl removeFields(JSAny fieldOrOptions); + external PipelineJsImpl replaceWith(JSAny fieldNameOrOptions); + external PipelineJsImpl findNearest(JSAny options); + external PipelineJsImpl union(JSAny otherOrOptions); + external PipelineJsImpl rawStage(JSString name, JSArray params, + [JSAny? options]); +} + +/// Options for pipeline execution (e.g. index mode). +@anonymous +@JS() +@staticInterop +abstract class PipelineExecuteOptions { + external factory PipelineExecuteOptions({JSString? indexMode}); +} + +extension PipelineExecuteOptionsExtension on PipelineExecuteOptions { + external JSString? get indexMode; + external set indexMode(JSString? v); +} + +/// Snapshot of pipeline execution results. +extension type PipelineSnapshotJsImpl._(JSObject _) implements JSObject { + /// Array of [PipelineResultJsImpl]. + external JSArray get results; + + /// Execution time (if provided by SDK). + external JSAny? get executionTime; +} + +/// Single result in a pipeline snapshot (document + data). +extension type PipelineResultJsImpl._(JSObject _) implements JSObject { + external DocumentReferenceJsImpl? get ref; + external JSObject? data(); + external JSAny? get createTime; + external JSAny? get updateTime; +} + +extension type SampleStageOptionsJsImpl._(JSObject _) implements JSObject { + SampleStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set documents(JSAny value); + // ignore: avoid_setters_without_getters + external set percentage(JSAny value); +} + +extension type SortStageOptionsJsImpl._(JSObject _) implements JSObject { + SortStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set orderings(JSAny value); +} + +extension type DistinctStageOptionsJsImpl._(JSObject _) implements JSObject { + DistinctStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set groups(JSAny value); +} + +extension type UnnestStageOptionsJsImpl._(JSObject _) implements JSObject { + UnnestStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set selectable(JSAny value); + // ignore: avoid_setters_without_getters + external set indexField(JSString? value); +} + +extension type RemoveFieldsStageOptionsJsImpl._(JSObject _) + implements JSObject { + RemoveFieldsStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set fields(JSArray value); +} + +extension type ReplaceWithStageOptionsJsImpl._(JSObject _) implements JSObject { + ReplaceWithStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set map(JSAny value); +} + +extension type FindNearestStageOptionsJsImpl._(JSObject _) implements JSObject { + FindNearestStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set field(JSAny value); + // ignore: avoid_setters_without_getters + external set vectorValue(JSAny value); + // ignore: avoid_setters_without_getters + external set distanceMeasure(JSString value); + // ignore: avoid_setters_without_getters + external set limit(JSNumber value); + // ignore: avoid_setters_without_getters + external set distanceField(JSString value); +} + +extension type PipelineExecuteOptionsJsImpl._(JSObject _) implements JSObject { + PipelineExecuteOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set indexMode(JSString value); + // ignore: avoid_setters_without_getters + external set pipeline(JSAny value); +} diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart new file mode 100644 index 000000000000..bc2db69e575d --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart @@ -0,0 +1,137 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:js_interop'; + +import 'package:cloud_firestore_web/src/interop/firestore_interop.dart' + as interop; +import 'package:cloud_firestore_web/src/pipeline_expression_parser_web.dart'; +import 'package:firebase_core/firebase_core.dart'; + +/// Builds a JS Pipeline from serialized [stages] and returns it ready to execute. +/// Keeps [executePipeline] thin: build → execute → convert. +interop.PipelineJsImpl buildPipelineFromStages( + interop.FirestoreJsImpl jsFirestore, + List> stages, +) { + final source = jsFirestore.pipeline(); + final first = stages.first; + final stageName = first['stage'] as String?; + + // Build source stage + interop.PipelineJsImpl pipeline = _applySourceStage( + source as interop.PipelineSourceJsImpl, jsFirestore, stageName, first); + + final converter = PipelineExpressionParserWeb(interop.pipelines, jsFirestore); + + // Apply remaining stages + for (var i = 1; i < stages.length; i++) { + pipeline = _applyStage(pipeline, stages[i], converter, jsFirestore); + } + return pipeline; +} + +interop.PipelineJsImpl _applySourceStage( + interop.PipelineSourceJsImpl source, + interop.FirestoreJsImpl jsFirestore, + String? stageName, + Map first, +) { + final args = first['args']; + return switch (stageName) { + 'collection' => source + .collection(((args as Map)['path']! as String).toJS), + 'collection_group' => source.collectionGroup( + ((args as Map)['path']! as String).toJS), + 'database' => source.database(), + 'documents' => source.documents( + (args as List) + .map((e) => (e as Map)['path']! as String) + .map((p) => interop.doc(jsFirestore as JSAny, p.toJS)) + .toList() + .toJS, + ), + _ => throw UnsupportedError( + 'Pipeline source stage "$stageName" is not supported on web.'), + }; +} + +interop.PipelineJsImpl _applyStage( + interop.PipelineJsImpl pipeline, + Map stage, + PipelineExpressionParserWeb converter, + interop.FirestoreJsImpl jsFirestore, +) { + final name = stage['stage'] as String?; + final args = stage['args']; + final map = args is Map ? args : {}; + + switch (name) { + case 'limit': + final limit = map['limit'] as int; + return pipeline.limit(limit.toJS); + case 'offset': + final offset = map['offset'] as int; + return pipeline.offset(offset.toJS); + case 'where': + final expression = map['expression']; + if (expression == null) return pipeline; + final condition = + converter.toBooleanExpression(expression as Map); + if (condition == null) { + throw UnsupportedError( + 'Pipeline where() on web: could not parse the condition expression.', + ); + } + return pipeline.where(condition); + case 'sort': + final orderings = map['orderings'] as List?; + if (orderings == null || orderings.isEmpty) return pipeline; + return pipeline.sort(converter.toSortOptions(orderings)); + case 'add_fields': + final expressions = map['expressions'] as List?; + if (expressions == null || expressions.isEmpty) return pipeline; + return pipeline.addFields(converter.toAddFieldsOptions(expressions)); + case 'select': + final expressions = map['expressions'] as List?; + if (expressions == null || expressions.isEmpty) return pipeline; + return pipeline.select(converter.toSelectOptions(expressions)); + case 'distinct': + final expressions = map['expressions'] as List?; + if (expressions == null || expressions.isEmpty) return pipeline; + return pipeline.distinct(converter.toDistinctOptions(expressions)); + case 'aggregate': + return pipeline.aggregate(converter.toAggregateOptionsFromFunctions(map)); + case 'aggregate_with_options': + return pipeline + .aggregate(converter.toAggregateOptionsFromStageAndOptions(map)); + case 'sample': + return pipeline.sample(converter.toSampleOptions(args)); + case 'unnest': + return pipeline.unnest(converter.toUnnestOptions(map)); + case 'remove_fields': + final fieldPaths = map['field_paths'] as List?; + if (fieldPaths == null || fieldPaths.isEmpty) return pipeline; + return pipeline.removeFields(converter.toRemoveFieldsOptions(fieldPaths)); + case 'replace_with': + final expression = map['expression']; + if (expression == null) return pipeline; + return pipeline.replaceWith( + converter.toReplaceWithOptions(expression as Map)); + case 'find_nearest': + return pipeline.findNearest(converter.toFindNearestOptions(map)); + case 'union': + final pipelineStages = map['pipeline'] as List>; + final otherPipeline = + buildPipelineFromStages(jsFirestore, pipelineStages); + return pipeline.union(otherPipeline); + default: + throw FirebaseException( + plugin: 'cloud_firestore', + code: 'unknown-pipeline-stage', + message: 'Unknown pipeline stage: $name', + ); + } +} diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart new file mode 100644 index 000000000000..722c28095d02 --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart @@ -0,0 +1,842 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:js_interop'; +import 'dart:typed_data'; + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart' + show Blob, GeoPoint, Timestamp, VectorValue; +import 'package:cloud_firestore_web/src/interop/firestore_interop.dart' + as interop; +import 'package:cloud_firestore_web/src/interop/utils/utils.dart'; +import 'package:firebase_core/firebase_core.dart'; + +/// Converts Dart serialized pipeline expressions/stage args into JS pipeline +/// types by calling the pipelines interop API (field, constant, equal, and, +/// ascending, etc.) that mirrors the Firebase JS SDK. +class PipelineExpressionParserWeb { + PipelineExpressionParserWeb(this._pipelines, this._jsFirestore); + + final interop.PipelinesJsImpl _pipelines; + final interop.FirestoreJsImpl _jsFirestore; + + static const _kName = 'name'; + static const _kArgs = 'args'; + static const _kLeft = 'left'; + static const _kRight = 'right'; + static const _kExpression = 'expression'; + static const _kField = 'field'; + static const _kAlias = 'alias'; + static const _kValue = 'value'; + + // ── Value expressions ───────────────────────────────────────────────────── + + /// Converts a serialized value expression to a JS Expression. + interop.ExpressionJsImpl toExpression(Map map) { + final name = map[_kName] as String?; + final argsMap = _argsOf(map); + switch (name) { + case 'field': + return _pipelines.field(((argsMap[_kField] as String?) ?? '').toJS); + case 'add': + return _binaryArithmetic(argsMap, (l, r) => l.add(r)); + case 'subtract': + return _binaryArithmetic(argsMap, (l, r) => l.subtract(r)); + case 'multiply': + return _binaryArithmetic(argsMap, (l, r) => l.multiply(r)); + case 'divide': + return _binaryArithmetic(argsMap, (l, r) => l.divide(r)); + case 'modulo': + return _binaryArithmetic(argsMap, (l, r) => l.modulo(r)); + case 'constant': + case 'null': + return _pipelines.constant(_constantValueToJs(argsMap[_kValue])); + case 'concat': + final expressions = argsMap['expressions'] as List?; + if (expressions == null || expressions.isEmpty) { + throw UnsupportedError('concat requires at least one expression'); + } + interop.ExpressionJsImpl result = + toExpression(expressions[0] as Map); + for (var i = 1; i < expressions.length; i++) { + result = result + .concat(toExpression(expressions[i] as Map)); + } + return result; + case 'length': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .length(); + case 'to_lower_case': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .toLower(); + case 'to_upper_case': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .toUpper(); + case 'trim': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .trim(); + case 'as_boolean': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .asBoolean(); + case 'is_error': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .isError(); + case 'is_absent': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .isAbsent(); + case 'substring': + return _pipelines.substring( + _expr(argsMap, _kExpression), + _expr(argsMap, 'start'), + _expr(argsMap, 'end'), + ); + case 'string_replace_all': + return _pipelines.stringReplaceAll( + _expr(argsMap, _kExpression), + _expr(argsMap, 'find'), + _expr(argsMap, 'replacement'), + ); + case 'split': + return _pipelines.split( + _expr(argsMap, _kExpression), + _expr(argsMap, 'delimiter'), + ); + case 'join': + return _pipelines.join( + _expr(argsMap, _kExpression), + _expr(argsMap, 'delimiter'), + ); + case 'if_absent': + return _pipelines.ifAbsent( + _expr(argsMap, _kExpression), + _expr(argsMap, 'else'), + ); + case 'if_error': + return _pipelines.ifError( + _expr(argsMap, _kExpression), + _expr(argsMap, 'catch'), + ); + case 'conditional': + return _pipelines.conditional( + toBooleanExpression(argsMap['condition'] as Map)!, + _expr(argsMap, 'then'), + _expr(argsMap, 'else'), + ); + case 'document_id': + final pathArg = argsMap[_kExpression]; + return _pipelines + .documentId(toExpression(pathArg as Map)); + case 'document_id_from_ref': + final path = argsMap['doc_ref'] as String?; + if (path == null || path.isEmpty) { + throw ArgumentError( + "document_id_from_ref requires a non-empty 'doc_ref' path"); + } + final docRef = interop.doc(_jsFirestore as JSAny, path.toJS); + return _pipelines.documentId(docRef); + case 'collection_id': + return _pipelines.collectionId(_expr(argsMap, _kExpression)); + case 'map_get': + { + final keyExprMap = argsMap['key'] as Map?; + if (keyExprMap == null) { + throw ArgumentError("map_get requires a 'key' argument"); + } + final keyString = _constantStringFromExpression(keyExprMap); + if (keyString == null) { + throw UnsupportedError( + 'mapGet on web only supports a constant string key '); + } + return _pipelines.mapGet( + _expr(argsMap, 'map'), + keyString.toJS, + ); + } + case 'map_keys': + return _pipelines.mapKeys(_expr(argsMap, _kExpression)); + case 'map_values': + return _pipelines.mapValues(_expr(argsMap, _kExpression)); + case 'current_timestamp': + return _pipelines.currentTimestamp(); + case 'timestamp_add': + return _pipelines.timestampAdd( + _expr(argsMap, 'timestamp'), + (argsMap['unit'] as String).toJS, + _expr(argsMap, 'amount'), + ); + case 'timestamp_subtract': + return _pipelines.timestampSubtract( + _expr(argsMap, 'timestamp'), + (argsMap['unit'] as String).toJS, + _expr(argsMap, 'amount'), + ); + case 'timestamp_truncate': + final tz = argsMap['timezone'] as String?; + return _pipelines.timestampTruncate( + _expr(argsMap, 'timestamp'), + (argsMap['unit'] as String).toJS, + tz?.toJS, + ); + case 'abs': + return _pipelines.abs(_expr(argsMap, _kExpression)); + case 'array_length': + return _pipelines.arrayLength(_expr(argsMap, _kExpression)); + case 'array_sum': + return _pipelines.arraySum(_expr(argsMap, _kExpression)); + case 'array_concat': + return _pipelines.arrayConcat( + _expr(argsMap, 'first'), + _expr(argsMap, 'second'), + ); + case 'array_concat_multiple': + final arrays = argsMap['arrays'] as List?; + if (arrays == null || arrays.length < 2) { + throw UnsupportedError( + 'array_concat_multiple requires at least two arrays'); + } + var arrResult = _pipelines.arrayConcat( + toExpression(arrays[0] as Map), + toExpression(arrays[1] as Map), + ); + for (var i = 2; i < arrays.length; i++) { + arrResult = _pipelines.arrayConcat( + arrResult, + toExpression(arrays[i] as Map), + ); + } + return arrResult; + case 'array_reverse': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayReverse(); + case 'array': + final elements = argsMap['elements'] as List?; + if (elements == null) { + throw UnsupportedError('array requires elements'); + } + final jsElements = elements + .map((e) => toExpression(e as Map)) + .toList() + .toJS; + return _pipelines.array(jsElements); + case 'array_contains': + return _jsArrayContains(argsMap) as interop.ExpressionJsImpl; + case 'array_contains_any': + final js = _jsArrayContainsAny(argsMap); + if (js == null) { + throw UnsupportedError('array_contains_any requires values'); + } + return js as interop.ExpressionJsImpl; + case 'array_contains_all': + final js = _jsArrayContainsAll(argsMap); + if (js == null) { + throw UnsupportedError( + 'array_contains_all requires values or array_expression', + ); + } + return js as interop.ExpressionJsImpl; + case 'equal_any': + final js = _jsEqualAny(argsMap); + if (js == null) throw UnsupportedError('equal_any requires values'); + return js as interop.ExpressionJsImpl; + case 'not_equal_any': + final js = _jsNotEqualAny(argsMap); + if (js == null) { + throw UnsupportedError('not_equal_any requires values'); + } + return js as interop.ExpressionJsImpl; + case 'map': + final data = argsMap['data'] as Map?; + if (data == null) { + throw UnsupportedError('map requires data'); + } + final m = {}; + for (final entry in data.entries) { + m[entry.key] = toExpression(entry.value as Map); + } + return _pipelines.map(jsify(m)! as JSObject); + case 'map_set': + final kv = argsMap['key_values'] as List?; + if (kv == null || kv.isEmpty || kv.length.isOdd) { + throw UnsupportedError( + 'map_set requires key_values with even length'); + } + var cur = _expr(argsMap, 'map') as interop.ExpressionJsImpl; + for (var i = 0; i < kv.length; i += 2) { + cur = cur.mapSet( + toExpression(kv[i] as Map), + toExpression(kv[i + 1] as Map), + ); + } + return cur; + case 'map_entries': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .mapEntries(); + case 'regex_find': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .regexFind(_expr(argsMap, 'pattern')); + case 'regex_find_all': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .regexFindAll(_expr(argsMap, 'pattern')); + case 'string_replace_one': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .stringReplaceOne( + _expr(argsMap, 'find'), + _expr(argsMap, 'replacement'), + ); + case 'string_index_of': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .stringIndexOf(_expr(argsMap, 'search')); + case 'string_repeat': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .stringRepeat(_expr(argsMap, 'repetitions')); + case 'ltrim': + { + final expr = _expr(argsMap, _kExpression) as interop.ExpressionJsImpl; + final v = argsMap['value']; + if (v == null) return expr.ltrim(); + return expr.ltrim(toExpression(v as Map)); + } + case 'rtrim': + { + final expr = _expr(argsMap, _kExpression) as interop.ExpressionJsImpl; + final v = argsMap['value']; + if (v == null) return expr.rtrim(); + return expr.rtrim(toExpression(v as Map)); + } + case 'type': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .type(); + case 'trunc': + { + final expr = _expr(argsMap, _kExpression) as interop.ExpressionJsImpl; + final dec = argsMap['decimals']; + if (dec == null) return expr.trunc(); + return expr.trunc(toExpression(dec as Map)); + } + case 'rand': + return _pipelines.rand(); + case 'array_first': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayFirst(); + case 'array_first_n': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayFirstN(_expr(argsMap, 'n')); + case 'array_last': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayLast(); + case 'array_last_n': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayLastN(_expr(argsMap, 'n')); + case 'maximum': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayMaximum(); + case 'maximum_n': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayMaximumN(_expr(argsMap, 'n')); + case 'minimum': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayMinimum(); + case 'minimum_n': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayMinimumN(_expr(argsMap, 'n')); + case 'array_index_of': + { + final base = _expr(argsMap, _kExpression) as interop.ExpressionJsImpl; + final el = _expr(argsMap, 'element'); + final occMap = argsMap['occurrence'] as Map?; + final occ = _constantStringFromExpression(occMap ?? {}); + if (occ == 'last') { + return base.arrayLastIndexOf(el); + } + if (occ == 'first') { + return base.arrayIndexOf(el); + } + throw UnsupportedError( + 'array_index_of requires occurrence constant first or last', + ); + } + case 'array_index_of_all': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayIndexOfAll(_expr(argsMap, 'element')); + default: + throw FirebaseException( + plugin: 'cloud_firestore', + code: 'unsupported-expression', + message: + "The pipeline expression '$name' is not supported on the web " + 'platform. The Firebase JS SDK may not expose this expression.', + ); + } + } + + // ── Boolean expressions ─────────────────────────────────────────────────── + + /// Converts a serialized boolean expression to a JS BooleanExpression. + /// + /// Returns null if [map] is not a recognized boolean expression. + JSAny? toBooleanExpression(Map map) { + final name = map[_kName] as String?; + final argsMap = _argsOf(map); + switch (name) { + case 'equal': + return _pipelines.equal( + _expr(argsMap, _kLeft), _expr(argsMap, _kRight)); + case 'not_equal': + return _pipelines.notEqual( + _expr(argsMap, _kLeft), _expr(argsMap, _kRight)); + case 'greater_than': + return _pipelines.greaterThan( + _expr(argsMap, _kLeft), _expr(argsMap, _kRight)); + case 'greater_than_or_equal': + return _pipelines.greaterThanOrEqual( + _expr(argsMap, _kLeft), _expr(argsMap, _kRight)); + case 'less_than': + return _pipelines.lessThan( + _expr(argsMap, _kLeft), _expr(argsMap, _kRight)); + case 'less_than_or_equal': + return _pipelines.lessThanOrEqual( + _expr(argsMap, _kLeft), _expr(argsMap, _kRight)); + case 'and': + case 'or': + case 'xor': + final exprMaps = argsMap['expressions'] as List?; + if (exprMaps == null || exprMaps.isEmpty) return null; + final exprs = exprMaps + .map((e) => toBooleanExpression(e as Map)) + .whereType() + .toList(); + if (exprs.isEmpty) return null; + var result = exprs.first; + for (var i = 1; i < exprs.length; i++) { + if (name == 'and') { + result = _pipelines.and(result, exprs[i]); + } else if (name == 'or') { + result = _pipelines.or(result, exprs[i]); + } else { + result = _pipelines.xor(result, exprs[i]); + } + } + return result; + case 'not': + final expr = argsMap[_kExpression] as Map; + final boolExpr = toBooleanExpression(expr); + if (boolExpr == null) { + throw UnsupportedError('not requires a boolean expression'); + } + return _pipelines.not(boolExpr); + case 'exists': + return _pipelines.exists(_expr(argsMap, _kExpression)); + case 'is_absent': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .isAbsent(); + case 'is_error': + return _pipelines.isError(_expr(argsMap, _kExpression)); + case 'array_contains': + return _jsArrayContains(argsMap); + case 'array_contains_any': + return _jsArrayContainsAny(argsMap); + case 'array_contains_all': + return _jsArrayContainsAll(argsMap); + case 'equal_any': + return _jsEqualAny(argsMap); + case 'not_equal_any': + return _jsNotEqualAny(argsMap); + case 'filter': + return _buildFilterExpression(argsMap); + case 'is_type': + final typeStr = argsMap['type'] as String?; + if (typeStr == null) { + throw UnsupportedError("is_type requires string 'type'"); + } + return _pipelines.isTypeExpr( + _expr(argsMap, _kExpression), + typeStr.toJS, + ); + default: + throw FirebaseException( + plugin: 'cloud_firestore', + code: 'unsupported-boolean-expression', + message: "The boolean expression '$name' is not supported on the web " + 'platform. The Firebase JS SDK may not expose this expression.', + ); + } + } + + // ── Stage options ───────────────────────────────────────────────────────── + + /// Converts orderings list to JS SortStageOptions. + /// + /// Each item shape: `{ expression: Map, order_direction: 'asc' | 'desc' }`. + JSAny toSortOptions(List orderings) { + final list = []; + for (final o in orderings) { + final m = o is Map ? o : {}; + final expr = m[_kExpression]; + if (expr == null) continue; + final exprJs = toExpression(expr as Map); + final dir = m['order_direction'] as String?; + list.add(dir == 'desc' + ? _pipelines.descending(exprJs) + : _pipelines.ascending(exprJs)); + } + if (list.isEmpty) { + throw UnsupportedError( + 'Pipeline sort() on web requires the Firebase JS pipeline expression API ' + '(ascending, descending). Ensure the pipelines module is loaded.', + ); + } + return interop.SortStageOptionsJsImpl()..orderings = list.toJS; + } + + /// Converts a single expression map to a JS Selectable (field or aliased). + JSAny toSelectable(Map map) { + final name = map[_kName] as String?; + final argsMap = _argsOf(map); + if (name == 'field') { + return _pipelines.field(((argsMap[_kField] as String?) ?? '').toJS); + } + if (name == _kAlias) { + final alias = argsMap[_kAlias] as String; + final expression = argsMap[_kExpression]; + return toExpression(expression as Map) + .asAlias(alias.toJS); + } + return toExpression(map); + } + + /// Converts add_fields expressions to JS AddFieldsStageOptions. + JSAny toAddFieldsOptions(List expressions) => + interop.AddFieldsOptionsJsImpl() + ..fields = _toSelectableList(expressions).toJS; + + /// Converts select stage expressions to JS SelectStageOptions. + JSAny toSelectOptions(List expressions) => + interop.SelectStageOptionsJsImpl() + ..selections = _toSelectableList(expressions).toJS; + + /// Converts distinct stage groups to JS DistinctStageOptions. + JSAny toDistinctOptions(List expressions) { + final list = _toSelectableList(expressions); + if (list.isEmpty) { + throw UnsupportedError( + 'Pipeline distinct() on web requires the Firebase JS pipeline expression API.', + ); + } + return interop.DistinctStageOptionsJsImpl()..groups = list.toJS; + } + + // ── Aggregate ───────────────────────────────────────────────────────────── + + /// Converts args for the 'aggregate' stage to JS AggregateStageOptions. + /// + /// Expects [map] to contain an [aggregate_functions] list. + interop.AggregateStageOptionsJsImpl toAggregateOptionsFromFunctions( + Map map) { + final list = map['aggregate_functions'] as List; + return _buildAccumulators(list); + } + + /// Converts args for the 'aggregate_with_options' stage to JS AggregateStageOptions. + /// + /// Expects [map] to contain an [aggregate_stage] map with [accumulators] + /// and optionally [groups]. + interop.AggregateStageOptionsJsImpl toAggregateOptionsFromStageAndOptions( + Map map) { + final stage = map['aggregate_stage'] as Map; + final list = stage['accumulators'] as List; + final groups = stage['groups'] as List?; + return _buildAccumulators(list, groups: groups); + } + + // ── Other stage options ─────────────────────────────────────────────────── + + /// Converts sample stage args to JS (integer count or SampleStageOptions). + /// + /// Dart serializes as `{ type: 'size', value: n }` or a raw number. + JSAny toSampleOptions(Map map) { + final args = map['type'] as String; + if (args == 'size') { + final value = map['value'] as num; + return interop.SampleStageOptionsJsImpl()..documents = value.toInt().toJS; + } else { + final value = map['value'] as num; + return interop.SampleStageOptionsJsImpl() + ..percentage = value.toDouble().toJS; + } + } + + /// Converts unnest stage args to JS UnnestStageOptions. + JSAny toUnnestOptions(Map map) { + final expression = map[_kExpression] as Map; + final indexField = map['index_field'] as String?; + final sel = toSelectable(expression); + return interop.UnnestStageOptionsJsImpl() + ..selectable = sel + ..indexField = indexField?.toJS; + } + + /// Converts remove_fields field paths to JS RemoveFieldsStageOptions. + JSAny toRemoveFieldsOptions(List fieldPaths) { + final paths = []; + for (final e in fieldPaths) { + final s = e is String + ? e + : (e is Map ? e[_kField] ?? e['path'] : null)?.toString(); + if (s != null) paths.add(s.toJS); + } + return interop.RemoveFieldsStageOptionsJsImpl()..fields = paths.toJS; + } + + /// Converts replace_with expression to JS ReplaceWithStageOptions. + JSAny toReplaceWithOptions(Map expression) { + return interop.ReplaceWithStageOptionsJsImpl() + ..map = toExpression(expression); + } + + /// Converts find_nearest args to JS FindNearestStageOptions. + interop.FindNearestStageOptionsJsImpl toFindNearestOptions( + Map map) { + final vectorField = + (map['vector_field'] as String?) ?? (map[_kField] as String?); + final vectorValue = map['vector_value'] as List?; + final distanceMeasure = (map['distance_measure'] as String?) ?? 'cosine'; + final limit = map['limit'] as int?; + final distanceField = map['distance_field'] as String?; + if (vectorField == null || vectorValue == null) { + throw UnsupportedError( + 'Pipeline findNearest() on web requires vector_field and vector_value.', + ); + } + final doubles = vectorValue.map((e) => (e as num).toDouble()).toList(); + final opts = interop.FindNearestStageOptionsJsImpl() + ..field = _pipelines.field(vectorField.toJS) + ..vectorValue = interop.vector(doubles.jsify()! as JSArray) + ..distanceMeasure = distanceMeasure.toJS; + if (limit != null) opts.limit = limit.toJS; + if (distanceField != null) opts.distanceField = distanceField.toJS; + return opts; + } + + // ── Private helpers ─────────────────────────────────────────────────────── + + /// Converts a [Constant] value to the correct JS type for the pipelines API. + /// + /// Each Dart type accepted by [Constant] is mapped to the corresponding + /// Firestore JS SDK interop type so that the JS SDK receives a properly typed + /// value (e.g. a JS `Timestamp`, `GeoPoint`, or `Bytes` object) rather than + /// a plain JS primitive or an unrecognised object. + JSAny? _constantValueToJs(Object? value) { + if (value == null) return null; + if (value is String) return value.toJS; + if (value is bool) return value.toJS; + if (value is int) return value.toJS; + if (value is double) return value.toJS; + if (value is DateTime) { + return interop.TimestampJsImpl.fromMillis( + value.millisecondsSinceEpoch.toJS) as JSAny; + } + + if (value is Timestamp) { + // Use seconds + nanoseconds directly to preserve sub-millisecond precision. + return interop.TimestampJsImpl(value.seconds.toJS, value.nanoseconds.toJS) + as JSAny; + } + if (value is GeoPoint) { + return interop.GeoPointJsImpl(value.latitude.toJS, value.longitude.toJS) + as JSAny; + } + if (value is Blob) { + return interop.BytesJsImpl.fromUint8Array(value.bytes.toJS) as JSAny; + } + if (value is List) { + return interop.BytesJsImpl.fromUint8Array(Uint8List.fromList(value).toJS) + as JSAny; + } + if (value is VectorValue) { + return interop.vector(value.toArray().jsify()! as JSArray) as JSAny; + } + if (value is Map) { + final path = value['path'] as String; + return interop.doc(_jsFirestore as JSAny, path.toJS) as JSAny; + } + return jsify(value); + } + + /// Extracts and safe-casts the 'args' sub-map from an expression map. + static Map _argsOf(Map map) { + final a = map[_kArgs]; + return a is Map ? a : const {}; + } + + /// Returns the string value if [exprMap] is a constant string expression; + /// otherwise null. + String? _constantStringFromExpression(Map exprMap) { + if ((exprMap[_kName] as String?) != 'constant') return null; + final args = _argsOf(exprMap); + final value = args[_kValue]; + return value is String ? value : null; + } + + /// Resolves [key] from [argsMap] as a value expression. + JSAny _expr(Map argsMap, String key) => + toExpression(argsMap[key] as Map); + + JSAny _jsArrayContains(Map argsMap) => + _pipelines.arrayContains( + _expr(argsMap, 'array'), + _expr(argsMap, 'element'), + ); + + JSAny? _jsArrayContainsAny(Map argsMap) { + final valuesMaps = argsMap['values'] as List?; + if (valuesMaps == null || valuesMaps.isEmpty) return null; + final valuesJs = valuesMaps + .map((v) => toExpression(v as Map)) + .toList() + .toJS; + return _pipelines.arrayContainsAny(_expr(argsMap, 'array'), valuesJs); + } + + JSAny? _jsArrayContainsAll(Map argsMap) { + final arrayExpr = _expr(argsMap, 'array'); + final valuesArg = argsMap['values'] as List?; + final arrayExpressionArg = argsMap['array_expression']; + if (valuesArg != null && valuesArg.isNotEmpty) { + final valuesJs = valuesArg + .map((v) => toExpression(v as Map)) + .toList() + .toJS; + return _pipelines.arrayContainsAll(arrayExpr, valuesJs); + } + if (arrayExpressionArg != null) { + return _pipelines.arrayContainsAll( + arrayExpr, + toExpression(arrayExpressionArg as Map), + ); + } + return null; + } + + JSAny? _jsEqualAny(Map argsMap) { + final valuesMaps = argsMap['values'] as List?; + if (valuesMaps == null || valuesMaps.isEmpty) return null; + final valuesJs = valuesMaps + .map((v) => toExpression(v as Map)) + .toList() + .toJS; + return _pipelines.equalAny(_expr(argsMap, 'value'), valuesJs); + } + + JSAny? _jsNotEqualAny(Map argsMap) { + final valuesMaps = argsMap['values'] as List?; + if (valuesMaps == null || valuesMaps.isEmpty) return null; + final valuesJs = valuesMaps + .map((v) => toExpression(v as Map)) + .toList() + .toJS; + return _pipelines.notEqualAny(_expr(argsMap, 'value'), valuesJs); + } + + interop.ExpressionJsImpl _binaryArithmetic( + Map argsMap, + interop.ExpressionJsImpl Function( + interop.ExpressionJsImpl left, interop.ExpressionJsImpl right) + op, + ) => + op( + toExpression(argsMap[_kLeft] as Map), + toExpression(argsMap[_kRight] as Map), + ); + + JSAny? _buildFilterExpression(Map argsMap) { + final operator = argsMap['operator'] as String?; + final expressions = argsMap['expressions'] as List?; + if (expressions == null || expressions.isEmpty) return null; + final jsList = expressions + .map((e) => toExpression(e as Map)) + .toList(); + if (jsList.length == 1) return jsList.single; + JSAny result = jsList[0]; + for (var i = 1; i < jsList.length; i++) { + result = operator == 'and' + ? _pipelines.and(result, jsList[i]) + : _pipelines.or(result, jsList[i]); + } + return result; + } + + List _toSelectableList(List expressions) => expressions + .map((e) => + toSelectable(e is Map ? e : {})) + .whereType() + .toList(); + + interop.AggregateStageOptionsJsImpl _buildAccumulators( + List items, { + List? groups, + }) { + final accumulators = items + .map((item) => _parseAccumulator(item as Map)) + .whereType() + .toList(); + + if (accumulators.isEmpty) { + throw UnsupportedError( + 'Pipeline aggregate() on web requires at least one valid accumulator.', + ); + } + + final opts = interop.AggregateStageOptionsJsImpl() + ..accumulators = accumulators.toJS; + if (groups != null && groups.isNotEmpty) { + opts.groups = _toSelectableList(groups).toJS; + } + return opts; + } + + JSAny? _parseAccumulator(Map item) { + final args = item[_kArgs] as Map; + final alias = args[_kAlias] as String?; + final aggregateFn = args['aggregate_function'] as Map?; + if (alias == null || aggregateFn == null) return null; + final fnName = aggregateFn[_kName] as String?; + if (fnName == null) return null; + final expressionMap = (aggregateFn[_kArgs] + as Map?)?[_kExpression] as Map?; + final exprJs = expressionMap != null ? toExpression(expressionMap) : null; + return _buildAggregateFunction(fnName, exprJs)?.asAlias(alias.toJS); + } + + /// Builds one JS aggregate function from a serialized [name] and optional [exprJs]. + interop.AggregateFunctionJsImpl? _buildAggregateFunction( + String name, JSAny? exprJs) { + switch (name) { + case 'count_all': + return _pipelines.countAll(); + case 'sum': + return exprJs != null ? _pipelines.sum(exprJs) : null; + case 'average': + return exprJs != null ? _pipelines.average(exprJs) : null; + case 'count': + return exprJs != null ? _pipelines.count(exprJs) : null; + case 'count_distinct': + return exprJs != null ? _pipelines.countDistinct(exprJs) : null; + case 'minimum': + return exprJs != null ? _pipelines.minimum(exprJs) : null; + case 'maximum': + return exprJs != null ? _pipelines.maximum(exprJs) : null; + case 'first': + return exprJs != null ? _pipelines.first(exprJs) : null; + case 'last': + return exprJs != null ? _pipelines.last(exprJs) : null; + case 'array_agg': + return exprJs != null ? _pipelines.arrayAgg(exprJs) : null; + case 'array_agg_distinct': + return exprJs != null ? _pipelines.arrayAggDistinct(exprJs) : null; + default: + return null; + } + } +} diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_web.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_web.dart new file mode 100644 index 000000000000..5872ce7c5aaa --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_web.dart @@ -0,0 +1,110 @@ +// ignore_for_file: require_trailing_commas +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:js_interop'; + +import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; +import 'package:cloud_firestore_web/src/interop/utils/utils.dart'; + +import 'document_reference_web.dart'; +import 'interop/firestore.dart' as firestore_interop; +import 'interop/firestore_interop.dart' as interop; + +/// Web implementation of [PipelinePlatform]. +class PipelineWeb extends PipelinePlatform { + final firestore_interop.Firestore _firestoreWeb; + + PipelineWeb( + FirebaseFirestorePlatform firestore, + this._firestoreWeb, + List>? stages, + ) : super(firestore, stages); + + @override + PipelinePlatform addStage(Map serializedStage) { + return PipelineWeb( + firestore, + _firestoreWeb, + [...stages, serializedStage], + ); + } + + @override + Future execute({ + Map? options, + }) async { + return firestore.executePipeline(stages, options: options); + } +} + +/// Web implementation of [PipelineSnapshotPlatform]. +class PipelineSnapshotWeb extends PipelineSnapshotPlatform { + PipelineSnapshotWeb(this._results, this._executionTime) : super(); + + final List _results; + final DateTime _executionTime; + + @override + List get results => _results; + + @override + DateTime get executionTime => _executionTime; +} + +/// Web implementation of [PipelineResultPlatform]. +class PipelineResultWeb extends PipelineResultPlatform { + PipelineResultWeb( + FirebaseFirestorePlatform firestore, + firestore_interop.Firestore firestoreWeb, + interop.PipelineResultJsImpl jsResult, + ) : _document = jsResult.ref != null + ? DocumentReferenceWeb( + firestore, + firestoreWeb, + jsResult.ref!.path.toDart, + ) + : null, + _createTime = _timestampToDateTime(jsResult.createTime), + _updateTime = _timestampToDateTime(jsResult.updateTime), + _data = _dataFromResult(jsResult), + super(); + + final DocumentReferencePlatform? _document; + final DateTime? _createTime; + final DateTime? _updateTime; + final Map? _data; + + static Map? _dataFromResult( + interop.PipelineResultJsImpl jsResult) { + final d = jsResult.data(); + if (d == null) return null; + final parsed = dartify(d); + return parsed != null + ? Map.from(parsed as Map) + : null; + } + + static DateTime? _timestampToDateTime(JSAny? value) { + if (value == null) return null; + final d = dartify(value); + if (d == null) return null; + if (d is DateTime) return d; + if (d is Timestamp) return d.toDate(); + if (d is int) return DateTime.fromMillisecondsSinceEpoch(d); + return null; + } + + @override + DocumentReferencePlatform? get document => _document; + + @override + DateTime? get createTime => _createTime; + + @override + DateTime? get updateTime => _updateTime; + + @override + Map? get data => _data; +} diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart index b70f503d9ff3..a3ae6f933db6 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart @@ -214,6 +214,17 @@ class FirebaseCoreWeb extends FirebasePlatform { return Future.value(); } + const firestoreServiceName = 'firestore'; + + if (service.name == firestoreServiceName) { + // Inject the Firestore Pipelines script. This bundle supports both + // Pipeline operations (Enterprise edition) and standard Firestore queries. + return injectSrcScript( + 'https://www.gstatic.com/firebasejs/$version/firebase-firestore-pipelines.js', + 'firebase_$firestoreServiceName', + ); + } + return injectSrcScript( 'https://www.gstatic.com/firebasejs/$version/firebase-${service.name}.js', 'firebase_${service.override ?? service.name}', From 278527207a4fb35a5854dd3f0a9405da9f80877c Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 13 Apr 2026 12:12:42 +0000 Subject: [PATCH 026/137] feat(ai): add unexpectedToolCall finish reason and corresponding tests (#18188) --- packages/firebase_ai/firebase_ai/lib/src/api.dart | 4 ++++ packages/firebase_ai/firebase_ai/test/api_test.dart | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 653ef2097013..7bda9372b61c 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -770,6 +770,9 @@ enum FinishReason { /// The candidate content was flagged for malformed function call reasons. malformedFunctionCall('MALFORMED_FUNCTION_CALL'), + /// The model produced an unexpected tool call. + unexpectedToolCall('UNEXPECTED_TOOL_CALL'), + /// Unknown reason. other('OTHER'); @@ -790,6 +793,7 @@ enum FinishReason { 'RECITATION' => FinishReason.recitation, 'OTHER' => FinishReason.other, 'MALFORMED_FUNCTION_CALL' => FinishReason.malformedFunctionCall, + 'UNEXPECTED_TOOL_CALL' => FinishReason.unexpectedToolCall, _ => throw FormatException('Unhandled FinishReason format', jsonObject), }; } diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index 156e22dfe154..6681aaf0ed1f 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -315,6 +315,7 @@ void main() { expect(FinishReason.recitation.toJson(), 'RECITATION'); expect(FinishReason.malformedFunctionCall.toJson(), 'MALFORMED_FUNCTION_CALL'); + expect(FinishReason.unexpectedToolCall.toJson(), 'UNEXPECTED_TOOL_CALL'); expect(FinishReason.other.toJson(), 'OTHER'); }); @@ -1048,6 +1049,18 @@ void main() { FinishReason.malformedFunctionCall); }); + test('parses unexpectedToolCall finishReason', () { + final jsonResponse = { + 'candidates': [ + {'finishReason': 'UNEXPECTED_TOOL_CALL'} + ] + }; + final response = + VertexSerialization().parseGenerateContentResponse(jsonResponse); + expect(response.candidates.first.finishReason, + FinishReason.unexpectedToolCall); + }); + test( 'parses groundingSupports and filters out entries without a segment', () { From c9863566007d191cf06a834d04fac138e8abbb63 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 13 Apr 2026 14:44:44 +0200 Subject: [PATCH 027/137] chore(release): publish packages (#18189) * chore(release): publish packages - firebase_app_check_platform_interface@0.3.0 - firebase_data_connect@0.3.0 - _flutterfire_internals@1.3.69 - cloud_firestore@6.3.0 - cloud_firestore_platform_interface@7.2.0 - cloud_firestore_web@5.3.0 - cloud_functions@6.2.0 - firebase_ai@3.11.0 - firebase_analytics@12.3.0 - firebase_app_check@0.4.3 - firebase_app_check_web@0.2.4 - firebase_app_installations@0.4.2 - firebase_auth@6.4.0 - firebase_core@4.7.0 - firebase_core_web@3.6.0 - firebase_crashlytics@5.2.0 - firebase_database@12.3.0 - firebase_in_app_messaging@0.9.2 - firebase_messaging@16.2.0 - firebase_ml_model_downloader@0.4.2 - firebase_performance@0.11.3 - firebase_remote_config@6.4.0 - firebase_storage@13.3.0 - firebase_remote_config_web@1.10.6 - firebase_in_app_messaging_platform_interface@0.2.5+20 - firebase_remote_config_platform_interface@2.1.2 - firebase_auth_platform_interface@8.1.9 - firebase_crashlytics_platform_interface@3.8.20 - firebase_messaging_web@4.1.5 - firebase_messaging_platform_interface@4.7.9 - firebase_app_installations_platform_interface@0.1.4+68 - firebase_database_platform_interface@0.3.1+1 - firebase_analytics_platform_interface@5.1.1 - firebase_app_installations_web@0.1.7+5 - firebase_analytics_web@0.6.1+5 - firebase_performance_platform_interface@0.1.6+7 - firebase_performance_web@0.1.8+5 - firebase_storage_platform_interface@5.2.20 - firebase_storage_web@3.11.5 - firebase_auth_web@6.1.5 - firebase_database_web@0.2.7+6 - firebase_ml_model_downloader_platform_interface@0.1.5+20 - cloud_functions_web@5.1.5 - cloud_functions_platform_interface@5.8.12 * chore: BoM Version 4.12.0 --- CHANGELOG.md | 195 ++++++++++++++++++ VERSIONS.md | 38 ++++ melos.yaml | 2 - packages/_flutterfire_internals/CHANGELOG.md | 4 + packages/_flutterfire_internals/pubspec.yaml | 4 +- .../cloud_firestore/CHANGELOG.md | 5 + .../cloud_firestore/example/pubspec.yaml | 4 +- .../ios/cloud_firestore/Package.swift | 4 +- .../macos/cloud_firestore/Package.swift | 4 +- .../pipeline_example/pubspec.yaml | 2 +- .../cloud_firestore/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../cloud_firestore_web/CHANGELOG.md | 4 + .../lib/src/cloud_firestore_version.dart | 2 +- .../cloud_firestore_web/pubspec.yaml | 10 +- .../cloud_functions/CHANGELOG.md | 4 + .../cloud_functions/example/pubspec.yaml | 4 +- .../ios/cloud_functions/Package.swift | 2 +- .../Sources/cloud_functions/Constants.swift | 2 +- .../macos/cloud_functions/Package.swift | 2 +- .../cloud_functions/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 4 +- .../cloud_functions_web/CHANGELOG.md | 4 + .../lib/src/cloud_functions_version.dart | 2 +- .../cloud_functions_web/pubspec.yaml | 8 +- packages/firebase_ai/firebase_ai/CHANGELOG.md | 7 + .../firebase_ai/example/pubspec.yaml | 6 +- .../lib/src/firebaseai_version.dart | 2 +- packages/firebase_ai/firebase_ai/pubspec.yaml | 8 +- .../firebase_analytics/CHANGELOG.md | 4 + .../firebase_analytics/example/pubspec.yaml | 4 +- .../ios/firebase_analytics/Package.swift | 2 +- .../macos/firebase_analytics/Package.swift | 2 +- .../firebase_analytics/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_analytics_web/CHANGELOG.md | 4 + .../lib/src/firebase_analytics_version.dart | 2 +- .../firebase_analytics_web/pubspec.yaml | 10 +- .../firebase_app_check/CHANGELOG.md | 5 + .../firebase_app_check/example/pubspec.yaml | 6 +- .../ios/firebase_app_check/Package.swift | 2 +- .../firebase_app_check/Constants.swift | 2 +- .../macos/firebase_app_check/Package.swift | 2 +- .../firebase_app_check/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_app_check_web/CHANGELOG.md | 5 + .../lib/src/firebase_app_check_version.dart | 2 +- .../firebase_app_check_web/pubspec.yaml | 10 +- .../firebase_app_installations/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../firebase_app_installations/Package.swift | 2 +- .../Constants.swift | 2 +- .../firebase_app_installations/Package.swift | 2 +- .../firebase_app_installations/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../firebase_app_installations_version.dart | 2 +- .../pubspec.yaml | 10 +- .../firebase_auth/firebase_auth/CHANGELOG.md | 5 + .../firebase_auth/example/pubspec.yaml | 6 +- .../ios/firebase_auth/Package.swift | 4 +- .../macos/firebase_auth/Package.swift | 4 +- .../firebase_auth/firebase_auth/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_auth_web/CHANGELOG.md | 4 + .../lib/src/firebase_auth_version.dart | 2 +- .../firebase_auth_web/pubspec.yaml | 8 +- .../firebase_core/firebase_core/CHANGELOG.md | 9 + .../firebase_core/example/pubspec.yaml | 2 +- .../ios/firebase_core/Package.swift | 4 +- .../macos/firebase_core/Package.swift | 4 +- .../firebase_core/firebase_core/pubspec.yaml | 4 +- .../firebase_core_web/CHANGELOG.md | 6 + .../lib/src/firebase_core_version.dart | 2 +- .../firebase_core_web/pubspec.yaml | 2 +- .../firebase_crashlytics/CHANGELOG.md | 5 + .../firebase_crashlytics/example/pubspec.yaml | 6 +- .../ios/firebase_crashlytics/Package.swift | 4 +- .../macos/firebase_crashlytics/Package.swift | 4 +- .../firebase_crashlytics/pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_data_connect/CHANGELOG.md | 5 + .../example/pubspec.yaml | 6 +- .../lib/src/dataconnect_version.dart | 2 +- .../firebase_data_connect/pubspec.yaml | 12 +- .../firebase_database/CHANGELOG.md | 5 + .../firebase_database/example/pubspec.yaml | 4 +- .../ios/firebase_database/Package.swift | 4 +- .../macos/firebase_database/Package.swift | 4 +- .../firebase_database/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_database_web/CHANGELOG.md | 4 + .../lib/src/firebase_database_version.dart | 2 +- .../firebase_database_web/pubspec.yaml | 8 +- .../firebase_in_app_messaging/CHANGELOG.md | 4 + .../example/pubspec.yaml | 8 +- .../firebase_in_app_messaging/Package.swift | 4 +- .../firebase_in_app_messaging/pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_messaging/CHANGELOG.md | 4 + .../firebase_messaging/example/pubspec.yaml | 4 +- .../ios/firebase_messaging/Package.swift | 4 +- .../macos/firebase_messaging/Package.swift | 4 +- .../firebase_messaging/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_messaging_web/CHANGELOG.md | 4 + .../lib/src/firebase_messaging_version.dart | 2 +- .../firebase_messaging_web/pubspec.yaml | 10 +- .../firebase_ml_model_downloader/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../Package.swift | 2 +- .../Constants.swift | 2 +- .../Package.swift | 2 +- .../firebase_ml_model_downloader/pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 4 +- .../firebase_performance/CHANGELOG.md | 4 + .../firebase_performance/example/pubspec.yaml | 4 +- .../ios/firebase_performance/Package.swift | 4 +- .../firebase_performance/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_performance_web/CHANGELOG.md | 4 + .../lib/src/firebase_performance_version.dart | 2 +- .../firebase_performance_web/pubspec.yaml | 10 +- .../firebase_remote_config/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../ios/firebase_remote_config/Package.swift | 2 +- .../firebase_remote_config/Constants.swift | 2 +- .../firebase_remote_config/Package.swift | 2 +- .../firebase_remote_config/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_remote_config_web/CHANGELOG.md | 4 + .../src/firebase_remote_config_version.dart | 2 +- .../firebase_remote_config_web/pubspec.yaml | 10 +- .../firebase_storage/CHANGELOG.md | 4 + .../firebase_storage/example/pubspec.yaml | 4 +- .../ios/firebase_storage/Package.swift | 4 +- .../macos/firebase_storage/Package.swift | 4 +- .../firebase_storage/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_storage_web/CHANGELOG.md | 4 + .../lib/src/firebase_storage_version.dart | 2 +- .../firebase_storage_web/pubspec.yaml | 10 +- scripts/versions.json | 28 +++ tests/pubspec.yaml | 70 +++---- 158 files changed, 753 insertions(+), 301 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bebc02c21d1..56855a5dffd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,201 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2026-04-13 - [BoM 4.12.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4120-2026-04-13) + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`firebase_app_check_platform_interface` - `v0.3.0`](#firebase_app_check_platform_interface---v030) + - [`firebase_data_connect` - `v0.3.0`](#firebase_data_connect---v030) + - [`_flutterfire_internals` - `v1.3.69`](#_flutterfire_internals---v1369) + - [`cloud_firestore` - `v6.3.0`](#cloud_firestore---v630) + - [`cloud_firestore_platform_interface` - `v7.2.0`](#cloud_firestore_platform_interface---v720) + - [`cloud_firestore_web` - `v5.3.0`](#cloud_firestore_web---v530) + - [`cloud_functions` - `v6.2.0`](#cloud_functions---v620) + - [`firebase_ai` - `v3.11.0`](#firebase_ai---v3110) + - [`firebase_analytics` - `v12.3.0`](#firebase_analytics---v1230) + - [`firebase_app_check` - `v0.4.3`](#firebase_app_check---v043) + - [`firebase_app_check_web` - `v0.2.4`](#firebase_app_check_web---v024) + - [`firebase_app_installations` - `v0.4.2`](#firebase_app_installations---v042) + - [`firebase_auth` - `v6.4.0`](#firebase_auth---v640) + - [`firebase_core` - `v4.7.0`](#firebase_core---v470) + - [`firebase_core_web` - `v3.6.0`](#firebase_core_web---v360) + - [`firebase_crashlytics` - `v5.2.0`](#firebase_crashlytics---v520) + - [`firebase_database` - `v12.3.0`](#firebase_database---v1230) + - [`firebase_in_app_messaging` - `v0.9.2`](#firebase_in_app_messaging---v092) + - [`firebase_messaging` - `v16.2.0`](#firebase_messaging---v1620) + - [`firebase_ml_model_downloader` - `v0.4.2`](#firebase_ml_model_downloader---v042) + - [`firebase_performance` - `v0.11.3`](#firebase_performance---v0113) + - [`firebase_remote_config` - `v6.4.0`](#firebase_remote_config---v640) + - [`firebase_storage` - `v13.3.0`](#firebase_storage---v1330) + - [`firebase_remote_config_web` - `v1.10.6`](#firebase_remote_config_web---v1106) + - [`firebase_in_app_messaging_platform_interface` - `v0.2.5+20`](#firebase_in_app_messaging_platform_interface---v02520) + - [`firebase_remote_config_platform_interface` - `v2.1.2`](#firebase_remote_config_platform_interface---v212) + - [`firebase_auth_platform_interface` - `v8.1.9`](#firebase_auth_platform_interface---v819) + - [`firebase_crashlytics_platform_interface` - `v3.8.20`](#firebase_crashlytics_platform_interface---v3820) + - [`firebase_messaging_web` - `v4.1.5`](#firebase_messaging_web---v415) + - [`firebase_messaging_platform_interface` - `v4.7.9`](#firebase_messaging_platform_interface---v479) + - [`firebase_app_installations_platform_interface` - `v0.1.4+68`](#firebase_app_installations_platform_interface---v01468) + - [`firebase_database_platform_interface` - `v0.3.1+1`](#firebase_database_platform_interface---v0311) + - [`firebase_analytics_platform_interface` - `v5.1.1`](#firebase_analytics_platform_interface---v511) + - [`firebase_app_installations_web` - `v0.1.7+5`](#firebase_app_installations_web---v0175) + - [`firebase_analytics_web` - `v0.6.1+5`](#firebase_analytics_web---v0615) + - [`firebase_performance_platform_interface` - `v0.1.6+7`](#firebase_performance_platform_interface---v0167) + - [`firebase_performance_web` - `v0.1.8+5`](#firebase_performance_web---v0185) + - [`firebase_storage_platform_interface` - `v5.2.20`](#firebase_storage_platform_interface---v5220) + - [`firebase_storage_web` - `v3.11.5`](#firebase_storage_web---v3115) + - [`firebase_auth_web` - `v6.1.5`](#firebase_auth_web---v615) + - [`firebase_database_web` - `v0.2.7+6`](#firebase_database_web---v0276) + - [`firebase_ml_model_downloader_platform_interface` - `v0.1.5+20`](#firebase_ml_model_downloader_platform_interface---v01520) + - [`cloud_functions_web` - `v5.1.5`](#cloud_functions_web---v515) + - [`cloud_functions_platform_interface` - `v5.8.12`](#cloud_functions_platform_interface---v5812) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `firebase_remote_config_web` - `v1.10.6` + - `firebase_in_app_messaging_platform_interface` - `v0.2.5+20` + - `firebase_remote_config_platform_interface` - `v2.1.2` + - `firebase_auth_platform_interface` - `v8.1.9` + - `firebase_crashlytics_platform_interface` - `v3.8.20` + - `firebase_messaging_web` - `v4.1.5` + - `firebase_messaging_platform_interface` - `v4.7.9` + - `firebase_app_installations_platform_interface` - `v0.1.4+68` + - `firebase_database_platform_interface` - `v0.3.1+1` + - `firebase_analytics_platform_interface` - `v5.1.1` + - `firebase_app_installations_web` - `v0.1.7+5` + - `firebase_analytics_web` - `v0.6.1+5` + - `firebase_performance_platform_interface` - `v0.1.6+7` + - `firebase_performance_web` - `v0.1.8+5` + - `firebase_storage_platform_interface` - `v5.2.20` + - `firebase_storage_web` - `v3.11.5` + - `firebase_auth_web` - `v6.1.5` + - `firebase_database_web` - `v0.2.7+6` + - `firebase_ml_model_downloader_platform_interface` - `v0.1.5+20` + - `cloud_functions_web` - `v5.1.5` + - `cloud_functions_platform_interface` - `v5.8.12` + +--- + +#### `firebase_app_check_platform_interface` - `v0.3.0` + + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + +#### `firebase_data_connect` - `v0.3.0` + + - **FEAT**(fdc): Streaming implementation for data connect ([#18174](https://github.com/firebase/flutterfire/issues/18174)). ([6ce6f6b2](https://github.com/firebase/flutterfire/commit/6ce6f6b2369b9d43e69b24b284d8ef816c430e31)) + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + +#### `_flutterfire_internals` - `v1.3.69` + + - **FIX**: improve error handling in _firebaseExceptionFromCoreFirebaseError ([#18177](https://github.com/firebase/flutterfire/issues/18177)). ([3c29048a](https://github.com/firebase/flutterfire/commit/3c29048a859b62f3f224b1fa3c8db61f78f63374)) + +#### `cloud_firestore` - `v6.3.0` + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `cloud_firestore_platform_interface` - `v7.2.0` + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + +#### `cloud_firestore_web` - `v5.3.0` + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + +#### `cloud_functions` - `v6.2.0` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_ai` - `v3.11.0` + + - **FEAT**(firebaseai): server prompt chat and function calling ([#17972](https://github.com/firebase/flutterfire/issues/17972)). ([4b8f2288](https://github.com/firebase/flutterfire/commit/4b8f22889808c0a55f4fc2abc52c72aa2d932379)) + - **FEAT**(firebaseai): add spm support for firebase_ai, and update example to running with spm ([#18159](https://github.com/firebase/flutterfire/issues/18159)). ([bb1e04f8](https://github.com/firebase/flutterfire/commit/bb1e04f8cd0f29cad3913af7bcf40744ffb2515a)) + - **FEAT**(firebaseai): deprecate imagen ([#18148](https://github.com/firebase/flutterfire/issues/18148)). ([99450317](https://github.com/firebase/flutterfire/commit/99450317d83f7b77ab192aed7071432785337789)) + - **FEAT**(firebaseai): Add ability for Schema class to export to json schema ([#18131](https://github.com/firebase/flutterfire/issues/18131)). ([5818a33c](https://github.com/firebase/flutterfire/commit/5818a33c060f775b4a00e11ad5ee04b71e939dad)) + +#### `firebase_analytics` - `v12.3.0` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_app_check` - `v0.4.3` + + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_app_check_web` - `v0.2.4` + + - **FIX**(app_check,web): fix an error that could occur when refreshing a token ([#18135](https://github.com/firebase/flutterfire/issues/18135)). ([6998e512](https://github.com/firebase/flutterfire/commit/6998e512ea5404a20ad81a0306aafaa607babc2a)) + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + +#### `firebase_app_installations` - `v0.4.2` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_auth` - `v6.4.0` + + - **FIX**(auth,ios): serialize Sign in with Apple to prevent crash on overlapping requests ([#18172](https://github.com/firebase/flutterfire/issues/18172)). ([752cbcaa](https://github.com/firebase/flutterfire/commit/752cbcaa57f887a8fea3bda728bb8482290fa049)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_core` - `v4.7.0` + + - **FEAT**(core): bump Firebase Android SDK to 34.12.0 ([#18185](https://github.com/firebase/flutterfire/issues/18185)). ([346a048f](https://github.com/firebase/flutterfire/commit/346a048f098090e6848fdd0f61a8bf7d01394676)) + - **FEAT**: bump Firebase iOS SDK to 12.12.0 ([#18187](https://github.com/firebase/flutterfire/issues/18187)). ([cc063bd9](https://github.com/firebase/flutterfire/commit/cc063bd9df1c59dd3bb8c25d067f8655bc268523)) + - **FEAT**: bump iOS SDK to version 12.11.0 ([#18161](https://github.com/firebase/flutterfire/issues/18161)). ([2664b2c2](https://github.com/firebase/flutterfire/commit/2664b2c2dab4d0147461ce4d3f7862267e880542)) + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + - **FEAT**: bump Firebase android SDK to 34.11.0 ([#18146](https://github.com/firebase/flutterfire/issues/18146)). ([2b50061a](https://github.com/firebase/flutterfire/commit/2b50061a689634957efba8bd17c196dd548a08a2)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_core_web` - `v3.6.0` + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + - **FEAT**: bump JS SDK to version 12.12.0 ([#18186](https://github.com/firebase/flutterfire/issues/18186)). ([3d943ed4](https://github.com/firebase/flutterfire/commit/3d943ed4154eb61617746825fc5c1c90f1e73d88)) + - **FEAT**: bump JS SDK to version 12.11.0 ([#18160](https://github.com/firebase/flutterfire/issues/18160)). ([b3ab0003](https://github.com/firebase/flutterfire/commit/b3ab00036c70debca59414ea236c5012fb841a63)) + +#### `firebase_crashlytics` - `v5.2.0` + + - **FIX**(crashlytics,android): fix an issue with deobfuscating flavored builds ([#18085](https://github.com/firebase/flutterfire/issues/18085)). ([55a7f6ff](https://github.com/firebase/flutterfire/commit/55a7f6ff17940487e29d8bc78779ca4cfce24b0c)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_database` - `v12.3.0` + + - **FEAT**(database,android): fix order issue ([#18142](https://github.com/firebase/flutterfire/issues/18142)). ([5dd661cb](https://github.com/firebase/flutterfire/commit/5dd661cb7b9efa9e02c1bc9233222860be8be7bd)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_in_app_messaging` - `v0.9.2` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_messaging` - `v16.2.0` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_ml_model_downloader` - `v0.4.2` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_performance` - `v0.11.3` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_remote_config` - `v6.4.0` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + +#### `firebase_storage` - `v13.3.0` + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + + ## 2026-03-23 - [BoM 4.11.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4110-2026-03-23) ### Changes diff --git a/VERSIONS.md b/VERSIONS.md index 4210c4a223d3..cfed51d60d40 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -4,6 +4,44 @@ This document is listing all the compatible versions of the FlutterFire plugins. # Versions +## [Flutter BoM 4.12.0 (2026-04-13)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-04-13) + +Install this version using FlutterFire CLI + +```bash +flutterfire install 4.12.0 +``` + +### Included Native Firebase SDK Versions +| Firebase SDK | Version | Link | +|--------------|---------|------| +| Android SDK | 34.12.0 | [Release Notes](https://firebase.google.com/support/release-notes/android) | +| iOS SDK | 12.12.0 | [Release Notes](https://firebase.google.com/support/release-notes/ios) | +| Web SDK | 12.12.0 | [Release Notes](https://firebase.google.com/support/release-notes/js) | +| Windows SDK | 13.5.0 | [Release Notes](https://firebase.google.com/support/release-notes/cpp-relnotes) | + +### FlutterFire Plugin Versions +| Plugin | Version | Dart Version | Flutter Version | +|--------|---------|--------------|-----------------| +| [cloud_firestore](https://pub.dev/packages/cloud_firestore/versions/6.3.0) | 6.3.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [cloud_functions](https://pub.dev/packages/cloud_functions/versions/6.2.0) | 6.2.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_ai](https://pub.dev/packages/firebase_ai/versions/3.11.0) | 3.11.0 | >=3.2.0 <4.0.0 | >=3.16.0 | +| [firebase_analytics](https://pub.dev/packages/firebase_analytics/versions/12.3.0) | 12.3.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_app_check](https://pub.dev/packages/firebase_app_check/versions/0.4.3) | 0.4.3 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_app_installations](https://pub.dev/packages/firebase_app_installations/versions/0.4.2) | 0.4.2 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_auth](https://pub.dev/packages/firebase_auth/versions/6.4.0) | 6.4.0 | >=3.2.0 <4.0.0 | >=3.16.0 | +| [firebase_core](https://pub.dev/packages/firebase_core/versions/4.7.0) | 4.7.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics/versions/5.2.0) | 5.2.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_data_connect](https://pub.dev/packages/firebase_data_connect/versions/0.3.0) | 0.3.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_database](https://pub.dev/packages/firebase_database/versions/12.3.0) | 12.3.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_in_app_messaging](https://pub.dev/packages/firebase_in_app_messaging/versions/0.9.2) | 0.9.2 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_messaging](https://pub.dev/packages/firebase_messaging/versions/16.2.0) | 16.2.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_ml_model_downloader](https://pub.dev/packages/firebase_ml_model_downloader/versions/0.4.2) | 0.4.2 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_performance](https://pub.dev/packages/firebase_performance/versions/0.11.3) | 0.11.3 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_remote_config](https://pub.dev/packages/firebase_remote_config/versions/6.4.0) | 6.4.0 | >=3.2.0 <4.0.0 | >=3.3.0 | +| [firebase_storage](https://pub.dev/packages/firebase_storage/versions/13.3.0) | 13.3.0 | >=3.2.0 <4.0.0 | >=3.3.0 | + + ## [Flutter BoM 4.11.0 (2026-03-23)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-03-23) Install this version using FlutterFire CLI diff --git a/melos.yaml b/melos.yaml index e1154f148da3..b0cbd7f6b3d0 100644 --- a/melos.yaml +++ b/melos.yaml @@ -22,8 +22,6 @@ command: dart run scripts/generate_versions_web.dart && \ dart run scripts/generate_versions_spm.dart && \ git add packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart && git add packages/*/*_web/lib/src/*_version.dart && git add packages/*/*/ios/*/Package.swift packages/*/*/macos/*/Package.swift && git add packages/*/*/ios/*/Sources/*/Constants.swift - post: | - dart run scripts/generate_tag_spm_firebase_core.dart bootstrap: # It seems so that running "pub get" in parallel has some issues (like diff --git a/packages/_flutterfire_internals/CHANGELOG.md b/packages/_flutterfire_internals/CHANGELOG.md index ff4690bcb279..879496c4e3d0 100644 --- a/packages/_flutterfire_internals/CHANGELOG.md +++ b/packages/_flutterfire_internals/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.69 + + - **FIX**: improve error handling in _firebaseExceptionFromCoreFirebaseError ([#18177](https://github.com/firebase/flutterfire/issues/18177)). ([3c29048a](https://github.com/firebase/flutterfire/commit/3c29048a859b62f3f224b1fa3c8db61f78f63374)) + ## 1.3.68 - Update a dependency to the latest release. diff --git a/packages/_flutterfire_internals/pubspec.yaml b/packages/_flutterfire_internals/pubspec.yaml index 485b78d0b208..c12377176ca4 100755 --- a/packages/_flutterfire_internals/pubspec.yaml +++ b/packages/_flutterfire_internals/pubspec.yaml @@ -2,7 +2,7 @@ name: _flutterfire_internals description: A package hosting Dart code shared between FlutterFire plugins. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/_flutterfire_internals -version: 1.3.68 +version: 1.3.69 environment: sdk: '>=3.2.0 <4.0.0' @@ -10,7 +10,7 @@ environment: dependencies: collection: ^1.0.0 - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md index 4f474ba4f5ec..3b0b92f00872 100644 --- a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.3.0 + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 6.2.0 - **FIX**(firestore,windows): fix a crash happening when terminating the firestore instance ([#18069](https://github.com/firebase/flutterfire/issues/18069)). ([adef1872](https://github.com/firebase/flutterfire/commit/adef1872b523b77e2309f3d7400e5a5fdd95738c)) diff --git a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml index f2edd2a204c9..01c8bde1efa1 100755 --- a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml @@ -5,8 +5,8 @@ environment: sdk: '>=3.2.0 <4.0.0' dependencies: - cloud_firestore: ^6.2.0 - firebase_core: ^4.6.0 + cloud_firestore: ^6.3.0 + firebase_core: ^4.7.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index 544b1f6a4d8b..0cc6ea4dff5e 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.1.3" -let firebase_sdk_version: Version = "12.11.0" +let library_version = "6.3.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index e32940c49da7..470dbf1e6153 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.1.3" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "6.3.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml index 9aea3d7d2c58..6186b0a60e8a 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -30,7 +30,7 @@ environment: dependencies: cloud_firestore: path: .. - firebase_core: ^4.4.0 + firebase_core: ^4.7.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pubspec.yaml index 8b5e8c826ab6..544142206d52 100755 --- a/packages/cloud_firestore/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pubspec.yaml @@ -4,7 +4,7 @@ description: live synchronization and offline support on Android and iOS. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore -version: 6.2.0 +version: 6.3.0 topics: - firebase - firestore @@ -20,10 +20,10 @@ environment: flutter: '>=3.3.0' dependencies: - cloud_firestore_platform_interface: ^7.1.0 - cloud_firestore_web: ^5.2.0 + cloud_firestore_platform_interface: ^7.2.0 + cloud_firestore_web: ^5.3.0 collection: ^1.0.0 - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md index 2ea9e08a6f60..f7038a52607d 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 7.2.0 + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + ## 7.1.0 - **REFACTOR**: fix formatting and analysis issues across the repo ([#18124](https://github.com/firebase/flutterfire/issues/18124)). ([ab79fd93](https://github.com/firebase/flutterfire/commit/ab79fd93ee4ccfeb478687623134b1cf8ab71c74)) diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml index 3a812504557f..72dd614e2e7c 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_firestore_platform_interface description: A common platform interface for the cloud_firestore plugin. -version: 7.1.0 +version: 7.2.0 homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface @@ -9,9 +9,9 @@ environment: flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 + _flutterfire_internals: ^1.3.69 collection: ^1.15.0 - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md index b6e35474af23..95127533fdad 100644 --- a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.3.0 + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + ## 5.2.0 - **REFACTOR**: fix formatting and analysis issues across the repo ([#18124](https://github.com/firebase/flutterfire/issues/18124)). ([ab79fd93](https://github.com/firebase/flutterfire/commit/ab79fd93ee4ccfeb478687623134b1cf8ab71c74)) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart index 305156baf450..ab9c93b832a8 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.2.0'; +const packageVersion = '6.3.0'; diff --git a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml index d44a714a4b83..81b1ddbee093 100644 --- a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml @@ -3,18 +3,18 @@ description: The web implementation of cloud_firestore homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web -version: 5.2.0 +version: 5.3.0 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 - cloud_firestore_platform_interface: ^7.1.0 + _flutterfire_internals: ^1.3.69 + cloud_firestore_platform_interface: ^7.2.0 collection: ^1.0.0 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/cloud_functions/cloud_functions/CHANGELOG.md b/packages/cloud_functions/cloud_functions/CHANGELOG.md index c37ecfbf7a2b..299beaa57077 100644 --- a/packages/cloud_functions/cloud_functions/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.2.0 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 6.1.0 - **FIX**(functions,web): fix a crash that could happen with the Int64 type ([#18066](https://github.com/firebase/flutterfire/issues/18066)). ([5eed50c1](https://github.com/firebase/flutterfire/commit/5eed50c15dd29ab97934a4bd0919378f61c46f9e)) diff --git a/packages/cloud_functions/cloud_functions/example/pubspec.yaml b/packages/cloud_functions/cloud_functions/example/pubspec.yaml index eda9b9a2d54e..ee17ae3cb745 100644 --- a/packages/cloud_functions/cloud_functions/example/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/example/pubspec.yaml @@ -6,8 +6,8 @@ environment: flutter: '>=3.3.0' dependencies: - cloud_functions: ^6.1.0 - firebase_core: ^4.6.0 + cloud_functions: ^6.2.0 + firebase_core: ^4.7.0 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift index feff7c887fc8..bed5ad375f66 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "cloud_functions", diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift index f83925b60ff3..f1fe1a27a2cb 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.1.0" +public let versionNumber = "6.2.0" diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift index f52247390a98..a9842df6228b 100644 --- a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "cloud_functions", diff --git a/packages/cloud_functions/cloud_functions/pubspec.yaml b/packages/cloud_functions/cloud_functions/pubspec.yaml index 14f02dc869cb..07d85d0a5545 100644 --- a/packages/cloud_functions/cloud_functions/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_functions description: A Flutter plugin allowing you to use Firebase Cloud Functions. -version: 6.1.0 +version: 6.2.0 homepage: https://firebase.google.com/docs/functions repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions topics: @@ -17,9 +17,9 @@ environment: flutter: '>=3.3.0' dependencies: - cloud_functions_platform_interface: ^5.8.11 - cloud_functions_web: ^5.1.4 - firebase_core: ^4.6.0 + cloud_functions_platform_interface: ^5.8.12 + cloud_functions_web: ^5.1.5 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md index afa88dfe65b5..29fac14b241f 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.8.12 + + - Update a dependency to the latest release. + ## 5.8.11 - **FIX**(functions): prevent collision when listening multiple times to the same stream ([#18052](https://github.com/firebase/flutterfire/issues/18052)). ([c13040e1](https://github.com/firebase/flutterfire/commit/c13040e15a42deddbf61b3180bbd002d58edca29)) diff --git a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml index 6b0438bb0364..0e1e096a2c5c 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml @@ -5,14 +5,14 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_fun # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 5.8.11 +version: 5.8.12 environment: sdk: '>=3.2.0 <4.0.0' flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md index 0089a3225fce..a5b1bed35734 100644 --- a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.5 + + - Update a dependency to the latest release. + ## 5.1.4 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart index 0bf512e408f0..305156baf450 100644 --- a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart +++ b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.1.0'; +const packageVersion = '6.2.0'; diff --git a/packages/cloud_functions/cloud_functions_web/pubspec.yaml b/packages/cloud_functions/cloud_functions_web/pubspec.yaml index ee26b10cb6f8..0a7050898e88 100644 --- a/packages/cloud_functions/cloud_functions_web/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_web/pubspec.yaml @@ -3,16 +3,16 @@ description: The web implementation of cloud_functions homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web -version: 5.1.4 +version: 5.1.5 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - cloud_functions_platform_interface: ^5.8.11 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 + cloud_functions_platform_interface: ^5.8.12 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index 52413ecfffa9..ae8a5abe6fc9 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,3 +1,10 @@ +## 3.11.0 + + - **FEAT**(firebaseai): server prompt chat and function calling ([#17972](https://github.com/firebase/flutterfire/issues/17972)). ([4b8f2288](https://github.com/firebase/flutterfire/commit/4b8f22889808c0a55f4fc2abc52c72aa2d932379)) + - **FEAT**(firebaseai): add spm support for firebase_ai, and update example to running with spm ([#18159](https://github.com/firebase/flutterfire/issues/18159)). ([bb1e04f8](https://github.com/firebase/flutterfire/commit/bb1e04f8cd0f29cad3913af7bcf40744ffb2515a)) + - **FEAT**(firebaseai): deprecate imagen ([#18148](https://github.com/firebase/flutterfire/issues/18148)). ([99450317](https://github.com/firebase/flutterfire/commit/99450317d83f7b77ab192aed7071432785337789)) + - **FEAT**(firebaseai): Add ability for Schema class to export to json schema ([#18131](https://github.com/firebase/flutterfire/issues/18131)). ([5818a33c](https://github.com/firebase/flutterfire/commit/5818a33c060f775b4a00e11ad5ee04b71e939dad)) + ## 3.10.0 - **FEAT**(firebaseai): add proper headers for X-Android-Package, X-Android-Cert and x-ios-bundle-identifier ([#18076](https://github.com/firebase/flutterfire/issues/18076)). ([1351e94e](https://github.com/firebase/flutterfire/commit/1351e94ed3213c458a955cebf05802f12838d5f7)) diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index 1dd1ee5ce2db..babc6bf4fb8a 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -22,9 +22,9 @@ dependencies: camera: ^0.11.2+1 camera_macos: ^0.0.9 cupertino_icons: ^1.0.6 - firebase_ai: ^3.10.0 - firebase_core: ^4.6.0 - firebase_storage: ^13.2.0 + firebase_ai: ^3.11.0 + firebase_core: ^4.7.0 + firebase_storage: ^13.3.0 flutter: sdk: flutter flutter_animate: ^4.5.2 diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart index ba2295b2f513..b2dd21028015 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.2.4'; +const packageVersion = '0.3.0'; diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index 9726f04b2316..4ef4c122d330 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI Logic SDK. -version: 3.10.0 +version: 3.11.0 homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: - firebase @@ -20,9 +20,9 @@ environment: flutter: ">=3.16.0" dependencies: - firebase_app_check: ^0.4.2 - firebase_auth: ^6.3.0 - firebase_core: ^4.6.0 + firebase_app_check: ^0.4.3 + firebase_auth: ^6.4.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md index 042386e13f25..e7e660ad1927 100644 --- a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.3.0 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 12.2.0 - **FIX**(analytics,iOS): Update hashedEmailAddress handling to use hex string conversion ([#18060](https://github.com/firebase/flutterfire/issues/18060)). ([80c6cff2](https://github.com/firebase/flutterfire/commit/80c6cff2836ef102c716d1e54eda8114b8ee629b)) diff --git a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml index fd27b92c5700..41c49ded48dd 100755 --- a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml @@ -6,8 +6,8 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_analytics: ^12.2.0 - firebase_core: ^4.6.0 + firebase_analytics: ^12.3.0 + firebase_core: ^4.7.0 flutter: sdk: flutter in_app_purchase: ^3.2.3 diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift index 22d9bd5c030f..b4fdddd4eef6 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift @@ -8,7 +8,7 @@ import Foundation import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" // Set FIREBASE_ANALYTICS_WITHOUT_ADID=true to use FirebaseAnalyticsWithoutAdIdSupport // e.g. FIREBASE_ANALYTICS_WITHOUT_ADID=true flutter build ios diff --git a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift index 0898c33f3b4f..8a2af6f8c70b 100644 --- a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_analytics", diff --git a/packages/firebase_analytics/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/pubspec.yaml index 48cba69ba250..f9adf7091b80 100755 --- a/packages/firebase_analytics/firebase_analytics/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/pubspec.yaml @@ -4,7 +4,7 @@ description: solution that provides insight on app usage and user engagement on Android and iOS. homepage: https://firebase.google.com/docs/analytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics -version: 12.2.0 +version: 12.3.0 topics: - firebase - analytics @@ -19,9 +19,9 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_analytics_platform_interface: ^5.1.0 - firebase_analytics_web: ^0.6.1+4 - firebase_core: ^4.6.0 + firebase_analytics_platform_interface: ^5.1.1 + firebase_analytics_web: ^0.6.1+5 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md index a248363ff5e0..f68c55ce1112 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.1 + + - Update a dependency to the latest release. + ## 5.1.0 - **FEAT**(analytics,iOS): add support for `logTransaction` ([#17995](https://github.com/firebase/flutterfire/issues/17995)). ([103d7ffa](https://github.com/firebase/flutterfire/commit/103d7ffa9343c654ec23c782a802b929dbf37d01)) diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml index 91b7279d0fb6..ad780d100a1d 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml @@ -2,15 +2,15 @@ name: firebase_analytics_platform_interface description: A common platform interface for the firebase_analytics plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface -version: 5.1.0 +version: 5.1.1 environment: sdk: '>=3.2.0 <4.0.0' flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md index e1cda268ba44..0c237ab3e62f 100644 --- a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.1+5 + + - Update a dependency to the latest release. + ## 0.6.1+4 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart index 26c81d959d07..a6da83ece02a 100644 --- a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart +++ b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.2.0'; +const packageVersion = '12.3.0'; diff --git a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml index 583b3cc365a0..721b85e0d42e 100644 --- a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml @@ -2,17 +2,17 @@ name: firebase_analytics_web description: The web implementation of firebase_analytics homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web -version: 0.6.1+4 +version: 0.6.1+5 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_analytics_platform_interface: ^5.1.0 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 + _flutterfire_internals: ^1.3.69 + firebase_analytics_platform_interface: ^5.1.1 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md index 44fec0c8068e..150487e89961 100644 --- a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.4.3 + + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 0.4.2 - **FEAT**(messaging,web): add support for debug tokens on Web ([#18057](https://github.com/firebase/flutterfire/issues/18057)). ([b853386e](https://github.com/firebase/flutterfire/commit/b853386e987d686eab4b8fd9b8dad14eda97479c)) diff --git a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml index a7a9f49a900f..a4c69a5c1fdc 100644 --- a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml @@ -9,9 +9,9 @@ environment: sdk: '>=3.2.0 <4.0.0' dependencies: - cloud_firestore: ^6.2.0 - firebase_app_check: ^0.4.2 - firebase_core: ^4.6.0 + cloud_firestore: ^6.3.0 + firebase_app_check: ^0.4.3 + firebase_core: ^4.7.0 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index 59c19bba50af..b68e8d6b85f8 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_app_check", diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift index 7dbfc84ba33b..f7b381f99b91 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2" +public let versionNumber = "0.4.3" diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift index b78be7a14dba..85aa6e775d67 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_app_check", diff --git a/packages/firebase_app_check/firebase_app_check/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/pubspec.yaml index 48ed3305f04e..2d87f6170235 100644 --- a/packages/firebase_app_check/firebase_app_check/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_app_check description: App Check works alongside other Firebase services to help protect your backend resources from abuse, such as billing fraud or phishing. homepage: https://firebase.google.com/docs/app-check repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check -version: 0.4.2 +version: 0.4.3 topics: - firebase - app-check @@ -17,9 +17,9 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_app_check_platform_interface: ^0.2.2 - firebase_app_check_web: ^0.2.3 - firebase_core: ^4.6.0 + firebase_app_check_platform_interface: ^0.3.0 + firebase_app_check_web: ^0.2.4 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md index b582ef26dc26..f09c21889e23 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0 + + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + ## 0.2.2 - **FEAT**(messaging,web): add support for debug tokens on Web ([#18057](https://github.com/firebase/flutterfire/issues/18057)). ([b853386e](https://github.com/firebase/flutterfire/commit/b853386e987d686eab4b8fd9b8dad14eda97479c)) diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 7fd0731274db..863fa956cacf 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -1,15 +1,15 @@ name: firebase_app_check_platform_interface description: A common platform interface for the firebase_app_check plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_platform_interface -version: 0.2.2 +version: 0.3.0 environment: sdk: '>=3.2.0 <4.0.0' flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md index f5dd0b7fa0b2..f2f90b5c5be4 100644 --- a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.2.4 + + - **FIX**(app_check,web): fix an error that could occur when refreshing a token ([#18135](https://github.com/firebase/flutterfire/issues/18135)). ([6998e512](https://github.com/firebase/flutterfire/commit/6998e512ea5404a20ad81a0306aafaa607babc2a)) + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + ## 0.2.3 - **FEAT**(messaging,web): add support for debug tokens on Web ([#18057](https://github.com/firebase/flutterfire/issues/18057)). ([b853386e](https://github.com/firebase/flutterfire/commit/b853386e987d686eab4b8fd9b8dad14eda97479c)) diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart index e538fa901e42..a6709bda51df 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.2'; +const packageVersion = '0.4.3'; diff --git a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml index 264586f2958a..7963fb3eb080 100644 --- a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml @@ -1,17 +1,17 @@ name: firebase_app_check_web description: The web implementation of firebase_app_check homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_web -version: 0.2.3 +version: 0.2.4 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_app_check_platform_interface: ^0.2.2 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 + _flutterfire_internals: ^1.3.69 + firebase_app_check_platform_interface: ^0.3.0 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md index fec1198534b0..468ba0805304 100644 --- a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 0.4.1 - **FEAT**(ios): migrate iOS to UIScene lifecycle ([#18054](https://github.com/firebase/flutterfire/issues/18054)). ([3ffa4110](https://github.com/firebase/flutterfire/commit/3ffa411098132fd5182a84be4e7a226106bc7451)) diff --git a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml index d70a3719ac82..ab7dc8c62514 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: sdk: '>=3.2.0 <4.0.0' dependencies: - firebase_core: ^4.6.0 - firebase_app_installations: ^0.4.1 + firebase_core: ^4.7.0 + firebase_app_installations: ^0.4.2 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift index 307f4f583d63..a1a486cc5ba8 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift index 96fe962609a3..c42bec0ea728 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.1" +public let versionNumber = "0.4.2" diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift index 1a47ca9ae6e5..c84a93ed438f 100644 --- a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml index 4339fc3b1eb0..afcdd587f055 100644 --- a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations description: A Flutter plugin allowing you to use Firebase Installations. -version: 0.4.1 +version: 0.4.2 homepage: https://firebase.google.com/docs/projects/manage-installations#flutter repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations topics: @@ -17,9 +17,9 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_app_installations_platform_interface: ^0.1.4+67 - firebase_app_installations_web: ^0.1.7+4 - firebase_core: ^4.6.0 + firebase_app_installations_platform_interface: ^0.1.4+68 + firebase_app_installations_web: ^0.1.7+5 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md index eee03dc13120..32f7114c0473 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+68 + + - Update a dependency to the latest release. + ## 0.1.4+67 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 71d312a8e9c4..572203d2940e 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_platform_interface description: A common platform interface for the firebase_app_installations plugin. -version: 0.1.4+67 +version: 0.1.4+68 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface @@ -9,8 +9,8 @@ environment: flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md index cc905206ef16..b7e1bedafe42 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.7+5 + + - Update a dependency to the latest release. + ## 0.1.7+4 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart index 56ae76ebdc1a..e538fa901e42 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart +++ b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.1'; +const packageVersion = '0.4.2'; diff --git a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml index 60b1c3954790..6fc659fa4222 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_web description: The web implementation of firebase_app_installations. -version: 0.1.7+4 +version: 0.1.7+5 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_app_installations_platform_interface: ^0.1.4+67 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 + _flutterfire_internals: ^1.3.69 + firebase_app_installations_platform_interface: ^0.1.4+68 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_auth/firebase_auth/CHANGELOG.md b/packages/firebase_auth/firebase_auth/CHANGELOG.md index d7d25139c76b..4a92009803d9 100644 --- a/packages/firebase_auth/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.4.0 + + - **FIX**(auth,ios): serialize Sign in with Apple to prevent crash on overlapping requests ([#18172](https://github.com/firebase/flutterfire/issues/18172)). ([752cbcaa](https://github.com/firebase/flutterfire/commit/752cbcaa57f887a8fea3bda728bb8482290fa049)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 6.3.0 - **FIX**(auth): fix inconsistence in casing in the native iOS SDK and Web SDK ([#18086](https://github.com/firebase/flutterfire/issues/18086)). ([60b5cd5c](https://github.com/firebase/flutterfire/commit/60b5cd5c7888fa932124958125e87bd39e1c323c)) diff --git a/packages/firebase_auth/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/firebase_auth/example/pubspec.yaml index 271adb256742..14d7328ef781 100644 --- a/packages/firebase_auth/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/example/pubspec.yaml @@ -6,9 +6,9 @@ environment: dependencies: barcode_widget: ^2.0.4 - firebase_auth: ^6.3.0 - firebase_core: ^4.6.0 - firebase_messaging: ^16.1.3 + firebase_auth: ^6.4.0 + firebase_core: ^4.7.0 + firebase_messaging: ^16.2.0 flutter: sdk: flutter flutter_facebook_auth: ^7.1.5 diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index a250c3e74394..2905220b029a 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.2.0" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "6.4.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index 96473233e110..691a98814c6f 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.2.0" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "6.4.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_auth/firebase_auth/pubspec.yaml b/packages/firebase_auth/firebase_auth/pubspec.yaml index e86bbd965275..9fffbe7119c3 100755 --- a/packages/firebase_auth/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling like Google, Facebook and Twitter. homepage: https://firebase.google.com/docs/auth repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth -version: 6.3.0 +version: 6.4.0 topics: - firebase - authentication @@ -20,9 +20,9 @@ environment: flutter: '>=3.16.0' dependencies: - firebase_auth_platform_interface: ^8.1.8 - firebase_auth_web: ^6.1.4 - firebase_core: ^4.6.0 + firebase_auth_platform_interface: ^8.1.9 + firebase_auth_web: ^6.1.5 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 flutter: sdk: flutter diff --git a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md index 95374b3a8bc2..1107d8192f3d 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 8.1.9 + + - Update a dependency to the latest release. + ## 8.1.8 - **REFACTOR**: fix formatting and analysis issues across the repo ([#18124](https://github.com/firebase/flutterfire/issues/18124)). ([ab79fd93](https://github.com/firebase/flutterfire/commit/ab79fd93ee4ccfeb478687623134b1cf8ab71c74)) diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml index fb2e20ce5f56..5e6e5a694c1b 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml @@ -4,16 +4,16 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_au repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 8.1.8 +version: 8.1.9 environment: sdk: '>=3.2.0 <4.0.0' flutter: '>=3.16.0' dependencies: - _flutterfire_internals: ^1.3.68 + _flutterfire_internals: ^1.3.69 collection: ^1.16.0 - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter http: ^1.1.0 diff --git a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md index fbfb4ffac53a..41e451368e0b 100644 --- a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.1.5 + + - Update a dependency to the latest release. + ## 6.1.4 - **FIX**(auth): fix inconsistence in casing in the native iOS SDK and Web SDK ([#18086](https://github.com/firebase/flutterfire/issues/18086)). ([60b5cd5c](https://github.com/firebase/flutterfire/commit/60b5cd5c7888fa932124958125e87bd39e1c323c)) diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart index ab9c93b832a8..14d87311cbb9 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.3.0'; +const packageVersion = '6.4.0'; diff --git a/packages/firebase_auth/firebase_auth_web/pubspec.yaml b/packages/firebase_auth/firebase_auth_web/pubspec.yaml index 3ee1a64e0ad1..a8813adafe3c 100644 --- a/packages/firebase_auth/firebase_auth_web/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_web/pubspec.yaml @@ -2,16 +2,16 @@ name: firebase_auth_web description: The web implementation of firebase_auth homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web -version: 6.1.4 +version: 6.1.5 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - firebase_auth_platform_interface: ^8.1.8 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 + firebase_auth_platform_interface: ^8.1.9 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_core/firebase_core/CHANGELOG.md b/packages/firebase_core/firebase_core/CHANGELOG.md index 724d4582bc4d..c43904a2cf08 100644 --- a/packages/firebase_core/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/firebase_core/CHANGELOG.md @@ -1,3 +1,12 @@ +## 4.7.0 + + - **FEAT**(core): bump Firebase Android SDK to 34.12.0 ([#18185](https://github.com/firebase/flutterfire/issues/18185)). ([346a048f](https://github.com/firebase/flutterfire/commit/346a048f098090e6848fdd0f61a8bf7d01394676)) + - **FEAT**: bump Firebase iOS SDK to 12.12.0 ([#18187](https://github.com/firebase/flutterfire/issues/18187)). ([cc063bd9](https://github.com/firebase/flutterfire/commit/cc063bd9df1c59dd3bb8c25d067f8655bc268523)) + - **FEAT**: bump iOS SDK to version 12.11.0 ([#18161](https://github.com/firebase/flutterfire/issues/18161)). ([2664b2c2](https://github.com/firebase/flutterfire/commit/2664b2c2dab4d0147461ce4d3f7862267e880542)) + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + - **FEAT**: bump Firebase android SDK to 34.11.0 ([#18146](https://github.com/firebase/flutterfire/issues/18146)). ([2b50061a](https://github.com/firebase/flutterfire/commit/2b50061a689634957efba8bd17c196dd548a08a2)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 4.6.0 - **FIX**(remote_config,windows): release mode wasn't linking properly for windows ([#18073](https://github.com/firebase/flutterfire/issues/18073)). ([ea1f309a](https://github.com/firebase/flutterfire/commit/ea1f309a33075fc06c082819f0653976c6d5214b)) diff --git a/packages/firebase_core/firebase_core/example/pubspec.yaml b/packages/firebase_core/firebase_core/example/pubspec.yaml index 03cbbe0dac94..4cb77afda207 100644 --- a/packages/firebase_core/firebase_core/example/pubspec.yaml +++ b/packages/firebase_core/firebase_core/example/pubspec.yaml @@ -5,7 +5,7 @@ environment: sdk: '>=3.2.0 <4.0.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index 4dbfd4acebd5..694cc8c8db64 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version_string = "4.5.0" -let firebase_sdk_version: Version = "12.9.0" +let library_version_string = "4.7.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index 65aaba7915d1..3a4557f03f3f 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version_string = "4.5.0" -let firebase_sdk_version: Version = "12.9.0" +let library_version_string = "4.7.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index 721448faa3f0..aef91256e870 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. homepage: https://firebase.google.com/docs/flutter/setup repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core -version: 4.6.0 +version: 4.7.0 topics: - firebase - core @@ -17,7 +17,7 @@ environment: dependencies: firebase_core_platform_interface: ^6.0.3 - firebase_core_web: ^3.5.1 + firebase_core_web: ^3.6.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_core/firebase_core_web/CHANGELOG.md b/packages/firebase_core/firebase_core_web/CHANGELOG.md index 0f7cd03e6ed1..228023192376 100644 --- a/packages/firebase_core/firebase_core_web/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_web/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.6.0 + + - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) + - **FEAT**: bump JS SDK to version 12.12.0 ([#18186](https://github.com/firebase/flutterfire/issues/18186)). ([3d943ed4](https://github.com/firebase/flutterfire/commit/3d943ed4154eb61617746825fc5c1c90f1e73d88)) + - **FEAT**: bump JS SDK to version 12.11.0 ([#18160](https://github.com/firebase/flutterfire/issues/18160)). ([b3ab0003](https://github.com/firebase/flutterfire/commit/b3ab00036c70debca59414ea236c5012fb841a63)) + ## 3.5.1 - Update a dependency to the latest release. diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart index b92a03e487fe..f30f2ff929a0 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '4.6.0'; +const packageVersion = '4.7.0'; diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index 54ce8f07fbca..e7cb2ce4055d 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_core_web description: The web implementation of firebase_core homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web -version: 3.5.1 +version: 3.6.0 environment: sdk: '>=3.4.0 <4.0.0' diff --git a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md index e51572825aaf..d8bf22a18039 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,8 @@ +## 5.2.0 + + - **FIX**(crashlytics,android): fix an issue with deobfuscating flavored builds ([#18085](https://github.com/firebase/flutterfire/issues/18085)). ([55a7f6ff](https://github.com/firebase/flutterfire/commit/55a7f6ff17940487e29d8bc78779ca4cfce24b0c)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 5.1.0 - **FEAT**(ios): migrate iOS to UIScene lifecycle ([#18054](https://github.com/firebase/flutterfire/issues/18054)). ([3ffa4110](https://github.com/firebase/flutterfire/commit/3ffa411098132fd5182a84be4e7a226106bc7451)) diff --git a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml index 7c21ce86575f..4f415aee5233 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml @@ -6,9 +6,9 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_analytics: ^12.2.0 - firebase_core: ^4.6.0 - firebase_crashlytics: ^5.1.0 + firebase_analytics: ^12.3.0 + firebase_core: ^4.7.0 + firebase_crashlytics: ^5.2.0 flutter: sdk: flutter diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index 586eeda0b7ff..e2ca155d2730 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "5.0.8" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "5.2.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index 61ffe48c3b67..60fff2af2364 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "5.0.8" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "5.2.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml index 37cee9a65d0e..ef3f5f07c9ea 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 5.1.0 +version: 5.2.0 homepage: https://firebase.google.com/docs/crashlytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics topics: @@ -19,9 +19,9 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_crashlytics_platform_interface: ^3.8.19 + firebase_crashlytics_platform_interface: ^3.8.20 flutter: sdk: flutter stack_trace: ^1.10.0 diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md index 9849ee09191c..1105b13a9626 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.8.20 + + - Update a dependency to the latest release. + ## 3.8.19 - Update a dependency to the latest release. diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml index 49ab3d585a14..c252b78a788b 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_crashlytics_platform_interface description: A common platform interface for the firebase_crashlytics plugin. -version: 3.8.19 +version: 3.8.20 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface @@ -9,9 +9,9 @@ environment: flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 + _flutterfire_internals: ^1.3.69 collection: ^1.15.0 - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md index 47ddabb56175..d50b697d0393 100644 --- a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md +++ b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.3.0 + + - **FEAT**(fdc): Streaming implementation for data connect ([#18174](https://github.com/firebase/flutterfire/issues/18174)). ([6ce6f6b2](https://github.com/firebase/flutterfire/commit/6ce6f6b2369b9d43e69b24b284d8ef816c430e31)) + - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) + ## 0.2.4 - **FIX**(data_connect): fix UTF 8 characters decoding in data connect ([#18120](https://github.com/firebase/flutterfire/issues/18120)). ([25ec5c42](https://github.com/firebase/flutterfire/commit/25ec5c429863c34f8473daad7f83487a31dcd7a1)) diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index fc91e9c9f3b9..7b66b85ecd5d 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -11,16 +11,16 @@ environment: dependencies: flutter: sdk: flutter - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 google_sign_in: ^6.1.0 - firebase_auth: ^6.3.0 + firebase_auth: ^6.4.0 firebase_data_connect: path: ../ cupertino_icons: ^1.0.6 flutter_rating_bar: ^4.0.1 protobuf: ^3.1.0 - firebase_app_check: ^0.4.2 + firebase_app_check: ^0.4.3 dev_dependencies: build_runner: ^2.3.3 diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart index a62e6b0ea102..4d967e86fa3f 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// version number for the package, should be align with pubspec.yaml. -const packageVersion = '0.2.4'; +const packageVersion = '0.3.0'; diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index 3bd28b86b42c..35acc8c3f8f0 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_data_connect description: 'Flutter plugin for Firebase Data Connect, a relational database service that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL.' -version: 0.2.4 +version: 0.3.0 homepage: https://firebase.google.com/docs/data-connect/quickstart?platform=flutter false_secrets: - example/** @@ -12,9 +12,9 @@ environment: dependencies: crypto: ^3.0.6 - firebase_app_check: ^0.4.2 - firebase_auth: ^6.3.0 - firebase_core: ^4.6.0 + firebase_app_check: ^0.4.3 + firebase_auth: ^6.4.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 fixnum: ^1.1.1 flutter: @@ -31,8 +31,8 @@ dependencies: dev_dependencies: build_runner: ^2.4.12 - firebase_app_check_platform_interface: ^0.2.2 - firebase_auth_platform_interface: ^8.1.8 + firebase_app_check_platform_interface: ^0.3.0 + firebase_auth_platform_interface: ^8.1.9 flutter_lints: ^4.0.0 flutter_test: sdk: flutter diff --git a/packages/firebase_database/firebase_database/CHANGELOG.md b/packages/firebase_database/firebase_database/CHANGELOG.md index ac0c39b975f6..5bce4614feac 100644 --- a/packages/firebase_database/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/firebase_database/CHANGELOG.md @@ -1,3 +1,8 @@ +## 12.3.0 + + - **FEAT**(database,android): fix order issue ([#18142](https://github.com/firebase/flutterfire/issues/18142)). ([5dd661cb](https://github.com/firebase/flutterfire/commit/5dd661cb7b9efa9e02c1bc9233222860be8be7bd)) + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 12.2.0 - **FIX**(database,iOS): remove unnecessary order modifier checks in query construction ([#18134](https://github.com/firebase/flutterfire/issues/18134)). ([4fa10c36](https://github.com/firebase/flutterfire/commit/4fa10c36d195d4cd67c39d89984cfe5a1eee5d85)) diff --git a/packages/firebase_database/firebase_database/example/pubspec.yaml b/packages/firebase_database/firebase_database/example/pubspec.yaml index 44454d902198..01b2b05e1abc 100755 --- a/packages/firebase_database/firebase_database/example/pubspec.yaml +++ b/packages/firebase_database/firebase_database/example/pubspec.yaml @@ -6,8 +6,8 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 - firebase_database: ^12.2.0 + firebase_core: ^4.7.0 + firebase_database: ^12.3.0 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index 2534193a23c4..55f5fa212eab 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "12.1.4" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "12.3.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index fe5afaddaec0..66d5719467c5 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "12.1.4" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "12.3.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index b04ba24786ca..1245083700f8 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. homepage: https://firebase.google.com/docs/database repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database -version: 12.2.0 +version: 12.3.0 topics: - firebase - database @@ -17,10 +17,10 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_database_platform_interface: ^0.3.1 - firebase_database_web: ^0.2.7+5 + firebase_database_platform_interface: ^0.3.1+1 + firebase_database_web: ^0.2.7+6 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md index a6092a3ce12d..073eae47b283 100755 --- a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.1+1 + + - Update a dependency to the latest release. + ## 0.3.1 - **FEAT**(database,windows): add support for Realtime Database to windows ([#18079](https://github.com/firebase/flutterfire/issues/18079)). ([007689f9](https://github.com/firebase/flutterfire/commit/007689f99866582828a063d174c52ebba13ac0ef)) diff --git a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml index bfbbcc7002a7..6333f8bc6b3c 100755 --- a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml +++ b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_platform_interface description: A common platform interface for the firebase_database plugin. -version: 0.3.1 +version: 0.3.1+1 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_platform_interface environment: @@ -8,9 +8,9 @@ environment: flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 + _flutterfire_internals: ^1.3.69 collection: ^1.14.3 - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_database/firebase_database_web/CHANGELOG.md b/packages/firebase_database/firebase_database_web/CHANGELOG.md index 837eaf1b5862..4a68d582f6d5 100644 --- a/packages/firebase_database/firebase_database_web/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.7+6 + + - Update a dependency to the latest release. + ## 0.2.7+5 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart index 26c81d959d07..a6da83ece02a 100644 --- a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.2.0'; +const packageVersion = '12.3.0'; diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index e241f66b3883..ba45c603be55 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_web description: The web implementation of firebase_database -version: 0.2.7+5 +version: 0.2.7+6 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_web environment: @@ -9,9 +9,9 @@ environment: dependencies: collection: ^1.18.0 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 - firebase_database_platform_interface: ^0.3.1 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 + firebase_database_platform_interface: ^0.3.1+1 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md index 56744bcaeb5b..5f4a400b9992 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 0.9.1 - **FEAT**(ios): migrate iOS to UIScene lifecycle ([#18054](https://github.com/firebase/flutterfire/issues/18054)). ([3ffa4110](https://github.com/firebase/flutterfire/commit/3ffa411098132fd5182a84be4e7a226106bc7451)) diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml index a4622ca2bde2..155716d97266 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml @@ -6,10 +6,10 @@ environment: sdk: '>=3.2.0 <4.0.0' dependencies: - firebase_analytics: ^12.2.0 - firebase_core: ^4.6.0 - firebase_in_app_messaging: ^0.9.1 - firebase_in_app_messaging_platform_interface: ^0.2.5+19 + firebase_analytics: ^12.3.0 + firebase_core: ^4.7.0 + firebase_in_app_messaging: ^0.9.2 + firebase_in_app_messaging_platform_interface: ^0.2.5+20 flutter: sdk: flutter diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index 967c759d4667..f27767d3c35c 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "0.9.0-7" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "0.9.2" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_in_app_messaging", diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml index b9e73439697a..ca1df6800a4d 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_in_app_messaging description: Flutter plugin for Firebase In-App Messaging. -version: 0.9.1 +version: 0.9.2 homepage: https://firebase.google.com/docs/in-app-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging topics: @@ -17,9 +17,9 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_in_app_messaging_platform_interface: ^0.2.5+19 + firebase_in_app_messaging_platform_interface: ^0.2.5+20 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md index 20b6dcab90d0..5811324022eb 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.5+20 + + - Update a dependency to the latest release. + ## 0.2.5+19 - Update a dependency to the latest release. diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml index e0190cdfd00c..812273735d34 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml @@ -3,15 +3,15 @@ description: A common platform interface for the firebase_in_app_messaging plugi homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface -version: 0.2.5+19 +version: 0.2.5+20 environment: sdk: '>=3.2.0 <4.0.0' flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md index e8b0c56fa251..649638dc7908 100644 --- a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 16.2.0 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 16.1.3 - **FIX**(messaging,ios): fix an issue where the scene initializer could be called twice in latest Flutter versions ([#18051](https://github.com/firebase/flutterfire/issues/18051)). ([5b602105](https://github.com/firebase/flutterfire/commit/5b602105faf9f64ac977a4266de5ee10785330bd)) diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index 3b4dd16c1a48..49a37810302b 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -6,8 +6,8 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 - firebase_messaging: ^16.1.3 + firebase_core: ^4.7.0 + firebase_messaging: ^16.2.0 flutter: sdk: flutter flutter_local_notifications: ^17.2.1 diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index 2907358115f9..d2437be8e0d4 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "16.1.2" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "16.2.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index e475afc47cb2..ef733d6db96e 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "16.1.2" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "16.2.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/pubspec.yaml index 16621ec0dd97..cbe5bbf4efa5 100644 --- a/packages/firebase_messaging/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. homepage: https://firebase.google.com/docs/cloud-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging -version: 16.1.3 +version: 16.2.0 topics: - firebase - messaging @@ -17,10 +17,10 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_messaging_platform_interface: ^4.7.8 - firebase_messaging_web: ^4.1.4 + firebase_messaging_platform_interface: ^4.7.9 + firebase_messaging_web: ^4.1.5 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md index e3055087b231..fdb475681a53 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.7.9 + + - Update a dependency to the latest release. + ## 4.7.8 - Update a dependency to the latest release. diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml index 28109d03b51b..e5502bac2a5c 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_messaging_platform_interface description: A common platform interface for the firebase_messaging plugin. -version: 4.7.8 +version: 4.7.9 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface @@ -9,8 +9,8 @@ environment: flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md index 682a008f94c7..be3ecee9e433 100644 --- a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.1.5 + + - Update a dependency to the latest release. + ## 4.1.4 - Update a dependency to the latest release. diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart index 518fb0119f1c..899437d9741e 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '16.1.3'; +const packageVersion = '16.2.0'; diff --git a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml index 7252cac92640..fc9f670c1864 100644 --- a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml @@ -2,17 +2,17 @@ name: firebase_messaging_web description: The web implementation of firebase_messaging homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web -version: 4.1.4 +version: 4.1.5 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 - firebase_messaging_platform_interface: ^4.7.8 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 + firebase_messaging_platform_interface: ^4.7.9 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md index 271df45e21de..c2e2912265ec 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 0.4.1 - **FEAT**(ios): migrate iOS to UIScene lifecycle ([#18054](https://github.com/firebase/flutterfire/issues/18054)). ([3ffa4110](https://github.com/firebase/flutterfire/commit/3ffa411098132fd5182a84be4e7a226106bc7451)) diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml index 2dc0801a060e..47eeb1d1fbfb 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml @@ -10,8 +10,8 @@ dependencies: flutter: sdk: flutter - firebase_core: ^4.6.0 - firebase_ml_model_downloader: ^0.4.1 + firebase_core: ^4.7.0 + firebase_ml_model_downloader: ^0.4.2 dev_dependencies: flutter_lints: ^4.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift index 401ec8921a0d..dfc5b53f229c 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift index 96fe962609a3..c42bec0ea728 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.1" +public let versionNumber = "0.4.2" diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift index 5f35240de0e7..350adb156226 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml index 3bbef56da010..55c02c635b8d 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader description: A Flutter plugin allowing you to use Firebase Ml Model Downloader. -version: 0.4.1 +version: 0.4.2 homepage: https://firebase.google.com/docs/ml/flutter/use-custom-models repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader topics: @@ -17,9 +17,9 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_ml_model_downloader_platform_interface: ^0.1.5+19 + firebase_ml_model_downloader_platform_interface: ^0.1.5+20 flutter: sdk: flutter diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md index 9756d23eb3f6..fd0c566e7b3d 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5+20 + + - Update a dependency to the latest release. + ## 0.1.5+19 - Update a dependency to the latest release. diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml index bd5c46b04b70..008d6f1e45a5 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader_platform_interface description: A common platform interface for the firebase_ml_model_downloader plugin. -version: 0.1.5+19 +version: 0.1.5+20 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface @@ -9,7 +9,7 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_performance/firebase_performance/CHANGELOG.md b/packages/firebase_performance/firebase_performance/CHANGELOG.md index f086b1346d31..3ffd44a59aa2 100644 --- a/packages/firebase_performance/firebase_performance/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.3 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 0.11.2 - **FIX**(android): remove kotlin-android since AGP 9 supports it ([#18059](https://github.com/firebase/flutterfire/issues/18059)). ([1e39ad1f](https://github.com/firebase/flutterfire/commit/1e39ad1f146ce23742731ceeb30ff36c440b816f)) diff --git a/packages/firebase_performance/firebase_performance/example/pubspec.yaml b/packages/firebase_performance/firebase_performance/example/pubspec.yaml index 10805d183ef7..5ef4bd4bbccc 100644 --- a/packages/firebase_performance/firebase_performance/example/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: sdk: '>=3.2.0 <4.0.0' dependencies: - firebase_core: ^4.6.0 - firebase_performance: ^0.11.2 + firebase_core: ^4.7.0 + firebase_performance: ^0.11.3 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index 8ca91978ac83..2d2e38300e95 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "0.11.1-5" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "0.11.3" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_performance", diff --git a/packages/firebase_performance/firebase_performance/pubspec.yaml b/packages/firebase_performance/firebase_performance/pubspec.yaml index 39a1de29b9d9..f3164191af76 100644 --- a/packages/firebase_performance/firebase_performance/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/pubspec.yaml @@ -5,7 +5,7 @@ description: iOS. homepage: https://firebase.google.com/docs/perf-mon repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance -version: 0.11.2 +version: 0.11.3 topics: - firebase - performance @@ -20,10 +20,10 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_performance_platform_interface: ^0.1.6+6 - firebase_performance_web: ^0.1.8+4 + firebase_performance_platform_interface: ^0.1.6+7 + firebase_performance_web: ^0.1.8+5 flutter: sdk: flutter diff --git a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md index e24542e89480..8a1cb17de7f6 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.6+7 + + - Update a dependency to the latest release. + ## 0.1.6+6 - **REFACTOR**: fix formatting and analysis issues across the repo ([#18124](https://github.com/firebase/flutterfire/issues/18124)). ([ab79fd93](https://github.com/firebase/flutterfire/commit/ab79fd93ee4ccfeb478687623134b1cf8ab71c74)) diff --git a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml index bd67b00c8b1f..9f8b80674720 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_performance_platform_interface description: A common platform interface for the firebase_performance plugin. -version: 0.1.6+6 +version: 0.1.6+7 homepage: https://firebase.google.com/docs/perf-mon/flutter/get-started environment: @@ -8,8 +8,8 @@ environment: flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 flutter: sdk: flutter plugin_platform_interface: ^2.1.3 diff --git a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md index ffc36e7d5ef0..5da573cb1599 100644 --- a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8+5 + + - Update a dependency to the latest release. + ## 0.1.8+4 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart index bad4a118632f..c304601e8f7e 100644 --- a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart +++ b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.11.2'; +const packageVersion = '0.11.3'; diff --git a/packages/firebase_performance/firebase_performance_web/pubspec.yaml b/packages/firebase_performance/firebase_performance_web/pubspec.yaml index b53bce4989fe..da98413ffd0b 100644 --- a/packages/firebase_performance/firebase_performance_web/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_web/pubspec.yaml @@ -1,17 +1,17 @@ name: firebase_performance_web description: Web implementation of Firebase Performance monitoring. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance_web -version: 0.1.8+4 +version: 0.1.8+5 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 - firebase_performance_platform_interface: ^0.1.6+6 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 + firebase_performance_platform_interface: ^0.1.6+7 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md index a4dbc97f0f9e..8be436bad143 100644 --- a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.4.0 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 6.3.0 - **FIX**(remote-config,ios): fix hot reload issue ([#18062](https://github.com/firebase/flutterfire/issues/18062)). ([5db57711](https://github.com/firebase/flutterfire/commit/5db577116139d469bcdf38dd58f69c1e5f61c87e)) diff --git a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml index 97afc16174d2..ad7b5d0cec8b 100644 --- a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml @@ -8,8 +8,8 @@ environment: dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - firebase_core: ^4.6.0 - firebase_remote_config: ^6.3.0 + firebase_core: ^4.7.0 + firebase_remote_config: ^6.4.0 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift index 804e4fdb9967..11ab5b10c9c7 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift index d2c573f04e70..2f534d106ebb 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "5.4.7" +public let versionNumber = "6.4.0" diff --git a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift index 1a3e14ec5488..7886d5044cd1 100644 --- a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.9.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml index e460e7389ba2..244af393050e 100644 --- a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml @@ -4,7 +4,7 @@ description: re-releasing. homepage: https://firebase.google.com/docs/remote-config repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config -version: 6.3.0 +version: 6.4.0 topics: - firebase - remote @@ -19,10 +19,10 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_remote_config_platform_interface: ^2.1.1 - firebase_remote_config_web: ^1.10.5 + firebase_remote_config_platform_interface: ^2.1.2 + firebase_remote_config_web: ^1.10.6 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md index 6f5c4eed2cb5..733346173ce6 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.2 + + - Update a dependency to the latest release. + ## 2.1.1 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml index 8d806b02ec00..26430f70ed34 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml @@ -4,15 +4,15 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_re repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.1.1 +version: 2.1.2 environment: sdk: '>=3.2.0 <4.0.0' flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md index 43c872ef7a3f..ad098bfdaaf4 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.6 + + - Update a dependency to the latest release. + ## 1.10.5 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart index ab9c93b832a8..14d87311cbb9 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart +++ b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.3.0'; +const packageVersion = '6.4.0'; diff --git a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml index dc4c2ada5299..ce73959f5b8b 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml @@ -3,17 +3,17 @@ description: The web implementation of firebase_remote_config homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web -version: 1.10.5 +version: 1.10.6 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 - firebase_remote_config_platform_interface: ^2.1.1 + _flutterfire_internals: ^1.3.69 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 + firebase_remote_config_platform_interface: ^2.1.2 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_storage/firebase_storage/CHANGELOG.md b/packages/firebase_storage/firebase_storage/CHANGELOG.md index 5a830e1f383d..f784862e4914 100644 --- a/packages/firebase_storage/firebase_storage/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage/CHANGELOG.md @@ -1,3 +1,7 @@ +## 13.3.0 + + - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) + ## 13.2.0 - **FIX**(storage,iOS): guard `useStorageEmulator` to prevent crash on hot restart ([#18116](https://github.com/firebase/flutterfire/issues/18116)). ([9919bf03](https://github.com/firebase/flutterfire/commit/9919bf035226a4b066ac1ef52859d5349eff61c6)) diff --git a/packages/firebase_storage/firebase_storage/example/pubspec.yaml b/packages/firebase_storage/firebase_storage/example/pubspec.yaml index bf43d06e4bcc..e0ee56516730 100755 --- a/packages/firebase_storage/firebase_storage/example/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/example/pubspec.yaml @@ -5,8 +5,8 @@ environment: sdk: '>=3.4.0 <4.0.0' dependencies: - firebase_core: ^4.6.0 - firebase_storage: ^13.2.0 + firebase_core: ^4.7.0 + firebase_storage: ^13.3.0 flutter: sdk: flutter image_picker: ^1.1.2 diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index 93c37b682939..c07526924658 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "13.1.0" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "13.3.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_storage", diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index fc4e98c134c9..f93b1007f6fd 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "13.1.0" -let firebase_sdk_version: Version = "12.9.0" +let library_version = "13.3.0" +let firebase_sdk_version: Version = "12.12.0" let package = Package( name: "firebase_storage", diff --git a/packages/firebase_storage/firebase_storage/pubspec.yaml b/packages/firebase_storage/firebase_storage/pubspec.yaml index c43348335a83..a61addff139d 100755 --- a/packages/firebase_storage/firebase_storage/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS. homepage: https://firebase.google.com/docs/storage/flutter/start repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage -version: 13.2.0 +version: 13.3.0 topics: - firebase - storage @@ -19,10 +19,10 @@ environment: flutter: '>=3.3.0' dependencies: - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_storage_platform_interface: ^5.2.19 - firebase_storage_web: ^3.11.4 + firebase_storage_platform_interface: ^5.2.20 + firebase_storage_web: ^3.11.5 flutter: sdk: flutter mime: ^2.0.0 diff --git a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md index cf66c6d1a1e2..119baabc56a3 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.2.20 + + - Update a dependency to the latest release. + ## 5.2.19 - **REFACTOR**: fix formatting and analysis issues across the repo ([#18124](https://github.com/firebase/flutterfire/issues/18124)). ([ab79fd93](https://github.com/firebase/flutterfire/commit/ab79fd93ee4ccfeb478687623134b1cf8ab71c74)) diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml index 33f2acba76e8..50456ad4f18a 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_storage_platform_interface description: A common platform interface for the firebase_storage plugin. -version: 5.2.19 +version: 5.2.20 homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface @@ -9,9 +9,9 @@ environment: flutter: '>=3.3.0' dependencies: - _flutterfire_internals: ^1.3.68 + _flutterfire_internals: ^1.3.69 collection: ^1.15.0 - firebase_core: ^4.6.0 + firebase_core: ^4.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md index 001a07a76582..b88403e0f1f0 100644 --- a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.11.5 + + - Update a dependency to the latest release. + ## 3.11.4 - **REFACTOR**: fix formatting and analysis issues across the repo ([#18124](https://github.com/firebase/flutterfire/issues/18124)). ([ab79fd93](https://github.com/firebase/flutterfire/commit/ab79fd93ee4ccfeb478687623134b1cf8ab71c74)) diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart index 9bc0658bd391..f4d489e96af4 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '13.2.0'; +const packageVersion = '13.3.0'; diff --git a/packages/firebase_storage/firebase_storage_web/pubspec.yaml b/packages/firebase_storage/firebase_storage_web/pubspec.yaml index 1defb01f2e5e..f98df35478f0 100644 --- a/packages/firebase_storage/firebase_storage_web/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_web/pubspec.yaml @@ -2,18 +2,18 @@ name: firebase_storage_web description: The web implementation of firebase_storage homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web -version: 3.11.4 +version: 3.11.5 environment: sdk: '>=3.4.0 <4.0.0' flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.68 + _flutterfire_internals: ^1.3.69 async: ^2.5.0 - firebase_core: ^4.6.0 - firebase_core_web: ^3.5.1 - firebase_storage_platform_interface: ^5.2.19 + firebase_core: ^4.7.0 + firebase_core_web: ^3.6.0 + firebase_storage_platform_interface: ^5.2.20 flutter: sdk: flutter flutter_web_plugins: diff --git a/scripts/versions.json b/scripts/versions.json index 62f891477e54..d5ffa2901f0f 100644 --- a/scripts/versions.json +++ b/scripts/versions.json @@ -1,4 +1,32 @@ { + "4.12.0": { + "date": "2026-04-13", + "firebase_sdk": { + "android": "34.12.0", + "ios": "12.12.0", + "web": "12.12.0", + "windows": "13.5.0" + }, + "packages": { + "cloud_firestore": "6.3.0", + "cloud_functions": "6.2.0", + "firebase_ai": "3.11.0", + "firebase_analytics": "12.3.0", + "firebase_app_check": "0.4.3", + "firebase_app_installations": "0.4.2", + "firebase_auth": "6.4.0", + "firebase_core": "4.7.0", + "firebase_crashlytics": "5.2.0", + "firebase_data_connect": "0.3.0", + "firebase_database": "12.3.0", + "firebase_in_app_messaging": "0.9.2", + "firebase_messaging": "16.2.0", + "firebase_ml_model_downloader": "0.4.2", + "firebase_performance": "0.11.3", + "firebase_remote_config": "6.4.0", + "firebase_storage": "13.3.0" + } + }, "4.11.0": { "date": "2026-03-23", "firebase_sdk": { diff --git a/tests/pubspec.yaml b/tests/pubspec.yaml index c91c640a39d6..99f7a1cf3cc1 100644 --- a/tests/pubspec.yaml +++ b/tests/pubspec.yaml @@ -9,43 +9,43 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions: ^6.1.0 - cloud_functions_platform_interface: ^5.8.11 - cloud_functions_web: ^5.1.4 + cloud_functions: ^6.2.0 + cloud_functions_platform_interface: ^5.8.12 + cloud_functions_web: ^5.1.5 collection: ^1.15.0 - firebase_ai: ^3.10.0 - firebase_analytics: ^12.2.0 - firebase_analytics_platform_interface: ^5.1.0 - firebase_analytics_web: ^0.6.1+4 - firebase_app_check: ^0.4.2 - firebase_app_check_platform_interface: ^0.2.2 - firebase_app_check_web: ^0.2.3 - firebase_app_installations: ^0.4.1 - firebase_app_installations_platform_interface: ^0.1.4+67 - firebase_app_installations_web: ^0.1.7+4 - firebase_auth: ^6.3.0 - firebase_auth_platform_interface: ^8.1.8 - firebase_auth_web: ^6.1.4 - firebase_core: ^4.6.0 + firebase_ai: ^3.11.0 + firebase_analytics: ^12.3.0 + firebase_analytics_platform_interface: ^5.1.1 + firebase_analytics_web: ^0.6.1+5 + firebase_app_check: ^0.4.3 + firebase_app_check_platform_interface: ^0.3.0 + firebase_app_check_web: ^0.2.4 + firebase_app_installations: ^0.4.2 + firebase_app_installations_platform_interface: ^0.1.4+68 + firebase_app_installations_web: ^0.1.7+5 + firebase_auth: ^6.4.0 + firebase_auth_platform_interface: ^8.1.9 + firebase_auth_web: ^6.1.5 + firebase_core: ^4.7.0 firebase_core_platform_interface: ^6.0.3 - firebase_core_web: ^3.5.1 - firebase_crashlytics: ^5.1.0 - firebase_crashlytics_platform_interface: ^3.8.19 - firebase_database: ^12.2.0 - firebase_database_platform_interface: ^0.3.1 - firebase_database_web: ^0.2.7+5 - firebase_messaging: ^16.1.3 - firebase_messaging_platform_interface: ^4.7.8 - firebase_messaging_web: ^4.1.4 - firebase_ml_model_downloader: ^0.4.1 - firebase_ml_model_downloader_platform_interface: ^0.1.5+19 - firebase_performance: ^0.11.2 - firebase_remote_config: ^6.3.0 - firebase_remote_config_platform_interface: ^2.1.1 - firebase_remote_config_web: ^1.10.5 - firebase_storage: ^13.2.0 - firebase_storage_platform_interface: ^5.2.19 - firebase_storage_web: ^3.11.4 + firebase_core_web: ^3.6.0 + firebase_crashlytics: ^5.2.0 + firebase_crashlytics_platform_interface: ^3.8.20 + firebase_database: ^12.3.0 + firebase_database_platform_interface: ^0.3.1+1 + firebase_database_web: ^0.2.7+6 + firebase_messaging: ^16.2.0 + firebase_messaging_platform_interface: ^4.7.9 + firebase_messaging_web: ^4.1.5 + firebase_ml_model_downloader: ^0.4.2 + firebase_ml_model_downloader_platform_interface: ^0.1.5+20 + firebase_performance: ^0.11.3 + firebase_remote_config: ^6.4.0 + firebase_remote_config_platform_interface: ^2.1.2 + firebase_remote_config_web: ^1.10.6 + firebase_storage: ^13.3.0 + firebase_storage_platform_interface: ^5.2.20 + firebase_storage_web: ^3.11.5 flutter: sdk: flutter http: ^1.0.0 From 385d93372f749843ee3d8ac409a878fa149ba7ed Mon Sep 17 00:00:00 2001 From: Ryan Wilson Date: Mon, 13 Apr 2026 16:01:19 -0400 Subject: [PATCH 028/137] feat(firebaseai): add Google Maps Grounding support (#18144) * feat(ai): add Google Maps Grounding support Introduces support for Google Maps Grounding to the firebase_ai SDK, establishing feature parity with other platforms. API Changes: - Added `Tool.googleMaps()` factory and `GoogleMaps` class. - Introduced `RetrievalConfig` and `LatLng` for dynamic location-based tool configurations. - Expanded `ToolConfig` to include an optional `retrievalConfig` property. - Added `GoogleMapsGroundingChunk` to represent parsed Maps location properties (`uri`, `title`, `placeId`). - Updated `GroundingChunk` to expose the new `maps` property alongside `web`. - Exported all new grounding models publicly via `firebase_ai.dart`. Example App: - Added a dedicated "Grounding" page (`grounding_page.dart`) to the main navigation menu. - Implemented dynamic UI toggles for both Search and Maps Grounding. - Implemented dynamic parsing and Markdown rendering of returned grounding chunks. Testing: - Added comprehensive JSON roundtrip serialization tests for all new Tool configurations. - Added parsing tests mapping Developer API JSON payloads to `GoogleMapsGroundingChunk`. - Manually tested newly added web app section with Vertex and Developer APIs * Fixes * Formatting and import fix * Update packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Gemini Code Review feedback * Remove unnecessary comment * Add WebGroundingChunk, improved sorting * update example to merge multimodel and add nano banana page * fix the new file year header * fix analyzer * fix the format * Add maps grounding to server prompt template * extra white space --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Cynthia J --- .../firebase_ai/example/lib/main.dart | 13 + .../example/lib/pages/grounding_page.dart | 303 ++++++++++++++++++ .../lib/pages/server_template_page.dart | 56 ++++ .../firebase_ai/lib/firebase_ai.dart | 10 +- .../firebase_ai/firebase_ai/lib/src/api.dart | 37 ++- .../src/server_template/template_chat.dart | 15 +- .../template_generative_model.dart | 17 +- .../src/server_template/template_tool.dart | 11 +- .../firebase_ai/firebase_ai/lib/src/tool.dart | 97 +++++- .../firebase_ai/test/developer_api_test.dart | 37 +++ .../test/firebase_vertexai_test.dart | 17 +- .../test/response_parsing_test.dart | 37 +++ .../test/server_template_test.dart | 66 ++++ .../firebase_ai/test/tool_test.dart | 58 +++- 14 files changed, 745 insertions(+), 29 deletions(-) create mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart diff --git a/packages/firebase_ai/firebase_ai/example/lib/main.dart b/packages/firebase_ai/firebase_ai/example/lib/main.dart index c978b210a066..bb42d139229c 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/main.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/main.dart @@ -29,6 +29,7 @@ import 'pages/json_schema_page.dart'; import 'pages/multimodal_page.dart'; import 'pages/schema_page.dart'; import 'pages/server_template_page.dart'; +import 'pages/grounding_page.dart'; import 'pages/token_count_page.dart'; void main() async { @@ -172,6 +173,11 @@ class _HomeScreenState extends State { title: 'Server Template', useVertexBackend: useVertexBackend, ); + case 10: + return GroundingPage( + title: 'Grounding', + useVertexBackend: useVertexBackend, + ); default: // Fallback to the first page in case of an unexpected index @@ -299,6 +305,13 @@ class _HomeScreenState extends State { label: 'Server', tooltip: 'Server Template', ), + BottomNavigationBarItem( + icon: Icon( + Icons.location_on, + ), + label: 'Grounding', + tooltip: 'Search & Maps Grounding', + ), ], currentIndex: _selectedIndex, onTap: _onItemTapped, diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart new file mode 100644 index 000000000000..8456be1a9e4c --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart @@ -0,0 +1,303 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:flutter/material.dart'; +import 'package:firebase_ai/firebase_ai.dart'; +import '../widgets/message_widget.dart'; + +class GroundingPage extends StatefulWidget { + const GroundingPage({ + super.key, + required this.title, + required this.useVertexBackend, + }); + + final String title; + final bool useVertexBackend; + + @override + State createState() => _GroundingPageState(); +} + +class _GroundingPageState extends State { + GenerativeModel? _model; + final ScrollController _scrollController = ScrollController(); + final TextEditingController _textController = TextEditingController(); + final TextEditingController _latController = TextEditingController(); + final TextEditingController _lngController = TextEditingController(); + final FocusNode _textFieldFocus = FocusNode(); + final List _messages = []; + + bool _loading = false; + bool _enableSearchGrounding = false; + bool _enableMapsGrounding = false; + + @override + void initState() { + super.initState(); + _latController.text = '37.422'; // Default Googleplex lat + _lngController.text = '-122.084'; // Default Googleplex lng + } + + void _initializeModel() { + List tools = []; + ToolConfig? toolConfig; + + if (_enableSearchGrounding) { + tools.add(Tool.googleSearch()); + } + + if (_enableMapsGrounding) { + tools.add(Tool.googleMaps()); + + final lat = double.tryParse(_latController.text); + final lng = double.tryParse(_lngController.text); + + if (lat != null && lng != null) { + toolConfig = ToolConfig( + retrievalConfig: RetrievalConfig( + latLng: LatLng(latitude: lat, longitude: lng), + ), + ); + } + } + + final aiProvider = widget.useVertexBackend + ? FirebaseAI.vertexAI(auth: FirebaseAuth.instance) + : FirebaseAI.googleAI(auth: FirebaseAuth.instance); + + _model = aiProvider.generativeModel( + model: 'gemini-2.5-flash', + tools: tools.isNotEmpty ? tools : null, + toolConfig: toolConfig, + ); + } + + void _scrollDown() { + WidgetsBinding.instance.addPostFrameCallback( + (_) => _scrollController.animateTo( + _scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 750), + curve: Curves.easeOutCirc, + ), + ); + } + + Future _sendPrompt(String message) async { + if (message.isEmpty) return; + + _initializeModel(); // Re-initialize before sending to capture current toggles + + setState(() { + _loading = true; + }); + + try { + _messages.add(MessageData(text: message, fromUser: true)); + + final response = await _model?.generateContent([Content.text(message)]); + + var text = response?.text; + + // Extract grounding metadata to display + final groundingMetadata = + response?.candidates.firstOrNull?.groundingMetadata; + if (groundingMetadata != null) { + final chunks = groundingMetadata.groundingChunks.map((chunk) { + if (chunk.web != null) { + final title = chunk.web!.title ?? chunk.web!.uri; + return '- [$title](${chunk.web!.uri})'; + } + if (chunk.maps != null) { + final title = chunk.maps!.title ?? chunk.maps!.uri; + return '- [${title ?? 'Maps Result'}](${chunk.maps!.uri ?? ''})'; + } + return '- Unknown chunk'; + }).join('\n'); + + if (chunks.isNotEmpty) { + text = '$text\n\n**Grounding Sources:**\n$chunks'; + } + } + + _messages.add(MessageData(text: text, fromUser: false)); + + if (text == null) { + _showError('No response from API.'); + return; + } + } catch (e) { + _showError(e.toString()); + } finally { + if (mounted) { + _textController.clear(); + setState(() { + _loading = false; + }); + _textFieldFocus.requestFocus(); + _scrollDown(); + } + } + } + + void _showError(String message) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('Something went wrong'), + content: SingleChildScrollView( + child: SelectableText(message), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('OK'), + ), + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Padding( + padding: const EdgeInsets.all(8), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: SwitchListTile( + title: const Text( + 'Search Grounding', + style: TextStyle(fontSize: 12), + ), + value: _enableSearchGrounding, + onChanged: (bool value) { + setState(() { + _enableSearchGrounding = value; + }); + }, + ), + ), + Expanded( + child: SwitchListTile( + title: const Text( + 'Maps Grounding', + style: TextStyle(fontSize: 12), + ), + value: _enableMapsGrounding, + onChanged: (bool value) { + setState(() { + _enableMapsGrounding = value; + }); + }, + ), + ), + ], + ), + if (_enableMapsGrounding) + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + children: [ + Expanded( + child: TextField( + controller: _latController, + decoration: + const InputDecoration(labelText: 'Latitude'), + keyboardType: const TextInputType.numberWithOptions( + decimal: true, + signed: true, + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: TextField( + controller: _lngController, + decoration: + const InputDecoration(labelText: 'Longitude'), + keyboardType: const TextInputType.numberWithOptions( + decimal: true, + signed: true, + ), + ), + ), + ], + ), + ), + const Divider(), + Expanded( + child: ListView.builder( + controller: _scrollController, + itemBuilder: (context, idx) { + final message = _messages[idx]; + return MessageWidget( + text: message.text, + isFromUser: message.fromUser ?? false, + ); + }, + itemCount: _messages.length, + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 25, + horizontal: 15, + ), + child: Row( + children: [ + Expanded( + child: TextField( + autofocus: true, + focusNode: _textFieldFocus, + controller: _textController, + onSubmitted: _sendPrompt, + decoration: const InputDecoration( + hintText: 'Enter a prompt...', + ), + ), + ), + const SizedBox.square(dimension: 15), + if (!_loading) + IconButton( + onPressed: () { + _sendPrompt(_textController.text); + }, + icon: Icon( + Icons.send, + color: Theme.of(context).colorScheme.primary, + ), + ) + else + const CircularProgressIndicator(), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart index c10c6e243323..ad351e4778c7 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/server_template_page.dart @@ -260,6 +260,18 @@ class _ServerTemplatePageState extends State { ), tooltip: 'URL Context', ), + IconButton( + onPressed: () async { + await _serverTemplateMapsGrounding( + _textController.text, + ); + }, + icon: Icon( + Icons.map, + color: Theme.of(context).colorScheme.primary, + ), + tooltip: 'Maps Grounding', + ), IconButton( onPressed: () async { await _sendServerTemplateMessage(_textController.text); @@ -356,6 +368,50 @@ class _ServerTemplatePageState extends State { }); } + Future _serverTemplateMapsGrounding(String message) async { + await _handleServerTemplateMessage(message, (message) async { + var response = await _templateGenerativeModel + // ignore: experimental_member_use + ?.generateContent( + 'cj-googlemaps', + inputs: {'question': message}, + toolConfig: TemplateToolConfig( + retrievalConfig: RetrievalConfig( + latLng: LatLng(latitude: 37.422, longitude: -122.084), // Googleplex + ), + ), + ); + + final candidate = response?.candidates.first; + if (candidate == null) { + _messages.add(MessageData(text: 'No response', fromUser: false)); + } else { + final responseText = candidate.text ?? ''; + final groundingMetadata = candidate.groundingMetadata; + + final buffer = StringBuffer(responseText); + if (groundingMetadata != null) { + buffer.writeln('\n\n--- Grounding Metadata ---'); + buffer.writeln('Grounding Chunks:'); + for (final chunk in groundingMetadata.groundingChunks) { + if (chunk.web != null) { + buffer.writeln(' - Web Chunk:'); + buffer.writeln(' - Title: ${chunk.web!.title}'); + buffer.writeln(' - URI: ${chunk.web!.uri}'); + } + if (chunk.maps != null) { + buffer.writeln(' - Maps Chunk:'); + buffer.writeln(' - Title: ${chunk.maps!.title}'); + buffer.writeln(' - URI: ${chunk.maps!.uri}'); + } + } + } + + _messages.add(MessageData(text: buffer.toString(), fromUser: false)); + } + }); + } + Future _serverTemplateAutoFunctionCall(String message) async { await _handleServerTemplateMessage(message, (message) async { // Inputs are no longer passed during sendMessage diff --git a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart index 730c8516c045..5702945342f1 100644 --- a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart @@ -22,6 +22,8 @@ export 'src/api.dart' FinishReason, GenerateContentResponse, GenerationConfig, + GoogleMapsGroundingChunk, + GroundingChunk, ThinkingConfig, ThinkingLevel, HarmBlockThreshold, @@ -32,7 +34,8 @@ export 'src/api.dart' ResponseModalities, SafetyRating, SafetySetting, - UsageMetadata; + UsageMetadata, + WebGroundingChunk; export 'src/base_model.dart' show GenerativeModel, @@ -128,5 +131,8 @@ export 'src/tool.dart' Tool, ToolConfig, GoogleSearch, + GoogleMaps, CodeExecution, - UrlContext; + UrlContext, + LatLng, + RetrievalConfig; diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 7bda9372b61c..625f5845e9c3 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -347,6 +347,23 @@ final class WebGroundingChunk { final String? domain; } +/// A grounding chunk sourced from Google Maps. +final class GoogleMapsGroundingChunk { + // ignore: public_member_api_docs + GoogleMapsGroundingChunk({this.uri, this.title, this.placeId}); + + /// The URI of the place. + final String? uri; + + /// The title of the place. + final String? title; + + /// This Place's resource name, in `places/{place_id}` format. + /// + /// This can be used to look up the place using the Google Maps API. + final String? placeId; +} + /// Represents a chunk of retrieved data that supports a claim in the model's /// response. /// @@ -354,10 +371,13 @@ final class WebGroundingChunk { /// enabled. final class GroundingChunk { // ignore: public_member_api_docs - GroundingChunk({this.web}); + GroundingChunk({this.web, this.maps}); /// Contains details if the grounding chunk is from a web source. final WebGroundingChunk? web; + + /// Contains details if the grounding chunk is from a Google Maps source. + final GoogleMapsGroundingChunk? maps; } /// Provides information about how a specific segment of the model's response @@ -1693,6 +1713,18 @@ WebGroundingChunk _parseWebGroundingChunk(Object? jsonObject) { ); } +GoogleMapsGroundingChunk _parseGoogleMapsGroundingChunk(Object? jsonObject) { + if (jsonObject is! Map) { + throw unhandledFormat('GoogleMapsGroundingChunk', jsonObject); + } + + return GoogleMapsGroundingChunk( + uri: jsonObject['uri'] as String?, + title: jsonObject['title'] as String?, + placeId: jsonObject['placeId'] as String?, + ); +} + GroundingChunk _parseGroundingChunk(Object? jsonObject) { if (jsonObject is! Map) { throw unhandledFormat('GroundingChunk', jsonObject); @@ -1702,6 +1734,9 @@ GroundingChunk _parseGroundingChunk(Object? jsonObject) { web: jsonObject['web'] != null ? _parseWebGroundingChunk(jsonObject['web']) : null, + maps: jsonObject['maps'] != null + ? _parseGoogleMapsGroundingChunk(jsonObject['maps']) + : null, ); } diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart index 26fb90dabc7d..2efa63689dba 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_chat.dart @@ -47,14 +47,13 @@ final class TemplateChatSession { Iterable content, String templateId, {required Map inputs, List? tools, - TemplateToolConfig? templateToolConfig}) _templateHistoryGenerateContent; + TemplateToolConfig? toolConfig}) _templateHistoryGenerateContent; final Stream Function( - Iterable content, String templateId, - {required Map inputs, - List? tools, - TemplateToolConfig? templateToolConfig}) - _templateHistoryGenerateContentStream; + Iterable content, String templateId, + {required Map inputs, + List? tools, + TemplateToolConfig? toolConfig}) _templateHistoryGenerateContentStream; final String _templateId; final Map _inputs; @@ -93,7 +92,7 @@ final class TemplateChatSession { _templateId, inputs: _inputs, tools: _tools, - templateToolConfig: _toolConfig, + toolConfig: _toolConfig, ); final functionCalls = response.functionCalls; @@ -161,7 +160,7 @@ final class TemplateChatSession { _templateId, inputs: _inputs, tools: _tools, - templateToolConfig: _toolConfig, + toolConfig: _toolConfig, ); final turnChunks = []; diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart index 41efccb4f460..0b94fc9eaea4 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_generative_model.dart @@ -69,14 +69,15 @@ final class TemplateGenerativeModel extends BaseTemplateApiClientModel { /// Sends a "templateGenerateContent" API request for the configured model. @experimental Future generateContent(String templateId, - {required Map inputs}) => + {required Map inputs, + TemplateToolConfig? toolConfig}) => makeTemplateRequest( TemplateTask.templateGenerateContent, templateId, inputs, null, // history null, // tools - null, // toolConfig + toolConfig, _serializationStrategy.parseGenerateContentResponse); /// Generates a stream of content responding to [templateId] and [inputs]. @@ -85,14 +86,14 @@ final class TemplateGenerativeModel extends BaseTemplateApiClientModel { /// and waits for the response. @experimental Stream generateContentStream(String templateId, - {required Map inputs}) { + {required Map inputs, TemplateToolConfig? toolConfig}) { return streamTemplateRequest( TemplateTask.templateStreamGenerateContent, templateId, inputs, null, // history null, // tools - null, // toolConfig + toolConfig, _serializationStrategy.parseGenerateContentResponse); } @@ -103,14 +104,14 @@ final class TemplateGenerativeModel extends BaseTemplateApiClientModel { Iterable history, String templateId, {required Map inputs, List? tools, - TemplateToolConfig? templateToolConfig}) => + TemplateToolConfig? toolConfig}) => makeTemplateRequest( TemplateTask.templateGenerateContent, templateId, inputs, history, tools, - templateToolConfig, + toolConfig, _serializationStrategy.parseGenerateContentResponse); /// Generates a stream of content from a template with the given [templateId], @@ -120,14 +121,14 @@ final class TemplateGenerativeModel extends BaseTemplateApiClientModel { Iterable history, String templateId, {required Map inputs, List? tools, - TemplateToolConfig? templateToolConfig}) { + TemplateToolConfig? toolConfig}) { return streamTemplateRequest( TemplateTask.templateStreamGenerateContent, templateId, inputs, history, tools, - templateToolConfig, + toolConfig, _serializationStrategy.parseGenerateContentResponse); } } diff --git a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart index 31c60af4b82f..603875020c3b 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/server_template/template_tool.dart @@ -14,6 +14,7 @@ import 'dart:async'; import '../schema.dart'; +import '../tool.dart'; /// A collection of template tools. final class TemplateTool { @@ -98,8 +99,14 @@ final class TemplateAutoFunctionDeclaration /// Config for template tools to use with server prompts. final class TemplateToolConfig { // ignore: public_member_api_docs - TemplateToolConfig(); + TemplateToolConfig({RetrievalConfig? retrievalConfig}) + : _retrievalConfig = retrievalConfig; + + final RetrievalConfig? _retrievalConfig; /// Convert to json object. - Map toJson() => {}; + Map toJson() => { + if (_retrievalConfig case final retrievalConfig?) + 'retrievalConfig': retrievalConfig.toJson(), + }; } diff --git a/packages/firebase_ai/firebase_ai/lib/src/tool.dart b/packages/firebase_ai/firebase_ai/lib/src/tool.dart index 29a7c7124c53..195db5f81836 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/tool.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/tool.dart @@ -24,12 +24,12 @@ import 'schema.dart'; final class Tool { // ignore: public_member_api_docs Tool._(this._functionDeclarations, this._googleSearch, this._codeExecution, - this._urlContext); + this._urlContext, this._googleMaps); /// Returns a [Tool] instance with list of [FunctionDeclaration]. static Tool functionDeclarations( List functionDeclarations) { - return Tool._(functionDeclarations, null, null, null); + return Tool._(functionDeclarations, null, null, null, null); } /// Creates a tool that allows the model to use Grounding with Google Search. @@ -50,13 +50,13 @@ final class Tool { /// /// Returns a `Tool` configured for Google Search. static Tool googleSearch({GoogleSearch googleSearch = const GoogleSearch()}) { - return Tool._(null, googleSearch, null, null); + return Tool._(null, googleSearch, null, null, null); } /// Returns a [Tool] instance that enables the model to use Code Execution. static Tool codeExecution( {CodeExecution codeExecution = const CodeExecution()}) { - return Tool._(null, null, codeExecution, null); + return Tool._(null, null, codeExecution, null, null); } /// Creates a tool that allows you to provide additional context to the models @@ -73,7 +73,27 @@ final class Tool { /// is in Public Preview, which means that the feature is not subject to any SLA /// or deprecation policy and could change in backwards-incompatible ways. static Tool urlContext({UrlContext urlContext = const UrlContext()}) { - return Tool._(null, null, null, urlContext); + return Tool._(null, null, null, urlContext, null); + } + + /// Creates a tool that allows the model to use Grounding with Google Maps. + /// + /// Grounding with Google Maps can be used to allow the model to connect to + /// Google Maps to access and incorporate location-based information into its + /// responses. + /// + /// When using this feature, you are required to comply with the + /// "Grounding with Google Maps" usage requirements for your chosen API + /// provider: + /// [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) + /// or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) + /// section within the Service Specific Terms). + /// + /// - [googleMaps]: An empty [GoogleMaps] object. + /// + /// Returns a `Tool` configured for Google Maps. + static Tool googleMaps({GoogleMaps googleMaps = const GoogleMaps()}) { + return Tool._(null, null, null, null, googleMaps); } /// A list of `FunctionDeclarations` available to the model that can be used @@ -97,6 +117,10 @@ final class Tool { /// A tool that allows providing URL context to the model. final UrlContext? _urlContext; + /// A tool that allows the model to connect to Google Maps to access + /// location-based information. + final GoogleMaps? _googleMaps; + /// Returns a list of all [AutoFunctionDeclaration] objects /// found within the [_functionDeclarations] list. List get autoFunctionDeclarations { @@ -117,6 +141,8 @@ final class Tool { 'codeExecution': _codeExecution.toJson(), if (_urlContext case final _urlContext?) 'urlContext': _urlContext.toJson(), + if (_googleMaps case final _googleMaps?) + 'googleMaps': _googleMaps.toJson(), }; } @@ -138,6 +164,23 @@ final class GoogleSearch { Map toJson() => {}; } +/// A tool that allows a Gemini model to connect to Google Maps to access and +/// incorporate location-based information into its responses. +/// +/// Important: If using Grounding with Google Maps, you are required to comply +/// with the "Grounding with Google Maps" usage requirements for your chosen API +/// provider: +/// [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) +/// or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) +/// section within the Service Specific Terms). +final class GoogleMaps { + // ignore: public_member_api_docs + const GoogleMaps(); + + /// Convert to json object. + Map toJson() => {}; +} + /// A tool that allows you to provide additional context to the models in the /// form of public web URLs. By including URLs in your request, the Gemini /// model will access the content from those pages to inform and enhance its @@ -229,15 +272,57 @@ final class AutoFunctionDeclaration extends FunctionDeclaration { /// Config for tools to use with model. final class ToolConfig { // ignore: public_member_api_docs - ToolConfig({this.functionCallingConfig}); + ToolConfig({this.functionCallingConfig, this.retrievalConfig}); /// Config for function calling. final FunctionCallingConfig? functionCallingConfig; + /// Config that specifies information which can be used by tools during inference calls. + final RetrievalConfig? retrievalConfig; + /// Convert to json object. Map toJson() => { if (functionCallingConfig case final config?) 'functionCallingConfig': config.toJson(), + if (retrievalConfig case final config?) + 'retrievalConfig': config.toJson(), + }; +} + +/// An object that represents a latitude/longitude pair. +final class LatLng { + // ignore: public_member_api_docs + LatLng({required this.latitude, required this.longitude}); + + /// The latitude in degrees. It must be in the range [-90.0, +90.0]. + final double latitude; + + /// The longitude in degrees. It must be in the range [-180.0, +180.0]. + final double longitude; + + /// Convert to json object. + Map toJson() => { + 'latitude': latitude, + 'longitude': longitude, + }; +} + +/// The configuration that specifies information which can be used by tools +/// during inference calls. +final class RetrievalConfig { + // ignore: public_member_api_docs + RetrievalConfig({this.latLng, this.languageCode}); + + /// A latitude/longitude pair. + final LatLng? latLng; + + /// The language code. + final String? languageCode; + + /// Convert to json object. + Map toJson() => { + if (latLng case final latLng?) 'latLng': latLng.toJson(), + if (languageCode case final languageCode?) 'languageCode': languageCode, }; } diff --git a/packages/firebase_ai/firebase_ai/test/developer_api_test.dart b/packages/firebase_ai/firebase_ai/test/developer_api_test.dart index 40ce3739e1b9..85116e454646 100644 --- a/packages/firebase_ai/firebase_ai/test/developer_api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/developer_api_test.dart @@ -219,6 +219,43 @@ void main() { expect(groundingSupports.groundingChunkIndices, [0]); }); + test('parses json with google maps grounding chunk', () { + final jsonResponse = { + 'candidates': [ + { + 'content': { + 'parts': [ + {'text': 'This is a maps response.'} + ] + }, + 'finishReason': 'STOP', + 'groundingMetadata': { + 'groundingChunks': [ + { + 'maps': { + 'uri': 'https://maps.google.com/?cid=123', + 'title': 'Google HQ', + 'placeId': 'ChIJS5dFe_cZzosR26ZvwqWaMAM', + } + } + ], + } + } + ] + }; + + final response = DeveloperSerialization() + .parseGenerateContentResponse(jsonResponse); + final groundingMetadata = response.candidates.first.groundingMetadata; + + expect(groundingMetadata, isNotNull); + final groundingChunk = groundingMetadata!.groundingChunks.first; + expect(groundingChunk.maps?.uri, 'https://maps.google.com/?cid=123'); + expect(groundingChunk.maps?.title, 'Google HQ'); + expect(groundingChunk.maps?.placeId, 'ChIJS5dFe_cZzosR26ZvwqWaMAM'); + expect(groundingChunk.web, isNull); + }); + test( 'parses groundingMetadata with all optional fields null/missing and empty lists', () { diff --git a/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart b/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart index ace2fa4d673c..71c347f24333 100644 --- a/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart +++ b/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart @@ -96,6 +96,21 @@ void main() { expect(vertexAIAppCheck.useLimitedUseAppCheckTokens, true); }); - // ... other tests (e.g., with different parameters) + test('generativeModel creation with Grounding tools', () { + final ai = FirebaseAI.googleAI(); + + final model = ai.generativeModel( + model: 'gemini-2.5-flash', + tools: [Tool.googleMaps()], + toolConfig: ToolConfig( + retrievalConfig: RetrievalConfig( + latLng: LatLng(latitude: 37.42, longitude: -122.08), + languageCode: 'en-US', + ), + ), + ); + + expect(model, isA()); + }); }); } diff --git a/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart b/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart index 5aa1809d2023..3078177f180b 100644 --- a/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart +++ b/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart @@ -1115,6 +1115,43 @@ void main() { expect(urlContextMetadata.urlMetadata[0].urlRetrievalStatus, UrlRetrievalStatus.error); }); + + test('parses json with google maps grounding chunk', () { + final jsonResponse = { + 'candidates': [ + { + 'content': { + 'parts': [ + {'text': 'This is a maps response.'} + ] + }, + 'finishReason': 'STOP', + 'groundingMetadata': { + 'groundingChunks': [ + { + 'maps': { + 'uri': 'https://maps.google.com/?cid=123', + 'title': 'Google HQ', + 'placeId': 'ChIJS5dFe_cZzosR26ZvwqWaMAM', + } + } + ], + } + } + ] + }; + + final response = + VertexSerialization().parseGenerateContentResponse(jsonResponse); + final groundingMetadata = response.candidates.first.groundingMetadata; + + expect(groundingMetadata, isNotNull); + final groundingChunk = groundingMetadata!.groundingChunks.first; + expect(groundingChunk.maps?.uri, 'https://maps.google.com/?cid=123'); + expect(groundingChunk.maps?.title, 'Google HQ'); + expect(groundingChunk.maps?.placeId, 'ChIJS5dFe_cZzosR26ZvwqWaMAM'); + expect(groundingChunk.web, isNull); + }); }); group('parses and throws error responses', () { diff --git a/packages/firebase_ai/firebase_ai/test/server_template_test.dart b/packages/firebase_ai/firebase_ai/test/server_template_test.dart index ebc2170e7037..71d0905a7424 100644 --- a/packages/firebase_ai/firebase_ai/test/server_template_test.dart +++ b/packages/firebase_ai/firebase_ai/test/server_template_test.dart @@ -86,6 +86,37 @@ void main() { expect(response.text, 'Some response'); }); + test('generateContent with TemplateToolConfig passes retrievalConfig', + () async { + final mockHttp = MockClient((request) async { + final body = jsonDecode(request.body) as Map; + expect(request.url.path, + endsWith('/templates/$templateId:templateGenerateContent')); + expect(body['inputs'], {'prompt': 'Some prompt'}); + expect(body['toolConfig'], { + 'retrievalConfig': { + 'latLng': {'latitude': 1.0, 'longitude': 2.0}, + 'languageCode': 'en' + } + }); + return http.Response(jsonEncode(_arbitraryGenerateContentResponse), 200, + headers: {'content-type': 'application/json'}); + }); + + final model = createModel(mockHttp); + final response = await model.generateContent( + templateId, + inputs: {'prompt': 'Some prompt'}, + toolConfig: TemplateToolConfig( + retrievalConfig: RetrievalConfig( + latLng: LatLng(latitude: 1, longitude: 2), + languageCode: 'en', + ), + ), + ); + expect(response.text, 'Some response'); + }); + test('generateContentStream can make successful request', () async { final mockHttp = MockClient((request) async { final body = jsonDecode(request.body) as Map; @@ -105,6 +136,41 @@ void main() { final response = await responseStream.first; expect(response.text, 'Some response'); }); + + test('generateContentStream with TemplateToolConfig passes retrievalConfig', + () async { + final mockHttp = MockClient((request) async { + final body = jsonDecode(request.body) as Map; + expect(request.url.path, + endsWith('/templates/$templateId:templateStreamGenerateContent')); + expect(body['inputs'], {'prompt': 'Some prompt'}); + expect(body['toolConfig'], { + 'retrievalConfig': { + 'latLng': {'latitude': 1.0, 'longitude': 2.0}, + 'languageCode': 'en' + } + }); + final responsePayload = jsonEncode(_arbitraryGenerateContentResponse); + final stream = Stream.value(utf8.encode('data: $responsePayload')); + final streamedResponse = http.StreamedResponse(stream, 200, + headers: {'content-type': 'application/json'}); + return http.Response.fromStream(streamedResponse); + }); + + final model = createModel(mockHttp); + final responseStream = model.generateContentStream( + templateId, + inputs: {'prompt': 'Some prompt'}, + toolConfig: TemplateToolConfig( + retrievalConfig: RetrievalConfig( + latLng: LatLng(latitude: 1, longitude: 2), + languageCode: 'en', + ), + ), + ); + final response = await responseStream.first; + expect(response.text, 'Some response'); + }); }); group('TemplateImagenModel', () { diff --git a/packages/firebase_ai/firebase_ai/test/tool_test.dart b/packages/firebase_ai/firebase_ai/test/tool_test.dart index 8ac727e3a963..ff5b06152612 100644 --- a/packages/firebase_ai/firebase_ai/test/tool_test.dart +++ b/packages/firebase_ai/firebase_ai/test/tool_test.dart @@ -314,6 +314,14 @@ void main() { }); }); + // Test Tool.googleMaps() + test('Tool.googleMaps()', () { + final tool = Tool.googleMaps(); + expect(tool.toJson(), { + 'googleMaps': {}, + }); + }); + // Test ToolConfig test('ToolConfig with FunctionCallingConfig', () { final config = ToolConfig( @@ -329,7 +337,50 @@ void main() { expect(config.toJson(), {}); }); - // Test GoogleSearch, CodeExecution, UrlContext toJson() + test('ToolConfig with RetrievalConfig', () { + final config = ToolConfig( + retrievalConfig: RetrievalConfig( + latLng: LatLng(latitude: 37.422, longitude: -122.084), + languageCode: 'en-US', + ), + ); + expect(config.toJson(), { + 'retrievalConfig': { + 'latLng': {'latitude': 37.422, 'longitude': -122.084}, + 'languageCode': 'en-US', + }, + }); + }); + + // Test LatLng and RetrievalConfig + test('LatLng.toJson()', () { + final latLng = LatLng(latitude: 37.42, longitude: -122.08); + expect(latLng.toJson(), {'latitude': 37.42, 'longitude': -122.08}); + }); + + test('RetrievalConfig.toJson() with all fields', () { + final config = RetrievalConfig( + latLng: LatLng(latitude: 1.2, longitude: 2.1), + languageCode: 'fr', + ); + expect(config.toJson(), { + 'latLng': {'latitude': 1.2, 'longitude': 2.1}, + 'languageCode': 'fr', + }); + }); + + test('RetrievalConfig.toJson() with partial fields', () { + final config1 = + RetrievalConfig(latLng: LatLng(latitude: 1.2, longitude: 2.1)); + expect(config1.toJson(), { + 'latLng': {'latitude': 1.2, 'longitude': 2.1} + }); + + final config2 = RetrievalConfig(languageCode: 'fr'); + expect(config2.toJson(), {'languageCode': 'fr'}); + }); + + // Test GoogleSearch, CodeExecution, UrlContext, GoogleMaps toJson() test('GoogleSearch.toJson()', () { const search = GoogleSearch(); expect(search.toJson(), {}); @@ -344,5 +395,10 @@ void main() { const context = UrlContext(); expect(context.toJson(), {}); }); + + test('GoogleMaps.toJson()', () { + const maps = GoogleMaps(); + expect(maps.toJson(), {}); + }); }); } From 90d2e1f70b23fdad8f2fa4ca0c5e5d744d4e4f69 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Tue, 14 Apr 2026 07:52:02 +0000 Subject: [PATCH 029/137] ci: fix swift check (#18190) * CI: fix swift check * revert * fix --- .github/workflows/all_plugins.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index d2d71d5a0fde..7e00a292bc5c 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -148,15 +148,15 @@ jobs: pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - name: Xcode run: sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 + with: + melos-version: '5.3.0' - name: Setup firebase_core example app to test Swift integration - # run this before running melos boostrap to ensure the example app is set up + # Run after melos bootstrap so workspace pubspec_overrides resolve unpublished package versions. run: | cd packages/firebase_core/firebase_core/example flutter pub add $FLUTTER_DEPENDENCIES cd ../../../.. - - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 - with: - melos-version: '5.3.0' - name: 'Swift Integration Setup' run: flutter config --enable-swift-package-manager - name: 'Build Apps with Swift Package Manager' From 889af7c7b8f7705a55cdd90e39d306858a2e9fd4 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Wed, 15 Apr 2026 16:26:14 +0200 Subject: [PATCH 030/137] feat(ai): add missing enum types (#18198) --- .../firebase_ai/firebase_ai/lib/src/api.dart | 22 +++++- .../firebase_ai/lib/src/developer/api.dart | 16 +++- .../firebase_ai/test/api_test.dart | 76 +++++++++++++++++++ 3 files changed, 110 insertions(+), 4 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 625f5845e9c3..2e8ed26fc1cb 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -626,7 +626,19 @@ enum HarmCategory { sexuallyExplicit('HARM_CATEGORY_SEXUALLY_EXPLICIT'), /// Promotes or enables access to harmful goods, services, and activities. - dangerousContent('HARM_CATEGORY_DANGEROUS_CONTENT'); + dangerousContent('HARM_CATEGORY_DANGEROUS_CONTENT'), + + /// Image content containing hate speech. + imageHate('HARM_CATEGORY_IMAGE_HATE'), + + /// Image content that is dangerous. + imageDangerousContent('HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT'), + + /// Image content containing harassment. + imageHarassment('HARM_CATEGORY_IMAGE_HARASSMENT'), + + /// Image content that is sexually explicit. + imageSexuallyExplicit('HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT'); const HarmCategory(this._jsonString); @@ -638,7 +650,13 @@ enum HarmCategory { 'HARM_CATEGORY_HATE_SPEECH' => HarmCategory.hateSpeech, 'HARM_CATEGORY_SEXUALLY_EXPLICIT' => HarmCategory.sexuallyExplicit, 'HARM_CATEGORY_DANGEROUS_CONTENT' => HarmCategory.dangerousContent, - _ => throw FormatException('Unhandled HarmCategory format', jsonObject), + 'HARM_CATEGORY_IMAGE_HATE' => HarmCategory.imageHate, + 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT' => + HarmCategory.imageDangerousContent, + 'HARM_CATEGORY_IMAGE_HARASSMENT' => HarmCategory.imageHarassment, + 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT' => + HarmCategory.imageSexuallyExplicit, + _ => HarmCategory.unknown, }; } diff --git a/packages/firebase_ai/firebase_ai/lib/src/developer/api.dart b/packages/firebase_ai/firebase_ai/lib/src/developer/api.dart index bb2e78811277..d89f711aea27 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/developer/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/developer/api.dart @@ -49,7 +49,13 @@ String _harmCategoryToJson(HarmCategory harmCategory) => switch (harmCategory) { HarmCategory.harassment => 'HARM_CATEGORY_HARASSMENT', HarmCategory.hateSpeech => 'HARM_CATEGORY_HATE_SPEECH', HarmCategory.sexuallyExplicit => 'HARM_CATEGORY_SEXUALLY_EXPLICIT', - HarmCategory.dangerousContent => 'HARM_CATEGORY_DANGEROUS_CONTENT' + HarmCategory.dangerousContent => 'HARM_CATEGORY_DANGEROUS_CONTENT', + HarmCategory.imageHate => 'HARM_CATEGORY_IMAGE_HATE', + HarmCategory.imageDangerousContent => + 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT', + HarmCategory.imageHarassment => 'HARM_CATEGORY_IMAGE_HARASSMENT', + HarmCategory.imageSexuallyExplicit => + 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT', }; Object _safetySettingToJson(SafetySetting safetySetting) { @@ -241,5 +247,11 @@ HarmCategory _parseHarmCategory(Object jsonObject) => switch (jsonObject) { 'HARM_CATEGORY_HATE_SPEECH' => HarmCategory.hateSpeech, 'HARM_CATEGORY_SEXUALLY_EXPLICIT' => HarmCategory.sexuallyExplicit, 'HARM_CATEGORY_DANGEROUS_CONTENT' => HarmCategory.dangerousContent, - _ => throw unhandledFormat('HarmCategory', jsonObject), + 'HARM_CATEGORY_IMAGE_HATE' => HarmCategory.imageHate, + 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT' => + HarmCategory.imageDangerousContent, + 'HARM_CATEGORY_IMAGE_HARASSMENT' => HarmCategory.imageHarassment, + 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT' => + HarmCategory.imageSexuallyExplicit, + _ => HarmCategory.unknown, }; diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index 6681aaf0ed1f..bc3352b869cc 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -289,6 +289,13 @@ void main() { 'HARM_CATEGORY_SEXUALLY_EXPLICIT'); expect(HarmCategory.dangerousContent.toJson(), 'HARM_CATEGORY_DANGEROUS_CONTENT'); + expect(HarmCategory.imageHate.toJson(), 'HARM_CATEGORY_IMAGE_HATE'); + expect(HarmCategory.imageDangerousContent.toJson(), + 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT'); + expect(HarmCategory.imageHarassment.toJson(), + 'HARM_CATEGORY_IMAGE_HARASSMENT'); + expect(HarmCategory.imageSexuallyExplicit.toJson(), + 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT'); }); test('HarmProbability toJson and toString', () { @@ -736,6 +743,75 @@ void main() { expect(response.usageMetadata!.candidatesTokensDetails, hasLength(1)); }); + test('parses image harm categories in safetyRatings', () { + final json = { + 'candidates': [ + { + 'content': { + 'role': 'model', + 'parts': [ + {'text': ''} + ] + }, + 'finishReason': 'STOP', + 'safetyRatings': [ + { + 'category': 'HARM_CATEGORY_IMAGE_DANGEROUS_CONTENT', + 'probability': 'NEGLIGIBLE' + }, + { + 'category': 'HARM_CATEGORY_IMAGE_SEXUALLY_EXPLICIT', + 'probability': 'NEGLIGIBLE' + }, + { + 'category': 'HARM_CATEGORY_IMAGE_HATE', + 'probability': 'NEGLIGIBLE' + }, + { + 'category': 'HARM_CATEGORY_IMAGE_HARASSMENT', + 'probability': 'NEGLIGIBLE' + }, + ] + } + ] + }; + final response = + VertexSerialization().parseGenerateContentResponse(json); + final ratings = response.candidates.first.safetyRatings!; + expect(ratings.map((r) => r.category), [ + HarmCategory.imageDangerousContent, + HarmCategory.imageSexuallyExplicit, + HarmCategory.imageHate, + HarmCategory.imageHarassment, + ]); + }); + + test('falls back to HarmCategory.unknown for unrecognized values', () { + final json = { + 'candidates': [ + { + 'content': { + 'role': 'model', + 'parts': [ + {'text': ''} + ] + }, + 'finishReason': 'STOP', + 'safetyRatings': [ + { + 'category': 'HARM_CATEGORY_SOMETHING_NEW', + 'probability': 'NEGLIGIBLE' + } + ] + } + ] + }; + final response = + VertexSerialization().parseGenerateContentResponse(json); + expect(response.candidates.first.safetyRatings!.first.category, + HarmCategory.unknown); + }); + group('usageMetadata parsing', () { test('parses usageMetadata when thoughtsTokenCount is set', () { final json = { From 4c17ca870a78ae6afeaad6006ca68e7999711ffd Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 16 Apr 2026 16:32:46 +0200 Subject: [PATCH 031/137] fix(fdc): remove unused logs (#18197) --- .../firebase_data_connect/lib/src/core/ref.dart | 5 ----- .../lib/src/network/websocket_transport.dart | 9 --------- 2 files changed, 14 deletions(-) diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart index 44cbf9ca45c1..e118e439e7cc 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/core/ref.dart @@ -342,7 +342,6 @@ class QueryRef extends OperationRef { _serverStreamSubscription?.cancel(); _serverStreamSubscription = null; _serverStream = null; - log("QueryRef $operationId: All subscribers cancelled. Unsubscribed from server stream."); } Stream> subscribe() { @@ -373,7 +372,6 @@ class QueryRef extends OperationRef { void _streamFromServer() async { bool shouldRetry = await _shouldRetry(); - log("QueryRef $operationId _streamFromServer loop started."); try { _serverStream = _transport.invokeStreamQuery( operationId, @@ -386,7 +384,6 @@ class QueryRef extends OperationRef { _serverStreamSubscription = _serverStream!.listen( (serverResponse) async { - log("QueryRef $operationId _streamFromServer loop received snapshot."); if (dataConnect.cacheManager != null) { try { await dataConnect.cacheManager! @@ -432,8 +429,6 @@ class QueryRef extends OperationRef { void publishResultToStream(QueryResult result) { if (_streamController != null) { _streamController?.add(result); - } else { - log("QueryRef $operationId _streamFromServer loop _streamController is null"); } } diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart index 0fb62e5fde33..01929700a033 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart @@ -150,7 +150,6 @@ class WebSocketTransport implements DataConnectTransport { if (_channel == null) return; final encoded = jsonEncode(json); if (encoded.isNotEmpty) { - developer.log("Sending stream message \n $encoded"); _channel!.sink.add(encoded); } } @@ -229,7 +228,6 @@ class WebSocketTransport implements DataConnectTransport { } else { bodyString = message as String; } - developer.log("Received stream response \n $bodyString"); final bodyJson = jsonDecode(bodyString) as Map; final response = StreamResponse.fromJson(bodyJson); @@ -309,8 +307,6 @@ class WebSocketTransport implements DataConnectTransport { Timer? _reconnectTimer; void _scheduleReconnect() { - developer.log( - '${DateTime.now()} _scheduleReconnect $_reconnectAttempts $_isReconnecting $_isExpectedDisconnect'); if (_isReconnecting || _isExpectedDisconnect) return; _isReconnecting = true; @@ -323,13 +319,9 @@ class WebSocketTransport implements DataConnectTransport { final delay = min( _initialReconnectDelayMs * pow(2, _reconnectAttempts).toInt(), _maxReconnectDelayMs); - var startTime = DateTime.now(); - developer.log('$startTime scheduling _performReconnect in $delay ms'); _reconnectTimer?.cancel(); _reconnectTimer = Timer(Duration(milliseconds: delay), () async { - developer.log( - '${DateTime.now()} calling delayed _performReconnect scheduled at $startTime'); _performReconnect(); }); } @@ -443,7 +435,6 @@ class WebSocketTransport implements DataConnectTransport { void _onDone() { if (_channel == null) return; - developer.log('WebSocket connection closed.'); _channel = null; _isReconnecting = false; if (!_isExpectedDisconnect) { From 1f1b4f078cb404f0d01fad450164e5ab1ed5e39b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:56:37 +0200 Subject: [PATCH 032/137] chore(deps): bump protobufjs (#18203) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.4.0 to 7.5.5. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.5) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.5.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../example/bundled-service-worker/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock index 64d0ae8cf139..c56b1050efcc 100644 --- a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock +++ b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock @@ -740,9 +740,9 @@ long@^5.0.0: integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w== protobufjs@^7.2.5: - version "7.4.0" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" - integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== + version "7.5.5" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.5.5.tgz#b7089ca4410374c75150baf277353ef76db69f96" + integrity sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" From 7e0a222700178a57d064c27b4ef62cefdda1e253 Mon Sep 17 00:00:00 2001 From: Engels Immanuel <40745212+Daeon97@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:35:04 +0100 Subject: [PATCH 033/137] feat(auth,android): add revokeAccessToken support for Android (#18206) (#18207) * feat(auth): add revokeAccessToken support for Android (#18206) * test(auth): add unit tests for newly exposed revokeAccessToken API (#18206) --- .../auth/FlutterFirebaseAuthPlugin.java | 21 ++++++++++ .../auth/GeneratedAndroidFirebaseAuth.java | 38 +++++++++++++++++++ .../firebase_auth/lib/src/firebase_auth.dart | 5 +++ .../test/firebase_auth_test.dart | 21 ++++++++++ .../method_channel_firebase_auth.dart | 14 +++++++ .../lib/src/pigeon/messages.pigeon.dart | 25 ++++++++++++ .../platform_interface_firebase_auth.dart | 5 +++ .../pigeons/messages.dart | 6 +++ .../test/pigeon/test_api.dart | 37 ++++++++++++++++++ .../platform_interface_auth_test.dart | 7 ++++ 10 files changed, 179 insertions(+) diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java index 1f9a73d433ab..74ee8c89aa14 100755 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java @@ -678,6 +678,27 @@ public void revokeTokenWithAuthorizationCode( result.success(); } + @Override + public void revokeAccessToken( + @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, + @NonNull String accessToken, + @NonNull GeneratedAndroidFirebaseAuth.VoidResult result) { + FirebaseAuth firebaseAuth = getAuthFromPigeon(app); + + firebaseAuth + .revokeAccessToken(accessToken) + .addOnCompleteListener( + task -> { + if (task.isSuccessful()) { + result.success(); + } else { + result.error( + FlutterFirebaseAuthPluginException.parserExceptionToFlutter( + task.getException())); + } + }); + } + @Override public void initializeRecaptchaConfig( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java index f9666b78087a..19545ba97da0 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java @@ -2642,6 +2642,11 @@ void revokeTokenWithAuthorizationCode( @NonNull String authorizationCode, @NonNull VoidResult result); + void revokeAccessToken( + @NonNull AuthPigeonFirebaseApp app, + @NonNull String accessToken, + @NonNull VoidResult result); + void initializeRecaptchaConfig(@NonNull AuthPigeonFirebaseApp app, @NonNull VoidResult result); /** The codec used by FirebaseAuthHostApi. */ @@ -3397,6 +3402,39 @@ public void error(Throwable error) { channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken" + + messageChannelSuffix, + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); + String accessTokenArg = (String) args.get(1); + VoidResult resultCallback = + new VoidResult() { + public void success() { + wrapped.add(0, null); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.revokeAccessToken(appArg, accessTokenArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } { BasicMessageChannel channel = new BasicMessageChannel<>( diff --git a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart index 027892a8c8d9..6906c839d281 100644 --- a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart @@ -798,6 +798,11 @@ class FirebaseAuth extends FirebasePluginPlatform { return _delegate.revokeTokenWithAuthorizationCode(authorizationCode); } + /// Android only. Revokes the provided accessToken. Currently supports revoking Apple-issued accessToken only. + Future revokeAccessToken(String accessToken) { + return _delegate.revokeAccessToken(accessToken); + } + /// Signs out the current user. /// /// If successful, it also updates diff --git a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart index d3a7bc6d837f..f53d18e5dccf 100644 --- a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart @@ -35,6 +35,7 @@ void main() { const String kMockSmsCode = '123456'; const String kMockLanguage = 'en'; const String kMockOobCode = 'oobcode'; + const String kMockAuthToken = '12460'; const String kMockURL = 'http://www.example.com'; const String kMockHost = 'www.example.com'; const String kMockValidPassword = @@ -778,6 +779,17 @@ void main() { }); }); + group('revokeAccessToken()', () { + test('should call delegate method', () async { + // Necessary as we otherwise get a "null is not a Future" error + when(mockAuthPlatform.revokeAccessToken(kMockAuthToken)) + .thenAnswer((i) async {}); + + await auth.revokeAccessToken(kMockAuthToken); + verify(mockAuthPlatform.revokeAccessToken(kMockAuthToken)); + }); + }); + group('passwordPolicy', () { test('passwordPolicy should be initialized with correct parameters', () async { @@ -1150,6 +1162,15 @@ class MockFirebaseAuth extends Mock returnValueForMissingStub: neverEndingFuture(), ); } + + @override + Future revokeAccessToken(String accessToken) { + return super.noSuchMethod( + Invocation.method(#revokeAccessToken, [accessToken]), + returnValue: neverEndingFuture(), + returnValueForMissingStub: neverEndingFuture(), + ); + } } class FakeFirebaseAuthPlatform extends Fake diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart index 187b01c1943d..28338f32cf8d 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart @@ -664,6 +664,20 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { } } + @override + Future revokeAccessToken(String accessToken) async { + if (defaultTargetPlatform != TargetPlatform.android) { + throw UnimplementedError( + 'revokeAccessToken() is only available on the Android platform.'); + } + + try { + await _api.revokeAccessToken(pigeonDefault, accessToken); + } catch (e, stack) { + convertPlatformException(e, stack); + } + } + @override Future initializeRecaptchaConfig() async { try { diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart index e66a71b7bc5a..dac092cd499f 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1479,6 +1479,31 @@ class FirebaseAuthHostApi { } } + Future revokeAccessToken( + AuthPigeonFirebaseApp app, String accessToken) async { + final String __pigeon_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken$__pigeon_messageChannelSuffix'; + final BasicMessageChannel __pigeon_channel = + BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = await __pigeon_channel + .send([app, accessToken]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + Future initializeRecaptchaConfig(AuthPigeonFirebaseApp app) async { final String __pigeon_channelName = 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.initializeRecaptchaConfig$__pigeon_messageChannelSuffix'; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart index a57a98532592..7b5feff9d4e5 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart @@ -717,6 +717,11 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { 'revokeTokenWithAuthorizationCode() is not implemented'); } + /// Android only. Revokes the provided accessToken. Currently supports revoking Apple-issued accessToken only. + Future revokeAccessToken(String accessToken) { + throw UnimplementedError('revokeAccessToken() is not implemented'); + } + /// Initializes the reCAPTCHA Enterprise client proactively to enhance reCAPTCHA signal collection and /// to complete reCAPTCHA-protected flows in a single attempt. Future initializeRecaptchaConfig() { diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart b/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart index a923a5481bd8..6a2e99337c5c 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart @@ -420,6 +420,12 @@ abstract class FirebaseAuthHostApi { String authorizationCode, ); + @async + void revokeAccessToken( + AuthPigeonFirebaseApp app, + String accessToken, + ); + @async void initializeRecaptchaConfig( AuthPigeonFirebaseApp app, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart index 91d5f6ef9641..b252487d4592 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart @@ -187,6 +187,8 @@ abstract class TestFirebaseAuthHostApi { Future revokeTokenWithAuthorizationCode( AuthPigeonFirebaseApp app, String authorizationCode); + Future revokeAccessToken(AuthPigeonFirebaseApp app, String accessToken); + Future initializeRecaptchaConfig(AuthPigeonFirebaseApp app); static void setUp( @@ -995,6 +997,41 @@ abstract class TestFirebaseAuthHostApi { }); } } + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken$messageChannelSuffix', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(__pigeon_channel, null); + } else { + _testBinaryMessengerBinding!.defaultBinaryMessenger + .setMockDecodedMessageHandler(__pigeon_channel, + (Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken was null.'); + final List args = (message as List?)!; + final AuthPigeonFirebaseApp? arg_app = + (args[0] as AuthPigeonFirebaseApp?); + assert(arg_app != null, + 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken was null, expected non-null AuthPigeonFirebaseApp.'); + final String? arg_accessToken = (args[1] as String?); + assert(arg_accessToken != null, + 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken was null, expected non-null String.'); + try { + await api.revokeAccessToken(arg_app!, arg_accessToken!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } { final BasicMessageChannel __pigeon_channel = BasicMessageChannel< Object?>( diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart index fd6ad03188b1..94371d8568af 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_auth_test.dart @@ -353,6 +353,13 @@ void main() { throwsUnimplementedError, ); }); + + test('throws if revokeAccessToken()', () async { + await expectLater( + () => firebaseAuthPlatform.revokeAccessToken('token'), + throwsUnimplementedError, + ); + }); }); } From 9f32c614a9fee53ceebc5540d91c76ba4fd91d8b Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:44:50 +0000 Subject: [PATCH 034/137] fix(functions, web): dartify results from cloud function stream (#18212) * fix(functions, web): dartify results from cloud function stream * fix test * chore: use _dartify to process results from cloud function stream --- .../lib/interop/functions.dart | 2 +- .../cloud_functions_e2e_test.dart | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/cloud_functions/cloud_functions_web/lib/interop/functions.dart b/packages/cloud_functions/cloud_functions_web/lib/interop/functions.dart index 0b548c34748f..e884d6954576 100644 --- a/packages/cloud_functions/cloud_functions_web/lib/interop/functions.dart +++ b/packages/cloud_functions/cloud_functions_web/lib/interop/functions.dart @@ -103,7 +103,7 @@ class HttpsCallable extends JsObjectWrapper { } final result = await streamResult.data.toDart; - yield {'result': result}; + yield {'result': _dartify(result)}; } } diff --git a/tests/integration_test/cloud_functions/cloud_functions_e2e_test.dart b/tests/integration_test/cloud_functions/cloud_functions_e2e_test.dart index 05b448a961bc..66eed657b3b3 100644 --- a/tests/integration_test/cloud_functions/cloud_functions_e2e_test.dart +++ b/tests/integration_test/cloud_functions/cloud_functions_e2e_test.dart @@ -397,6 +397,24 @@ void main() { ); }); + test( + 'Result.data is Map for object-shaped JSON', + () async { + final stream = callable.stream({ + 'type': 'deepMap', + 'inputData': data.deepMap, + }); + final terminalEvent = await stream.where((e) => e is Result).last; + expect(terminalEvent, isA()); + final result = (terminalEvent as Result).result; + expect( + result.data, + isA>(), + ); + }, + skip: !kIsWeb, + ); + test('accepts a [List]', () async { final stream = callable.stream(data.list).where((event) => event is Chunk); From cb6b4aeffc568755ea3eebe32b998f00237bf5ad Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 21 Apr 2026 11:59:38 +0200 Subject: [PATCH 035/137] feat: upgrade pigeon to version 26.3.4 (#18205) * feat: upgrade pigeon to version 26.3.4 * fix cloud firestore * fix * fix * fixes * fix * format * fix: resolve post-merge CI failures for pigeon upgrade --- melos.yaml | 8 + .../cloud_firestore/analysis_options.yaml | 11 + .../FlutterFirebaseFirestorePlugin.java | 109 +- .../GeneratedAndroidFirebaseFirestore.java | 1614 ++++++--- .../DocumentSnapshotsStreamHandler.java | 8 +- .../OnTransactionResultListener.java | 4 +- .../QuerySnapshotsStreamHandler.java | 30 +- .../TransactionStreamHandler.java | 16 +- .../firestore/utils/ExceptionConverter.java | 10 + .../firestore/utils/PigeonParser.java | 34 +- .../example/android/app/build.gradle | 2 +- .../ios/Flutter/AppFrameworkInfo.plist | 2 - .../ios/Runner.xcodeproj/project.pbxproj | 2 + .../macos/Runner.xcodeproj/project.pbxproj | 22 + .../xcshareddata/xcschemes/Runner.xcscheme | 19 + .../example/macos/Runner/AppDelegate.swift | 4 + .../FLTDocumentSnapshotStreamHandler.m | 8 +- .../FLTFirebaseFirestorePlugin.m | 104 +- .../FLTQuerySnapshotStreamHandler.m | 32 +- .../FLTTransactionStreamHandler.m | 29 +- .../cloud_firestore/FirestoreMessages.g.m | 1476 +++++--- .../cloud_firestore/FirestorePigeonParser.m | 43 +- .../Private/FLTTransactionStreamHandler.h | 12 +- .../Private/FirestorePigeonParser.h | 20 +- .../Public/CustomPigeonHeaderFirestore.h | 6 +- .../Public/FirestoreMessages.g.h | 225 +- .../test/test_firestore_message_codec.dart | 2 +- .../windows/cloud_firestore_plugin.cpp | 137 +- .../windows/cloud_firestore_plugin.h | 30 +- .../cloud_firestore/windows/messages.g.cpp | 2053 ++++++++--- .../cloud_firestore/windows/messages.g.h | 724 ++-- .../method_channel_aggregate_query.dart | 2 +- .../method_channel_document_change.dart | 4 +- .../method_channel_document_reference.dart | 8 +- .../method_channel_firestore.dart | 22 +- .../method_channel_pipeline_snapshot.dart | 4 +- .../method_channel/method_channel_query.dart | 29 +- .../method_channel_query_snapshot.dart | 2 +- .../method_channel_transaction.dart | 18 +- .../method_channel_write_batch.dart | 16 +- .../lib/src/pigeon/messages.pigeon.dart | 1961 +++++----- .../platform_interface_document_snapshot.dart | 2 +- .../platform_interface_transaction.dart | 2 +- .../pigeons/generate_pigeon.sh | 67 +- .../pigeons/messages.dart | 96 +- .../pubspec.yaml | 2 +- .../test/pigeon/test_api.dart | 1364 ++++--- .../utils/test_firestore_message_codec.dart | 2 +- .../lib/src/utils/web_utils.dart | 2 +- .../cloud_functions/analysis_options.yaml | 3 +- .../GeneratedAndroidCloudFunctions.g.kt | 4 +- .../CloudFunctionsMessages.g.swift | 4 +- .../cloud_functions/windows/messages.g.cpp | 241 +- .../cloud_functions/windows/messages.g.h | 36 +- .../lib/src/pigeon/messages.pigeon.dart | 88 +- .../pubspec.yaml | 2 +- .../test/pigeon/test_api.dart | 36 +- .../firebase_analytics/analysis_options.yaml | 1 + .../GeneratedAndroidFirebaseAnalytics.g.kt | 155 +- .../FirebaseAnalyticsMessages.g.swift | 125 +- .../firebase_analytics/windows/messages.g.cpp | 281 +- .../firebase_analytics/windows/messages.g.h | 63 +- .../lib/src/pigeon/messages.pigeon.dart | 399 +- .../pubspec.yaml | 2 +- .../test/pigeon/test_api.dart | 140 +- .../firebase_app_check/analysis_options.yaml | 10 + .../lib/src/pigeon/messages.pigeon.dart | 2 +- .../pubspec.yaml | 2 +- packages/firebase_auth/analysis_options.yaml | 1 + .../auth/FlutterFirebaseAuthPlugin.java | 28 +- .../auth/FlutterFirebaseAuthUser.java | 32 +- .../auth/FlutterFirebaseMultiFactor.java | 15 +- .../auth/FlutterFirebaseTotpMultiFactor.java | 4 +- .../auth/GeneratedAndroidFirebaseAuth.java | 2144 ++++++----- .../PhoneNumberVerificationStreamHandler.java | 2 +- .../plugins/firebase/auth/PigeonParser.java | 59 +- .../example/android/app/build.gradle | 2 +- .../macos/Runner.xcodeproj/project.pbxproj | 56 +- .../xcshareddata/xcschemes/Runner.xcscheme | 19 + .../firebase_auth/FLTFirebaseAuthPlugin.m | 135 +- .../FLTPhoneNumberVerificationStreamHandler.m | 4 +- .../Sources/firebase_auth/PigeonParser.m | 81 +- .../firebase_auth/firebase_auth_messages.g.m | 1799 +++++---- .../FLTPhoneNumberVerificationStreamHandler.h | 2 +- .../include/Private/PigeonParser.h | 22 +- .../include/Public/CustomPigeonHeader.h | 6 +- .../include/Public/firebase_auth_messages.g.h | 213 +- .../test/firebase_auth_test.dart | 16 +- .../firebase_auth/test/user_test.dart | 16 +- .../windows/firebase_auth_plugin.cpp | 147 +- .../windows/firebase_auth_plugin.h | 90 +- .../firebase_auth/windows/messages.g.cpp | 2818 +++++++++------ .../firebase_auth/windows/messages.g.h | 1066 +++--- .../lib/firebase_auth_platform_interface.dart | 6 +- .../lib/src/id_token_result.dart | 2 +- .../method_channel_firebase_auth.dart | 20 +- .../method_channel_multi_factor.dart | 4 +- .../method_channel/method_channel_user.dart | 12 +- .../method_channel_user_credential.dart | 2 +- .../src/method_channel/utils/exception.dart | 7 +- .../method_channel/utils/pigeon_helper.dart | 2 +- .../lib/src/pigeon/messages.pigeon.dart | 3217 ++++++++--------- .../platform_interface_firebase_auth.dart | 6 +- .../platform_interface_user.dart | 4 +- .../lib/src/user_info.dart | 4 +- .../pigeons/messages.dart | 162 +- .../pubspec.yaml | 2 +- .../test/id_token_result_test.dart | 4 +- .../method_channel_user_credential_test.dart | 20 +- .../test/pigeon/test_api.dart | 1594 +++----- ...atform_interface_user_credential_test.dart | 6 +- .../platform_interface_user_test.dart | 8 +- .../lib/firebase_auth_web.dart | 2 +- .../lib/src/firebase_auth_web_user.dart | 4 +- .../lib/src/utils/web_utils.dart | 2 +- packages/firebase_core/analysis_options.yaml | 1 + .../core/GeneratedAndroidFirebaseCore.java | 238 +- .../include/firebase_core/messages.g.h | 4 +- .../Sources/firebase_core/messages.g.m | 170 +- .../firebase_core/windows/messages.g.cpp | 330 +- .../firebase_core/windows/messages.g.h | 83 +- .../lib/src/pigeon/messages.pigeon.dart | 291 +- .../lib/src/pigeon/test_api.dart | 84 +- .../pubspec.yaml | 2 +- .../GeneratedAndroidFirebaseDatabase.g.kt | 253 +- .../FirebaseDatabaseMessages.g.swift | 223 +- .../firebase_database/windows/messages.g.cpp | 474 ++- .../firebase_database/windows/messages.g.h | 219 +- .../lib/src/pigeon/messages.pigeon.dart | 744 ++-- .../pubspec.yaml | 2 +- .../test/pigeon/test_api.dart | 446 +-- .../analysis_options.yaml | 3 +- .../GeneratedAndroidFirebasePerformance.g.kt | 186 +- .../FirebasePerformanceMessages.g.swift | 161 +- .../windows/messages.g.cpp | 315 +- .../firebase_performance/windows/messages.g.h | 108 +- .../lib/src/pigeon/messages.pigeon.dart | 282 +- .../pubspec.yaml | 3 +- .../test/pigeon/test_api.dart | 91 +- .../analysis_options.yaml | 1 + .../GeneratedAndroidFirebaseRemoteConfig.g.kt | 155 +- .../FirebaseRemoteConfigMessages.g.swift | 128 +- .../windows/messages.g.cpp | 279 +- .../windows/messages.g.h | 54 +- .../lib/src/pigeon/messages.pigeon.dart | 360 +- .../pubspec.yaml | 2 +- .../firebase_storage/analysis_options.yaml | 4 + .../storage/FlutterFirebaseStoragePlugin.kt | 100 +- .../GeneratedAndroidFirebaseStorage.g.kt | 791 ++-- .../storage/TaskStateChannelStreamHandler.kt | 10 +- .../example/android/app/build.gradle | 2 +- .../ios/Flutter/AppFrameworkInfo.plist | 2 - .../ios/Runner.xcodeproj/project.pbxproj | 18 +- .../firebase_storage/example/macos/Podfile | 2 +- .../macos/Runner.xcodeproj/project.pbxproj | 21 + .../xcshareddata/xcschemes/Runner.xcscheme | 1 + .../FLTFirebaseStoragePlugin.swift | 86 +- .../FirebaseStorageMessages.g.swift | 656 +++- .../windows/firebase_storage_plugin.cpp | 123 +- .../windows/firebase_storage_plugin.h | 82 +- .../firebase_storage/windows/messages.g.cpp | 1118 ++++-- .../firebase_storage/windows/messages.g.h | 402 +- .../method_channel_firebase_storage.dart | 24 +- .../method_channel_reference.dart | 48 +- .../method_channel/method_channel_task.dart | 20 +- .../lib/src/pigeon/messages.pigeon.dart | 1324 ++++--- .../pigeons/messages.dart | 120 +- .../pubspec.yaml | 2 +- .../test/pigeon/test_api.dart | 945 ++--- 169 files changed, 22617 insertions(+), 14836 deletions(-) create mode 100644 packages/cloud_firestore/analysis_options.yaml create mode 100644 packages/firebase_app_check/analysis_options.yaml diff --git a/melos.yaml b/melos.yaml index b0cbd7f6b3d0..097dd2c48f92 100644 --- a/melos.yaml +++ b/melos.yaml @@ -239,6 +239,7 @@ scripts: melos exec -- "flutter pub run pigeon --input ./pigeons/messages.dart" && \ melos run generate:pigeon:macos --no-select && \ melos run generate:pigeon:android --no-select && \ + melos run generate:pigeon:windows --no-select && \ melos run format-ci --no-select packageFilters: fileExists: 'pigeons/messages.dart' @@ -259,6 +260,13 @@ scripts: dirExists: 'android' description: Transform the method toList() into a public one to be used in EventChannel + generate:pigeon:windows: + run: | + melos exec -- "perl -i -pe 's{^(\s+::flutter::EncodableList ToEncodableList\(\) const;)\n}{ public:\n\$1\n private:\n}' ./windows/messages.g.h" + packageFilters: + fileExists: 'windows/messages.g.h' + description: Make ToEncodableList public so it can be called from plugin code. + # Additional cleanup lifecycle script, executed when `melos clean` is run. postclean: > melos exec -c 6 -- "flutter clean" diff --git a/packages/cloud_firestore/analysis_options.yaml b/packages/cloud_firestore/analysis_options.yaml new file mode 100644 index 000000000000..5dcab3c843d2 --- /dev/null +++ b/packages/cloud_firestore/analysis_options.yaml @@ -0,0 +1,11 @@ +# Copyright 2026 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# in the LICENSE file. + +include: ../../analysis_options.yaml + +analyzer: + exclude: + - cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart + - cloud_firestore_platform_interface/test/pigeon/test_api.dart + - cloud_firestore_platform_interface/pigeons/messages.dart diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java index e7af885e3454..14cea06420c1 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java @@ -77,8 +77,7 @@ public class FlutterFirebaseFirestorePlugin private static final String METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_firestore"; final StandardMethodCodec MESSAGE_CODEC = - new StandardMethodCodec( - io.flutter.plugins.firebase.firestore.FlutterFirebaseFirestoreMessageCodec.INSTANCE); + new StandardMethodCodec(GeneratedAndroidFirebaseFirestore.PigeonCodec.INSTANCE); private BinaryMessenger binaryMessenger; @@ -183,7 +182,7 @@ private void initInstance(BinaryMessenger messenger) { FlutterFirebasePluginRegistry.registerPlugin(METHOD_CHANNEL_NAME, this); - GeneratedAndroidFirebaseFirestore.FirebaseFirestoreHostApi.setup(binaryMessenger, this); + GeneratedAndroidFirebaseFirestore.FirebaseFirestoreHostApi.setUp(binaryMessenger, this); } @Override @@ -355,10 +354,10 @@ public void loadBundle( public void namedQueryGet( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull String name, - @NonNull GeneratedAndroidFirebaseFirestore.PigeonGetOptions options, + @NonNull GeneratedAndroidFirebaseFirestore.InternalGetOptions options, @NonNull GeneratedAndroidFirebaseFirestore.Result< - GeneratedAndroidFirebaseFirestore.PigeonQuerySnapshot> + GeneratedAndroidFirebaseFirestore.InternalQuerySnapshot> result) { cachedThreadPool.execute( @@ -391,13 +390,13 @@ public void namedQueryGet( @Override public void clearPersistence( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore firestore = getFirestoreFromPigeon(app); Tasks.await(firestore.clearPersistence()); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -407,13 +406,13 @@ public void clearPersistence( @Override public void disableNetwork( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore firestore = getFirestoreFromPigeon(app); Tasks.await(firestore.disableNetwork()); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -423,13 +422,13 @@ public void disableNetwork( @Override public void enableNetwork( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore firestore = getFirestoreFromPigeon(app); Tasks.await(firestore.enableNetwork()); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -439,14 +438,14 @@ public void enableNetwork( @Override public void terminate( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore firestore = getFirestoreFromPigeon(app); Tasks.await(firestore.terminate()); destroyCachedFirebaseFirestoreInstanceForKey(firestore); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -456,13 +455,13 @@ public void terminate( @Override public void waitForPendingWrites( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore firestore = getFirestoreFromPigeon(app); Tasks.await(firestore.waitForPendingWrites()); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -475,14 +474,14 @@ public void waitForPendingWrites( public void setIndexConfiguration( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull String indexConfiguration, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore firestore = getFirestoreFromPigeon(app); Tasks.await(firestore.setIndexConfiguration(indexConfiguration)); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -493,7 +492,7 @@ public void setIndexConfiguration( public void persistenceCacheIndexManagerRequest( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull GeneratedAndroidFirebaseFirestore.PersistenceCacheIndexManagerRequest request, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { PersistentCacheIndexManager indexManager = @@ -514,20 +513,20 @@ public void persistenceCacheIndexManagerRequest( Log.d(TAG, "`PersistentCacheIndexManager` is not available."); } - result.success(null); + result.success(); }); } @Override public void setLoggingEnabled( @NonNull Boolean loggingEnabled, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore.setLoggingEnabled(loggingEnabled); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -570,12 +569,12 @@ public void transactionCreate( @Override public void transactionStoreResult( @NonNull String transactionId, - @NonNull GeneratedAndroidFirebaseFirestore.PigeonTransactionResult resultType, - @Nullable List commands, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.InternalTransactionResult resultType, + @Nullable List commands, + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { Objects.requireNonNull(transactionHandlers.get(transactionId)) .receiveTransactionResponse(resultType, commands); - result.success(null); + result.success(); } @Override @@ -585,7 +584,7 @@ public void transactionGet( @NonNull String path, @NonNull GeneratedAndroidFirebaseFirestore.Result< - GeneratedAndroidFirebaseFirestore.PigeonDocumentSnapshot> + GeneratedAndroidFirebaseFirestore.InternalDocumentSnapshot> result) { cachedThreadPool.execute( () -> { @@ -616,7 +615,7 @@ public void transactionGet( public void documentReferenceSet( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull GeneratedAndroidFirebaseFirestore.DocumentReferenceRequest request, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { @@ -639,7 +638,8 @@ public void documentReferenceSet( setTask = documentReference.set(data); } - result.success(Tasks.await(setTask)); + Tasks.await(setTask); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -650,7 +650,7 @@ public void documentReferenceSet( public void documentReferenceUpdate( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull GeneratedAndroidFirebaseFirestore.DocumentReferenceRequest request, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { @@ -683,9 +683,9 @@ public void documentReferenceUpdate( flattenData.add(fieldPath); flattenData.add(data.get(fieldPath)); } - result.success( - Tasks.await( - documentReference.update(firstFieldPath, firstObject, flattenData.toArray()))); + Tasks.await( + documentReference.update(firstFieldPath, firstObject, flattenData.toArray())); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -698,7 +698,7 @@ public void documentReferenceGet( @NonNull GeneratedAndroidFirebaseFirestore.DocumentReferenceRequest request, @NonNull GeneratedAndroidFirebaseFirestore.Result< - GeneratedAndroidFirebaseFirestore.PigeonDocumentSnapshot> + GeneratedAndroidFirebaseFirestore.InternalDocumentSnapshot> result) { cachedThreadPool.execute( () -> { @@ -726,14 +726,15 @@ public void documentReferenceGet( public void documentReferenceDelete( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull GeneratedAndroidFirebaseFirestore.DocumentReferenceRequest request, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { DocumentReference documentReference = getFirestoreFromPigeon(app).document(request.getPath()); - result.success(Tasks.await(documentReference.delete())); + Tasks.await(documentReference.delete()); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -745,11 +746,11 @@ public void queryGet( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull String path, @NonNull Boolean isCollectionGroup, - @NonNull GeneratedAndroidFirebaseFirestore.PigeonQueryParameters parameters, - @NonNull GeneratedAndroidFirebaseFirestore.PigeonGetOptions options, + @NonNull GeneratedAndroidFirebaseFirestore.InternalQueryParameters parameters, + @NonNull GeneratedAndroidFirebaseFirestore.InternalGetOptions options, @NonNull GeneratedAndroidFirebaseFirestore.Result< - GeneratedAndroidFirebaseFirestore.PigeonQuerySnapshot> + GeneratedAndroidFirebaseFirestore.InternalQuerySnapshot> result) { cachedThreadPool.execute( () -> { @@ -784,7 +785,7 @@ public void queryGet( public void aggregateQuery( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull String path, - @NonNull GeneratedAndroidFirebaseFirestore.PigeonQueryParameters parameters, + @NonNull GeneratedAndroidFirebaseFirestore.InternalQueryParameters parameters, @NonNull GeneratedAndroidFirebaseFirestore.AggregateSource source, @NonNull List queries, @NonNull Boolean isCollectionGroup, @@ -876,16 +877,16 @@ public void aggregateQuery( @Override public void writeBatchCommit( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, - @NonNull List writes, - @NonNull GeneratedAndroidFirebaseFirestore.Result result) { + @NonNull List writes, + @NonNull GeneratedAndroidFirebaseFirestore.VoidResult result) { cachedThreadPool.execute( () -> { try { FirebaseFirestore firestore = getFirestoreFromPigeon(app); WriteBatch batch = firestore.batch(); - for (GeneratedAndroidFirebaseFirestore.PigeonTransactionCommand write : writes) { - GeneratedAndroidFirebaseFirestore.PigeonTransactionType type = + for (GeneratedAndroidFirebaseFirestore.InternalTransactionCommand write : writes) { + GeneratedAndroidFirebaseFirestore.InternalTransactionType type = Objects.requireNonNull(write.getType()); String path = Objects.requireNonNull(write.getPath()); DocumentReference documentReference = firestore.document(path); @@ -925,7 +926,7 @@ public void writeBatchCommit( @SuppressWarnings("unchecked") Map setData = (Map) (Map) Objects.requireNonNull(write.getData()); - GeneratedAndroidFirebaseFirestore.PigeonDocumentOption options = + GeneratedAndroidFirebaseFirestore.InternalDocumentOption options = Objects.requireNonNull(write.getOption()); if (options.getMerge() != null && options.getMerge()) { @@ -948,7 +949,7 @@ public void writeBatchCommit( } Tasks.await(batch.commit()); - result.success(null); + result.success(); } catch (Exception e) { ExceptionConverter.sendErrorToFlutter(result, e); } @@ -960,8 +961,8 @@ public void querySnapshot( @NonNull GeneratedAndroidFirebaseFirestore.FirestorePigeonFirebaseApp app, @NonNull String path, @NonNull Boolean isCollectionGroup, - @NonNull GeneratedAndroidFirebaseFirestore.PigeonQueryParameters parameters, - @NonNull GeneratedAndroidFirebaseFirestore.PigeonGetOptions options, + @NonNull GeneratedAndroidFirebaseFirestore.InternalQueryParameters parameters, + @NonNull GeneratedAndroidFirebaseFirestore.InternalGetOptions options, @NonNull Boolean includeMetadataChanges, @NonNull GeneratedAndroidFirebaseFirestore.ListenSource source, @NonNull GeneratedAndroidFirebaseFirestore.Result result) { @@ -1018,7 +1019,7 @@ public void executePipeline( @Nullable Map options, @NonNull GeneratedAndroidFirebaseFirestore.Result< - GeneratedAndroidFirebaseFirestore.PigeonPipelineSnapshot> + GeneratedAndroidFirebaseFirestore.InternalPipelineSnapshot> result) { cachedThreadPool.execute( () -> { @@ -1028,14 +1029,14 @@ public void executePipeline( // Execute pipeline using Android Firestore SDK Pipeline.Snapshot snapshot = PipelineParser.executePipeline(firestore, stages, options); - // Convert Pipeline.Snapshot to PigeonPipelineSnapshot - List pipelineResults = + // Convert Pipeline.Snapshot to InternalPipelineSnapshot + List pipelineResults = new ArrayList<>(); // Iterate through snapshot results for (PipelineResult pipelineResult : snapshot.getResults()) { - GeneratedAndroidFirebaseFirestore.PigeonPipelineResult.Builder resultBuilder = - new GeneratedAndroidFirebaseFirestore.PigeonPipelineResult.Builder(); + GeneratedAndroidFirebaseFirestore.InternalPipelineResult.Builder resultBuilder = + new GeneratedAndroidFirebaseFirestore.InternalPipelineResult.Builder(); if (pipelineResult.getRef() != null) { resultBuilder.setDocumentPath(pipelineResult.getRef().getPath()); } @@ -1056,8 +1057,8 @@ public void executePipeline( } // Build the snapshot - GeneratedAndroidFirebaseFirestore.PigeonPipelineSnapshot.Builder snapshotBuilder = - new GeneratedAndroidFirebaseFirestore.PigeonPipelineSnapshot.Builder(); + GeneratedAndroidFirebaseFirestore.InternalPipelineSnapshot.Builder snapshotBuilder = + new GeneratedAndroidFirebaseFirestore.InternalPipelineSnapshot.Builder(); snapshotBuilder.setResults(pipelineResults); // Set execution time when available. Do not fabricate a value when null. diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java index bf5bb3fff9ef..60f2d8ff6638 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java @@ -1,11 +1,14 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon package io.flutter.plugins.firebase.firestore; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.CLASS; + import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -13,14 +16,174 @@ import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MessageCodec; import java.io.ByteArrayOutputStream; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; /** Generated class from Pigeon. */ @SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) public class GeneratedAndroidFirebaseFirestore { + static boolean pigeonDoubleEquals(double a, double b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == 0.0 ? 0.0 : a) == (b == 0.0 ? 0.0 : b) || (Double.isNaN(a) && Double.isNaN(b)); + } + + static boolean pigeonFloatEquals(float a, float b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == 0.0f ? 0.0f : a) == (b == 0.0f ? 0.0f : b) || (Float.isNaN(a) && Float.isNaN(b)); + } + + static int pigeonDoubleHashCode(double d) { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + if (d == 0.0) { + d = 0.0; + } + long bits = Double.doubleToLongBits(d); + return (int) (bits ^ (bits >>> 32)); + } + + static int pigeonFloatHashCode(float f) { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + if (f == 0.0f) { + f = 0.0f; + } + return Float.floatToIntBits(f); + } + + static boolean pigeonDeepEquals(Object a, Object b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a instanceof byte[] && b instanceof byte[]) { + return Arrays.equals((byte[]) a, (byte[]) b); + } + if (a instanceof int[] && b instanceof int[]) { + return Arrays.equals((int[]) a, (int[]) b); + } + if (a instanceof long[] && b instanceof long[]) { + return Arrays.equals((long[]) a, (long[]) b); + } + if (a instanceof double[] && b instanceof double[]) { + double[] da = (double[]) a; + double[] db = (double[]) b; + if (da.length != db.length) { + return false; + } + for (int i = 0; i < da.length; i++) { + if (!pigeonDoubleEquals(da[i], db[i])) { + return false; + } + } + return true; + } + if (a instanceof List && b instanceof List) { + List listA = (List) a; + List listB = (List) b; + if (listA.size() != listB.size()) { + return false; + } + for (int i = 0; i < listA.size(); i++) { + if (!pigeonDeepEquals(listA.get(i), listB.get(i))) { + return false; + } + } + return true; + } + if (a instanceof Map && b instanceof Map) { + Map mapA = (Map) a; + Map mapB = (Map) b; + if (mapA.size() != mapB.size()) { + return false; + } + for (Map.Entry entryA : mapA.entrySet()) { + Object keyA = entryA.getKey(); + Object valueA = entryA.getValue(); + boolean found = false; + for (Map.Entry entryB : mapB.entrySet()) { + Object keyB = entryB.getKey(); + if (pigeonDeepEquals(keyA, keyB)) { + Object valueB = entryB.getValue(); + if (pigeonDeepEquals(valueA, valueB)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; + } + if (a instanceof Double && b instanceof Double) { + return pigeonDoubleEquals((double) a, (double) b); + } + if (a instanceof Float && b instanceof Float) { + return pigeonFloatEquals((float) a, (float) b); + } + return a.equals(b); + } + + static int pigeonDeepHashCode(Object value) { + if (value == null) { + return 0; + } + if (value instanceof byte[]) { + return Arrays.hashCode((byte[]) value); + } + if (value instanceof int[]) { + return Arrays.hashCode((int[]) value); + } + if (value instanceof long[]) { + return Arrays.hashCode((long[]) value); + } + if (value instanceof double[]) { + double[] da = (double[]) value; + int result = 1; + for (double d : da) { + result = 31 * result + pigeonDoubleHashCode(d); + } + return result; + } + if (value instanceof List) { + int result = 1; + for (Object item : (List) value) { + result = 31 * result + pigeonDeepHashCode(item); + } + return result; + } + if (value instanceof Map) { + int result = 0; + for (Map.Entry entry : ((Map) value).entrySet()) { + result += + ((pigeonDeepHashCode(entry.getKey()) * 31) ^ pigeonDeepHashCode(entry.getValue())); + } + return result; + } + if (value instanceof Object[]) { + int result = 1; + for (Object item : (Object[]) value) { + result = 31 * result + pigeonDeepHashCode(item); + } + return result; + } + if (value instanceof Double) { + return pigeonDoubleHashCode((double) value); + } + if (value instanceof Float) { + return pigeonFloatHashCode((float) value); + } + return value.hashCode(); + } /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ public static class FlutterError extends RuntimeException { @@ -40,7 +203,7 @@ public FlutterError(@NonNull String code, @Nullable String message, @Nullable Ob @NonNull protected static ArrayList wrapError(@NonNull Throwable exception) { - ArrayList errorList = new ArrayList(3); + ArrayList errorList = new ArrayList<>(3); if (exception instanceof FlutterError) { FlutterError error = (FlutterError) exception; errorList.add(error.code); @@ -55,6 +218,10 @@ protected static ArrayList wrapError(@NonNull Throwable exception) { return errorList; } + @Target(METHOD) + @Retention(CLASS) + @interface CanIgnoreReturnValue {} + /** An enumeration of document change types. */ public enum DocumentChangeType { /** Indicates a new document was added to the set of documents matching the query. */ @@ -69,7 +236,7 @@ public enum DocumentChangeType { final int index; - private DocumentChangeType(final int index) { + DocumentChangeType(final int index) { this.index = index; } } @@ -99,7 +266,7 @@ public enum Source { final int index; - private Source(final int index) { + Source(final int index) { this.index = index; } } @@ -128,7 +295,7 @@ public enum ListenSource { final int index; - private ListenSource(final int index) { + ListenSource(final int index) { this.index = index; } } @@ -149,7 +316,7 @@ public enum ServerTimestampBehavior { final int index; - private ServerTimestampBehavior(final int index) { + ServerTimestampBehavior(final int index) { this.index = index; } } @@ -161,7 +328,7 @@ public enum AggregateSource { final int index; - private AggregateSource(final int index) { + AggregateSource(final int index) { this.index = index; } } @@ -177,23 +344,23 @@ public enum PersistenceCacheIndexManagerRequest { final int index; - private PersistenceCacheIndexManagerRequest(final int index) { + PersistenceCacheIndexManagerRequest(final int index) { this.index = index; } } - public enum PigeonTransactionResult { + public enum InternalTransactionResult { SUCCESS(0), FAILURE(1); final int index; - private PigeonTransactionResult(final int index) { + InternalTransactionResult(final int index) { this.index = index; } } - public enum PigeonTransactionType { + public enum InternalTransactionType { GET(0), UPDATE(1), SET(2), @@ -201,7 +368,7 @@ public enum PigeonTransactionType { final int index; - private PigeonTransactionType(final int index) { + InternalTransactionType(final int index) { this.index = index; } } @@ -213,13 +380,13 @@ public enum AggregateType { final int index; - private AggregateType(final int index) { + AggregateType(final int index) { this.index = index; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonFirebaseSettings { + public static final class InternalFirebaseSettings { private @Nullable Boolean persistenceEnabled; public @Nullable Boolean getPersistenceEnabled() { @@ -274,12 +441,43 @@ public void setIgnoreUndefinedProperties(@NonNull Boolean setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonFirebaseSettings() {} + InternalFirebaseSettings() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalFirebaseSettings that = (InternalFirebaseSettings) o; + return pigeonDeepEquals(persistenceEnabled, that.persistenceEnabled) + && pigeonDeepEquals(host, that.host) + && pigeonDeepEquals(sslEnabled, that.sslEnabled) + && pigeonDeepEquals(cacheSizeBytes, that.cacheSizeBytes) + && pigeonDeepEquals(ignoreUndefinedProperties, that.ignoreUndefinedProperties); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + persistenceEnabled, + host, + sslEnabled, + cacheSizeBytes, + ignoreUndefinedProperties + }; + return pigeonDeepHashCode(fields); + } public static final class Builder { private @Nullable Boolean persistenceEnabled; + @CanIgnoreReturnValue public @NonNull Builder setPersistenceEnabled(@Nullable Boolean setterArg) { this.persistenceEnabled = setterArg; return this; @@ -287,6 +485,7 @@ public static final class Builder { private @Nullable String host; + @CanIgnoreReturnValue public @NonNull Builder setHost(@Nullable String setterArg) { this.host = setterArg; return this; @@ -294,6 +493,7 @@ public static final class Builder { private @Nullable Boolean sslEnabled; + @CanIgnoreReturnValue public @NonNull Builder setSslEnabled(@Nullable Boolean setterArg) { this.sslEnabled = setterArg; return this; @@ -301,6 +501,7 @@ public static final class Builder { private @Nullable Long cacheSizeBytes; + @CanIgnoreReturnValue public @NonNull Builder setCacheSizeBytes(@Nullable Long setterArg) { this.cacheSizeBytes = setterArg; return this; @@ -308,13 +509,14 @@ public static final class Builder { private @Nullable Boolean ignoreUndefinedProperties; + @CanIgnoreReturnValue public @NonNull Builder setIgnoreUndefinedProperties(@NonNull Boolean setterArg) { this.ignoreUndefinedProperties = setterArg; return this; } - public @NonNull PigeonFirebaseSettings build() { - PigeonFirebaseSettings pigeonReturn = new PigeonFirebaseSettings(); + public @NonNull InternalFirebaseSettings build() { + InternalFirebaseSettings pigeonReturn = new InternalFirebaseSettings(); pigeonReturn.setPersistenceEnabled(persistenceEnabled); pigeonReturn.setHost(host); pigeonReturn.setSslEnabled(sslEnabled); @@ -326,7 +528,7 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(5); + ArrayList toListResult = new ArrayList<>(5); toListResult.add(persistenceEnabled); toListResult.add(host); toListResult.add(sslEnabled); @@ -335,22 +537,17 @@ public ArrayList toList() { return toListResult; } - static @NonNull PigeonFirebaseSettings fromList(@NonNull ArrayList list) { - PigeonFirebaseSettings pigeonResult = new PigeonFirebaseSettings(); - Object persistenceEnabled = list.get(0); + static @NonNull InternalFirebaseSettings fromList(@NonNull ArrayList pigeonVar_list) { + InternalFirebaseSettings pigeonResult = new InternalFirebaseSettings(); + Object persistenceEnabled = pigeonVar_list.get(0); pigeonResult.setPersistenceEnabled((Boolean) persistenceEnabled); - Object host = list.get(1); + Object host = pigeonVar_list.get(1); pigeonResult.setHost((String) host); - Object sslEnabled = list.get(2); + Object sslEnabled = pigeonVar_list.get(2); pigeonResult.setSslEnabled((Boolean) sslEnabled); - Object cacheSizeBytes = list.get(3); - pigeonResult.setCacheSizeBytes( - (cacheSizeBytes == null) - ? null - : ((cacheSizeBytes instanceof Integer) - ? (Integer) cacheSizeBytes - : (Long) cacheSizeBytes)); - Object ignoreUndefinedProperties = list.get(4); + Object cacheSizeBytes = pigeonVar_list.get(3); + pigeonResult.setCacheSizeBytes((Long) cacheSizeBytes); + Object ignoreUndefinedProperties = pigeonVar_list.get(4); pigeonResult.setIgnoreUndefinedProperties((Boolean) ignoreUndefinedProperties); return pigeonResult; } @@ -371,13 +568,13 @@ public void setAppName(@NonNull String setterArg) { this.appName = setterArg; } - private @NonNull PigeonFirebaseSettings settings; + private @NonNull InternalFirebaseSettings settings; - public @NonNull PigeonFirebaseSettings getSettings() { + public @NonNull InternalFirebaseSettings getSettings() { return settings; } - public void setSettings(@NonNull PigeonFirebaseSettings setterArg) { + public void setSettings(@NonNull InternalFirebaseSettings setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"settings\" is null."); } @@ -400,24 +597,47 @@ public void setDatabaseURL(@NonNull String setterArg) { /** Constructor is non-public to enforce null safety; use Builder. */ FirestorePigeonFirebaseApp() {} + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + FirestorePigeonFirebaseApp that = (FirestorePigeonFirebaseApp) o; + return pigeonDeepEquals(appName, that.appName) + && pigeonDeepEquals(settings, that.settings) + && pigeonDeepEquals(databaseURL, that.databaseURL); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), appName, settings, databaseURL}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable String appName; + @CanIgnoreReturnValue public @NonNull Builder setAppName(@NonNull String setterArg) { this.appName = setterArg; return this; } - private @Nullable PigeonFirebaseSettings settings; + private @Nullable InternalFirebaseSettings settings; - public @NonNull Builder setSettings(@NonNull PigeonFirebaseSettings setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setSettings(@NonNull InternalFirebaseSettings setterArg) { this.settings = setterArg; return this; } private @Nullable String databaseURL; + @CanIgnoreReturnValue public @NonNull Builder setDatabaseURL(@NonNull String setterArg) { this.databaseURL = setterArg; return this; @@ -434,30 +654,27 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(3); + ArrayList toListResult = new ArrayList<>(3); toListResult.add(appName); - toListResult.add((settings == null) ? null : settings.toList()); + toListResult.add(settings); toListResult.add(databaseURL); return toListResult; } - static @NonNull FirestorePigeonFirebaseApp fromList(@NonNull ArrayList list) { + static @NonNull FirestorePigeonFirebaseApp fromList(@NonNull ArrayList pigeonVar_list) { FirestorePigeonFirebaseApp pigeonResult = new FirestorePigeonFirebaseApp(); - Object appName = list.get(0); + Object appName = pigeonVar_list.get(0); pigeonResult.setAppName((String) appName); - Object settings = list.get(1); - pigeonResult.setSettings( - (settings == null) - ? null - : PigeonFirebaseSettings.fromList((ArrayList) settings)); - Object databaseURL = list.get(2); + Object settings = pigeonVar_list.get(1); + pigeonResult.setSettings((InternalFirebaseSettings) settings); + Object databaseURL = pigeonVar_list.get(2); pigeonResult.setDatabaseURL((String) databaseURL); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonSnapshotMetadata { + public static final class InternalSnapshotMetadata { private @NonNull Boolean hasPendingWrites; public @NonNull Boolean getHasPendingWrites() { @@ -485,12 +702,32 @@ public void setIsFromCache(@NonNull Boolean setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonSnapshotMetadata() {} + InternalSnapshotMetadata() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalSnapshotMetadata that = (InternalSnapshotMetadata) o; + return pigeonDeepEquals(hasPendingWrites, that.hasPendingWrites) + && pigeonDeepEquals(isFromCache, that.isFromCache); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), hasPendingWrites, isFromCache}; + return pigeonDeepHashCode(fields); + } public static final class Builder { private @Nullable Boolean hasPendingWrites; + @CanIgnoreReturnValue public @NonNull Builder setHasPendingWrites(@NonNull Boolean setterArg) { this.hasPendingWrites = setterArg; return this; @@ -498,13 +735,14 @@ public static final class Builder { private @Nullable Boolean isFromCache; + @CanIgnoreReturnValue public @NonNull Builder setIsFromCache(@NonNull Boolean setterArg) { this.isFromCache = setterArg; return this; } - public @NonNull PigeonSnapshotMetadata build() { - PigeonSnapshotMetadata pigeonReturn = new PigeonSnapshotMetadata(); + public @NonNull InternalSnapshotMetadata build() { + InternalSnapshotMetadata pigeonReturn = new InternalSnapshotMetadata(); pigeonReturn.setHasPendingWrites(hasPendingWrites); pigeonReturn.setIsFromCache(isFromCache); return pigeonReturn; @@ -513,24 +751,24 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(2); + ArrayList toListResult = new ArrayList<>(2); toListResult.add(hasPendingWrites); toListResult.add(isFromCache); return toListResult; } - static @NonNull PigeonSnapshotMetadata fromList(@NonNull ArrayList list) { - PigeonSnapshotMetadata pigeonResult = new PigeonSnapshotMetadata(); - Object hasPendingWrites = list.get(0); + static @NonNull InternalSnapshotMetadata fromList(@NonNull ArrayList pigeonVar_list) { + InternalSnapshotMetadata pigeonResult = new InternalSnapshotMetadata(); + Object hasPendingWrites = pigeonVar_list.get(0); pigeonResult.setHasPendingWrites((Boolean) hasPendingWrites); - Object isFromCache = list.get(1); + Object isFromCache = pigeonVar_list.get(1); pigeonResult.setIsFromCache((Boolean) isFromCache); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonDocumentSnapshot { + public static final class InternalDocumentSnapshot { private @NonNull String path; public @NonNull String getPath() { @@ -554,13 +792,13 @@ public void setData(@Nullable Map setterArg) { this.data = setterArg; } - private @NonNull PigeonSnapshotMetadata metadata; + private @NonNull InternalSnapshotMetadata metadata; - public @NonNull PigeonSnapshotMetadata getMetadata() { + public @NonNull InternalSnapshotMetadata getMetadata() { return metadata; } - public void setMetadata(@NonNull PigeonSnapshotMetadata setterArg) { + public void setMetadata(@NonNull InternalSnapshotMetadata setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"metadata\" is null."); } @@ -568,12 +806,33 @@ public void setMetadata(@NonNull PigeonSnapshotMetadata setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonDocumentSnapshot() {} + InternalDocumentSnapshot() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalDocumentSnapshot that = (InternalDocumentSnapshot) o; + return pigeonDeepEquals(path, that.path) + && pigeonDeepEquals(data, that.data) + && pigeonDeepEquals(metadata, that.metadata); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), path, data, metadata}; + return pigeonDeepHashCode(fields); + } public static final class Builder { private @Nullable String path; + @CanIgnoreReturnValue public @NonNull Builder setPath(@NonNull String setterArg) { this.path = setterArg; return this; @@ -581,20 +840,22 @@ public static final class Builder { private @Nullable Map data; + @CanIgnoreReturnValue public @NonNull Builder setData(@Nullable Map setterArg) { this.data = setterArg; return this; } - private @Nullable PigeonSnapshotMetadata metadata; + private @Nullable InternalSnapshotMetadata metadata; - public @NonNull Builder setMetadata(@NonNull PigeonSnapshotMetadata setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setMetadata(@NonNull InternalSnapshotMetadata setterArg) { this.metadata = setterArg; return this; } - public @NonNull PigeonDocumentSnapshot build() { - PigeonDocumentSnapshot pigeonReturn = new PigeonDocumentSnapshot(); + public @NonNull InternalDocumentSnapshot build() { + InternalDocumentSnapshot pigeonReturn = new InternalDocumentSnapshot(); pigeonReturn.setPath(path); pigeonReturn.setData(data); pigeonReturn.setMetadata(metadata); @@ -604,30 +865,27 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(3); + ArrayList toListResult = new ArrayList<>(3); toListResult.add(path); toListResult.add(data); - toListResult.add((metadata == null) ? null : metadata.toList()); + toListResult.add(metadata); return toListResult; } - static @NonNull PigeonDocumentSnapshot fromList(@NonNull ArrayList list) { - PigeonDocumentSnapshot pigeonResult = new PigeonDocumentSnapshot(); - Object path = list.get(0); + static @NonNull InternalDocumentSnapshot fromList(@NonNull ArrayList pigeonVar_list) { + InternalDocumentSnapshot pigeonResult = new InternalDocumentSnapshot(); + Object path = pigeonVar_list.get(0); pigeonResult.setPath((String) path); - Object data = list.get(1); + Object data = pigeonVar_list.get(1); pigeonResult.setData((Map) data); - Object metadata = list.get(2); - pigeonResult.setMetadata( - (metadata == null) - ? null - : PigeonSnapshotMetadata.fromList((ArrayList) metadata)); + Object metadata = pigeonVar_list.get(2); + pigeonResult.setMetadata((InternalSnapshotMetadata) metadata); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonDocumentChange { + public static final class InternalDocumentChange { private @NonNull DocumentChangeType type; public @NonNull DocumentChangeType getType() { @@ -641,13 +899,13 @@ public void setType(@NonNull DocumentChangeType setterArg) { this.type = setterArg; } - private @NonNull PigeonDocumentSnapshot document; + private @NonNull InternalDocumentSnapshot document; - public @NonNull PigeonDocumentSnapshot getDocument() { + public @NonNull InternalDocumentSnapshot getDocument() { return document; } - public void setDocument(@NonNull PigeonDocumentSnapshot setterArg) { + public void setDocument(@NonNull InternalDocumentSnapshot setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"document\" is null."); } @@ -681,26 +939,50 @@ public void setNewIndex(@NonNull Long setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonDocumentChange() {} + InternalDocumentChange() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalDocumentChange that = (InternalDocumentChange) o; + return pigeonDeepEquals(type, that.type) + && pigeonDeepEquals(document, that.document) + && pigeonDeepEquals(oldIndex, that.oldIndex) + && pigeonDeepEquals(newIndex, that.newIndex); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), type, document, oldIndex, newIndex}; + return pigeonDeepHashCode(fields); + } public static final class Builder { private @Nullable DocumentChangeType type; + @CanIgnoreReturnValue public @NonNull Builder setType(@NonNull DocumentChangeType setterArg) { this.type = setterArg; return this; } - private @Nullable PigeonDocumentSnapshot document; + private @Nullable InternalDocumentSnapshot document; - public @NonNull Builder setDocument(@NonNull PigeonDocumentSnapshot setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setDocument(@NonNull InternalDocumentSnapshot setterArg) { this.document = setterArg; return this; } private @Nullable Long oldIndex; + @CanIgnoreReturnValue public @NonNull Builder setOldIndex(@NonNull Long setterArg) { this.oldIndex = setterArg; return this; @@ -708,13 +990,14 @@ public static final class Builder { private @Nullable Long newIndex; + @CanIgnoreReturnValue public @NonNull Builder setNewIndex(@NonNull Long setterArg) { this.newIndex = setterArg; return this; } - public @NonNull PigeonDocumentChange build() { - PigeonDocumentChange pigeonReturn = new PigeonDocumentChange(); + public @NonNull InternalDocumentChange build() { + InternalDocumentChange pigeonReturn = new InternalDocumentChange(); pigeonReturn.setType(type); pigeonReturn.setDocument(document); pigeonReturn.setOldIndex(oldIndex); @@ -725,72 +1008,63 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(4); - toListResult.add(type == null ? null : type.index); - toListResult.add((document == null) ? null : document.toList()); + ArrayList toListResult = new ArrayList<>(4); + toListResult.add(type); + toListResult.add(document); toListResult.add(oldIndex); toListResult.add(newIndex); return toListResult; } - static @NonNull PigeonDocumentChange fromList(@NonNull ArrayList list) { - PigeonDocumentChange pigeonResult = new PigeonDocumentChange(); - Object type = list.get(0); - pigeonResult.setType(DocumentChangeType.values()[(int) type]); - Object document = list.get(1); - pigeonResult.setDocument( - (document == null) - ? null - : PigeonDocumentSnapshot.fromList((ArrayList) document)); - Object oldIndex = list.get(2); - pigeonResult.setOldIndex( - (oldIndex == null) - ? null - : ((oldIndex instanceof Integer) ? (Integer) oldIndex : (Long) oldIndex)); - Object newIndex = list.get(3); - pigeonResult.setNewIndex( - (newIndex == null) - ? null - : ((newIndex instanceof Integer) ? (Integer) newIndex : (Long) newIndex)); + static @NonNull InternalDocumentChange fromList(@NonNull ArrayList pigeonVar_list) { + InternalDocumentChange pigeonResult = new InternalDocumentChange(); + Object type = pigeonVar_list.get(0); + pigeonResult.setType((DocumentChangeType) type); + Object document = pigeonVar_list.get(1); + pigeonResult.setDocument((InternalDocumentSnapshot) document); + Object oldIndex = pigeonVar_list.get(2); + pigeonResult.setOldIndex((Long) oldIndex); + Object newIndex = pigeonVar_list.get(3); + pigeonResult.setNewIndex((Long) newIndex); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonQuerySnapshot { - private @NonNull List documents; + public static final class InternalQuerySnapshot { + private @NonNull List documents; - public @NonNull List getDocuments() { + public @NonNull List getDocuments() { return documents; } - public void setDocuments(@NonNull List setterArg) { + public void setDocuments(@NonNull List setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"documents\" is null."); } this.documents = setterArg; } - private @NonNull List documentChanges; + private @NonNull List documentChanges; - public @NonNull List getDocumentChanges() { + public @NonNull List getDocumentChanges() { return documentChanges; } - public void setDocumentChanges(@NonNull List setterArg) { + public void setDocumentChanges(@NonNull List setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"documentChanges\" is null."); } this.documentChanges = setterArg; } - private @NonNull PigeonSnapshotMetadata metadata; + private @NonNull InternalSnapshotMetadata metadata; - public @NonNull PigeonSnapshotMetadata getMetadata() { + public @NonNull InternalSnapshotMetadata getMetadata() { return metadata; } - public void setMetadata(@NonNull PigeonSnapshotMetadata setterArg) { + public void setMetadata(@NonNull InternalSnapshotMetadata setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"metadata\" is null."); } @@ -798,33 +1072,56 @@ public void setMetadata(@NonNull PigeonSnapshotMetadata setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonQuerySnapshot() {} + InternalQuerySnapshot() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalQuerySnapshot that = (InternalQuerySnapshot) o; + return pigeonDeepEquals(documents, that.documents) + && pigeonDeepEquals(documentChanges, that.documentChanges) + && pigeonDeepEquals(metadata, that.metadata); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), documents, documentChanges, metadata}; + return pigeonDeepHashCode(fields); + } public static final class Builder { - private @Nullable List documents; + private @Nullable List documents; - public @NonNull Builder setDocuments(@NonNull List setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setDocuments(@NonNull List setterArg) { this.documents = setterArg; return this; } - private @Nullable List documentChanges; + private @Nullable List documentChanges; - public @NonNull Builder setDocumentChanges(@NonNull List setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setDocumentChanges(@NonNull List setterArg) { this.documentChanges = setterArg; return this; } - private @Nullable PigeonSnapshotMetadata metadata; + private @Nullable InternalSnapshotMetadata metadata; - public @NonNull Builder setMetadata(@NonNull PigeonSnapshotMetadata setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setMetadata(@NonNull InternalSnapshotMetadata setterArg) { this.metadata = setterArg; return this; } - public @NonNull PigeonQuerySnapshot build() { - PigeonQuerySnapshot pigeonReturn = new PigeonQuerySnapshot(); + public @NonNull InternalQuerySnapshot build() { + InternalQuerySnapshot pigeonReturn = new InternalQuerySnapshot(); pigeonReturn.setDocuments(documents); pigeonReturn.setDocumentChanges(documentChanges); pigeonReturn.setMetadata(metadata); @@ -834,30 +1131,27 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(3); + ArrayList toListResult = new ArrayList<>(3); toListResult.add(documents); toListResult.add(documentChanges); - toListResult.add((metadata == null) ? null : metadata.toList()); + toListResult.add(metadata); return toListResult; } - static @NonNull PigeonQuerySnapshot fromList(@NonNull ArrayList list) { - PigeonQuerySnapshot pigeonResult = new PigeonQuerySnapshot(); - Object documents = list.get(0); - pigeonResult.setDocuments((List) documents); - Object documentChanges = list.get(1); - pigeonResult.setDocumentChanges((List) documentChanges); - Object metadata = list.get(2); - pigeonResult.setMetadata( - (metadata == null) - ? null - : PigeonSnapshotMetadata.fromList((ArrayList) metadata)); + static @NonNull InternalQuerySnapshot fromList(@NonNull ArrayList pigeonVar_list) { + InternalQuerySnapshot pigeonResult = new InternalQuerySnapshot(); + Object documents = pigeonVar_list.get(0); + pigeonResult.setDocuments((List) documents); + Object documentChanges = pigeonVar_list.get(1); + pigeonResult.setDocumentChanges((List) documentChanges); + Object metadata = pigeonVar_list.get(2); + pigeonResult.setMetadata((InternalSnapshotMetadata) metadata); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonPipelineResult { + public static final class InternalPipelineResult { private @Nullable String documentPath; public @Nullable String getDocumentPath() { @@ -899,10 +1193,32 @@ public void setData(@Nullable Map setterArg) { this.data = setterArg; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalPipelineResult that = (InternalPipelineResult) o; + return pigeonDeepEquals(documentPath, that.documentPath) + && pigeonDeepEquals(createTime, that.createTime) + && pigeonDeepEquals(updateTime, that.updateTime) + && pigeonDeepEquals(data, that.data); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), documentPath, createTime, updateTime, data}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable String documentPath; + @CanIgnoreReturnValue public @NonNull Builder setDocumentPath(@Nullable String setterArg) { this.documentPath = setterArg; return this; @@ -910,6 +1226,7 @@ public static final class Builder { private @Nullable Long createTime; + @CanIgnoreReturnValue public @NonNull Builder setCreateTime(@Nullable Long setterArg) { this.createTime = setterArg; return this; @@ -917,6 +1234,7 @@ public static final class Builder { private @Nullable Long updateTime; + @CanIgnoreReturnValue public @NonNull Builder setUpdateTime(@Nullable Long setterArg) { this.updateTime = setterArg; return this; @@ -924,13 +1242,14 @@ public static final class Builder { private @Nullable Map data; + @CanIgnoreReturnValue public @NonNull Builder setData(@Nullable Map setterArg) { this.data = setterArg; return this; } - public @NonNull PigeonPipelineResult build() { - PigeonPipelineResult pigeonReturn = new PigeonPipelineResult(); + public @NonNull InternalPipelineResult build() { + InternalPipelineResult pigeonReturn = new InternalPipelineResult(); pigeonReturn.setDocumentPath(documentPath); pigeonReturn.setCreateTime(createTime); pigeonReturn.setUpdateTime(updateTime); @@ -941,7 +1260,7 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(4); + ArrayList toListResult = new ArrayList<>(4); toListResult.add(documentPath); toListResult.add(createTime); toListResult.add(updateTime); @@ -949,35 +1268,29 @@ public ArrayList toList() { return toListResult; } - static @NonNull PigeonPipelineResult fromList(@NonNull ArrayList list) { - PigeonPipelineResult pigeonResult = new PigeonPipelineResult(); - Object documentPath = list.get(0); + static @NonNull InternalPipelineResult fromList(@NonNull ArrayList pigeonVar_list) { + InternalPipelineResult pigeonResult = new InternalPipelineResult(); + Object documentPath = pigeonVar_list.get(0); pigeonResult.setDocumentPath((String) documentPath); - Object createTime = list.get(1); - pigeonResult.setCreateTime( - (createTime == null) - ? null - : ((createTime instanceof Integer) ? (Integer) createTime : (Long) createTime)); - Object updateTime = list.get(2); - pigeonResult.setUpdateTime( - (updateTime == null) - ? null - : ((updateTime instanceof Integer) ? (Integer) updateTime : (Long) updateTime)); - Object data = list.get(3); + Object createTime = pigeonVar_list.get(1); + pigeonResult.setCreateTime((Long) createTime); + Object updateTime = pigeonVar_list.get(2); + pigeonResult.setUpdateTime((Long) updateTime); + Object data = pigeonVar_list.get(3); pigeonResult.setData((Map) data); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonPipelineSnapshot { - private @NonNull List results; + public static final class InternalPipelineSnapshot { + private @NonNull List results; - public @NonNull List getResults() { + public @NonNull List getResults() { return results; } - public void setResults(@NonNull List setterArg) { + public void setResults(@NonNull List setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"results\" is null."); } @@ -998,26 +1311,47 @@ public void setExecutionTime(@NonNull Long setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonPipelineSnapshot() {} + InternalPipelineSnapshot() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalPipelineSnapshot that = (InternalPipelineSnapshot) o; + return pigeonDeepEquals(results, that.results) + && pigeonDeepEquals(executionTime, that.executionTime); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), results, executionTime}; + return pigeonDeepHashCode(fields); + } public static final class Builder { - private @Nullable List results; + private @Nullable List results; - public @NonNull Builder setResults(@NonNull List setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setResults(@NonNull List setterArg) { this.results = setterArg; return this; } private @Nullable Long executionTime; + @CanIgnoreReturnValue public @NonNull Builder setExecutionTime(@NonNull Long setterArg) { this.executionTime = setterArg; return this; } - public @NonNull PigeonPipelineSnapshot build() { - PigeonPipelineSnapshot pigeonReturn = new PigeonPipelineSnapshot(); + public @NonNull InternalPipelineSnapshot build() { + InternalPipelineSnapshot pigeonReturn = new InternalPipelineSnapshot(); pigeonReturn.setResults(results); pigeonReturn.setExecutionTime(executionTime); return pigeonReturn; @@ -1026,29 +1360,24 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(2); + ArrayList toListResult = new ArrayList<>(2); toListResult.add(results); toListResult.add(executionTime); return toListResult; } - static @NonNull PigeonPipelineSnapshot fromList(@NonNull ArrayList list) { - PigeonPipelineSnapshot pigeonResult = new PigeonPipelineSnapshot(); - Object results = list.get(0); - pigeonResult.setResults((List) results); - Object executionTime = list.get(1); - pigeonResult.setExecutionTime( - (executionTime == null) - ? null - : ((executionTime instanceof Integer) - ? (Integer) executionTime - : (Long) executionTime)); + static @NonNull InternalPipelineSnapshot fromList(@NonNull ArrayList pigeonVar_list) { + InternalPipelineSnapshot pigeonResult = new InternalPipelineSnapshot(); + Object results = pigeonVar_list.get(0); + pigeonResult.setResults((List) results); + Object executionTime = pigeonVar_list.get(1); + pigeonResult.setExecutionTime((Long) executionTime); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonGetOptions { + public static final class InternalGetOptions { private @NonNull Source source; public @NonNull Source getSource() { @@ -1076,12 +1405,32 @@ public void setServerTimestampBehavior(@NonNull ServerTimestampBehavior setterAr } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonGetOptions() {} + InternalGetOptions() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalGetOptions that = (InternalGetOptions) o; + return pigeonDeepEquals(source, that.source) + && pigeonDeepEquals(serverTimestampBehavior, that.serverTimestampBehavior); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), source, serverTimestampBehavior}; + return pigeonDeepHashCode(fields); + } public static final class Builder { private @Nullable Source source; + @CanIgnoreReturnValue public @NonNull Builder setSource(@NonNull Source setterArg) { this.source = setterArg; return this; @@ -1089,14 +1438,15 @@ public static final class Builder { private @Nullable ServerTimestampBehavior serverTimestampBehavior; + @CanIgnoreReturnValue public @NonNull Builder setServerTimestampBehavior( @NonNull ServerTimestampBehavior setterArg) { this.serverTimestampBehavior = setterArg; return this; } - public @NonNull PigeonGetOptions build() { - PigeonGetOptions pigeonReturn = new PigeonGetOptions(); + public @NonNull InternalGetOptions build() { + InternalGetOptions pigeonReturn = new InternalGetOptions(); pigeonReturn.setSource(source); pigeonReturn.setServerTimestampBehavior(serverTimestampBehavior); return pigeonReturn; @@ -1105,25 +1455,24 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(2); - toListResult.add(source == null ? null : source.index); - toListResult.add(serverTimestampBehavior == null ? null : serverTimestampBehavior.index); + ArrayList toListResult = new ArrayList<>(2); + toListResult.add(source); + toListResult.add(serverTimestampBehavior); return toListResult; } - static @NonNull PigeonGetOptions fromList(@NonNull ArrayList list) { - PigeonGetOptions pigeonResult = new PigeonGetOptions(); - Object source = list.get(0); - pigeonResult.setSource(Source.values()[(int) source]); - Object serverTimestampBehavior = list.get(1); - pigeonResult.setServerTimestampBehavior( - ServerTimestampBehavior.values()[(int) serverTimestampBehavior]); + static @NonNull InternalGetOptions fromList(@NonNull ArrayList pigeonVar_list) { + InternalGetOptions pigeonResult = new InternalGetOptions(); + Object source = pigeonVar_list.get(0); + pigeonResult.setSource((Source) source); + Object serverTimestampBehavior = pigeonVar_list.get(1); + pigeonResult.setServerTimestampBehavior((ServerTimestampBehavior) serverTimestampBehavior); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonDocumentOption { + public static final class InternalDocumentOption { private @Nullable Boolean merge; public @Nullable Boolean getMerge() { @@ -1144,10 +1493,29 @@ public void setMergeFields(@Nullable List> setterArg) { this.mergeFields = setterArg; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalDocumentOption that = (InternalDocumentOption) o; + return pigeonDeepEquals(merge, that.merge) && pigeonDeepEquals(mergeFields, that.mergeFields); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), merge, mergeFields}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable Boolean merge; + @CanIgnoreReturnValue public @NonNull Builder setMerge(@Nullable Boolean setterArg) { this.merge = setterArg; return this; @@ -1155,13 +1523,14 @@ public static final class Builder { private @Nullable List> mergeFields; + @CanIgnoreReturnValue public @NonNull Builder setMergeFields(@Nullable List> setterArg) { this.mergeFields = setterArg; return this; } - public @NonNull PigeonDocumentOption build() { - PigeonDocumentOption pigeonReturn = new PigeonDocumentOption(); + public @NonNull InternalDocumentOption build() { + InternalDocumentOption pigeonReturn = new InternalDocumentOption(); pigeonReturn.setMerge(merge); pigeonReturn.setMergeFields(mergeFields); return pigeonReturn; @@ -1170,31 +1539,31 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(2); + ArrayList toListResult = new ArrayList<>(2); toListResult.add(merge); toListResult.add(mergeFields); return toListResult; } - static @NonNull PigeonDocumentOption fromList(@NonNull ArrayList list) { - PigeonDocumentOption pigeonResult = new PigeonDocumentOption(); - Object merge = list.get(0); + static @NonNull InternalDocumentOption fromList(@NonNull ArrayList pigeonVar_list) { + InternalDocumentOption pigeonResult = new InternalDocumentOption(); + Object merge = pigeonVar_list.get(0); pigeonResult.setMerge((Boolean) merge); - Object mergeFields = list.get(1); + Object mergeFields = pigeonVar_list.get(1); pigeonResult.setMergeFields((List>) mergeFields); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonTransactionCommand { - private @NonNull PigeonTransactionType type; + public static final class InternalTransactionCommand { + private @NonNull InternalTransactionType type; - public @NonNull PigeonTransactionType getType() { + public @NonNull InternalTransactionType getType() { return type; } - public void setType(@NonNull PigeonTransactionType setterArg) { + public void setType(@NonNull InternalTransactionType setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"type\" is null."); } @@ -1224,30 +1593,53 @@ public void setData(@Nullable Map setterArg) { this.data = setterArg; } - private @Nullable PigeonDocumentOption option; + private @Nullable InternalDocumentOption option; - public @Nullable PigeonDocumentOption getOption() { + public @Nullable InternalDocumentOption getOption() { return option; } - public void setOption(@Nullable PigeonDocumentOption setterArg) { + public void setOption(@Nullable InternalDocumentOption setterArg) { this.option = setterArg; } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonTransactionCommand() {} + InternalTransactionCommand() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalTransactionCommand that = (InternalTransactionCommand) o; + return pigeonDeepEquals(type, that.type) + && pigeonDeepEquals(path, that.path) + && pigeonDeepEquals(data, that.data) + && pigeonDeepEquals(option, that.option); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), type, path, data, option}; + return pigeonDeepHashCode(fields); + } public static final class Builder { - private @Nullable PigeonTransactionType type; + private @Nullable InternalTransactionType type; - public @NonNull Builder setType(@NonNull PigeonTransactionType setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setType(@NonNull InternalTransactionType setterArg) { this.type = setterArg; return this; } private @Nullable String path; + @CanIgnoreReturnValue public @NonNull Builder setPath(@NonNull String setterArg) { this.path = setterArg; return this; @@ -1255,20 +1647,22 @@ public static final class Builder { private @Nullable Map data; + @CanIgnoreReturnValue public @NonNull Builder setData(@Nullable Map setterArg) { this.data = setterArg; return this; } - private @Nullable PigeonDocumentOption option; + private @Nullable InternalDocumentOption option; - public @NonNull Builder setOption(@Nullable PigeonDocumentOption setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setOption(@Nullable InternalDocumentOption setterArg) { this.option = setterArg; return this; } - public @NonNull PigeonTransactionCommand build() { - PigeonTransactionCommand pigeonReturn = new PigeonTransactionCommand(); + public @NonNull InternalTransactionCommand build() { + InternalTransactionCommand pigeonReturn = new InternalTransactionCommand(); pigeonReturn.setType(type); pigeonReturn.setPath(path); pigeonReturn.setData(data); @@ -1279,25 +1673,24 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(4); - toListResult.add(type == null ? null : type.index); + ArrayList toListResult = new ArrayList<>(4); + toListResult.add(type); toListResult.add(path); toListResult.add(data); - toListResult.add((option == null) ? null : option.toList()); + toListResult.add(option); return toListResult; } - static @NonNull PigeonTransactionCommand fromList(@NonNull ArrayList list) { - PigeonTransactionCommand pigeonResult = new PigeonTransactionCommand(); - Object type = list.get(0); - pigeonResult.setType(PigeonTransactionType.values()[(int) type]); - Object path = list.get(1); + static @NonNull InternalTransactionCommand fromList(@NonNull ArrayList pigeonVar_list) { + InternalTransactionCommand pigeonResult = new InternalTransactionCommand(); + Object type = pigeonVar_list.get(0); + pigeonResult.setType((InternalTransactionType) type); + Object path = pigeonVar_list.get(1); pigeonResult.setPath((String) path); - Object data = list.get(2); + Object data = pigeonVar_list.get(2); pigeonResult.setData((Map) data); - Object option = list.get(3); - pigeonResult.setOption( - (option == null) ? null : PigeonDocumentOption.fromList((ArrayList) option)); + Object option = pigeonVar_list.get(3); + pigeonResult.setOption((InternalDocumentOption) option); return pigeonResult; } } @@ -1327,13 +1720,13 @@ public void setData(@Nullable Map setterArg) { this.data = setterArg; } - private @Nullable PigeonDocumentOption option; + private @Nullable InternalDocumentOption option; - public @Nullable PigeonDocumentOption getOption() { + public @Nullable InternalDocumentOption getOption() { return option; } - public void setOption(@Nullable PigeonDocumentOption setterArg) { + public void setOption(@Nullable InternalDocumentOption setterArg) { this.option = setterArg; } @@ -1360,10 +1753,34 @@ public void setServerTimestampBehavior(@Nullable ServerTimestampBehavior setterA /** Constructor is non-public to enforce null safety; use Builder. */ DocumentReferenceRequest() {} + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DocumentReferenceRequest that = (DocumentReferenceRequest) o; + return pigeonDeepEquals(path, that.path) + && pigeonDeepEquals(data, that.data) + && pigeonDeepEquals(option, that.option) + && pigeonDeepEquals(source, that.source) + && pigeonDeepEquals(serverTimestampBehavior, that.serverTimestampBehavior); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] {getClass(), path, data, option, source, serverTimestampBehavior}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable String path; + @CanIgnoreReturnValue public @NonNull Builder setPath(@NonNull String setterArg) { this.path = setterArg; return this; @@ -1371,20 +1788,23 @@ public static final class Builder { private @Nullable Map data; + @CanIgnoreReturnValue public @NonNull Builder setData(@Nullable Map setterArg) { this.data = setterArg; return this; } - private @Nullable PigeonDocumentOption option; + private @Nullable InternalDocumentOption option; - public @NonNull Builder setOption(@Nullable PigeonDocumentOption setterArg) { + @CanIgnoreReturnValue + public @NonNull Builder setOption(@Nullable InternalDocumentOption setterArg) { this.option = setterArg; return this; } private @Nullable Source source; + @CanIgnoreReturnValue public @NonNull Builder setSource(@Nullable Source setterArg) { this.source = setterArg; return this; @@ -1392,6 +1812,7 @@ public static final class Builder { private @Nullable ServerTimestampBehavior serverTimestampBehavior; + @CanIgnoreReturnValue public @NonNull Builder setServerTimestampBehavior( @Nullable ServerTimestampBehavior setterArg) { this.serverTimestampBehavior = setterArg; @@ -1411,37 +1832,33 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(5); + ArrayList toListResult = new ArrayList<>(5); toListResult.add(path); toListResult.add(data); - toListResult.add((option == null) ? null : option.toList()); - toListResult.add(source == null ? null : source.index); - toListResult.add(serverTimestampBehavior == null ? null : serverTimestampBehavior.index); + toListResult.add(option); + toListResult.add(source); + toListResult.add(serverTimestampBehavior); return toListResult; } - static @NonNull DocumentReferenceRequest fromList(@NonNull ArrayList list) { + static @NonNull DocumentReferenceRequest fromList(@NonNull ArrayList pigeonVar_list) { DocumentReferenceRequest pigeonResult = new DocumentReferenceRequest(); - Object path = list.get(0); + Object path = pigeonVar_list.get(0); pigeonResult.setPath((String) path); - Object data = list.get(1); + Object data = pigeonVar_list.get(1); pigeonResult.setData((Map) data); - Object option = list.get(2); - pigeonResult.setOption( - (option == null) ? null : PigeonDocumentOption.fromList((ArrayList) option)); - Object source = list.get(3); - pigeonResult.setSource(source == null ? null : Source.values()[(int) source]); - Object serverTimestampBehavior = list.get(4); - pigeonResult.setServerTimestampBehavior( - serverTimestampBehavior == null - ? null - : ServerTimestampBehavior.values()[(int) serverTimestampBehavior]); + Object option = pigeonVar_list.get(2); + pigeonResult.setOption((InternalDocumentOption) option); + Object source = pigeonVar_list.get(3); + pigeonResult.setSource((Source) source); + Object serverTimestampBehavior = pigeonVar_list.get(4); + pigeonResult.setServerTimestampBehavior((ServerTimestampBehavior) serverTimestampBehavior); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonQueryParameters { + public static final class InternalQueryParameters { private @Nullable List> where; public @Nullable List> getWhere() { @@ -1532,10 +1949,49 @@ public void setFilters(@Nullable Map setterArg) { this.filters = setterArg; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalQueryParameters that = (InternalQueryParameters) o; + return pigeonDeepEquals(where, that.where) + && pigeonDeepEquals(orderBy, that.orderBy) + && pigeonDeepEquals(limit, that.limit) + && pigeonDeepEquals(limitToLast, that.limitToLast) + && pigeonDeepEquals(startAt, that.startAt) + && pigeonDeepEquals(startAfter, that.startAfter) + && pigeonDeepEquals(endAt, that.endAt) + && pigeonDeepEquals(endBefore, that.endBefore) + && pigeonDeepEquals(filters, that.filters); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + where, + orderBy, + limit, + limitToLast, + startAt, + startAfter, + endAt, + endBefore, + filters + }; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable List> where; + @CanIgnoreReturnValue public @NonNull Builder setWhere(@Nullable List> setterArg) { this.where = setterArg; return this; @@ -1543,6 +1999,7 @@ public static final class Builder { private @Nullable List> orderBy; + @CanIgnoreReturnValue public @NonNull Builder setOrderBy(@Nullable List> setterArg) { this.orderBy = setterArg; return this; @@ -1550,6 +2007,7 @@ public static final class Builder { private @Nullable Long limit; + @CanIgnoreReturnValue public @NonNull Builder setLimit(@Nullable Long setterArg) { this.limit = setterArg; return this; @@ -1557,6 +2015,7 @@ public static final class Builder { private @Nullable Long limitToLast; + @CanIgnoreReturnValue public @NonNull Builder setLimitToLast(@Nullable Long setterArg) { this.limitToLast = setterArg; return this; @@ -1564,6 +2023,7 @@ public static final class Builder { private @Nullable List startAt; + @CanIgnoreReturnValue public @NonNull Builder setStartAt(@Nullable List setterArg) { this.startAt = setterArg; return this; @@ -1571,6 +2031,7 @@ public static final class Builder { private @Nullable List startAfter; + @CanIgnoreReturnValue public @NonNull Builder setStartAfter(@Nullable List setterArg) { this.startAfter = setterArg; return this; @@ -1578,6 +2039,7 @@ public static final class Builder { private @Nullable List endAt; + @CanIgnoreReturnValue public @NonNull Builder setEndAt(@Nullable List setterArg) { this.endAt = setterArg; return this; @@ -1585,6 +2047,7 @@ public static final class Builder { private @Nullable List endBefore; + @CanIgnoreReturnValue public @NonNull Builder setEndBefore(@Nullable List setterArg) { this.endBefore = setterArg; return this; @@ -1592,13 +2055,14 @@ public static final class Builder { private @Nullable Map filters; + @CanIgnoreReturnValue public @NonNull Builder setFilters(@Nullable Map setterArg) { this.filters = setterArg; return this; } - public @NonNull PigeonQueryParameters build() { - PigeonQueryParameters pigeonReturn = new PigeonQueryParameters(); + public @NonNull InternalQueryParameters build() { + InternalQueryParameters pigeonReturn = new InternalQueryParameters(); pigeonReturn.setWhere(where); pigeonReturn.setOrderBy(orderBy); pigeonReturn.setLimit(limit); @@ -1614,7 +2078,7 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(9); + ArrayList toListResult = new ArrayList<>(9); toListResult.add(where); toListResult.add(orderBy); toListResult.add(limit); @@ -1627,29 +2091,25 @@ public ArrayList toList() { return toListResult; } - static @NonNull PigeonQueryParameters fromList(@NonNull ArrayList list) { - PigeonQueryParameters pigeonResult = new PigeonQueryParameters(); - Object where = list.get(0); + static @NonNull InternalQueryParameters fromList(@NonNull ArrayList pigeonVar_list) { + InternalQueryParameters pigeonResult = new InternalQueryParameters(); + Object where = pigeonVar_list.get(0); pigeonResult.setWhere((List>) where); - Object orderBy = list.get(1); + Object orderBy = pigeonVar_list.get(1); pigeonResult.setOrderBy((List>) orderBy); - Object limit = list.get(2); - pigeonResult.setLimit( - (limit == null) ? null : ((limit instanceof Integer) ? (Integer) limit : (Long) limit)); - Object limitToLast = list.get(3); - pigeonResult.setLimitToLast( - (limitToLast == null) - ? null - : ((limitToLast instanceof Integer) ? (Integer) limitToLast : (Long) limitToLast)); - Object startAt = list.get(4); + Object limit = pigeonVar_list.get(2); + pigeonResult.setLimit((Long) limit); + Object limitToLast = pigeonVar_list.get(3); + pigeonResult.setLimitToLast((Long) limitToLast); + Object startAt = pigeonVar_list.get(4); pigeonResult.setStartAt((List) startAt); - Object startAfter = list.get(5); + Object startAfter = pigeonVar_list.get(5); pigeonResult.setStartAfter((List) startAfter); - Object endAt = list.get(6); + Object endAt = pigeonVar_list.get(6); pigeonResult.setEndAt((List) endAt); - Object endBefore = list.get(7); + Object endBefore = pigeonVar_list.get(7); pigeonResult.setEndBefore((List) endBefore); - Object filters = list.get(8); + Object filters = pigeonVar_list.get(8); pigeonResult.setFilters((Map) filters); return pigeonResult; } @@ -1683,10 +2143,29 @@ public void setField(@Nullable String setterArg) { /** Constructor is non-public to enforce null safety; use Builder. */ AggregateQuery() {} + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AggregateQuery that = (AggregateQuery) o; + return pigeonDeepEquals(type, that.type) && pigeonDeepEquals(field, that.field); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), type, field}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable AggregateType type; + @CanIgnoreReturnValue public @NonNull Builder setType(@NonNull AggregateType setterArg) { this.type = setterArg; return this; @@ -1694,6 +2173,7 @@ public static final class Builder { private @Nullable String field; + @CanIgnoreReturnValue public @NonNull Builder setField(@Nullable String setterArg) { this.field = setterArg; return this; @@ -1709,17 +2189,17 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(2); - toListResult.add(type == null ? null : type.index); + ArrayList toListResult = new ArrayList<>(2); + toListResult.add(type); toListResult.add(field); return toListResult; } - static @NonNull AggregateQuery fromList(@NonNull ArrayList list) { + static @NonNull AggregateQuery fromList(@NonNull ArrayList pigeonVar_list) { AggregateQuery pigeonResult = new AggregateQuery(); - Object type = list.get(0); - pigeonResult.setType(AggregateType.values()[(int) type]); - Object field = list.get(1); + Object type = pigeonVar_list.get(0); + pigeonResult.setType((AggregateType) type); + Object field = pigeonVar_list.get(1); pigeonResult.setField((String) field); return pigeonResult; } @@ -1763,10 +2243,31 @@ public void setValue(@Nullable Double setterArg) { /** Constructor is non-public to enforce null safety; use Builder. */ AggregateQueryResponse() {} + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AggregateQueryResponse that = (AggregateQueryResponse) o; + return pigeonDeepEquals(type, that.type) + && pigeonDeepEquals(field, that.field) + && pigeonDeepEquals(value, that.value); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), type, field, value}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable AggregateType type; + @CanIgnoreReturnValue public @NonNull Builder setType(@NonNull AggregateType setterArg) { this.type = setterArg; return this; @@ -1774,6 +2275,7 @@ public static final class Builder { private @Nullable String field; + @CanIgnoreReturnValue public @NonNull Builder setField(@Nullable String setterArg) { this.field = setterArg; return this; @@ -1781,6 +2283,7 @@ public static final class Builder { private @Nullable Double value; + @CanIgnoreReturnValue public @NonNull Builder setValue(@Nullable Double setterArg) { this.value = setterArg; return this; @@ -1797,71 +2300,116 @@ public static final class Builder { @NonNull public ArrayList toList() { - ArrayList toListResult = new ArrayList(3); - toListResult.add(type == null ? null : type.index); + ArrayList toListResult = new ArrayList<>(3); + toListResult.add(type); toListResult.add(field); toListResult.add(value); return toListResult; } - static @NonNull AggregateQueryResponse fromList(@NonNull ArrayList list) { + static @NonNull AggregateQueryResponse fromList(@NonNull ArrayList pigeonVar_list) { AggregateQueryResponse pigeonResult = new AggregateQueryResponse(); - Object type = list.get(0); - pigeonResult.setType(AggregateType.values()[(int) type]); - Object field = list.get(1); + Object type = pigeonVar_list.get(0); + pigeonResult.setType((AggregateType) type); + Object field = pigeonVar_list.get(1); pigeonResult.setField((String) field); - Object value = list.get(2); + Object value = pigeonVar_list.get(2); pigeonResult.setValue((Double) value); return pigeonResult; } } - public interface Result { - @SuppressWarnings("UnknownNullness") - void success(T result); - - void error(@NonNull Throwable error); - } - - private static class FirebaseFirestoreHostApiCodec extends FlutterFirebaseFirestoreMessageCodec { - public static final FirebaseFirestoreHostApiCodec INSTANCE = - new FirebaseFirestoreHostApiCodec(); + public static class PigeonCodec extends FlutterFirebaseFirestoreMessageCodec { + public static final PigeonCodec INSTANCE = new PigeonCodec(); - private FirebaseFirestoreHostApiCodec() {} + private PigeonCodec() {} @Override protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { switch (type) { - case (byte) 128: - return AggregateQuery.fromList((ArrayList) readValue(buffer)); case (byte) 129: - return AggregateQueryResponse.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null ? null : DocumentChangeType.values()[((Long) value).intValue()]; + } case (byte) 130: - return DocumentReferenceRequest.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null ? null : Source.values()[((Long) value).intValue()]; + } case (byte) 131: - return FirestorePigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null ? null : ListenSource.values()[((Long) value).intValue()]; + } case (byte) 132: - return PigeonDocumentChange.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null + ? null + : ServerTimestampBehavior.values()[((Long) value).intValue()]; + } case (byte) 133: - return PigeonDocumentOption.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null ? null : AggregateSource.values()[((Long) value).intValue()]; + } case (byte) 134: - return PigeonDocumentSnapshot.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null + ? null + : PersistenceCacheIndexManagerRequest.values()[((Long) value).intValue()]; + } case (byte) 135: - return PigeonFirebaseSettings.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null + ? null + : InternalTransactionResult.values()[((Long) value).intValue()]; + } case (byte) 136: - return PigeonGetOptions.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null + ? null + : InternalTransactionType.values()[((Long) value).intValue()]; + } case (byte) 137: - return PigeonPipelineResult.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null ? null : AggregateType.values()[((Long) value).intValue()]; + } case (byte) 138: - return PigeonPipelineSnapshot.fromList((ArrayList) readValue(buffer)); + return InternalFirebaseSettings.fromList((ArrayList) readValue(buffer)); case (byte) 139: - return PigeonQueryParameters.fromList((ArrayList) readValue(buffer)); + return FirestorePigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); case (byte) 140: - return PigeonQuerySnapshot.fromList((ArrayList) readValue(buffer)); + return InternalSnapshotMetadata.fromList((ArrayList) readValue(buffer)); case (byte) 141: - return PigeonSnapshotMetadata.fromList((ArrayList) readValue(buffer)); + return InternalDocumentSnapshot.fromList((ArrayList) readValue(buffer)); case (byte) 142: - return PigeonTransactionCommand.fromList((ArrayList) readValue(buffer)); + return InternalDocumentChange.fromList((ArrayList) readValue(buffer)); + case (byte) 143: + return InternalQuerySnapshot.fromList((ArrayList) readValue(buffer)); + case (byte) 144: + return InternalPipelineResult.fromList((ArrayList) readValue(buffer)); + case (byte) 145: + return InternalPipelineSnapshot.fromList((ArrayList) readValue(buffer)); + case (byte) 146: + return InternalGetOptions.fromList((ArrayList) readValue(buffer)); + case (byte) 147: + return InternalDocumentOption.fromList((ArrayList) readValue(buffer)); + case (byte) 148: + return InternalTransactionCommand.fromList((ArrayList) readValue(buffer)); + case (byte) 149: + return DocumentReferenceRequest.fromList((ArrayList) readValue(buffer)); + case (byte) 150: + return InternalQueryParameters.fromList((ArrayList) readValue(buffer)); + case (byte) 151: + return AggregateQuery.fromList((ArrayList) readValue(buffer)); + case (byte) 152: + return AggregateQueryResponse.fromList((ArrayList) readValue(buffer)); default: return super.readValueOfType(type, buffer); } @@ -1869,57 +2417,109 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { @Override protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof AggregateQuery) { - stream.write(128); - writeValue(stream, ((AggregateQuery) value).toList()); - } else if (value instanceof AggregateQueryResponse) { + if (value instanceof DocumentChangeType) { stream.write(129); - writeValue(stream, ((AggregateQueryResponse) value).toList()); - } else if (value instanceof DocumentReferenceRequest) { + writeValue(stream, value == null ? null : ((DocumentChangeType) value).index); + } else if (value instanceof Source) { stream.write(130); - writeValue(stream, ((DocumentReferenceRequest) value).toList()); - } else if (value instanceof FirestorePigeonFirebaseApp) { + writeValue(stream, value == null ? null : ((Source) value).index); + } else if (value instanceof ListenSource) { stream.write(131); - writeValue(stream, ((FirestorePigeonFirebaseApp) value).toList()); - } else if (value instanceof PigeonDocumentChange) { + writeValue(stream, value == null ? null : ((ListenSource) value).index); + } else if (value instanceof ServerTimestampBehavior) { stream.write(132); - writeValue(stream, ((PigeonDocumentChange) value).toList()); - } else if (value instanceof PigeonDocumentOption) { + writeValue(stream, value == null ? null : ((ServerTimestampBehavior) value).index); + } else if (value instanceof AggregateSource) { stream.write(133); - writeValue(stream, ((PigeonDocumentOption) value).toList()); - } else if (value instanceof PigeonDocumentSnapshot) { + writeValue(stream, value == null ? null : ((AggregateSource) value).index); + } else if (value instanceof PersistenceCacheIndexManagerRequest) { stream.write(134); - writeValue(stream, ((PigeonDocumentSnapshot) value).toList()); - } else if (value instanceof PigeonFirebaseSettings) { + writeValue( + stream, value == null ? null : ((PersistenceCacheIndexManagerRequest) value).index); + } else if (value instanceof InternalTransactionResult) { stream.write(135); - writeValue(stream, ((PigeonFirebaseSettings) value).toList()); - } else if (value instanceof PigeonGetOptions) { + writeValue(stream, value == null ? null : ((InternalTransactionResult) value).index); + } else if (value instanceof InternalTransactionType) { stream.write(136); - writeValue(stream, ((PigeonGetOptions) value).toList()); - } else if (value instanceof PigeonPipelineResult) { + writeValue(stream, value == null ? null : ((InternalTransactionType) value).index); + } else if (value instanceof AggregateType) { stream.write(137); - writeValue(stream, ((PigeonPipelineResult) value).toList()); - } else if (value instanceof PigeonPipelineSnapshot) { + writeValue(stream, value == null ? null : ((AggregateType) value).index); + } else if (value instanceof InternalFirebaseSettings) { stream.write(138); - writeValue(stream, ((PigeonPipelineSnapshot) value).toList()); - } else if (value instanceof PigeonQueryParameters) { + writeValue(stream, ((InternalFirebaseSettings) value).toList()); + } else if (value instanceof FirestorePigeonFirebaseApp) { stream.write(139); - writeValue(stream, ((PigeonQueryParameters) value).toList()); - } else if (value instanceof PigeonQuerySnapshot) { + writeValue(stream, ((FirestorePigeonFirebaseApp) value).toList()); + } else if (value instanceof InternalSnapshotMetadata) { stream.write(140); - writeValue(stream, ((PigeonQuerySnapshot) value).toList()); - } else if (value instanceof PigeonSnapshotMetadata) { + writeValue(stream, ((InternalSnapshotMetadata) value).toList()); + } else if (value instanceof InternalDocumentSnapshot) { stream.write(141); - writeValue(stream, ((PigeonSnapshotMetadata) value).toList()); - } else if (value instanceof PigeonTransactionCommand) { + writeValue(stream, ((InternalDocumentSnapshot) value).toList()); + } else if (value instanceof InternalDocumentChange) { stream.write(142); - writeValue(stream, ((PigeonTransactionCommand) value).toList()); + writeValue(stream, ((InternalDocumentChange) value).toList()); + } else if (value instanceof InternalQuerySnapshot) { + stream.write(143); + writeValue(stream, ((InternalQuerySnapshot) value).toList()); + } else if (value instanceof InternalPipelineResult) { + stream.write(144); + writeValue(stream, ((InternalPipelineResult) value).toList()); + } else if (value instanceof InternalPipelineSnapshot) { + stream.write(145); + writeValue(stream, ((InternalPipelineSnapshot) value).toList()); + } else if (value instanceof InternalGetOptions) { + stream.write(146); + writeValue(stream, ((InternalGetOptions) value).toList()); + } else if (value instanceof InternalDocumentOption) { + stream.write(147); + writeValue(stream, ((InternalDocumentOption) value).toList()); + } else if (value instanceof InternalTransactionCommand) { + stream.write(148); + writeValue(stream, ((InternalTransactionCommand) value).toList()); + } else if (value instanceof DocumentReferenceRequest) { + stream.write(149); + writeValue(stream, ((DocumentReferenceRequest) value).toList()); + } else if (value instanceof InternalQueryParameters) { + stream.write(150); + writeValue(stream, ((InternalQueryParameters) value).toList()); + } else if (value instanceof AggregateQuery) { + stream.write(151); + writeValue(stream, ((AggregateQuery) value).toList()); + } else if (value instanceof AggregateQueryResponse) { + stream.write(152); + writeValue(stream, ((AggregateQueryResponse) value).toList()); } else { super.writeValue(stream, value); } } } + /** Asynchronous error handling return type for non-nullable API method returns. */ + public interface Result { + /** Success case callback method for handling returns. */ + void success(@NonNull T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for nullable API method returns. */ + public interface NullableResult { + /** Success case callback method for handling returns. */ + void success(@Nullable T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for void API method returns. */ + public interface VoidResult { + /** Success case callback method for handling returns. */ + void success(); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseFirestoreHostApi { @@ -1931,26 +2531,25 @@ void loadBundle( void namedQueryGet( @NonNull FirestorePigeonFirebaseApp app, @NonNull String name, - @NonNull PigeonGetOptions options, - @NonNull Result result); + @NonNull InternalGetOptions options, + @NonNull Result result); - void clearPersistence(@NonNull FirestorePigeonFirebaseApp app, @NonNull Result result); + void clearPersistence(@NonNull FirestorePigeonFirebaseApp app, @NonNull VoidResult result); - void disableNetwork(@NonNull FirestorePigeonFirebaseApp app, @NonNull Result result); + void disableNetwork(@NonNull FirestorePigeonFirebaseApp app, @NonNull VoidResult result); - void enableNetwork(@NonNull FirestorePigeonFirebaseApp app, @NonNull Result result); + void enableNetwork(@NonNull FirestorePigeonFirebaseApp app, @NonNull VoidResult result); - void terminate(@NonNull FirestorePigeonFirebaseApp app, @NonNull Result result); + void terminate(@NonNull FirestorePigeonFirebaseApp app, @NonNull VoidResult result); - void waitForPendingWrites( - @NonNull FirestorePigeonFirebaseApp app, @NonNull Result result); + void waitForPendingWrites(@NonNull FirestorePigeonFirebaseApp app, @NonNull VoidResult result); void setIndexConfiguration( @NonNull FirestorePigeonFirebaseApp app, @NonNull String indexConfiguration, - @NonNull Result result); + @NonNull VoidResult result); - void setLoggingEnabled(@NonNull Boolean loggingEnabled, @NonNull Result result); + void setLoggingEnabled(@NonNull Boolean loggingEnabled, @NonNull VoidResult result); void snapshotsInSyncSetup( @NonNull FirestorePigeonFirebaseApp app, @NonNull Result result); @@ -1963,48 +2562,48 @@ void transactionCreate( void transactionStoreResult( @NonNull String transactionId, - @NonNull PigeonTransactionResult resultType, - @Nullable List commands, - @NonNull Result result); + @NonNull InternalTransactionResult resultType, + @Nullable List commands, + @NonNull VoidResult result); void transactionGet( @NonNull FirestorePigeonFirebaseApp app, @NonNull String transactionId, @NonNull String path, - @NonNull Result result); + @NonNull Result result); void documentReferenceSet( @NonNull FirestorePigeonFirebaseApp app, @NonNull DocumentReferenceRequest request, - @NonNull Result result); + @NonNull VoidResult result); void documentReferenceUpdate( @NonNull FirestorePigeonFirebaseApp app, @NonNull DocumentReferenceRequest request, - @NonNull Result result); + @NonNull VoidResult result); void documentReferenceGet( @NonNull FirestorePigeonFirebaseApp app, @NonNull DocumentReferenceRequest request, - @NonNull Result result); + @NonNull Result result); void documentReferenceDelete( @NonNull FirestorePigeonFirebaseApp app, @NonNull DocumentReferenceRequest request, - @NonNull Result result); + @NonNull VoidResult result); void queryGet( @NonNull FirestorePigeonFirebaseApp app, @NonNull String path, @NonNull Boolean isCollectionGroup, - @NonNull PigeonQueryParameters parameters, - @NonNull PigeonGetOptions options, - @NonNull Result result); + @NonNull InternalQueryParameters parameters, + @NonNull InternalGetOptions options, + @NonNull Result result); void aggregateQuery( @NonNull FirestorePigeonFirebaseApp app, @NonNull String path, - @NonNull PigeonQueryParameters parameters, + @NonNull InternalQueryParameters parameters, @NonNull AggregateSource source, @NonNull List queries, @NonNull Boolean isCollectionGroup, @@ -2012,15 +2611,15 @@ void aggregateQuery( void writeBatchCommit( @NonNull FirestorePigeonFirebaseApp app, - @NonNull List writes, - @NonNull Result result); + @NonNull List writes, + @NonNull VoidResult result); void querySnapshot( @NonNull FirestorePigeonFirebaseApp app, @NonNull String path, @NonNull Boolean isCollectionGroup, - @NonNull PigeonQueryParameters parameters, - @NonNull PigeonGetOptions options, + @NonNull InternalQueryParameters parameters, + @NonNull InternalGetOptions options, @NonNull Boolean includeMetadataChanges, @NonNull ListenSource source, @NonNull Result result); @@ -2035,34 +2634,43 @@ void documentReferenceSnapshot( void persistenceCacheIndexManagerRequest( @NonNull FirestorePigeonFirebaseApp app, @NonNull PersistenceCacheIndexManagerRequest request, - @NonNull Result result); + @NonNull VoidResult result); void executePipeline( @NonNull FirestorePigeonFirebaseApp app, @NonNull List> stages, @Nullable Map options, - @NonNull Result result); + @NonNull Result result); /** The codec used by FirebaseFirestoreHostApi. */ static @NonNull MessageCodec getCodec() { - return FirebaseFirestoreHostApiCodec.INSTANCE; + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `FirebaseFirestoreHostApi` to handle messages through the * `binaryMessenger`. */ - static void setup( + static void setUp( @NonNull BinaryMessenger binaryMessenger, @Nullable FirebaseFirestoreHostApi api) { + setUp(binaryMessenger, "", api); + } + + static void setUp( + @NonNull BinaryMessenger binaryMessenger, + @NonNull String messageChannelSuffix, + @Nullable FirebaseFirestoreHostApi api) { + messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix; { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); byte[] bundleArg = (byte[]) args.get(1); @@ -2089,19 +2697,20 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); String nameArg = (String) args.get(1); - PigeonGetOptions optionsArg = (PigeonGetOptions) args.get(2); - Result resultCallback = - new Result() { - public void success(PigeonQuerySnapshot result) { + InternalGetOptions optionsArg = (InternalGetOptions) args.get(2); + Result resultCallback = + new Result() { + public void success(InternalQuerySnapshot result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2122,17 +2731,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2153,17 +2763,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2184,17 +2795,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2215,17 +2827,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2246,17 +2859,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2277,18 +2891,19 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); String indexConfigurationArg = (String) args.get(1); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2309,17 +2924,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; Boolean loggingEnabledArg = (Boolean) args.get(0); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2340,12 +2956,13 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); Result resultCallback = @@ -2371,16 +2988,17 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); - Number timeoutArg = (Number) args.get(1); - Number maxAttemptsArg = (Number) args.get(2); + Long timeoutArg = (Long) args.get(1); + Long maxAttemptsArg = (Long) args.get(2); Result resultCallback = new Result() { public void success(String result) { @@ -2394,11 +3012,7 @@ public void error(Throwable error) { } }; - api.transactionCreate( - appArg, - (timeoutArg == null) ? null : timeoutArg.longValue(), - (maxAttemptsArg == null) ? null : maxAttemptsArg.longValue(), - resultCallback); + api.transactionCreate(appArg, timeoutArg, maxAttemptsArg, resultCallback); }); } else { channel.setMessageHandler(null); @@ -2408,21 +3022,21 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; String transactionIdArg = (String) args.get(0); - PigeonTransactionResult resultTypeArg = - PigeonTransactionResult.values()[(int) args.get(1)]; - List commandsArg = - (List) args.get(2); - Result resultCallback = - new Result() { - public void success(Void result) { + InternalTransactionResult resultTypeArg = (InternalTransactionResult) args.get(1); + List commandsArg = + (List) args.get(2); + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2444,19 +3058,20 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); String transactionIdArg = (String) args.get(1); String pathArg = (String) args.get(2); - Result resultCallback = - new Result() { - public void success(PigeonDocumentSnapshot result) { + Result resultCallback = + new Result() { + public void success(InternalDocumentSnapshot result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2477,18 +3092,19 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); DocumentReferenceRequest requestArg = (DocumentReferenceRequest) args.get(1); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2509,18 +3125,19 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); DocumentReferenceRequest requestArg = (DocumentReferenceRequest) args.get(1); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2541,18 +3158,19 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); DocumentReferenceRequest requestArg = (DocumentReferenceRequest) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonDocumentSnapshot result) { + Result resultCallback = + new Result() { + public void success(InternalDocumentSnapshot result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2573,18 +3191,19 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); DocumentReferenceRequest requestArg = (DocumentReferenceRequest) args.get(1); - Result resultCallback = - new Result() { - public void success(Void result) { + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2605,21 +3224,22 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); String pathArg = (String) args.get(1); Boolean isCollectionGroupArg = (Boolean) args.get(2); - PigeonQueryParameters parametersArg = (PigeonQueryParameters) args.get(3); - PigeonGetOptions optionsArg = (PigeonGetOptions) args.get(4); - Result resultCallback = - new Result() { - public void success(PigeonQuerySnapshot result) { + InternalQueryParameters parametersArg = (InternalQueryParameters) args.get(3); + InternalGetOptions optionsArg = (InternalGetOptions) args.get(4); + Result resultCallback = + new Result() { + public void success(InternalQuerySnapshot result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2646,17 +3266,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); String pathArg = (String) args.get(1); - PigeonQueryParameters parametersArg = (PigeonQueryParameters) args.get(2); - AggregateSource sourceArg = AggregateSource.values()[(int) args.get(3)]; + InternalQueryParameters parametersArg = (InternalQueryParameters) args.get(2); + AggregateSource sourceArg = (AggregateSource) args.get(3); List queriesArg = (List) args.get(4); Boolean isCollectionGroupArg = (Boolean) args.get(5); Result> resultCallback = @@ -2689,19 +3310,20 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); - List writesArg = - (List) args.get(1); - Result resultCallback = - new Result() { - public void success(Void result) { + List writesArg = + (List) args.get(1); + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2722,20 +3344,21 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); String pathArg = (String) args.get(1); Boolean isCollectionGroupArg = (Boolean) args.get(2); - PigeonQueryParameters parametersArg = (PigeonQueryParameters) args.get(3); - PigeonGetOptions optionsArg = (PigeonGetOptions) args.get(4); + InternalQueryParameters parametersArg = (InternalQueryParameters) args.get(3); + InternalGetOptions optionsArg = (InternalGetOptions) args.get(4); Boolean includeMetadataChangesArg = (Boolean) args.get(5); - ListenSource sourceArg = ListenSource.values()[(int) args.get(6)]; + ListenSource sourceArg = (ListenSource) args.get(6); Result resultCallback = new Result() { public void success(String result) { @@ -2767,17 +3390,18 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); DocumentReferenceRequest parametersArg = (DocumentReferenceRequest) args.get(1); Boolean includeMetadataChangesArg = (Boolean) args.get(2); - ListenSource sourceArg = ListenSource.values()[(int) args.get(3)]; + ListenSource sourceArg = (ListenSource) args.get(3); Result resultCallback = new Result() { public void success(String result) { @@ -2802,19 +3426,20 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); PersistenceCacheIndexManagerRequest requestArg = - PersistenceCacheIndexManagerRequest.values()[(int) args.get(1)]; - Result resultCallback = - new Result() { - public void success(Void result) { + (PersistenceCacheIndexManagerRequest) args.get(1); + VoidResult resultCallback = + new VoidResult() { + public void success() { wrapped.add(0, null); reply.reply(wrapped); } @@ -2835,19 +3460,20 @@ public void error(Throwable error) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, - "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline", + "dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline" + + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; FirestorePigeonFirebaseApp appArg = (FirestorePigeonFirebaseApp) args.get(0); List> stagesArg = (List>) args.get(1); Map optionsArg = (Map) args.get(2); - Result resultCallback = - new Result() { - public void success(PigeonPipelineSnapshot result) { + Result resultCallback = + new Result() { + public void success(InternalPipelineSnapshot result) { wrapped.add(0, result); reply.reply(wrapped); } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/DocumentSnapshotsStreamHandler.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/DocumentSnapshotsStreamHandler.java index 270966a3176e..b2e1245d2e87 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/DocumentSnapshotsStreamHandler.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/DocumentSnapshotsStreamHandler.java @@ -62,9 +62,13 @@ public void onListen(Object arguments, EventSink events) { onCancel(null); } else { + // Emit the Pigeon object directly; the Pigeon-aware codec on the + // MessageChannel serializes it end-to-end. Pigeon 26 no longer flattens + // nested types via `.toList()`, so calling `.toList()` here would send a + // raw list that the Dart side can no longer decode. events.success( - PigeonParser.toPigeonDocumentSnapshot(documentSnapshot, serverTimestampBehavior) - .toList()); + PigeonParser.toPigeonDocumentSnapshot( + documentSnapshot, serverTimestampBehavior)); } }); } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/OnTransactionResultListener.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/OnTransactionResultListener.java index 665858ec6290..e0974cad01e0 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/OnTransactionResultListener.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/OnTransactionResultListener.java @@ -12,6 +12,6 @@ /** callback when a transaction result has been computed. */ public interface OnTransactionResultListener { void receiveTransactionResponse( - GeneratedAndroidFirebaseFirestore.PigeonTransactionResult resultType, - List commands); + GeneratedAndroidFirebaseFirestore.InternalTransactionResult resultType, + List commands); } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java index c48f3941d8ca..e0fe62b31ec7 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java @@ -8,7 +8,6 @@ import static io.flutter.plugins.firebase.firestore.FlutterFirebaseFirestorePlugin.DEFAULT_ERROR_CODE; -import com.google.firebase.firestore.DocumentChange; import com.google.firebase.firestore.DocumentSnapshot; import com.google.firebase.firestore.ListenSource; import com.google.firebase.firestore.ListenerRegistration; @@ -19,7 +18,6 @@ import io.flutter.plugin.common.EventChannel.StreamHandler; import io.flutter.plugins.firebase.firestore.utils.ExceptionConverter; import io.flutter.plugins.firebase.firestore.utils.PigeonParser; -import java.util.ArrayList; import java.util.Map; public class QuerySnapshotsStreamHandler implements StreamHandler { @@ -61,28 +59,12 @@ public void onListen(Object arguments, EventSink events) { onCancel(null); } else { - ArrayList toListResult = new ArrayList(3); - ArrayList documents = - new ArrayList(querySnapshot.getDocuments().size()); - ArrayList documentChanges = - new ArrayList(querySnapshot.getDocumentChanges().size()); - for (DocumentSnapshot documentSnapshot : querySnapshot.getDocuments()) { - documents.add( - PigeonParser.toPigeonDocumentSnapshot( - documentSnapshot, serverTimestampBehavior) - .toList()); - } - for (DocumentChange documentChange : querySnapshot.getDocumentChanges()) { - documentChanges.add( - PigeonParser.toPigeonDocumentChange(documentChange, serverTimestampBehavior) - .toList()); - } - toListResult.add(documents); - toListResult.add(documentChanges); - toListResult.add( - PigeonParser.toPigeonSnapshotMetadata(querySnapshot.getMetadata()).toList()); - - events.success(toListResult); + // Emit the Pigeon object directly; the Pigeon-aware codec serializes + // nested `InternalDocumentSnapshot` / `InternalDocumentChange` / + // `InternalSnapshotMetadata` with their proper type codes. Pigeon 26 + // no longer flattens nested types via `.toList()`. + events.success( + PigeonParser.toPigeonQuerySnapshot(querySnapshot, serverTimestampBehavior)); } }); } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/TransactionStreamHandler.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/TransactionStreamHandler.java index 67c6c1fac5bb..32f16bc2555b 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/TransactionStreamHandler.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/TransactionStreamHandler.java @@ -59,8 +59,8 @@ public TransactionStreamHandler( } final Semaphore semaphore = new Semaphore(0); - private GeneratedAndroidFirebaseFirestore.PigeonTransactionResult resultType; - private List commands; + private GeneratedAndroidFirebaseFirestore.InternalTransactionResult resultType; + private List commands; final Handler mainLooper = new Handler(Looper.getMainLooper()); @@ -91,11 +91,13 @@ public void onListen(Object arguments, EventSink events) { return FlutterFirebaseFirestoreTransactionResult.complete(); } - if (resultType == GeneratedAndroidFirebaseFirestore.PigeonTransactionResult.FAILURE) { + if (resultType + == GeneratedAndroidFirebaseFirestore.InternalTransactionResult.FAILURE) { return FlutterFirebaseFirestoreTransactionResult.complete(); } - for (GeneratedAndroidFirebaseFirestore.PigeonTransactionCommand command : commands) { + for (GeneratedAndroidFirebaseFirestore.InternalTransactionCommand command : + commands) { DocumentReference documentReference = firestore.document(command.getPath()); switch (command.getType()) { @@ -129,7 +131,7 @@ public void onListen(Object arguments, EventSink events) { } case SET: { - GeneratedAndroidFirebaseFirestore.PigeonDocumentOption options = + GeneratedAndroidFirebaseFirestore.InternalDocumentOption options = Objects.requireNonNull(command.getOption()); SetOptions setOptions = null; @@ -187,8 +189,8 @@ public void onCancel(Object arguments) { @Override public void receiveTransactionResponse( - GeneratedAndroidFirebaseFirestore.PigeonTransactionResult resultType, - List commands) { + GeneratedAndroidFirebaseFirestore.InternalTransactionResult resultType, + List commands) { this.resultType = resultType; this.commands = commands; semaphore.release(); diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExceptionConverter.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExceptionConverter.java index 49fb299dd04d..a7538cd73bfb 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExceptionConverter.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExceptionConverter.java @@ -63,4 +63,14 @@ public static void sendErrorToFlutter( exception != null ? exception.getMessage() : null, exceptionDetails)); } + + public static void sendErrorToFlutter( + GeneratedAndroidFirebaseFirestore.VoidResult result, Exception exception) { + Map exceptionDetails = ExceptionConverter.createDetails(exception); + result.error( + new GeneratedAndroidFirebaseFirestore.FlutterError( + DEFAULT_ERROR_CODE, + exception != null ? exception.getMessage() : null, + exceptionDetails)); + } } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java index 84ca398a85f3..305a62120f8b 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java @@ -56,11 +56,11 @@ public static DocumentSnapshot.ServerTimestampBehavior parsePigeonServerTimestam } } - public static GeneratedAndroidFirebaseFirestore.PigeonQuerySnapshot toPigeonQuerySnapshot( + public static GeneratedAndroidFirebaseFirestore.InternalQuerySnapshot toPigeonQuerySnapshot( com.google.firebase.firestore.QuerySnapshot querySnapshot, DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior) { - GeneratedAndroidFirebaseFirestore.PigeonQuerySnapshot.Builder pigeonQuerySnapshot = - new GeneratedAndroidFirebaseFirestore.PigeonQuerySnapshot.Builder(); + GeneratedAndroidFirebaseFirestore.InternalQuerySnapshot.Builder pigeonQuerySnapshot = + new GeneratedAndroidFirebaseFirestore.InternalQuerySnapshot.Builder(); pigeonQuerySnapshot.setMetadata(toPigeonSnapshotMetadata(querySnapshot.getMetadata())); pigeonQuerySnapshot.setDocumentChanges( toPigeonDocumentChanges(querySnapshot.getDocumentChanges(), serverTimestampBehavior)); @@ -69,20 +69,20 @@ public static GeneratedAndroidFirebaseFirestore.PigeonQuerySnapshot toPigeonQuer return pigeonQuerySnapshot.build(); } - public static GeneratedAndroidFirebaseFirestore.PigeonSnapshotMetadata toPigeonSnapshotMetadata( + public static GeneratedAndroidFirebaseFirestore.InternalSnapshotMetadata toPigeonSnapshotMetadata( com.google.firebase.firestore.SnapshotMetadata snapshotMetadata) { - GeneratedAndroidFirebaseFirestore.PigeonSnapshotMetadata.Builder pigeonSnapshotMetadata = - new GeneratedAndroidFirebaseFirestore.PigeonSnapshotMetadata.Builder(); + GeneratedAndroidFirebaseFirestore.InternalSnapshotMetadata.Builder pigeonSnapshotMetadata = + new GeneratedAndroidFirebaseFirestore.InternalSnapshotMetadata.Builder(); pigeonSnapshotMetadata.setHasPendingWrites(snapshotMetadata.hasPendingWrites()); pigeonSnapshotMetadata.setIsFromCache(snapshotMetadata.isFromCache()); return pigeonSnapshotMetadata.build(); } - public static List + public static List toPigeonDocumentChanges( List documentChanges, DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior) { - List pigeonDocumentChanges = + List pigeonDocumentChanges = new ArrayList<>(documentChanges.size()); for (com.google.firebase.firestore.DocumentChange documentChange : documentChanges) { pigeonDocumentChanges.add(toPigeonDocumentChange(documentChange, serverTimestampBehavior)); @@ -90,11 +90,11 @@ public static GeneratedAndroidFirebaseFirestore.PigeonSnapshotMetadata toPigeonS return pigeonDocumentChanges; } - public static GeneratedAndroidFirebaseFirestore.PigeonDocumentChange toPigeonDocumentChange( + public static GeneratedAndroidFirebaseFirestore.InternalDocumentChange toPigeonDocumentChange( com.google.firebase.firestore.DocumentChange documentChange, DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior) { - GeneratedAndroidFirebaseFirestore.PigeonDocumentChange.Builder pigeonDocumentChange = - new GeneratedAndroidFirebaseFirestore.PigeonDocumentChange.Builder(); + GeneratedAndroidFirebaseFirestore.InternalDocumentChange.Builder pigeonDocumentChange = + new GeneratedAndroidFirebaseFirestore.InternalDocumentChange.Builder(); pigeonDocumentChange.setType(toPigeonDocumentChangeType(documentChange.getType())); pigeonDocumentChange.setOldIndex((long) documentChange.getOldIndex()); pigeonDocumentChange.setNewIndex((long) documentChange.getNewIndex()); @@ -129,22 +129,22 @@ public static ListenSource parseListenSource( } } - public static GeneratedAndroidFirebaseFirestore.PigeonDocumentSnapshot toPigeonDocumentSnapshot( + public static GeneratedAndroidFirebaseFirestore.InternalDocumentSnapshot toPigeonDocumentSnapshot( com.google.firebase.firestore.DocumentSnapshot documentSnapshot, DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior) { - GeneratedAndroidFirebaseFirestore.PigeonDocumentSnapshot.Builder pigeonDocumentSnapshot = - new GeneratedAndroidFirebaseFirestore.PigeonDocumentSnapshot.Builder(); + GeneratedAndroidFirebaseFirestore.InternalDocumentSnapshot.Builder pigeonDocumentSnapshot = + new GeneratedAndroidFirebaseFirestore.InternalDocumentSnapshot.Builder(); pigeonDocumentSnapshot.setMetadata(toPigeonSnapshotMetadata(documentSnapshot.getMetadata())); pigeonDocumentSnapshot.setData(documentSnapshot.getData(serverTimestampBehavior)); pigeonDocumentSnapshot.setPath(documentSnapshot.getReference().getPath()); return pigeonDocumentSnapshot.build(); } - public static List + public static List toPigeonDocumentSnapshots( List documentSnapshots, DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior) { - List pigeonDocumentSnapshots = + List pigeonDocumentSnapshots = new ArrayList<>(documentSnapshots.size()); for (com.google.firebase.firestore.DocumentSnapshot documentSnapshot : documentSnapshots) { pigeonDocumentSnapshots.add( @@ -165,7 +165,7 @@ public static Query parseQuery( FirebaseFirestore firestore, @NonNull String path, boolean isCollectionGroup, - GeneratedAndroidFirebaseFirestore.PigeonQueryParameters parameters) { + GeneratedAndroidFirebaseFirestore.InternalQueryParameters parameters) { try { Query query; if (isCollectionGroup) { diff --git a/packages/cloud_firestore/cloud_firestore/example/android/app/build.gradle b/packages/cloud_firestore/cloud_firestore/example/android/app/build.gradle index cf782a8a5d88..b572f8ff646f 100644 --- a/packages/cloud_firestore/cloud_firestore/example/android/app/build.gradle +++ b/packages/cloud_firestore/cloud_firestore/example/android/app/build.gradle @@ -45,7 +45,7 @@ android { applicationId = "io.flutter.plugins.firebase.firestore.example" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdk = 23 + minSdkVersion = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutterVersionCode.toInteger() versionName = flutterVersionName diff --git a/packages/cloud_firestore/cloud_firestore/example/ios/Flutter/AppFrameworkInfo.plist b/packages/cloud_firestore/cloud_firestore/example/ios/Flutter/AppFrameworkInfo.plist index 7c5696400627..391a902b2beb 100644 --- a/packages/cloud_firestore/cloud_firestore/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/cloud_firestore/cloud_firestore/example/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 12.0 diff --git a/packages/cloud_firestore/cloud_firestore/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cloud_firestore/cloud_firestore/example/ios/Runner.xcodeproj/project.pbxproj index cd6121c60ef7..9ded141d1e15 100644 --- a/packages/cloud_firestore/cloud_firestore/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cloud_firestore/cloud_firestore/example/ios/Runner.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A2D71CA981BE46B8B7F14013 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; E8EC7192C60686BF1D599360 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -68,6 +69,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, diff --git a/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/project.pbxproj index 38a0d1b5c6cf..16ab9abc74ca 100644 --- a/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 7C6B704452E88DBDC96F005F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1127055D8A6FA8F8B81D64A8 /* Pods_Runner.framework */; }; F086503D2C16E7BB001AC8E8 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F086503C2C16E7BB001AC8E8 /* GoogleService-Info.plist */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -85,6 +86,7 @@ 8075C6E6575C8FD1BB2ACCEE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; F086503C2C16E7BB001AC8E8 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -99,6 +101,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, 7C6B704452E88DBDC96F005F /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -160,6 +163,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -222,6 +226,9 @@ productType = "com.apple.product-type.bundle.unit-test"; }; 33CC10EC2044A3C60003C045 /* Runner */ = { + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( @@ -248,6 +255,9 @@ /* Begin PBXProject section */ 33CC10E52044A3C60003C045 /* Project object */ = { + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + ); isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; @@ -784,6 +794,18 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15368eccb25a..ee5d00fc0aa9 100644 --- a/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/cloud_firestore/cloud_firestore/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + diff --git a/packages/cloud_firestore/cloud_firestore/example/macos/Runner/AppDelegate.swift b/packages/cloud_firestore/cloud_firestore/example/macos/Runner/AppDelegate.swift index 8e02df288835..b3c176141221 100644 --- a/packages/cloud_firestore/cloud_firestore/example/macos/Runner/AppDelegate.swift +++ b/packages/cloud_firestore/cloud_firestore/example/macos/Runner/AppDelegate.swift @@ -6,4 +6,8 @@ class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTDocumentSnapshotStreamHandler.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTDocumentSnapshotStreamHandler.m index a787f8ad92b9..e8119c70d761 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTDocumentSnapshotStreamHandler.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTDocumentSnapshotStreamHandler.m @@ -55,9 +55,11 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments }); } else { dispatch_async(dispatch_get_main_queue(), ^{ - events( - [[FirestorePigeonParser toPigeonDocumentSnapshot:snapshot - serverTimestampBehavior:self.serverTimestampBehavior] toList]); + // Emit the Pigeon object directly; the Pigeon-aware codec on the + // MessageChannel serializes it end-to-end. Pigeon 26 no longer flattens + // nested types via `toList`. + events([FirestorePigeonParser toPigeonDocumentSnapshot:snapshot + serverTimestampBehavior:self.serverTimestampBehavior]); }); } }; diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m index ab826056264f..66ca1c3a12ac 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTFirebaseFirestorePlugin.m @@ -21,6 +21,14 @@ #import "include/cloud_firestore/Private/FLTTransactionStreamHandler.h" #import "include/cloud_firestore/Private/FirestorePigeonParser.h" #import "include/cloud_firestore/Public/FLTFirebaseFirestorePlugin.h" +#import "include/cloud_firestore/Public/FirestoreMessages.g.h" + +// Forward-declare the Pigeon-generated reader/writer defined in +// `FirestoreMessages.g.m`. It bundles `FLTFirebaseFirestoreReader/Writer` with +// Pigeon type serialization, so it's safe to use on the plugin's method/event +// channels. +@interface FirebaseFirestoreHostApiCodecReaderWriter : FlutterStandardReaderWriter +@end NSString *const kFLTFirebaseFirestoreChannelName = @"plugins.flutter.io/firebase_firestore"; NSString *const kFLTFirebaseFirestoreQuerySnapshotEventChannelName = @@ -106,8 +114,13 @@ @implementation FLTFirebaseFirestorePlugin { } + (void)initialize { - _codec = - [FlutterStandardMethodCodec codecWithReaderWriter:[FLTFirebaseFirestoreReaderWriter new]]; + // Use the Pigeon-generated reader/writer for MethodChannel/EventChannels so + // Pigeon types emitted by stream handlers (e.g. `InternalDocumentSnapshot`, + // `InternalSnapshotMetadata`) serialize correctly. The reader/writer extend + // `FLTFirebaseFirestoreReader/Writer`, so Firestore-specific types + // (Timestamp, GeoPoint, FieldValue, ...) still round-trip. + _codec = [FlutterStandardMethodCodec + codecWithReaderWriter:[[FirebaseFirestoreHostApiCodecReaderWriter alloc] init]]; } #pragma mark - FlutterPlugin @@ -151,7 +164,7 @@ + (void)registerWithRegistrar:(NSObject *)registrar { #else [registrar publish:instance]; #endif - FirebaseFirestoreHostApiSetup(registrar.messenger, instance); + SetUpFirebaseFirestoreHostApi(registrar.messenger, instance); } - (void)cleanupEventListeners { @@ -353,7 +366,7 @@ - (void)terminate:(id)arguments withMethodCallResult:(FLTFirebaseMethodCallResul - (void)documentReferenceGetApp:(nonnull FirestorePigeonFirebaseApp *)app request:(nonnull DocumentReferenceRequest *)request - completion:(nonnull void (^)(PigeonDocumentSnapshot *_Nullable, + completion:(nonnull void (^)(InternalDocumentSnapshot *_Nullable, FlutterError *_Nullable))completion { FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; FIRDocumentReference *document = [firestore documentWithPath:request.path]; @@ -402,7 +415,7 @@ - (void)documentReferenceSetApp:(nonnull FirestorePigeonFirebaseApp *)app - (void)documentReferenceSnapshotApp:(nonnull FirestorePigeonFirebaseApp *)app parameters:(nonnull DocumentReferenceRequest *)parameters - includeMetadataChanges:(nonnull NSNumber *)includeMetadataChanges + includeMetadataChanges:(BOOL)includeMetadataChanges source:(ListenSource)source completion:(nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { @@ -418,7 +431,6 @@ - (void)documentReferenceSnapshotApp:(nonnull FirestorePigeonFirebaseApp *)app initWithFirestore:firestore reference:document includeMetadataChanges:includeMetadataChanges - .boolValue serverTimestampBehavior:serverTimestampBehavior source:listenSource]], nil); @@ -467,8 +479,8 @@ - (void)loadBundleApp:(nonnull FirestorePigeonFirebaseApp *)app - (void)namedQueryGetApp:(nonnull FirestorePigeonFirebaseApp *)app name:(nonnull NSString *)name - options:(nonnull PigeonGetOptions *)options - completion:(nonnull void (^)(PigeonQuerySnapshot *_Nullable, + options:(nonnull InternalGetOptions *)options + completion:(nonnull void (^)(InternalQuerySnapshot *_Nullable, FlutterError *_Nullable))completion { FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; @@ -505,16 +517,16 @@ - (void)namedQueryGetApp:(nonnull FirestorePigeonFirebaseApp *)app - (void)queryGetApp:(nonnull FirestorePigeonFirebaseApp *)app path:(nonnull NSString *)path - isCollectionGroup:(nonnull NSNumber *)isCollectionGroup - parameters:(nonnull PigeonQueryParameters *)parameters - options:(nonnull PigeonGetOptions *)options - completion:(nonnull void (^)(PigeonQuerySnapshot *_Nullable, + isCollectionGroup:(BOOL)isCollectionGroup + parameters:(nonnull InternalQueryParameters *)parameters + options:(nonnull InternalGetOptions *)options + completion:(nonnull void (^)(InternalQuerySnapshot *_Nullable, FlutterError *_Nullable))completion { FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; FIRQuery *query = [FirestorePigeonParser parseQueryWithParameters:parameters firestore:firestore path:path - isCollectionGroup:[isCollectionGroup boolValue]]; + isCollectionGroup:isCollectionGroup]; if (query == nil) { completion(nil, [FlutterError errorWithCode:@"error-parsing" message:@"An error occurred while parsing query arguments, " @@ -542,10 +554,10 @@ - (void)queryGetApp:(nonnull FirestorePigeonFirebaseApp *)app - (void)querySnapshotApp:(nonnull FirestorePigeonFirebaseApp *)app path:(nonnull NSString *)path - isCollectionGroup:(nonnull NSNumber *)isCollectionGroup - parameters:(nonnull PigeonQueryParameters *)parameters - options:(nonnull PigeonGetOptions *)options - includeMetadataChanges:(nonnull NSNumber *)includeMetadataChanges + isCollectionGroup:(BOOL)isCollectionGroup + parameters:(nonnull InternalQueryParameters *)parameters + options:(nonnull InternalGetOptions *)options + includeMetadataChanges:(BOOL)includeMetadataChanges source:(ListenSource)source completion: (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { @@ -553,7 +565,7 @@ - (void)querySnapshotApp:(nonnull FirestorePigeonFirebaseApp *)app FIRQuery *query = [FirestorePigeonParser parseQueryWithParameters:parameters firestore:firestore path:path - isCollectionGroup:[isCollectionGroup boolValue]]; + isCollectionGroup:isCollectionGroup]; if (query == nil) { completion(nil, [FlutterError errorWithCode:@"error-parsing" message:@"An error occurred while parsing query arguments, " @@ -572,7 +584,6 @@ - (void)querySnapshotApp:(nonnull FirestorePigeonFirebaseApp *)app initWithFirestore:firestore query:query includeMetadataChanges:includeMetadataChanges - .boolValue serverTimestampBehavior:serverTimestampBehavior source:listenSource]], nil); @@ -618,9 +629,9 @@ - (void)persistenceCacheIndexManagerRequestApp:(FirestorePigeonFirebaseApp *)app completion(nil); } -- (void)setLoggingEnabledLoggingEnabled:(nonnull NSNumber *)loggingEnabled +- (void)setLoggingEnabledLoggingEnabled:(BOOL)loggingEnabled completion:(nonnull void (^)(FlutterError *_Nullable))completion { - [FIRFirestore enableLogging:[loggingEnabled boolValue]]; + [FIRFirestore enableLogging:loggingEnabled]; completion(nil); } @@ -643,7 +654,7 @@ - (void)terminateApp:(nonnull FirestorePigeonFirebaseApp *)app - (void)transactionGetApp:(nonnull FirestorePigeonFirebaseApp *)app transactionId:(nonnull NSString *)transactionId path:(nonnull NSString *)path - completion:(nonnull void (^)(PigeonDocumentSnapshot *_Nullable, + completion:(nonnull void (^)(InternalDocumentSnapshot *_Nullable, FlutterError *_Nullable))completion { // Dispatching to main thread allow us to ensure that the auth token are fetched in time // for the transaction @@ -680,8 +691,9 @@ - (void)transactionGetApp:(nonnull FirestorePigeonFirebaseApp *)app } - (void)transactionStoreResultTransactionId:(nonnull NSString *)transactionId - resultType:(PigeonTransactionResult)resultType - commands:(nullable NSArray *)commands + resultType:(InternalTransactionResult)resultType + commands: + (nullable NSArray *)commands completion:(nonnull void (^)(FlutterError *_Nullable))completion { [_transactionHandlers[transactionId] receiveTransactionResponse:resultType commands:commands]; @@ -701,26 +713,26 @@ - (void)waitForPendingWritesApp:(nonnull FirestorePigeonFirebaseApp *)app } - (void)writeBatchCommitApp:(nonnull FirestorePigeonFirebaseApp *)app - writes:(nonnull NSArray *)writes + writes:(nonnull NSArray *)writes completion:(nonnull void (^)(FlutterError *_Nullable))completion { FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; FIRWriteBatch *batch = [firestore batch]; - for (PigeonTransactionCommand *write in writes) { - PigeonTransactionType type = write.type; + for (InternalTransactionCommand *write in writes) { + InternalTransactionType type = write.type; NSString *path = write.path; FIRDocumentReference *reference = [firestore documentWithPath:path]; switch (type) { - case PigeonTransactionTypeGet: + case InternalTransactionTypeGet: break; - case PigeonTransactionTypeDeleteType: + case InternalTransactionTypeDeleteType: [batch deleteDocument:reference]; break; - case PigeonTransactionTypeUpdate: + case InternalTransactionTypeUpdate: [batch updateData:write.data forDocument:reference]; break; - case PigeonTransactionTypeSet: + case InternalTransactionTypeSet: if ([write.option.merge isEqual:@YES]) { [batch setData:write.data forDocument:reference merge:YES]; } else if (write.option.mergeFields) { @@ -756,8 +768,8 @@ - (void)snapshotsInSyncSetupApp:(nonnull FirestorePigeonFirebaseApp *)app } - (void)transactionCreateApp:(nonnull FirestorePigeonFirebaseApp *)app - timeout:(nonnull NSNumber *)timeout - maxAttempts:(nonnull NSNumber *)maxAttempts + timeout:(NSInteger)timeout + maxAttempts:(NSInteger)maxAttempts completion: (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; @@ -786,10 +798,10 @@ - (void)transactionCreateApp:(nonnull FirestorePigeonFirebaseApp *)app - (void)aggregateQueryApp:(nonnull FirestorePigeonFirebaseApp *)app path:(nonnull NSString *)path - parameters:(nonnull PigeonQueryParameters *)parameters + parameters:(nonnull InternalQueryParameters *)parameters source:(AggregateSource)source queries:(nonnull NSArray *)queries - isCollectionGroup:(NSNumber *)isCollectionGroup + isCollectionGroup:(BOOL)isCollectionGroup completion:(nonnull void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion { FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; @@ -797,7 +809,7 @@ - (void)aggregateQueryApp:(nonnull FirestorePigeonFirebaseApp *)app FIRQuery *query = [FirestorePigeonParser parseQueryWithParameters:parameters firestore:firestore path:path - isCollectionGroup:[isCollectionGroup boolValue]]; + isCollectionGroup:isCollectionGroup]; if (query == nil) { completion(nil, [FlutterError errorWithCode:@"error-parsing" message:@"An error occurred while parsing query arguments, " @@ -901,7 +913,7 @@ - (void)aggregateQueryApp:(nonnull FirestorePigeonFirebaseApp *)app - (void)executePipelineApp:(nonnull FirestorePigeonFirebaseApp *)app stages:(nonnull NSArray *> *)stages options:(nullable NSDictionary *)options - completion:(nonnull void (^)(PigeonPipelineSnapshot *_Nullable, + completion:(nonnull void (^)(InternalPipelineSnapshot *_Nullable, FlutterError *_Nullable))completion { FIRFirestore *firestore = [self getFIRFirestoreFromAppNameFromPigeon:app]; @@ -923,7 +935,7 @@ - (void)executePipelineApp:(nonnull FirestorePigeonFirebaseApp *)app return; } - NSMutableArray *pigeonResults = + NSMutableArray *pigeonResults = [NSMutableArray array]; NSArray *results = [snapshot results]; if ([results isKindOfClass:[NSArray class]]) { @@ -937,11 +949,11 @@ - (void)executePipelineApp:(nonnull FirestorePigeonFirebaseApp *)app NSNumber *updateTime = FLTPipelineTimestampToMs([result valueForKey:@"update_time"]); NSDictionary *data = FLTPipelineNullSafe([result data]); - PigeonPipelineResult *pigeonResult = - [PigeonPipelineResult makeWithDocumentPath:path - createTime:createTime - updateTime:updateTime - data:data]; + InternalPipelineResult *pigeonResult = + [InternalPipelineResult makeWithDocumentPath:path + createTime:createTime + updateTime:updateTime + data:data]; [pigeonResults addObject:pigeonResult]; } } @@ -953,9 +965,9 @@ - (void)executePipelineApp:(nonnull FirestorePigeonFirebaseApp *)app @((int64_t)([[NSDate date] timeIntervalSince1970] * 1000)); } - PigeonPipelineSnapshot *pigeonSnapshot = - [PigeonPipelineSnapshot makeWithResults:pigeonResults - executionTime:executionTime]; + InternalPipelineSnapshot *pigeonSnapshot = [InternalPipelineSnapshot + makeWithResults:pigeonResults + executionTime:[executionTime longLongValue]]; completion(pigeonSnapshot, nil); }]; } diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m index bb80a2d6e69e..b90ee46db10a 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m @@ -65,32 +65,12 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments }); } else { dispatch_async(dispatch_get_main_queue(), ^{ - NSMutableArray *toListResult = [[NSMutableArray alloc] initWithCapacity:3]; - - NSMutableArray *documents = - [[NSMutableArray alloc] initWithCapacity:snapshot.documents.count]; - NSMutableArray *documentChanges = - [[NSMutableArray alloc] initWithCapacity:snapshot.documentChanges.count]; - - for (FIRDocumentSnapshot *documentSnapshot in snapshot.documents) { - [documents addObject:[[FirestorePigeonParser - toPigeonDocumentSnapshot:documentSnapshot - serverTimestampBehavior:self.serverTimestampBehavior] toList]]; - } - - for (FIRDocumentChange *documentChange in snapshot.documentChanges) { - [documentChanges - addObject:[[FirestorePigeonParser toPigeonDocumentChange:documentChange - serverTimestampBehavior:self.serverTimestampBehavior] - toList]]; - } - - [toListResult addObject:documents]; - [toListResult addObject:documentChanges]; - [toListResult - addObject:[[FirestorePigeonParser toPigeonSnapshotMetadata:snapshot.metadata] toList]]; - - events(toListResult); + // Emit the Pigeon object directly; the Pigeon-aware codec serializes nested + // `InternalDocumentSnapshot` / `InternalDocumentChange` / `InternalSnapshotMetadata` + // with their proper type codes. Pigeon 26 no longer flattens nested types + // via `toList`. + events([FirestorePigeonParser toPigeonQuerySnapshot:snapshot + serverTimestampBehavior:self.serverTimestampBehavior]); }); } }; diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTTransactionStreamHandler.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTTransactionStreamHandler.m index 29252ca4821c..8cd347b0b269 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTTransactionStreamHandler.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTTransactionStreamHandler.m @@ -17,8 +17,8 @@ @interface FLTTransactionStreamHandler () @property(nonatomic, copy, nonnull) void (^started)(FIRTransaction *); @property(nonatomic, copy, nonnull) void (^ended)(void); @property(strong) dispatch_semaphore_t semaphore; -@property PigeonTransactionResult resultType; -@property NSArray *commands; +@property InternalTransactionResult resultType; +@property NSArray *commands; @end @@ -28,8 +28,8 @@ @implementation FLTTransactionStreamHandler { - (instancetype)initWithId:(NSString *)transactionId firestore:(FIRFirestore *)firestore - timeout:(nonnull NSNumber *)timeout - maxAttempts:(nonnull NSNumber *)maxAttempts + timeout:(NSInteger)timeout + maxAttempts:(NSInteger)maxAttempts started:(void (^)(FIRTransaction *))startedListener ended:(void (^)(void))endedListener { self = [super init]; @@ -60,8 +60,7 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments }); long timedOut = dispatch_semaphore_wait( - strongSelf.semaphore, - dispatch_time(DISPATCH_TIME_NOW, [self.timeout integerValue] * NSEC_PER_MSEC)); + strongSelf.semaphore, dispatch_time(DISPATCH_TIME_NOW, self.timeout * NSEC_PER_MSEC)); if (timedOut) { NSArray *codeAndMessage = [FLTFirebaseFirestoreUtils @@ -80,24 +79,24 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments }); } - if (self.resultType == PigeonTransactionResultFailure) { + if (self.resultType == InternalTransactionResultFailure) { // Do nothing - already handled in Dart land. return nil; } - for (PigeonTransactionCommand *command in self.commands) { - PigeonTransactionType commandType = command.type; + for (InternalTransactionCommand *command in self.commands) { + InternalTransactionType commandType = command.type; NSString *documentPath = command.path; FIRDocumentReference *reference = [self.firestore documentWithPath:documentPath]; switch (commandType) { - case PigeonTransactionTypeDeleteType: + case InternalTransactionTypeDeleteType: [transaction deleteDocument:reference]; break; - case PigeonTransactionTypeUpdate: + case InternalTransactionTypeUpdate: [transaction updateData:command.data forDocument:reference]; break; - case PigeonTransactionTypeSet: + case InternalTransactionTypeSet: if ([command.option.merge isEqual:@YES]) { [transaction setData:command.data forDocument:reference merge:YES]; } else if (command.option.mergeFields) { @@ -142,7 +141,7 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments strongSelf.ended(); }; FIRTransactionOptions *options = [[FIRTransactionOptions alloc] init]; - options.maxAttempts = _maxAttempts.integerValue; + options.maxAttempts = _maxAttempts; [_firestore runTransactionWithOptions:options block:transactionRunBlock @@ -157,8 +156,8 @@ - (FlutterError *_Nullable)onCancelWithArguments:(id _Nullable)arguments { return nil; } -- (void)receiveTransactionResponse:(PigeonTransactionResult)resultType - commands:(NSArray *)commands { +- (void)receiveTransactionResponse:(InternalTransactionResult)resultType + commands:(NSArray *)commands { self.resultType = resultType; self.commands = commands; diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m index 891377333685..f9594c6e943f 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestoreMessages.g.m @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #import "FirestoreMessages.g.h" @@ -9,14 +9,115 @@ #import "FLTFirebaseFirestoreWriter.h" #if TARGET_OS_OSX -#import +@import FlutterMacOS; #else -#import +@import Flutter; #endif -#if !__has_feature(objc_arc) -#error File requires ARC to be enabled. -#endif +static BOOL __attribute__((unused)) FLTPigeonDeepEquals(id _Nullable a, id _Nullable b) { + if (a == b) { + return YES; + } + if (a == nil) { + return b == [NSNull null]; + } + if (b == nil) { + return a == [NSNull null]; + } + if ([a isKindOfClass:[NSNumber class]] && [b isKindOfClass:[NSNumber class]]) { + return + [a isEqual:b] || (isnan([(NSNumber *)a doubleValue]) && isnan([(NSNumber *)b doubleValue])); + } + if ([a isKindOfClass:[NSArray class]] && [b isKindOfClass:[NSArray class]]) { + NSArray *arrayA = (NSArray *)a; + NSArray *arrayB = (NSArray *)b; + if (arrayA.count != arrayB.count) { + return NO; + } + for (NSUInteger i = 0; i < arrayA.count; i++) { + if (!FLTPigeonDeepEquals(arrayA[i], arrayB[i])) { + return NO; + } + } + return YES; + } + if ([a isKindOfClass:[NSDictionary class]] && [b isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictA = (NSDictionary *)a; + NSDictionary *dictB = (NSDictionary *)b; + if (dictA.count != dictB.count) { + return NO; + } + for (id keyA in dictA) { + id valueA = dictA[keyA]; + BOOL found = NO; + for (id keyB in dictB) { + if (FLTPigeonDeepEquals(keyA, keyB)) { + id valueB = dictB[keyB]; + if (FLTPigeonDeepEquals(valueA, valueB)) { + found = YES; + break; + } else { + return NO; + } + } + } + if (!found) { + return NO; + } + } + return YES; + } + return [a isEqual:b]; +} + +static NSUInteger __attribute__((unused)) FLTPigeonDeepHash(id _Nullable value) { + if (value == nil || value == (id)[NSNull null]) { + return 0; + } + if ([value isKindOfClass:[NSNumber class]]) { + NSNumber *n = (NSNumber *)value; + double d = n.doubleValue; + if (isnan(d)) { + // Normalize NaN to a consistent hash. + return (NSUInteger)0x7FF8000000000000; + } + if (d == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + d = 0.0; + } + return @(d).hash; + } + if ([value isKindOfClass:[NSArray class]]) { + NSUInteger result = 1; + for (id item in (NSArray *)value) { + result = result * 31 + FLTPigeonDeepHash(item); + } + return result; + } + if ([value isKindOfClass:[NSDictionary class]]) { + NSUInteger result = 0; + NSDictionary *dict = (NSDictionary *)value; + for (id key in dict) { + result += ((FLTPigeonDeepHash(key) * 31) ^ FLTPigeonDeepHash(dict[key])); + } + return result; + } + return [value hash]; +} + +static NSArray *wrapResult(id result, FlutterError *error) { + if (error) { + return @[ + error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] + ]; + } + return @[ result ?: [NSNull null] ]; +} + +static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { + id result = array[key]; + return (result == [NSNull null]) ? nil : result; +} /// An enumeration of document change types. @implementation DocumentChangeTypeBox @@ -89,8 +190,8 @@ - (instancetype)initWithValue:(PersistenceCacheIndexManagerRequest)value { } @end -@implementation PigeonTransactionResultBox -- (instancetype)initWithValue:(PigeonTransactionResult)value { +@implementation InternalTransactionResultBox +- (instancetype)initWithValue:(InternalTransactionResult)value { self = [super init]; if (self) { _value = value; @@ -99,8 +200,8 @@ - (instancetype)initWithValue:(PigeonTransactionResult)value { } @end -@implementation PigeonTransactionTypeBox -- (instancetype)initWithValue:(PigeonTransactionType)value { +@implementation InternalTransactionTypeBox +- (instancetype)initWithValue:(InternalTransactionType)value { self = [super init]; if (self) { _value = value; @@ -119,116 +220,103 @@ - (instancetype)initWithValue:(AggregateType)value { } @end -static NSArray *wrapResult(id result, FlutterError *error) { - if (error) { - return @[ - error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] - ]; - } - return @[ result ?: [NSNull null] ]; -} -static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { - id result = array[key]; - return (result == [NSNull null]) ? nil : result; -} - -@interface PigeonFirebaseSettings () -+ (PigeonFirebaseSettings *)fromList:(NSArray *)list; -+ (nullable PigeonFirebaseSettings *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalFirebaseSettings () ++ (InternalFirebaseSettings *)fromList:(NSArray *)list; ++ (nullable InternalFirebaseSettings *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end @interface FirestorePigeonFirebaseApp () -+ (FirestorePigeonFirebaseApp *)fromList:(NSArray *)list; -+ (nullable FirestorePigeonFirebaseApp *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; ++ (FirestorePigeonFirebaseApp *)fromList:(NSArray *)list; ++ (nullable FirestorePigeonFirebaseApp *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonSnapshotMetadata () -+ (PigeonSnapshotMetadata *)fromList:(NSArray *)list; -+ (nullable PigeonSnapshotMetadata *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalSnapshotMetadata () ++ (InternalSnapshotMetadata *)fromList:(NSArray *)list; ++ (nullable InternalSnapshotMetadata *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonDocumentSnapshot () -+ (PigeonDocumentSnapshot *)fromList:(NSArray *)list; -+ (nullable PigeonDocumentSnapshot *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalDocumentSnapshot () ++ (InternalDocumentSnapshot *)fromList:(NSArray *)list; ++ (nullable InternalDocumentSnapshot *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonDocumentChange () -+ (PigeonDocumentChange *)fromList:(NSArray *)list; -+ (nullable PigeonDocumentChange *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalDocumentChange () ++ (InternalDocumentChange *)fromList:(NSArray *)list; ++ (nullable InternalDocumentChange *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonQuerySnapshot () -+ (PigeonQuerySnapshot *)fromList:(NSArray *)list; -+ (nullable PigeonQuerySnapshot *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalQuerySnapshot () ++ (InternalQuerySnapshot *)fromList:(NSArray *)list; ++ (nullable InternalQuerySnapshot *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonPipelineResult () -+ (PigeonPipelineResult *)fromList:(NSArray *)list; -+ (nullable PigeonPipelineResult *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalPipelineResult () ++ (InternalPipelineResult *)fromList:(NSArray *)list; ++ (nullable InternalPipelineResult *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonPipelineSnapshot () -+ (PigeonPipelineSnapshot *)fromList:(NSArray *)list; -+ (nullable PigeonPipelineSnapshot *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalPipelineSnapshot () ++ (InternalPipelineSnapshot *)fromList:(NSArray *)list; ++ (nullable InternalPipelineSnapshot *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonGetOptions () -+ (PigeonGetOptions *)fromList:(NSArray *)list; -+ (nullable PigeonGetOptions *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalGetOptions () ++ (InternalGetOptions *)fromList:(NSArray *)list; ++ (nullable InternalGetOptions *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonDocumentOption () -+ (PigeonDocumentOption *)fromList:(NSArray *)list; -+ (nullable PigeonDocumentOption *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalDocumentOption () ++ (InternalDocumentOption *)fromList:(NSArray *)list; ++ (nullable InternalDocumentOption *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonTransactionCommand () -+ (PigeonTransactionCommand *)fromList:(NSArray *)list; -+ (nullable PigeonTransactionCommand *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalTransactionCommand () ++ (InternalTransactionCommand *)fromList:(NSArray *)list; ++ (nullable InternalTransactionCommand *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end @interface DocumentReferenceRequest () -+ (DocumentReferenceRequest *)fromList:(NSArray *)list; -+ (nullable DocumentReferenceRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; ++ (DocumentReferenceRequest *)fromList:(NSArray *)list; ++ (nullable DocumentReferenceRequest *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonQueryParameters () -+ (PigeonQueryParameters *)fromList:(NSArray *)list; -+ (nullable PigeonQueryParameters *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalQueryParameters () ++ (InternalQueryParameters *)fromList:(NSArray *)list; ++ (nullable InternalQueryParameters *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end @interface AggregateQuery () -+ (AggregateQuery *)fromList:(NSArray *)list; -+ (nullable AggregateQuery *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; ++ (AggregateQuery *)fromList:(NSArray *)list; ++ (nullable AggregateQuery *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end @interface AggregateQueryResponse () -+ (AggregateQueryResponse *)fromList:(NSArray *)list; -+ (nullable AggregateQueryResponse *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; ++ (AggregateQueryResponse *)fromList:(NSArray *)list; ++ (nullable AggregateQueryResponse *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@implementation PigeonFirebaseSettings +@implementation InternalFirebaseSettings + (instancetype)makeWithPersistenceEnabled:(nullable NSNumber *)persistenceEnabled host:(nullable NSString *)host sslEnabled:(nullable NSNumber *)sslEnabled cacheSizeBytes:(nullable NSNumber *)cacheSizeBytes - ignoreUndefinedProperties:(NSNumber *)ignoreUndefinedProperties { - PigeonFirebaseSettings *pigeonResult = [[PigeonFirebaseSettings alloc] init]; + ignoreUndefinedProperties:(BOOL)ignoreUndefinedProperties { + InternalFirebaseSettings *pigeonResult = [[InternalFirebaseSettings alloc] init]; pigeonResult.persistenceEnabled = persistenceEnabled; pigeonResult.host = host; pigeonResult.sslEnabled = sslEnabled; @@ -236,33 +324,56 @@ + (instancetype)makeWithPersistenceEnabled:(nullable NSNumber *)persistenceEnabl pigeonResult.ignoreUndefinedProperties = ignoreUndefinedProperties; return pigeonResult; } -+ (PigeonFirebaseSettings *)fromList:(NSArray *)list { - PigeonFirebaseSettings *pigeonResult = [[PigeonFirebaseSettings alloc] init]; ++ (InternalFirebaseSettings *)fromList:(NSArray *)list { + InternalFirebaseSettings *pigeonResult = [[InternalFirebaseSettings alloc] init]; pigeonResult.persistenceEnabled = GetNullableObjectAtIndex(list, 0); pigeonResult.host = GetNullableObjectAtIndex(list, 1); pigeonResult.sslEnabled = GetNullableObjectAtIndex(list, 2); pigeonResult.cacheSizeBytes = GetNullableObjectAtIndex(list, 3); - pigeonResult.ignoreUndefinedProperties = GetNullableObjectAtIndex(list, 4); - NSAssert(pigeonResult.ignoreUndefinedProperties != nil, @""); + pigeonResult.ignoreUndefinedProperties = [GetNullableObjectAtIndex(list, 4) boolValue]; return pigeonResult; } -+ (nullable PigeonFirebaseSettings *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonFirebaseSettings fromList:list] : nil; ++ (nullable InternalFirebaseSettings *)nullableFromList:(NSArray *)list { + return (list) ? [InternalFirebaseSettings fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.persistenceEnabled ?: [NSNull null]), - (self.host ?: [NSNull null]), - (self.sslEnabled ?: [NSNull null]), - (self.cacheSizeBytes ?: [NSNull null]), - (self.ignoreUndefinedProperties ?: [NSNull null]), + self.persistenceEnabled ?: [NSNull null], + self.host ?: [NSNull null], + self.sslEnabled ?: [NSNull null], + self.cacheSizeBytes ?: [NSNull null], + @(self.ignoreUndefinedProperties), ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalFirebaseSettings *other = (InternalFirebaseSettings *)object; + return FLTPigeonDeepEquals(self.persistenceEnabled, other.persistenceEnabled) && + FLTPigeonDeepEquals(self.host, other.host) && + FLTPigeonDeepEquals(self.sslEnabled, other.sslEnabled) && + FLTPigeonDeepEquals(self.cacheSizeBytes, other.cacheSizeBytes) && + self.ignoreUndefinedProperties == other.ignoreUndefinedProperties; +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.persistenceEnabled); + result = result * 31 + FLTPigeonDeepHash(self.host); + result = result * 31 + FLTPigeonDeepHash(self.sslEnabled); + result = result * 31 + FLTPigeonDeepHash(self.cacheSizeBytes); + result = result * 31 + @(self.ignoreUndefinedProperties).hash; + return result; +} @end @implementation FirestorePigeonFirebaseApp + (instancetype)makeWithAppName:(NSString *)appName - settings:(PigeonFirebaseSettings *)settings + settings:(InternalFirebaseSettings *)settings databaseURL:(NSString *)databaseURL { FirestorePigeonFirebaseApp *pigeonResult = [[FirestorePigeonFirebaseApp alloc] init]; pigeonResult.appName = appName; @@ -270,306 +381,482 @@ + (instancetype)makeWithAppName:(NSString *)appName pigeonResult.databaseURL = databaseURL; return pigeonResult; } -+ (FirestorePigeonFirebaseApp *)fromList:(NSArray *)list { ++ (FirestorePigeonFirebaseApp *)fromList:(NSArray *)list { FirestorePigeonFirebaseApp *pigeonResult = [[FirestorePigeonFirebaseApp alloc] init]; pigeonResult.appName = GetNullableObjectAtIndex(list, 0); - NSAssert(pigeonResult.appName != nil, @""); - pigeonResult.settings = - [PigeonFirebaseSettings nullableFromList:(GetNullableObjectAtIndex(list, 1))]; - NSAssert(pigeonResult.settings != nil, @""); + pigeonResult.settings = GetNullableObjectAtIndex(list, 1); pigeonResult.databaseURL = GetNullableObjectAtIndex(list, 2); - NSAssert(pigeonResult.databaseURL != nil, @""); return pigeonResult; } -+ (nullable FirestorePigeonFirebaseApp *)nullableFromList:(NSArray *)list { ++ (nullable FirestorePigeonFirebaseApp *)nullableFromList:(NSArray *)list { return (list) ? [FirestorePigeonFirebaseApp fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.appName ?: [NSNull null]), - (self.settings ? [self.settings toList] : [NSNull null]), - (self.databaseURL ?: [NSNull null]), + self.appName ?: [NSNull null], + self.settings ?: [NSNull null], + self.databaseURL ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + FirestorePigeonFirebaseApp *other = (FirestorePigeonFirebaseApp *)object; + return FLTPigeonDeepEquals(self.appName, other.appName) && + FLTPigeonDeepEquals(self.settings, other.settings) && + FLTPigeonDeepEquals(self.databaseURL, other.databaseURL); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.appName); + result = result * 31 + FLTPigeonDeepHash(self.settings); + result = result * 31 + FLTPigeonDeepHash(self.databaseURL); + return result; +} @end -@implementation PigeonSnapshotMetadata -+ (instancetype)makeWithHasPendingWrites:(NSNumber *)hasPendingWrites - isFromCache:(NSNumber *)isFromCache { - PigeonSnapshotMetadata *pigeonResult = [[PigeonSnapshotMetadata alloc] init]; +@implementation InternalSnapshotMetadata ++ (instancetype)makeWithHasPendingWrites:(BOOL)hasPendingWrites isFromCache:(BOOL)isFromCache { + InternalSnapshotMetadata *pigeonResult = [[InternalSnapshotMetadata alloc] init]; pigeonResult.hasPendingWrites = hasPendingWrites; pigeonResult.isFromCache = isFromCache; return pigeonResult; } -+ (PigeonSnapshotMetadata *)fromList:(NSArray *)list { - PigeonSnapshotMetadata *pigeonResult = [[PigeonSnapshotMetadata alloc] init]; - pigeonResult.hasPendingWrites = GetNullableObjectAtIndex(list, 0); - NSAssert(pigeonResult.hasPendingWrites != nil, @""); - pigeonResult.isFromCache = GetNullableObjectAtIndex(list, 1); - NSAssert(pigeonResult.isFromCache != nil, @""); ++ (InternalSnapshotMetadata *)fromList:(NSArray *)list { + InternalSnapshotMetadata *pigeonResult = [[InternalSnapshotMetadata alloc] init]; + pigeonResult.hasPendingWrites = [GetNullableObjectAtIndex(list, 0) boolValue]; + pigeonResult.isFromCache = [GetNullableObjectAtIndex(list, 1) boolValue]; return pigeonResult; } -+ (nullable PigeonSnapshotMetadata *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonSnapshotMetadata fromList:list] : nil; ++ (nullable InternalSnapshotMetadata *)nullableFromList:(NSArray *)list { + return (list) ? [InternalSnapshotMetadata fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.hasPendingWrites ?: [NSNull null]), - (self.isFromCache ?: [NSNull null]), + @(self.hasPendingWrites), + @(self.isFromCache), ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalSnapshotMetadata *other = (InternalSnapshotMetadata *)object; + return self.hasPendingWrites == other.hasPendingWrites && self.isFromCache == other.isFromCache; +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.hasPendingWrites).hash; + result = result * 31 + @(self.isFromCache).hash; + return result; +} @end -@implementation PigeonDocumentSnapshot +@implementation InternalDocumentSnapshot + (instancetype)makeWithPath:(NSString *)path data:(nullable NSDictionary *)data - metadata:(PigeonSnapshotMetadata *)metadata { - PigeonDocumentSnapshot *pigeonResult = [[PigeonDocumentSnapshot alloc] init]; + metadata:(InternalSnapshotMetadata *)metadata { + InternalDocumentSnapshot *pigeonResult = [[InternalDocumentSnapshot alloc] init]; pigeonResult.path = path; pigeonResult.data = data; pigeonResult.metadata = metadata; return pigeonResult; } -+ (PigeonDocumentSnapshot *)fromList:(NSArray *)list { - PigeonDocumentSnapshot *pigeonResult = [[PigeonDocumentSnapshot alloc] init]; ++ (InternalDocumentSnapshot *)fromList:(NSArray *)list { + InternalDocumentSnapshot *pigeonResult = [[InternalDocumentSnapshot alloc] init]; pigeonResult.path = GetNullableObjectAtIndex(list, 0); - NSAssert(pigeonResult.path != nil, @""); pigeonResult.data = GetNullableObjectAtIndex(list, 1); - pigeonResult.metadata = - [PigeonSnapshotMetadata nullableFromList:(GetNullableObjectAtIndex(list, 2))]; - NSAssert(pigeonResult.metadata != nil, @""); + pigeonResult.metadata = GetNullableObjectAtIndex(list, 2); return pigeonResult; } -+ (nullable PigeonDocumentSnapshot *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonDocumentSnapshot fromList:list] : nil; ++ (nullable InternalDocumentSnapshot *)nullableFromList:(NSArray *)list { + return (list) ? [InternalDocumentSnapshot fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.path ?: [NSNull null]), - (self.data ?: [NSNull null]), - (self.metadata ? [self.metadata toList] : [NSNull null]), + self.path ?: [NSNull null], + self.data ?: [NSNull null], + self.metadata ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalDocumentSnapshot *other = (InternalDocumentSnapshot *)object; + return FLTPigeonDeepEquals(self.path, other.path) && FLTPigeonDeepEquals(self.data, other.data) && + FLTPigeonDeepEquals(self.metadata, other.metadata); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.path); + result = result * 31 + FLTPigeonDeepHash(self.data); + result = result * 31 + FLTPigeonDeepHash(self.metadata); + return result; +} @end -@implementation PigeonDocumentChange +@implementation InternalDocumentChange + (instancetype)makeWithType:(DocumentChangeType)type - document:(PigeonDocumentSnapshot *)document - oldIndex:(NSNumber *)oldIndex - newIndex:(NSNumber *)newIndex { - PigeonDocumentChange *pigeonResult = [[PigeonDocumentChange alloc] init]; + document:(InternalDocumentSnapshot *)document + oldIndex:(NSInteger)oldIndex + newIndex:(NSInteger)newIndex { + InternalDocumentChange *pigeonResult = [[InternalDocumentChange alloc] init]; pigeonResult.type = type; pigeonResult.document = document; pigeonResult.oldIndex = oldIndex; - pigeonResult.index = newIndex; + pigeonResult.newIndex = newIndex; return pigeonResult; } -+ (PigeonDocumentChange *)fromList:(NSArray *)list { - PigeonDocumentChange *pigeonResult = [[PigeonDocumentChange alloc] init]; - pigeonResult.type = [GetNullableObjectAtIndex(list, 0) integerValue]; - pigeonResult.document = - [PigeonDocumentSnapshot nullableFromList:(GetNullableObjectAtIndex(list, 1))]; - NSAssert(pigeonResult.document != nil, @""); - pigeonResult.oldIndex = GetNullableObjectAtIndex(list, 2); - NSAssert(pigeonResult.oldIndex != nil, @""); - pigeonResult.index = GetNullableObjectAtIndex(list, 3); - NSAssert(pigeonResult.index != nil, @""); ++ (InternalDocumentChange *)fromList:(NSArray *)list { + InternalDocumentChange *pigeonResult = [[InternalDocumentChange alloc] init]; + DocumentChangeTypeBox *boxedDocumentChangeType = GetNullableObjectAtIndex(list, 0); + pigeonResult.type = boxedDocumentChangeType.value; + pigeonResult.document = GetNullableObjectAtIndex(list, 1); + pigeonResult.oldIndex = [GetNullableObjectAtIndex(list, 2) integerValue]; + pigeonResult.newIndex = [GetNullableObjectAtIndex(list, 3) integerValue]; return pigeonResult; } -+ (nullable PigeonDocumentChange *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonDocumentChange fromList:list] : nil; ++ (nullable InternalDocumentChange *)nullableFromList:(NSArray *)list { + return (list) ? [InternalDocumentChange fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - @(self.type), - (self.document ? [self.document toList] : [NSNull null]), - (self.oldIndex ?: [NSNull null]), - (self.index ?: [NSNull null]), + [[DocumentChangeTypeBox alloc] initWithValue:self.type], + self.document ?: [NSNull null], + @(self.oldIndex), + @(self.newIndex), ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalDocumentChange *other = (InternalDocumentChange *)object; + return self.type == other.type && FLTPigeonDeepEquals(self.document, other.document) && + self.oldIndex == other.oldIndex && self.newIndex == other.newIndex; +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.type).hash; + result = result * 31 + FLTPigeonDeepHash(self.document); + result = result * 31 + @(self.oldIndex).hash; + result = result * 31 + @(self.newIndex).hash; + return result; +} @end -@implementation PigeonQuerySnapshot -+ (instancetype)makeWithDocuments:(NSArray *)documents - documentChanges:(NSArray *)documentChanges - metadata:(PigeonSnapshotMetadata *)metadata { - PigeonQuerySnapshot *pigeonResult = [[PigeonQuerySnapshot alloc] init]; +@implementation InternalQuerySnapshot ++ (instancetype)makeWithDocuments:(NSArray *)documents + documentChanges:(NSArray *)documentChanges + metadata:(InternalSnapshotMetadata *)metadata { + InternalQuerySnapshot *pigeonResult = [[InternalQuerySnapshot alloc] init]; pigeonResult.documents = documents; pigeonResult.documentChanges = documentChanges; pigeonResult.metadata = metadata; return pigeonResult; } -+ (PigeonQuerySnapshot *)fromList:(NSArray *)list { - PigeonQuerySnapshot *pigeonResult = [[PigeonQuerySnapshot alloc] init]; ++ (InternalQuerySnapshot *)fromList:(NSArray *)list { + InternalQuerySnapshot *pigeonResult = [[InternalQuerySnapshot alloc] init]; pigeonResult.documents = GetNullableObjectAtIndex(list, 0); - NSAssert(pigeonResult.documents != nil, @""); pigeonResult.documentChanges = GetNullableObjectAtIndex(list, 1); - NSAssert(pigeonResult.documentChanges != nil, @""); - pigeonResult.metadata = - [PigeonSnapshotMetadata nullableFromList:(GetNullableObjectAtIndex(list, 2))]; - NSAssert(pigeonResult.metadata != nil, @""); + pigeonResult.metadata = GetNullableObjectAtIndex(list, 2); return pigeonResult; } -+ (nullable PigeonQuerySnapshot *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonQuerySnapshot fromList:list] : nil; ++ (nullable InternalQuerySnapshot *)nullableFromList:(NSArray *)list { + return (list) ? [InternalQuerySnapshot fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.documents ?: [NSNull null]), - (self.documentChanges ?: [NSNull null]), - (self.metadata ? [self.metadata toList] : [NSNull null]), + self.documents ?: [NSNull null], + self.documentChanges ?: [NSNull null], + self.metadata ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalQuerySnapshot *other = (InternalQuerySnapshot *)object; + return FLTPigeonDeepEquals(self.documents, other.documents) && + FLTPigeonDeepEquals(self.documentChanges, other.documentChanges) && + FLTPigeonDeepEquals(self.metadata, other.metadata); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.documents); + result = result * 31 + FLTPigeonDeepHash(self.documentChanges); + result = result * 31 + FLTPigeonDeepHash(self.metadata); + return result; +} @end -@implementation PigeonPipelineResult +@implementation InternalPipelineResult + (instancetype)makeWithDocumentPath:(nullable NSString *)documentPath createTime:(nullable NSNumber *)createTime updateTime:(nullable NSNumber *)updateTime data:(nullable NSDictionary *)data { - PigeonPipelineResult *pigeonResult = [[PigeonPipelineResult alloc] init]; + InternalPipelineResult *pigeonResult = [[InternalPipelineResult alloc] init]; pigeonResult.documentPath = documentPath; pigeonResult.createTime = createTime; pigeonResult.updateTime = updateTime; pigeonResult.data = data; return pigeonResult; } -+ (PigeonPipelineResult *)fromList:(NSArray *)list { - PigeonPipelineResult *pigeonResult = [[PigeonPipelineResult alloc] init]; ++ (InternalPipelineResult *)fromList:(NSArray *)list { + InternalPipelineResult *pigeonResult = [[InternalPipelineResult alloc] init]; pigeonResult.documentPath = GetNullableObjectAtIndex(list, 0); pigeonResult.createTime = GetNullableObjectAtIndex(list, 1); pigeonResult.updateTime = GetNullableObjectAtIndex(list, 2); pigeonResult.data = GetNullableObjectAtIndex(list, 3); return pigeonResult; } -+ (nullable PigeonPipelineResult *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonPipelineResult fromList:list] : nil; ++ (nullable InternalPipelineResult *)nullableFromList:(NSArray *)list { + return (list) ? [InternalPipelineResult fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.documentPath ?: [NSNull null]), - (self.createTime ?: [NSNull null]), - (self.updateTime ?: [NSNull null]), - (self.data ?: [NSNull null]), + self.documentPath ?: [NSNull null], + self.createTime ?: [NSNull null], + self.updateTime ?: [NSNull null], + self.data ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalPipelineResult *other = (InternalPipelineResult *)object; + return FLTPigeonDeepEquals(self.documentPath, other.documentPath) && + FLTPigeonDeepEquals(self.createTime, other.createTime) && + FLTPigeonDeepEquals(self.updateTime, other.updateTime) && + FLTPigeonDeepEquals(self.data, other.data); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.documentPath); + result = result * 31 + FLTPigeonDeepHash(self.createTime); + result = result * 31 + FLTPigeonDeepHash(self.updateTime); + result = result * 31 + FLTPigeonDeepHash(self.data); + return result; +} @end -@implementation PigeonPipelineSnapshot -+ (instancetype)makeWithResults:(NSArray *)results - executionTime:(NSNumber *)executionTime { - PigeonPipelineSnapshot *pigeonResult = [[PigeonPipelineSnapshot alloc] init]; +@implementation InternalPipelineSnapshot ++ (instancetype)makeWithResults:(NSArray *)results + executionTime:(NSInteger)executionTime { + InternalPipelineSnapshot *pigeonResult = [[InternalPipelineSnapshot alloc] init]; pigeonResult.results = results; pigeonResult.executionTime = executionTime; return pigeonResult; } -+ (PigeonPipelineSnapshot *)fromList:(NSArray *)list { - PigeonPipelineSnapshot *pigeonResult = [[PigeonPipelineSnapshot alloc] init]; ++ (InternalPipelineSnapshot *)fromList:(NSArray *)list { + InternalPipelineSnapshot *pigeonResult = [[InternalPipelineSnapshot alloc] init]; pigeonResult.results = GetNullableObjectAtIndex(list, 0); - NSAssert(pigeonResult.results != nil, @""); - pigeonResult.executionTime = GetNullableObjectAtIndex(list, 1); - NSAssert(pigeonResult.executionTime != nil, @""); + pigeonResult.executionTime = [GetNullableObjectAtIndex(list, 1) integerValue]; return pigeonResult; } -+ (nullable PigeonPipelineSnapshot *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonPipelineSnapshot fromList:list] : nil; ++ (nullable InternalPipelineSnapshot *)nullableFromList:(NSArray *)list { + return (list) ? [InternalPipelineSnapshot fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.results ?: [NSNull null]), - (self.executionTime ?: [NSNull null]), + self.results ?: [NSNull null], + @(self.executionTime), ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalPipelineSnapshot *other = (InternalPipelineSnapshot *)object; + return FLTPigeonDeepEquals(self.results, other.results) && + self.executionTime == other.executionTime; +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.results); + result = result * 31 + @(self.executionTime).hash; + return result; +} @end -@implementation PigeonGetOptions +@implementation InternalGetOptions + (instancetype)makeWithSource:(Source)source serverTimestampBehavior:(ServerTimestampBehavior)serverTimestampBehavior { - PigeonGetOptions *pigeonResult = [[PigeonGetOptions alloc] init]; + InternalGetOptions *pigeonResult = [[InternalGetOptions alloc] init]; pigeonResult.source = source; pigeonResult.serverTimestampBehavior = serverTimestampBehavior; return pigeonResult; } -+ (PigeonGetOptions *)fromList:(NSArray *)list { - PigeonGetOptions *pigeonResult = [[PigeonGetOptions alloc] init]; - pigeonResult.source = [GetNullableObjectAtIndex(list, 0) integerValue]; - pigeonResult.serverTimestampBehavior = [GetNullableObjectAtIndex(list, 1) integerValue]; ++ (InternalGetOptions *)fromList:(NSArray *)list { + InternalGetOptions *pigeonResult = [[InternalGetOptions alloc] init]; + SourceBox *boxedSource = GetNullableObjectAtIndex(list, 0); + pigeonResult.source = boxedSource.value; + ServerTimestampBehaviorBox *boxedServerTimestampBehavior = GetNullableObjectAtIndex(list, 1); + pigeonResult.serverTimestampBehavior = boxedServerTimestampBehavior.value; return pigeonResult; } -+ (nullable PigeonGetOptions *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonGetOptions fromList:list] : nil; ++ (nullable InternalGetOptions *)nullableFromList:(NSArray *)list { + return (list) ? [InternalGetOptions fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - @(self.source), - @(self.serverTimestampBehavior), + [[SourceBox alloc] initWithValue:self.source], + [[ServerTimestampBehaviorBox alloc] initWithValue:self.serverTimestampBehavior], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalGetOptions *other = (InternalGetOptions *)object; + return self.source == other.source && + self.serverTimestampBehavior == other.serverTimestampBehavior; +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.source).hash; + result = result * 31 + @(self.serverTimestampBehavior).hash; + return result; +} @end -@implementation PigeonDocumentOption +@implementation InternalDocumentOption + (instancetype)makeWithMerge:(nullable NSNumber *)merge mergeFields:(nullable NSArray *> *)mergeFields { - PigeonDocumentOption *pigeonResult = [[PigeonDocumentOption alloc] init]; + InternalDocumentOption *pigeonResult = [[InternalDocumentOption alloc] init]; pigeonResult.merge = merge; pigeonResult.mergeFields = mergeFields; return pigeonResult; } -+ (PigeonDocumentOption *)fromList:(NSArray *)list { - PigeonDocumentOption *pigeonResult = [[PigeonDocumentOption alloc] init]; ++ (InternalDocumentOption *)fromList:(NSArray *)list { + InternalDocumentOption *pigeonResult = [[InternalDocumentOption alloc] init]; pigeonResult.merge = GetNullableObjectAtIndex(list, 0); pigeonResult.mergeFields = GetNullableObjectAtIndex(list, 1); return pigeonResult; } -+ (nullable PigeonDocumentOption *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonDocumentOption fromList:list] : nil; ++ (nullable InternalDocumentOption *)nullableFromList:(NSArray *)list { + return (list) ? [InternalDocumentOption fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.merge ?: [NSNull null]), - (self.mergeFields ?: [NSNull null]), + self.merge ?: [NSNull null], + self.mergeFields ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalDocumentOption *other = (InternalDocumentOption *)object; + return FLTPigeonDeepEquals(self.merge, other.merge) && + FLTPigeonDeepEquals(self.mergeFields, other.mergeFields); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.merge); + result = result * 31 + FLTPigeonDeepHash(self.mergeFields); + return result; +} @end -@implementation PigeonTransactionCommand -+ (instancetype)makeWithType:(PigeonTransactionType)type +@implementation InternalTransactionCommand ++ (instancetype)makeWithType:(InternalTransactionType)type path:(NSString *)path data:(nullable NSDictionary *)data - option:(nullable PigeonDocumentOption *)option { - PigeonTransactionCommand *pigeonResult = [[PigeonTransactionCommand alloc] init]; + option:(nullable InternalDocumentOption *)option { + InternalTransactionCommand *pigeonResult = [[InternalTransactionCommand alloc] init]; pigeonResult.type = type; pigeonResult.path = path; pigeonResult.data = data; pigeonResult.option = option; return pigeonResult; } -+ (PigeonTransactionCommand *)fromList:(NSArray *)list { - PigeonTransactionCommand *pigeonResult = [[PigeonTransactionCommand alloc] init]; - pigeonResult.type = [GetNullableObjectAtIndex(list, 0) integerValue]; ++ (InternalTransactionCommand *)fromList:(NSArray *)list { + InternalTransactionCommand *pigeonResult = [[InternalTransactionCommand alloc] init]; + InternalTransactionTypeBox *boxedInternalTransactionType = GetNullableObjectAtIndex(list, 0); + pigeonResult.type = boxedInternalTransactionType.value; pigeonResult.path = GetNullableObjectAtIndex(list, 1); - NSAssert(pigeonResult.path != nil, @""); pigeonResult.data = GetNullableObjectAtIndex(list, 2); - pigeonResult.option = [PigeonDocumentOption nullableFromList:(GetNullableObjectAtIndex(list, 3))]; + pigeonResult.option = GetNullableObjectAtIndex(list, 3); return pigeonResult; } -+ (nullable PigeonTransactionCommand *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonTransactionCommand fromList:list] : nil; ++ (nullable InternalTransactionCommand *)nullableFromList:(NSArray *)list { + return (list) ? [InternalTransactionCommand fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - @(self.type), - (self.path ?: [NSNull null]), - (self.data ?: [NSNull null]), - (self.option ? [self.option toList] : [NSNull null]), + [[InternalTransactionTypeBox alloc] initWithValue:self.type], + self.path ?: [NSNull null], + self.data ?: [NSNull null], + self.option ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalTransactionCommand *other = (InternalTransactionCommand *)object; + return self.type == other.type && FLTPigeonDeepEquals(self.path, other.path) && + FLTPigeonDeepEquals(self.data, other.data) && + FLTPigeonDeepEquals(self.option, other.option); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.type).hash; + result = result * 31 + FLTPigeonDeepHash(self.path); + result = result * 31 + FLTPigeonDeepHash(self.data); + result = result * 31 + FLTPigeonDeepHash(self.option); + return result; +} @end @implementation DocumentReferenceRequest + (instancetype)makeWithPath:(NSString *)path data:(nullable NSDictionary *)data - option:(nullable PigeonDocumentOption *)option + option:(nullable InternalDocumentOption *)option source:(nullable SourceBox *)source serverTimestampBehavior:(nullable ServerTimestampBehaviorBox *)serverTimestampBehavior { DocumentReferenceRequest *pigeonResult = [[DocumentReferenceRequest alloc] init]; @@ -580,42 +867,53 @@ + (instancetype)makeWithPath:(NSString *)path pigeonResult.serverTimestampBehavior = serverTimestampBehavior; return pigeonResult; } -+ (DocumentReferenceRequest *)fromList:(NSArray *)list { ++ (DocumentReferenceRequest *)fromList:(NSArray *)list { DocumentReferenceRequest *pigeonResult = [[DocumentReferenceRequest alloc] init]; pigeonResult.path = GetNullableObjectAtIndex(list, 0); - NSAssert(pigeonResult.path != nil, @""); pigeonResult.data = GetNullableObjectAtIndex(list, 1); - pigeonResult.option = [PigeonDocumentOption nullableFromList:(GetNullableObjectAtIndex(list, 2))]; - NSNumber *sourceAsNumber = GetNullableObjectAtIndex(list, 3); - SourceBox *source = - sourceAsNumber == nil ? nil : [[SourceBox alloc] initWithValue:[sourceAsNumber integerValue]]; - pigeonResult.source = source; - NSNumber *serverTimestampBehaviorAsNumber = GetNullableObjectAtIndex(list, 4); - ServerTimestampBehaviorBox *serverTimestampBehavior = - serverTimestampBehaviorAsNumber == nil - ? nil - : [[ServerTimestampBehaviorBox alloc] - initWithValue:[serverTimestampBehaviorAsNumber integerValue]]; - pigeonResult.serverTimestampBehavior = serverTimestampBehavior; + pigeonResult.option = GetNullableObjectAtIndex(list, 2); + pigeonResult.source = GetNullableObjectAtIndex(list, 3); + pigeonResult.serverTimestampBehavior = GetNullableObjectAtIndex(list, 4); return pigeonResult; } -+ (nullable DocumentReferenceRequest *)nullableFromList:(NSArray *)list { ++ (nullable DocumentReferenceRequest *)nullableFromList:(NSArray *)list { return (list) ? [DocumentReferenceRequest fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.path ?: [NSNull null]), - (self.data ?: [NSNull null]), - (self.option ? [self.option toList] : [NSNull null]), - (self.source == nil ? [NSNull null] : [NSNumber numberWithInteger:self.source.value]), - (self.serverTimestampBehavior == nil - ? [NSNull null] - : [NSNumber numberWithInteger:self.serverTimestampBehavior.value]), + self.path ?: [NSNull null], + self.data ?: [NSNull null], + self.option ?: [NSNull null], + self.source ?: [NSNull null], + self.serverTimestampBehavior ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + DocumentReferenceRequest *other = (DocumentReferenceRequest *)object; + return FLTPigeonDeepEquals(self.path, other.path) && FLTPigeonDeepEquals(self.data, other.data) && + FLTPigeonDeepEquals(self.option, other.option) && + FLTPigeonDeepEquals(self.source, other.source) && + FLTPigeonDeepEquals(self.serverTimestampBehavior, other.serverTimestampBehavior); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.path); + result = result * 31 + FLTPigeonDeepHash(self.data); + result = result * 31 + FLTPigeonDeepHash(self.option); + result = result * 31 + FLTPigeonDeepHash(self.source); + result = result * 31 + FLTPigeonDeepHash(self.serverTimestampBehavior); + return result; +} @end -@implementation PigeonQueryParameters +@implementation InternalQueryParameters + (instancetype)makeWithWhere:(nullable NSArray *> *)where orderBy:(nullable NSArray *> *)orderBy limit:(nullable NSNumber *)limit @@ -625,7 +923,7 @@ + (instancetype)makeWithWhere:(nullable NSArray *> *)where endAt:(nullable NSArray *)endAt endBefore:(nullable NSArray *)endBefore filters:(nullable NSDictionary *)filters { - PigeonQueryParameters *pigeonResult = [[PigeonQueryParameters alloc] init]; + InternalQueryParameters *pigeonResult = [[InternalQueryParameters alloc] init]; pigeonResult.where = where; pigeonResult.orderBy = orderBy; pigeonResult.limit = limit; @@ -637,8 +935,8 @@ + (instancetype)makeWithWhere:(nullable NSArray *> *)where pigeonResult.filters = filters; return pigeonResult; } -+ (PigeonQueryParameters *)fromList:(NSArray *)list { - PigeonQueryParameters *pigeonResult = [[PigeonQueryParameters alloc] init]; ++ (InternalQueryParameters *)fromList:(NSArray *)list { + InternalQueryParameters *pigeonResult = [[InternalQueryParameters alloc] init]; pigeonResult.where = GetNullableObjectAtIndex(list, 0); pigeonResult.orderBy = GetNullableObjectAtIndex(list, 1); pigeonResult.limit = GetNullableObjectAtIndex(list, 2); @@ -650,22 +948,54 @@ + (PigeonQueryParameters *)fromList:(NSArray *)list { pigeonResult.filters = GetNullableObjectAtIndex(list, 8); return pigeonResult; } -+ (nullable PigeonQueryParameters *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonQueryParameters fromList:list] : nil; ++ (nullable InternalQueryParameters *)nullableFromList:(NSArray *)list { + return (list) ? [InternalQueryParameters fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - (self.where ?: [NSNull null]), - (self.orderBy ?: [NSNull null]), - (self.limit ?: [NSNull null]), - (self.limitToLast ?: [NSNull null]), - (self.startAt ?: [NSNull null]), - (self.startAfter ?: [NSNull null]), - (self.endAt ?: [NSNull null]), - (self.endBefore ?: [NSNull null]), - (self.filters ?: [NSNull null]), + self.where ?: [NSNull null], + self.orderBy ?: [NSNull null], + self.limit ?: [NSNull null], + self.limitToLast ?: [NSNull null], + self.startAt ?: [NSNull null], + self.startAfter ?: [NSNull null], + self.endAt ?: [NSNull null], + self.endBefore ?: [NSNull null], + self.filters ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalQueryParameters *other = (InternalQueryParameters *)object; + return FLTPigeonDeepEquals(self.where, other.where) && + FLTPigeonDeepEquals(self.orderBy, other.orderBy) && + FLTPigeonDeepEquals(self.limit, other.limit) && + FLTPigeonDeepEquals(self.limitToLast, other.limitToLast) && + FLTPigeonDeepEquals(self.startAt, other.startAt) && + FLTPigeonDeepEquals(self.startAfter, other.startAfter) && + FLTPigeonDeepEquals(self.endAt, other.endAt) && + FLTPigeonDeepEquals(self.endBefore, other.endBefore) && + FLTPigeonDeepEquals(self.filters, other.filters); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.where); + result = result * 31 + FLTPigeonDeepHash(self.orderBy); + result = result * 31 + FLTPigeonDeepHash(self.limit); + result = result * 31 + FLTPigeonDeepHash(self.limitToLast); + result = result * 31 + FLTPigeonDeepHash(self.startAt); + result = result * 31 + FLTPigeonDeepHash(self.startAfter); + result = result * 31 + FLTPigeonDeepHash(self.endAt); + result = result * 31 + FLTPigeonDeepHash(self.endBefore); + result = result * 31 + FLTPigeonDeepHash(self.filters); + return result; +} @end @implementation AggregateQuery @@ -675,21 +1005,39 @@ + (instancetype)makeWithType:(AggregateType)type field:(nullable NSString *)fiel pigeonResult.field = field; return pigeonResult; } -+ (AggregateQuery *)fromList:(NSArray *)list { ++ (AggregateQuery *)fromList:(NSArray *)list { AggregateQuery *pigeonResult = [[AggregateQuery alloc] init]; - pigeonResult.type = [GetNullableObjectAtIndex(list, 0) integerValue]; + AggregateTypeBox *boxedAggregateType = GetNullableObjectAtIndex(list, 0); + pigeonResult.type = boxedAggregateType.value; pigeonResult.field = GetNullableObjectAtIndex(list, 1); return pigeonResult; } -+ (nullable AggregateQuery *)nullableFromList:(NSArray *)list { ++ (nullable AggregateQuery *)nullableFromList:(NSArray *)list { return (list) ? [AggregateQuery fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - @(self.type), - (self.field ?: [NSNull null]), + [[AggregateTypeBox alloc] initWithValue:self.type], + self.field ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + AggregateQuery *other = (AggregateQuery *)object; + return self.type == other.type && FLTPigeonDeepEquals(self.field, other.field); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.type).hash; + result = result * 31 + FLTPigeonDeepHash(self.field); + return result; +} @end @implementation AggregateQueryResponse @@ -702,23 +1050,43 @@ + (instancetype)makeWithType:(AggregateType)type pigeonResult.value = value; return pigeonResult; } -+ (AggregateQueryResponse *)fromList:(NSArray *)list { ++ (AggregateQueryResponse *)fromList:(NSArray *)list { AggregateQueryResponse *pigeonResult = [[AggregateQueryResponse alloc] init]; - pigeonResult.type = [GetNullableObjectAtIndex(list, 0) integerValue]; + AggregateTypeBox *boxedAggregateType = GetNullableObjectAtIndex(list, 0); + pigeonResult.type = boxedAggregateType.value; pigeonResult.field = GetNullableObjectAtIndex(list, 1); pigeonResult.value = GetNullableObjectAtIndex(list, 2); return pigeonResult; } -+ (nullable AggregateQueryResponse *)nullableFromList:(NSArray *)list { ++ (nullable AggregateQueryResponse *)nullableFromList:(NSArray *)list { return (list) ? [AggregateQueryResponse fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - @(self.type), - (self.field ?: [NSNull null]), - (self.value ?: [NSNull null]), + [[AggregateTypeBox alloc] initWithValue:self.type], + self.field ?: [NSNull null], + self.value ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + AggregateQueryResponse *other = (AggregateQueryResponse *)object; + return self.type == other.type && FLTPigeonDeepEquals(self.field, other.field) && + FLTPigeonDeepEquals(self.value, other.value); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.type).hash; + result = result * 31 + FLTPigeonDeepHash(self.field); + result = result * 31 + FLTPigeonDeepHash(self.value); + return result; +} @end @interface FirebaseFirestoreHostApiCodecReader : FLTFirebaseFirestoreReader @@ -726,36 +1094,89 @@ @interface FirebaseFirestoreHostApiCodecReader : FLTFirebaseFirestoreReader @implementation FirebaseFirestoreHostApiCodecReader - (nullable id)readValueOfType:(UInt8)type { switch (type) { - case 128: - return [AggregateQuery fromList:[self readValue]]; - case 129: - return [AggregateQueryResponse fromList:[self readValue]]; - case 130: - return [DocumentReferenceRequest fromList:[self readValue]]; - case 131: - return [FirestorePigeonFirebaseApp fromList:[self readValue]]; - case 132: - return [PigeonDocumentChange fromList:[self readValue]]; - case 133: - return [PigeonDocumentOption fromList:[self readValue]]; - case 134: - return [PigeonDocumentSnapshot fromList:[self readValue]]; - case 135: - return [PigeonFirebaseSettings fromList:[self readValue]]; - case 136: - return [PigeonGetOptions fromList:[self readValue]]; - case 137: - return [PigeonPipelineResult fromList:[self readValue]]; + case 129: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[DocumentChangeTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 130: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil ? nil + : [[SourceBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 131: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[ListenSourceBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 132: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[ServerTimestampBehaviorBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 133: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[AggregateSourceBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 134: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil ? nil + : [[PersistenceCacheIndexManagerRequestBox alloc] + initWithValue:[enumAsNumber integerValue]]; + } + case 135: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[InternalTransactionResultBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 136: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[InternalTransactionTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + } + case 137: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[AggregateTypeBox alloc] initWithValue:[enumAsNumber integerValue]]; + } case 138: - return [PigeonPipelineSnapshot fromList:[self readValue]]; + return [InternalFirebaseSettings fromList:[self readValue]]; case 139: - return [PigeonQueryParameters fromList:[self readValue]]; + return [FirestorePigeonFirebaseApp fromList:[self readValue]]; case 140: - return [PigeonQuerySnapshot fromList:[self readValue]]; + return [InternalSnapshotMetadata fromList:[self readValue]]; case 141: - return [PigeonSnapshotMetadata fromList:[self readValue]]; + return [InternalDocumentSnapshot fromList:[self readValue]]; case 142: - return [PigeonTransactionCommand fromList:[self readValue]]; + return [InternalDocumentChange fromList:[self readValue]]; + case 143: + return [InternalQuerySnapshot fromList:[self readValue]]; + case 144: + return [InternalPipelineResult fromList:[self readValue]]; + case 145: + return [InternalPipelineSnapshot fromList:[self readValue]]; + case 146: + return [InternalGetOptions fromList:[self readValue]]; + case 147: + return [InternalDocumentOption fromList:[self readValue]]; + case 148: + return [InternalTransactionCommand fromList:[self readValue]]; + case 149: + return [DocumentReferenceRequest fromList:[self readValue]]; + case 150: + return [InternalQueryParameters fromList:[self readValue]]; + case 151: + return [AggregateQuery fromList:[self readValue]]; + case 152: + return [AggregateQueryResponse fromList:[self readValue]]; default: return [super readValueOfType:type]; } @@ -766,51 +1187,87 @@ @interface FirebaseFirestoreHostApiCodecWriter : FLTFirebaseFirestoreWriter @end @implementation FirebaseFirestoreHostApiCodecWriter - (void)writeValue:(id)value { - if ([value isKindOfClass:[AggregateQuery class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[AggregateQueryResponse class]]) { + if ([value isKindOfClass:[DocumentChangeTypeBox class]]) { + DocumentChangeTypeBox *box = (DocumentChangeTypeBox *)value; [self writeByte:129]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[DocumentReferenceRequest class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[SourceBox class]]) { + SourceBox *box = (SourceBox *)value; [self writeByte:130]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[FirestorePigeonFirebaseApp class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[ListenSourceBox class]]) { + ListenSourceBox *box = (ListenSourceBox *)value; [self writeByte:131]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonDocumentChange class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[ServerTimestampBehaviorBox class]]) { + ServerTimestampBehaviorBox *box = (ServerTimestampBehaviorBox *)value; [self writeByte:132]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonDocumentOption class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[AggregateSourceBox class]]) { + AggregateSourceBox *box = (AggregateSourceBox *)value; [self writeByte:133]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonDocumentSnapshot class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[PersistenceCacheIndexManagerRequestBox class]]) { + PersistenceCacheIndexManagerRequestBox *box = (PersistenceCacheIndexManagerRequestBox *)value; [self writeByte:134]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonFirebaseSettings class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[InternalTransactionResultBox class]]) { + InternalTransactionResultBox *box = (InternalTransactionResultBox *)value; [self writeByte:135]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonGetOptions class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[InternalTransactionTypeBox class]]) { + InternalTransactionTypeBox *box = (InternalTransactionTypeBox *)value; [self writeByte:136]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonPipelineResult class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[AggregateTypeBox class]]) { + AggregateTypeBox *box = (AggregateTypeBox *)value; [self writeByte:137]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonPipelineSnapshot class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[InternalFirebaseSettings class]]) { [self writeByte:138]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonQueryParameters class]]) { + } else if ([value isKindOfClass:[FirestorePigeonFirebaseApp class]]) { [self writeByte:139]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonQuerySnapshot class]]) { + } else if ([value isKindOfClass:[InternalSnapshotMetadata class]]) { [self writeByte:140]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonSnapshotMetadata class]]) { + } else if ([value isKindOfClass:[InternalDocumentSnapshot class]]) { [self writeByte:141]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonTransactionCommand class]]) { + } else if ([value isKindOfClass:[InternalDocumentChange class]]) { [self writeByte:142]; [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalQuerySnapshot class]]) { + [self writeByte:143]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalPipelineResult class]]) { + [self writeByte:144]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalPipelineSnapshot class]]) { + [self writeByte:145]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalGetOptions class]]) { + [self writeByte:146]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalDocumentOption class]]) { + [self writeByte:147]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalTransactionCommand class]]) { + [self writeByte:148]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[DocumentReferenceRequest class]]) { + [self writeByte:149]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalQueryParameters class]]) { + [self writeByte:150]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[AggregateQuery class]]) { + [self writeByte:151]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[AggregateQueryResponse class]]) { + [self writeByte:152]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } @@ -828,7 +1285,7 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { } @end -NSObject *FirebaseFirestoreHostApiGetCodec(void) { +NSObject *GetFirebaseFirestoreHostApiCodec(void) { static FlutterStandardMessageCodec *sSharedObject = nil; static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ @@ -838,22 +1295,32 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { }); return sSharedObject; } - -void FirebaseFirestoreHostApiSetup(id binaryMessenger, +void SetUpFirebaseFirestoreHostApi(id binaryMessenger, NSObject *api) { + SetUpFirebaseFirestoreHostApiWithSuffix(binaryMessenger, api, @""); +} + +void SetUpFirebaseFirestoreHostApiWithSuffix(id binaryMessenger, + NSObject *api, + NSString *messageChannelSuffix) { + messageChannelSuffix = messageChannelSuffix.length > 0 + ? [NSString stringWithFormat:@".%@", messageChannelSuffix] + : @""; { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.loadBundle" + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.loadBundle", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(loadBundleApp:bundle:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(loadBundleApp:bundle:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); FlutterStandardTypedData *arg_bundle = GetNullableObjectAtIndex(args, 1); [api loadBundleApp:arg_app @@ -868,24 +1335,27 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.namedQueryGet" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.namedQueryGet", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(namedQueryGetApp:name:options:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(namedQueryGetApp:name:options:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_name = GetNullableObjectAtIndex(args, 1); - PigeonGetOptions *arg_options = GetNullableObjectAtIndex(args, 2); + InternalGetOptions *arg_options = GetNullableObjectAtIndex(args, 2); [api namedQueryGetApp:arg_app name:arg_name options:arg_options - completion:^(PigeonQuerySnapshot *_Nullable output, + completion:^(InternalQuerySnapshot *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -896,17 +1366,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.clearPersistence" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.clearPersistence", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(clearPersistenceApp:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(clearPersistenceApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api clearPersistenceApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -919,17 +1392,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.disableNetwork" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.disableNetwork", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(disableNetworkApp:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(disableNetworkApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api disableNetworkApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -942,17 +1418,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.enableNetwork" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.enableNetwork", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(enableNetworkApp:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(enableNetworkApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api enableNetworkApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -965,17 +1444,19 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.terminate" + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.terminate", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(terminateApp:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(terminateApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api terminateApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -988,17 +1469,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.waitForPendingWrites" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.waitForPendingWrites", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(waitForPendingWritesApp:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(waitForPendingWritesApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api waitForPendingWritesApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -1011,10 +1495,13 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.setIndexConfiguration" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.setIndexConfiguration", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector( @@ -1023,7 +1510,7 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"@selector(setIndexConfigurationApp:indexConfiguration:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_indexConfiguration = GetNullableObjectAtIndex(args, 1); [api setIndexConfigurationApp:arg_app @@ -1038,18 +1525,21 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.setLoggingEnabled" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.setLoggingEnabled", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(setLoggingEnabledLoggingEnabled:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(setLoggingEnabledLoggingEnabled:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - NSNumber *arg_loggingEnabled = GetNullableObjectAtIndex(args, 0); + NSArray *args = message; + BOOL arg_loggingEnabled = [GetNullableObjectAtIndex(args, 0) boolValue]; [api setLoggingEnabledLoggingEnabled:arg_loggingEnabled completion:^(FlutterError *_Nullable error) { callback(wrapResult(nil, error)); @@ -1061,17 +1551,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.snapshotsInSyncSetup" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.snapshotsInSyncSetup", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(snapshotsInSyncSetupApp:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(snapshotsInSyncSetupApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api snapshotsInSyncSetupApp:arg_app completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { @@ -1084,10 +1577,13 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.transactionCreate" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.transactionCreate", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(transactionCreateApp:timeout:maxAttempts:completion:)], @@ -1095,10 +1591,10 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"@selector(transactionCreateApp:timeout:maxAttempts:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - NSNumber *arg_timeout = GetNullableObjectAtIndex(args, 1); - NSNumber *arg_maxAttempts = GetNullableObjectAtIndex(args, 2); + NSInteger arg_timeout = [GetNullableObjectAtIndex(args, 1) integerValue]; + NSInteger arg_maxAttempts = [GetNullableObjectAtIndex(args, 2) integerValue]; [api transactionCreateApp:arg_app timeout:arg_timeout maxAttempts:arg_maxAttempts @@ -1112,10 +1608,13 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.transactionStoreResult" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.transactionStoreResult", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(transactionStoreResultTransactionId:resultType: commands:completion:)], @@ -1123,10 +1622,12 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"@selector(transactionStoreResultTransactionId:resultType:commands:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; NSString *arg_transactionId = GetNullableObjectAtIndex(args, 0); - PigeonTransactionResult arg_resultType = [GetNullableObjectAtIndex(args, 1) integerValue]; - NSArray *arg_commands = GetNullableObjectAtIndex(args, 2); + InternalTransactionResultBox *boxedInternalTransactionResult = + GetNullableObjectAtIndex(args, 1); + InternalTransactionResult arg_resultType = boxedInternalTransactionResult.value; + NSArray *arg_commands = GetNullableObjectAtIndex(args, 2); [api transactionStoreResultTransactionId:arg_transactionId resultType:arg_resultType commands:arg_commands @@ -1140,10 +1641,13 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.transactionGet" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.transactionGet", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(transactionGetApp:transactionId:path:completion:)], @@ -1151,14 +1655,14 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"@selector(transactionGetApp:transactionId:path:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_transactionId = GetNullableObjectAtIndex(args, 1); NSString *arg_path = GetNullableObjectAtIndex(args, 2); [api transactionGetApp:arg_app transactionId:arg_transactionId path:arg_path - completion:^(PigeonDocumentSnapshot *_Nullable output, + completion:^(InternalDocumentSnapshot *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1169,17 +1673,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.documentReferenceSet" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.documentReferenceSet", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(documentReferenceSetApp:request:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(documentReferenceSetApp:request:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); DocumentReferenceRequest *arg_request = GetNullableObjectAtIndex(args, 1); [api documentReferenceSetApp:arg_app @@ -1194,17 +1701,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.documentReferenceUpdate" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.documentReferenceUpdate", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(documentReferenceUpdateApp:request:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(documentReferenceUpdateApp:request:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); DocumentReferenceRequest *arg_request = GetNullableObjectAtIndex(args, 1); [api documentReferenceUpdateApp:arg_app @@ -1219,22 +1729,25 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.documentReferenceGet" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.documentReferenceGet", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(documentReferenceGetApp:request:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(documentReferenceGetApp:request:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); DocumentReferenceRequest *arg_request = GetNullableObjectAtIndex(args, 1); [api documentReferenceGetApp:arg_app request:arg_request - completion:^(PigeonDocumentSnapshot *_Nullable output, + completion:^(InternalDocumentSnapshot *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1245,17 +1758,20 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.documentReferenceDelete" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.documentReferenceDelete", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(documentReferenceDeleteApp:request:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(documentReferenceDeleteApp:request:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); DocumentReferenceRequest *arg_request = GetNullableObjectAtIndex(args, 1); [api documentReferenceDeleteApp:arg_app @@ -1270,10 +1786,12 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.queryGet" + initWithName:[NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.queryGet", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(queryGetApp:path:isCollectionGroup:parameters: options:completion:)], @@ -1281,18 +1799,18 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"@selector(queryGetApp:path:isCollectionGroup:parameters:options:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_path = GetNullableObjectAtIndex(args, 1); - NSNumber *arg_isCollectionGroup = GetNullableObjectAtIndex(args, 2); - PigeonQueryParameters *arg_parameters = GetNullableObjectAtIndex(args, 3); - PigeonGetOptions *arg_options = GetNullableObjectAtIndex(args, 4); + BOOL arg_isCollectionGroup = [GetNullableObjectAtIndex(args, 2) boolValue]; + InternalQueryParameters *arg_parameters = GetNullableObjectAtIndex(args, 3); + InternalGetOptions *arg_options = GetNullableObjectAtIndex(args, 4); [api queryGetApp:arg_app path:arg_path isCollectionGroup:arg_isCollectionGroup parameters:arg_parameters options:arg_options - completion:^(PigeonQuerySnapshot *_Nullable output, + completion:^(InternalQuerySnapshot *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1303,10 +1821,13 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.aggregateQuery" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.aggregateQuery", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(aggregateQueryApp:path:parameters:source:queries: isCollectionGroup:completion:)], @@ -1315,13 +1836,14 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_path = GetNullableObjectAtIndex(args, 1); - PigeonQueryParameters *arg_parameters = GetNullableObjectAtIndex(args, 2); - AggregateSource arg_source = [GetNullableObjectAtIndex(args, 3) integerValue]; + InternalQueryParameters *arg_parameters = GetNullableObjectAtIndex(args, 2); + AggregateSourceBox *boxedAggregateSource = GetNullableObjectAtIndex(args, 3); + AggregateSource arg_source = boxedAggregateSource.value; NSArray *arg_queries = GetNullableObjectAtIndex(args, 4); - NSNumber *arg_isCollectionGroup = GetNullableObjectAtIndex(args, 5); + BOOL arg_isCollectionGroup = [GetNullableObjectAtIndex(args, 5) boolValue]; [api aggregateQueryApp:arg_app path:arg_path parameters:arg_parameters @@ -1339,19 +1861,22 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.writeBatchCommit" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.writeBatchCommit", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(writeBatchCommitApp:writes:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(writeBatchCommitApp:writes:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - NSArray *arg_writes = GetNullableObjectAtIndex(args, 1); + NSArray *arg_writes = GetNullableObjectAtIndex(args, 1); [api writeBatchCommitApp:arg_app writes:arg_writes completion:^(FlutterError *_Nullable error) { @@ -1364,10 +1889,13 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.querySnapshot" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.querySnapshot", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(querySnapshotApp:path:isCollectionGroup:parameters: @@ -1377,14 +1905,15 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"includeMetadataChanges:source:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_path = GetNullableObjectAtIndex(args, 1); - NSNumber *arg_isCollectionGroup = GetNullableObjectAtIndex(args, 2); - PigeonQueryParameters *arg_parameters = GetNullableObjectAtIndex(args, 3); - PigeonGetOptions *arg_options = GetNullableObjectAtIndex(args, 4); - NSNumber *arg_includeMetadataChanges = GetNullableObjectAtIndex(args, 5); - ListenSource arg_source = [GetNullableObjectAtIndex(args, 6) integerValue]; + BOOL arg_isCollectionGroup = [GetNullableObjectAtIndex(args, 2) boolValue]; + InternalQueryParameters *arg_parameters = GetNullableObjectAtIndex(args, 3); + InternalGetOptions *arg_options = GetNullableObjectAtIndex(args, 4); + BOOL arg_includeMetadataChanges = [GetNullableObjectAtIndex(args, 5) boolValue]; + ListenSourceBox *boxedListenSource = GetNullableObjectAtIndex(args, 6); + ListenSource arg_source = boxedListenSource.value; [api querySnapshotApp:arg_app path:arg_path isCollectionGroup:arg_isCollectionGroup @@ -1402,10 +1931,13 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.documentReferenceSnapshot" + initWithName: + [NSString stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.documentReferenceSnapshot", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(documentReferenceSnapshotApp:parameters: includeMetadataChanges:source:completion:)], @@ -1414,11 +1946,12 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); DocumentReferenceRequest *arg_parameters = GetNullableObjectAtIndex(args, 1); - NSNumber *arg_includeMetadataChanges = GetNullableObjectAtIndex(args, 2); - ListenSource arg_source = [GetNullableObjectAtIndex(args, 3) integerValue]; + BOOL arg_includeMetadataChanges = [GetNullableObjectAtIndex(args, 2) boolValue]; + ListenSourceBox *boxedListenSource = GetNullableObjectAtIndex(args, 3); + ListenSource arg_source = boxedListenSource.value; [api documentReferenceSnapshotApp:arg_app parameters:arg_parameters includeMetadataChanges:arg_includeMetadataChanges @@ -1434,10 +1967,14 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest" + initWithName: + [NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_interface." + @"FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector( @@ -1446,10 +1983,12 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, @"@selector(persistenceCacheIndexManagerRequestApp:request:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + PersistenceCacheIndexManagerRequestBox *boxedPersistenceCacheIndexManagerRequest = + GetNullableObjectAtIndex(args, 1); PersistenceCacheIndexManagerRequest arg_request = - [GetNullableObjectAtIndex(args, 1) integerValue]; + boxedPersistenceCacheIndexManagerRequest.value; [api persistenceCacheIndexManagerRequestApp:arg_app request:arg_request completion:^(FlutterError *_Nullable error) { @@ -1462,24 +2001,27 @@ void FirebaseFirestoreHostApiSetup(id binaryMessenger, } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] - initWithName:@"dev.flutter.pigeon.cloud_firestore_platform_interface." - @"FirebaseFirestoreHostApi.executePipeline" + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.cloud_firestore_platform_" + @"interface.FirebaseFirestoreHostApi.executePipeline", + messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseFirestoreHostApiGetCodec()]; + codec:GetFirebaseFirestoreHostApiCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(executePipelineApp:stages:options:completion:)], @"FirebaseFirestoreHostApi api (%@) doesn't respond to " @"@selector(executePipelineApp:stages:options:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; FirestorePigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSArray *> *arg_stages = GetNullableObjectAtIndex(args, 1); NSDictionary *arg_options = GetNullableObjectAtIndex(args, 2); [api executePipelineApp:arg_app stages:arg_stages options:arg_options - completion:^(PigeonPipelineSnapshot *_Nullable output, + completion:^(InternalPipelineSnapshot *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestorePigeonParser.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestorePigeonParser.m index 1103e92e4e7b..0178847b7426 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestorePigeonParser.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FirestorePigeonParser.m @@ -60,7 +60,7 @@ + (FIRFilter *_Nonnull)filterFromJson:(NSDictionary *_Nullable)m @throw [NSException exceptionWithName:@"InvalidOperator" reason:@"Invalid operator" userInfo:nil]; } -+ (FIRQuery *_Nonnull)parseQueryWithParameters:(nonnull PigeonQueryParameters *)parameters ++ (FIRQuery *_Nonnull)parseQueryWithParameters:(nonnull InternalQueryParameters *)parameters firestore:(nonnull FIRFirestore *)firestore path:(nonnull NSString *)path isCollectionGroup:(Boolean)isCollectionGroup { @@ -218,17 +218,16 @@ + (FIRListenSource)parseListenSource:(ListenSource)source { } } -+ (PigeonSnapshotMetadata *_Nonnull)toPigeonSnapshotMetadata: ++ (InternalSnapshotMetadata *_Nonnull)toPigeonSnapshotMetadata: (FIRSnapshotMetadata *_Nonnull)snapshotMetadata { - return [PigeonSnapshotMetadata - makeWithHasPendingWrites:[NSNumber numberWithBool:snapshotMetadata.hasPendingWrites] - isFromCache:[NSNumber numberWithBool:snapshotMetadata.isFromCache]]; + return [InternalSnapshotMetadata makeWithHasPendingWrites:snapshotMetadata.hasPendingWrites + isFromCache:snapshotMetadata.isFromCache]; } -+ (PigeonDocumentSnapshot *_Nonnull) ++ (InternalDocumentSnapshot *_Nonnull) toPigeonDocumentSnapshot:(FIRDocumentSnapshot *_Nonnull)documentSnapshot serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior { - return [PigeonDocumentSnapshot + return [InternalDocumentSnapshot makeWithPath:documentSnapshot.reference.path data:[documentSnapshot dataWithServerTimestampBehavior:serverTimestampBehavior] metadata:[FirestorePigeonParser toPigeonSnapshotMetadata:documentSnapshot.metadata]]; @@ -249,11 +248,11 @@ + (DocumentChangeType)toPigeonDocumentChangeType:(FIRDocumentChangeType)document } } -+ (PigeonDocumentChange *_Nonnull)toPigeonDocumentChange:(FIRDocumentChange *_Nonnull)documentChange - serverTimestampBehavior: - (FIRServerTimestampBehavior)serverTimestampBehavior { - NSNumber *oldIndex; - NSNumber *newIndex; ++ (InternalDocumentChange *_Nonnull) + toPigeonDocumentChange:(FIRDocumentChange *_Nonnull)documentChange + serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior { + NSInteger oldIndex; + NSInteger newIndex; // Note the Firestore C++ SDK here returns a maxed UInt that is != NSUIntegerMax, so we make one // ourselves so we can convert to -1 for Dart. @@ -261,19 +260,19 @@ + (PigeonDocumentChange *_Nonnull)toPigeonDocumentChange:(FIRDocumentChange *_No if (documentChange.newIndex == NSNotFound || documentChange.newIndex == 4294967295 || documentChange.newIndex == MAX_VAL) { - newIndex = @([@(-1) intValue]); + newIndex = -1; } else { - newIndex = @([@(documentChange.newIndex) intValue]); + newIndex = (NSInteger)documentChange.newIndex; } if (documentChange.oldIndex == NSNotFound || documentChange.oldIndex == 4294967295 || documentChange.oldIndex == MAX_VAL) { - oldIndex = @([@(-1) intValue]); + oldIndex = -1; } else { - oldIndex = @([@(documentChange.oldIndex) intValue]); + oldIndex = (NSInteger)documentChange.oldIndex; } - return [PigeonDocumentChange + return [InternalDocumentChange makeWithType:[FirestorePigeonParser toPigeonDocumentChangeType:documentChange.type] document:[FirestorePigeonParser toPigeonDocumentSnapshot:documentChange.document serverTimestampBehavior:serverTimestampBehavior] @@ -281,7 +280,7 @@ + (PigeonDocumentChange *_Nonnull)toPigeonDocumentChange:(FIRDocumentChange *_No newIndex:newIndex]; } -+ (NSArray *_Nonnull) ++ (NSArray *_Nonnull) toPigeonDocumentChanges:(NSArray *_Nonnull)documentChanges serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior { NSMutableArray *pigeonDocumentChanges = [NSMutableArray array]; @@ -293,16 +292,16 @@ + (PigeonDocumentChange *_Nonnull)toPigeonDocumentChange:(FIRDocumentChange *_No return pigeonDocumentChanges; } -+ (PigeonQuerySnapshot *_Nonnull)toPigeonQuerySnapshot:(FIRQuerySnapshot *_Nonnull)querySnaphot - serverTimestampBehavior: - (FIRServerTimestampBehavior)serverTimestampBehavior { ++ (InternalQuerySnapshot *_Nonnull)toPigeonQuerySnapshot:(FIRQuerySnapshot *_Nonnull)querySnaphot + serverTimestampBehavior: + (FIRServerTimestampBehavior)serverTimestampBehavior { NSMutableArray *documentSnapshots = [NSMutableArray array]; for (FIRDocumentSnapshot *documentSnapshot in querySnaphot.documents) { [documentSnapshots addObject:[FirestorePigeonParser toPigeonDocumentSnapshot:documentSnapshot serverTimestampBehavior:serverTimestampBehavior]]; } - return [PigeonQuerySnapshot + return [InternalQuerySnapshot makeWithDocuments:documentSnapshots documentChanges:[FirestorePigeonParser toPigeonDocumentChanges:querySnaphot.documentChanges serverTimestampBehavior:serverTimestampBehavior] diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTTransactionStreamHandler.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTTransactionStreamHandler.h index 213570d9887b..c40a148efa5d 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTTransactionStreamHandler.h +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FLTTransactionStreamHandler.h @@ -25,17 +25,17 @@ NS_ASSUME_NONNULL_BEGIN @interface FLTTransactionStreamHandler : NSObject @property(nonatomic, strong) FIRFirestore *firestore; -@property(nonatomic, strong) NSNumber *timeout; -@property(nonatomic, strong) NSNumber *maxAttempts; +@property(nonatomic, assign) NSInteger timeout; +@property(nonatomic, assign) NSInteger maxAttempts; - (instancetype)initWithId:(NSString *)transactionId firestore:(FIRFirestore *)firestore - timeout:(nonnull NSNumber *)timeout - maxAttempts:(nonnull NSNumber *)maxAttempts + timeout:(NSInteger)timeout + maxAttempts:(NSInteger)maxAttempts started:(void (^)(FIRTransaction *))startedListener ended:(void (^)(void))endedListener; -- (void)receiveTransactionResponse:(PigeonTransactionResult)resultType - commands:(NSArray *)commands; +- (void)receiveTransactionResponse:(InternalTransactionResult)resultType + commands:(NSArray *)commands; @end diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FirestorePigeonParser.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FirestorePigeonParser.h index e197ef7592b0..5fa20d98759f 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FirestorePigeonParser.h +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Private/FirestorePigeonParser.h @@ -19,7 +19,7 @@ + (FIRFilter *_Nonnull)filterFromJson:(NSDictionary *_Nullable)map; -+ (FIRQuery *_Nonnull)parseQueryWithParameters:(nonnull PigeonQueryParameters *)parameters ++ (FIRQuery *_Nonnull)parseQueryWithParameters:(nonnull InternalQueryParameters *)parameters firestore:(nonnull FIRFirestore *)firestore path:(nonnull NSString *)path isCollectionGroup:(Boolean)isCollectionGroup; @@ -34,25 +34,25 @@ + (FIRListenSource)parseListenSource:(ListenSource)source; -+ (PigeonSnapshotMetadata *_Nonnull)toPigeonSnapshotMetadata: ++ (InternalSnapshotMetadata *_Nonnull)toPigeonSnapshotMetadata: (FIRSnapshotMetadata *_Nonnull)snapshotMetadata; -+ (PigeonDocumentSnapshot *_Nonnull) ++ (InternalDocumentSnapshot *_Nonnull) toPigeonDocumentSnapshot:(FIRDocumentSnapshot *_Nonnull)documentSnapshot serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior; + (DocumentChangeType)toPigeonDocumentChangeType:(FIRDocumentChangeType)documentChangeType; -+ (PigeonDocumentChange *_Nonnull)toPigeonDocumentChange:(FIRDocumentChange *_Nonnull)documentChange - serverTimestampBehavior: - (FIRServerTimestampBehavior)serverTimestampBehavior; ++ (InternalDocumentChange *_Nonnull) + toPigeonDocumentChange:(FIRDocumentChange *_Nonnull)documentChange + serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior; -+ (NSArray *_Nonnull) ++ (NSArray *_Nonnull) toPigeonDocumentChanges:(NSArray *_Nonnull)documentChanges serverTimestampBehavior:(FIRServerTimestampBehavior)serverTimestampBehavior; -+ (PigeonQuerySnapshot *_Nonnull)toPigeonQuerySnapshot:(FIRQuerySnapshot *_Nonnull)querySnaphot - serverTimestampBehavior: - (FIRServerTimestampBehavior)serverTimestampBehavior; ++ (InternalQuerySnapshot *_Nonnull)toPigeonQuerySnapshot:(FIRQuerySnapshot *_Nonnull)querySnaphot + serverTimestampBehavior: + (FIRServerTimestampBehavior)serverTimestampBehavior; @end diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/CustomPigeonHeaderFirestore.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/CustomPigeonHeaderFirestore.h index 3cfb88fa5cf9..7127b0061f58 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/CustomPigeonHeaderFirestore.h +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/CustomPigeonHeaderFirestore.h @@ -3,14 +3,14 @@ // found in the LICENSE file. #import "FirestoreMessages.g.h" -@interface PigeonDocumentSnapshot (Map) +@interface InternalDocumentSnapshot (Map) - (NSDictionary *)toList; @end -@interface PigeonDocumentChange (Map) +@interface InternalDocumentChange (Map) - (NSDictionary *)toList; @end -@interface PigeonSnapshotMetadata (Map) +@interface InternalSnapshotMetadata (Map) - (NSDictionary *)toList; @end diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h index f3955862ae04..7fd40daf7fcf 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h @@ -1,10 +1,10 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import +@import Foundation; @protocol FlutterBinaryMessenger; @protocol FlutterMessageCodec; @@ -123,28 +123,28 @@ typedef NS_ENUM(NSUInteger, PersistenceCacheIndexManagerRequest) { - (instancetype)initWithValue:(PersistenceCacheIndexManagerRequest)value; @end -typedef NS_ENUM(NSUInteger, PigeonTransactionResult) { - PigeonTransactionResultSuccess = 0, - PigeonTransactionResultFailure = 1, +typedef NS_ENUM(NSUInteger, InternalTransactionResult) { + InternalTransactionResultSuccess = 0, + InternalTransactionResultFailure = 1, }; -/// Wrapper for PigeonTransactionResult to allow for nullability. -@interface PigeonTransactionResultBox : NSObject -@property(nonatomic, assign) PigeonTransactionResult value; -- (instancetype)initWithValue:(PigeonTransactionResult)value; +/// Wrapper for InternalTransactionResult to allow for nullability. +@interface InternalTransactionResultBox : NSObject +@property(nonatomic, assign) InternalTransactionResult value; +- (instancetype)initWithValue:(InternalTransactionResult)value; @end -typedef NS_ENUM(NSUInteger, PigeonTransactionType) { - PigeonTransactionTypeGet = 0, - PigeonTransactionTypeUpdate = 1, - PigeonTransactionTypeSet = 2, - PigeonTransactionTypeDeleteType = 3, +typedef NS_ENUM(NSUInteger, InternalTransactionType) { + InternalTransactionTypeGet = 0, + InternalTransactionTypeUpdate = 1, + InternalTransactionTypeSet = 2, + InternalTransactionTypeDeleteType = 3, }; -/// Wrapper for PigeonTransactionType to allow for nullability. -@interface PigeonTransactionTypeBox : NSObject -@property(nonatomic, assign) PigeonTransactionType value; -- (instancetype)initWithValue:(PigeonTransactionType)value; +/// Wrapper for InternalTransactionType to allow for nullability. +@interface InternalTransactionTypeBox : NSObject +@property(nonatomic, assign) InternalTransactionType value; +- (instancetype)initWithValue:(InternalTransactionType)value; @end typedef NS_ENUM(NSUInteger, AggregateType) { @@ -159,93 +159,92 @@ typedef NS_ENUM(NSUInteger, AggregateType) { - (instancetype)initWithValue:(AggregateType)value; @end -@class PigeonFirebaseSettings; +@class InternalFirebaseSettings; @class FirestorePigeonFirebaseApp; -@class PigeonSnapshotMetadata; -@class PigeonDocumentSnapshot; -@class PigeonDocumentChange; -@class PigeonQuerySnapshot; -@class PigeonPipelineResult; -@class PigeonPipelineSnapshot; -@class PigeonGetOptions; -@class PigeonDocumentOption; -@class PigeonTransactionCommand; +@class InternalSnapshotMetadata; +@class InternalDocumentSnapshot; +@class InternalDocumentChange; +@class InternalQuerySnapshot; +@class InternalPipelineResult; +@class InternalPipelineSnapshot; +@class InternalGetOptions; +@class InternalDocumentOption; +@class InternalTransactionCommand; @class DocumentReferenceRequest; -@class PigeonQueryParameters; +@class InternalQueryParameters; @class AggregateQuery; @class AggregateQueryResponse; -@interface PigeonFirebaseSettings : NSObject +@interface InternalFirebaseSettings : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithPersistenceEnabled:(nullable NSNumber *)persistenceEnabled host:(nullable NSString *)host sslEnabled:(nullable NSNumber *)sslEnabled cacheSizeBytes:(nullable NSNumber *)cacheSizeBytes - ignoreUndefinedProperties:(NSNumber *)ignoreUndefinedProperties; + ignoreUndefinedProperties:(BOOL)ignoreUndefinedProperties; @property(nonatomic, strong, nullable) NSNumber *persistenceEnabled; @property(nonatomic, copy, nullable) NSString *host; @property(nonatomic, strong, nullable) NSNumber *sslEnabled; @property(nonatomic, strong, nullable) NSNumber *cacheSizeBytes; -@property(nonatomic, strong) NSNumber *ignoreUndefinedProperties; +@property(nonatomic, assign) BOOL ignoreUndefinedProperties; @end @interface FirestorePigeonFirebaseApp : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithAppName:(NSString *)appName - settings:(PigeonFirebaseSettings *)settings + settings:(InternalFirebaseSettings *)settings databaseURL:(NSString *)databaseURL; @property(nonatomic, copy) NSString *appName; -@property(nonatomic, strong) PigeonFirebaseSettings *settings; +@property(nonatomic, strong) InternalFirebaseSettings *settings; @property(nonatomic, copy) NSString *databaseURL; @end -@interface PigeonSnapshotMetadata : NSObject +@interface InternalSnapshotMetadata : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithHasPendingWrites:(NSNumber *)hasPendingWrites - isFromCache:(NSNumber *)isFromCache; -@property(nonatomic, strong) NSNumber *hasPendingWrites; -@property(nonatomic, strong) NSNumber *isFromCache; ++ (instancetype)makeWithHasPendingWrites:(BOOL)hasPendingWrites isFromCache:(BOOL)isFromCache; +@property(nonatomic, assign) BOOL hasPendingWrites; +@property(nonatomic, assign) BOOL isFromCache; @end -@interface PigeonDocumentSnapshot : NSObject +@interface InternalDocumentSnapshot : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithPath:(NSString *)path data:(nullable NSDictionary *)data - metadata:(PigeonSnapshotMetadata *)metadata; + metadata:(InternalSnapshotMetadata *)metadata; @property(nonatomic, copy) NSString *path; -@property(nonatomic, strong, nullable) NSDictionary *data; -@property(nonatomic, strong) PigeonSnapshotMetadata *metadata; +@property(nonatomic, copy, nullable) NSDictionary *data; +@property(nonatomic, strong) InternalSnapshotMetadata *metadata; @end -@interface PigeonDocumentChange : NSObject +@interface InternalDocumentChange : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithType:(DocumentChangeType)type - document:(PigeonDocumentSnapshot *)document - oldIndex:(NSNumber *)oldIndex - newIndex:(NSNumber *)newIndex; + document:(InternalDocumentSnapshot *)document + oldIndex:(NSInteger)oldIndex + newIndex:(NSInteger)newIndex; @property(nonatomic, assign) DocumentChangeType type; -@property(nonatomic, strong) PigeonDocumentSnapshot *document; -@property(nonatomic, strong) NSNumber *oldIndex; -@property(nonatomic, strong) NSNumber *index; +@property(nonatomic, strong) InternalDocumentSnapshot *document; +@property(nonatomic, assign) NSInteger oldIndex; +@property(nonatomic, assign) NSInteger newIndex; @end -@interface PigeonQuerySnapshot : NSObject +@interface InternalQuerySnapshot : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithDocuments:(NSArray *)documents - documentChanges:(NSArray *)documentChanges - metadata:(PigeonSnapshotMetadata *)metadata; -@property(nonatomic, strong) NSArray *documents; -@property(nonatomic, strong) NSArray *documentChanges; -@property(nonatomic, strong) PigeonSnapshotMetadata *metadata; ++ (instancetype)makeWithDocuments:(NSArray *)documents + documentChanges:(NSArray *)documentChanges + metadata:(InternalSnapshotMetadata *)metadata; +@property(nonatomic, copy) NSArray *documents; +@property(nonatomic, copy) NSArray *documentChanges; +@property(nonatomic, strong) InternalSnapshotMetadata *metadata; @end -@interface PigeonPipelineResult : NSObject +@interface InternalPipelineResult : NSObject + (instancetype)makeWithDocumentPath:(nullable NSString *)documentPath createTime:(nullable NSNumber *)createTime updateTime:(nullable NSNumber *)updateTime @@ -254,19 +253,19 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @property(nonatomic, strong, nullable) NSNumber *createTime; @property(nonatomic, strong, nullable) NSNumber *updateTime; /// All fields in the result (from PipelineResult.data() on Android). -@property(nonatomic, strong, nullable) NSDictionary *data; +@property(nonatomic, copy, nullable) NSDictionary *data; @end -@interface PigeonPipelineSnapshot : NSObject +@interface InternalPipelineSnapshot : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithResults:(NSArray *)results - executionTime:(NSNumber *)executionTime; -@property(nonatomic, strong) NSArray *results; -@property(nonatomic, strong) NSNumber *executionTime; ++ (instancetype)makeWithResults:(NSArray *)results + executionTime:(NSInteger)executionTime; +@property(nonatomic, copy) NSArray *results; +@property(nonatomic, assign) NSInteger executionTime; @end -@interface PigeonGetOptions : NSObject +@interface InternalGetOptions : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithSource:(Source)source @@ -275,24 +274,24 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @property(nonatomic, assign) ServerTimestampBehavior serverTimestampBehavior; @end -@interface PigeonDocumentOption : NSObject +@interface InternalDocumentOption : NSObject + (instancetype)makeWithMerge:(nullable NSNumber *)merge mergeFields:(nullable NSArray *> *)mergeFields; @property(nonatomic, strong, nullable) NSNumber *merge; -@property(nonatomic, strong, nullable) NSArray *> *mergeFields; +@property(nonatomic, copy, nullable) NSArray *> *mergeFields; @end -@interface PigeonTransactionCommand : NSObject +@interface InternalTransactionCommand : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithType:(PigeonTransactionType)type ++ (instancetype)makeWithType:(InternalTransactionType)type path:(NSString *)path data:(nullable NSDictionary *)data - option:(nullable PigeonDocumentOption *)option; -@property(nonatomic, assign) PigeonTransactionType type; + option:(nullable InternalDocumentOption *)option; +@property(nonatomic, assign) InternalTransactionType type; @property(nonatomic, copy) NSString *path; -@property(nonatomic, strong, nullable) NSDictionary *data; -@property(nonatomic, strong, nullable) PigeonDocumentOption *option; +@property(nonatomic, copy, nullable) NSDictionary *data; +@property(nonatomic, strong, nullable) InternalDocumentOption *option; @end @interface DocumentReferenceRequest : NSObject @@ -300,17 +299,17 @@ typedef NS_ENUM(NSUInteger, AggregateType) { - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithPath:(NSString *)path data:(nullable NSDictionary *)data - option:(nullable PigeonDocumentOption *)option + option:(nullable InternalDocumentOption *)option source:(nullable SourceBox *)source serverTimestampBehavior:(nullable ServerTimestampBehaviorBox *)serverTimestampBehavior; @property(nonatomic, copy) NSString *path; -@property(nonatomic, strong, nullable) NSDictionary *data; -@property(nonatomic, strong, nullable) PigeonDocumentOption *option; +@property(nonatomic, copy, nullable) NSDictionary *data; +@property(nonatomic, strong, nullable) InternalDocumentOption *option; @property(nonatomic, strong, nullable) SourceBox *source; @property(nonatomic, strong, nullable) ServerTimestampBehaviorBox *serverTimestampBehavior; @end -@interface PigeonQueryParameters : NSObject +@interface InternalQueryParameters : NSObject + (instancetype)makeWithWhere:(nullable NSArray *> *)where orderBy:(nullable NSArray *> *)orderBy limit:(nullable NSNumber *)limit @@ -320,15 +319,15 @@ typedef NS_ENUM(NSUInteger, AggregateType) { endAt:(nullable NSArray *)endAt endBefore:(nullable NSArray *)endBefore filters:(nullable NSDictionary *)filters; -@property(nonatomic, strong, nullable) NSArray *> *where; -@property(nonatomic, strong, nullable) NSArray *> *orderBy; +@property(nonatomic, copy, nullable) NSArray *> *where; +@property(nonatomic, copy, nullable) NSArray *> *orderBy; @property(nonatomic, strong, nullable) NSNumber *limit; @property(nonatomic, strong, nullable) NSNumber *limitToLast; -@property(nonatomic, strong, nullable) NSArray *startAt; -@property(nonatomic, strong, nullable) NSArray *startAfter; -@property(nonatomic, strong, nullable) NSArray *endAt; -@property(nonatomic, strong, nullable) NSArray *endBefore; -@property(nonatomic, strong, nullable) NSDictionary *filters; +@property(nonatomic, copy, nullable) NSArray *startAt; +@property(nonatomic, copy, nullable) NSArray *startAfter; +@property(nonatomic, copy, nullable) NSArray *endAt; +@property(nonatomic, copy, nullable) NSArray *endBefore; +@property(nonatomic, copy, nullable) NSDictionary *filters; @end @interface AggregateQuery : NSObject @@ -350,8 +349,8 @@ typedef NS_ENUM(NSUInteger, AggregateType) { @property(nonatomic, strong, nullable) NSNumber *value; @end -/// The codec used by FirebaseFirestoreHostApi. -NSObject *FirebaseFirestoreHostApiGetCodec(void); +/// The codec used by all APIs. +NSObject *GetFirebaseFirestoreHostApiCodec(void); @protocol FirebaseFirestoreHostApi - (void)loadBundleApp:(FirestorePigeonFirebaseApp *)app @@ -359,9 +358,9 @@ NSObject *FirebaseFirestoreHostApiGetCodec(void); completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)namedQueryGetApp:(FirestorePigeonFirebaseApp *)app name:(NSString *)name - options:(PigeonGetOptions *)options + options:(InternalGetOptions *)options completion: - (void (^)(PigeonQuerySnapshot *_Nullable, FlutterError *_Nullable))completion; + (void (^)(InternalQuerySnapshot *_Nullable, FlutterError *_Nullable))completion; - (void)clearPersistenceApp:(FirestorePigeonFirebaseApp *)app completion:(void (^)(FlutterError *_Nullable))completion; - (void)disableNetworkApp:(FirestorePigeonFirebaseApp *)app @@ -375,23 +374,24 @@ NSObject *FirebaseFirestoreHostApiGetCodec(void); - (void)setIndexConfigurationApp:(FirestorePigeonFirebaseApp *)app indexConfiguration:(NSString *)indexConfiguration completion:(void (^)(FlutterError *_Nullable))completion; -- (void)setLoggingEnabledLoggingEnabled:(NSNumber *)loggingEnabled +- (void)setLoggingEnabledLoggingEnabled:(BOOL)loggingEnabled completion:(void (^)(FlutterError *_Nullable))completion; - (void)snapshotsInSyncSetupApp:(FirestorePigeonFirebaseApp *)app completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)transactionCreateApp:(FirestorePigeonFirebaseApp *)app - timeout:(NSNumber *)timeout - maxAttempts:(NSNumber *)maxAttempts + timeout:(NSInteger)timeout + maxAttempts:(NSInteger)maxAttempts completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)transactionStoreResultTransactionId:(NSString *)transactionId - resultType:(PigeonTransactionResult)resultType - commands:(nullable NSArray *)commands + resultType:(InternalTransactionResult)resultType + commands: + (nullable NSArray *)commands completion:(void (^)(FlutterError *_Nullable))completion; - (void)transactionGetApp:(FirestorePigeonFirebaseApp *)app transactionId:(NSString *)transactionId path:(NSString *)path - completion: - (void (^)(PigeonDocumentSnapshot *_Nullable, FlutterError *_Nullable))completion; + completion:(void (^)(InternalDocumentSnapshot *_Nullable, + FlutterError *_Nullable))completion; - (void)documentReferenceSetApp:(FirestorePigeonFirebaseApp *)app request:(DocumentReferenceRequest *)request completion:(void (^)(FlutterError *_Nullable))completion; @@ -400,39 +400,40 @@ NSObject *FirebaseFirestoreHostApiGetCodec(void); completion:(void (^)(FlutterError *_Nullable))completion; - (void)documentReferenceGetApp:(FirestorePigeonFirebaseApp *)app request:(DocumentReferenceRequest *)request - completion:(void (^)(PigeonDocumentSnapshot *_Nullable, + completion:(void (^)(InternalDocumentSnapshot *_Nullable, FlutterError *_Nullable))completion; - (void)documentReferenceDeleteApp:(FirestorePigeonFirebaseApp *)app request:(DocumentReferenceRequest *)request completion:(void (^)(FlutterError *_Nullable))completion; - (void)queryGetApp:(FirestorePigeonFirebaseApp *)app path:(NSString *)path - isCollectionGroup:(NSNumber *)isCollectionGroup - parameters:(PigeonQueryParameters *)parameters - options:(PigeonGetOptions *)options - completion:(void (^)(PigeonQuerySnapshot *_Nullable, FlutterError *_Nullable))completion; + isCollectionGroup:(BOOL)isCollectionGroup + parameters:(InternalQueryParameters *)parameters + options:(InternalGetOptions *)options + completion: + (void (^)(InternalQuerySnapshot *_Nullable, FlutterError *_Nullable))completion; - (void)aggregateQueryApp:(FirestorePigeonFirebaseApp *)app path:(NSString *)path - parameters:(PigeonQueryParameters *)parameters + parameters:(InternalQueryParameters *)parameters source:(AggregateSource)source queries:(NSArray *)queries - isCollectionGroup:(NSNumber *)isCollectionGroup + isCollectionGroup:(BOOL)isCollectionGroup completion:(void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion; - (void)writeBatchCommitApp:(FirestorePigeonFirebaseApp *)app - writes:(NSArray *)writes + writes:(NSArray *)writes completion:(void (^)(FlutterError *_Nullable))completion; - (void)querySnapshotApp:(FirestorePigeonFirebaseApp *)app path:(NSString *)path - isCollectionGroup:(NSNumber *)isCollectionGroup - parameters:(PigeonQueryParameters *)parameters - options:(PigeonGetOptions *)options - includeMetadataChanges:(NSNumber *)includeMetadataChanges + isCollectionGroup:(BOOL)isCollectionGroup + parameters:(InternalQueryParameters *)parameters + options:(InternalGetOptions *)options + includeMetadataChanges:(BOOL)includeMetadataChanges source:(ListenSource)source completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)documentReferenceSnapshotApp:(FirestorePigeonFirebaseApp *)app parameters:(DocumentReferenceRequest *)parameters - includeMetadataChanges:(NSNumber *)includeMetadataChanges + includeMetadataChanges:(BOOL)includeMetadataChanges source:(ListenSource)source completion: (void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; @@ -442,11 +443,15 @@ NSObject *FirebaseFirestoreHostApiGetCodec(void); - (void)executePipelineApp:(FirestorePigeonFirebaseApp *)app stages:(NSArray *> *)stages options:(nullable NSDictionary *)options - completion:(void (^)(PigeonPipelineSnapshot *_Nullable, + completion:(void (^)(InternalPipelineSnapshot *_Nullable, FlutterError *_Nullable))completion; @end -extern void FirebaseFirestoreHostApiSetup(id binaryMessenger, +extern void SetUpFirebaseFirestoreHostApi(id binaryMessenger, NSObject *_Nullable api); +extern void SetUpFirebaseFirestoreHostApiWithSuffix( + id binaryMessenger, NSObject *_Nullable api, + NSString *messageChannelSuffix); + NS_ASSUME_NONNULL_END diff --git a/packages/cloud_firestore/cloud_firestore/test/test_firestore_message_codec.dart b/packages/cloud_firestore/cloud_firestore/test/test_firestore_message_codec.dart index 7a56ecd2b89a..c7ad874ffd2e 100644 --- a/packages/cloud_firestore/cloud_firestore/test/test_firestore_message_codec.dart +++ b/packages/cloud_firestore/cloud_firestore/test/test_firestore_message_codec.dart @@ -77,7 +77,7 @@ class TestFirestoreMessageCodec extends FirestoreMessageCodec { values['path'], FirestorePigeonFirebaseApp( appName: "['DEFAULT']", - settings: PigeonFirebaseSettings(ignoreUndefinedProperties: true), + settings: InternalFirebaseSettings(ignoreUndefinedProperties: true), databaseURL: '', ), ); diff --git a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp index 4550d6b3acf0..597a60adbae1 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp +++ b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp @@ -291,12 +291,12 @@ FlutterError CloudFirestorePlugin::ParseError( firebase::firestore::Source GetSourceFromPigeon(const Source& pigeonSource) { switch (pigeonSource) { - case Source::serverAndCache: + case Source::kServerAndCache: default: return firebase::firestore::Source::kDefault; - case Source::server: + case Source::kServer: return firebase::firestore::Source::kServer; - case Source::cache: + case Source::kCache: return firebase::firestore::Source::kCache; } } @@ -305,13 +305,13 @@ firebase::firestore::DocumentSnapshot::ServerTimestampBehavior GetServerTimestampBehaviorFromPigeon( const ServerTimestampBehavior& pigeonServerTimestampBehavior) { switch (pigeonServerTimestampBehavior) { - case ServerTimestampBehavior::estimate: + case ServerTimestampBehavior::kEstimate: return firebase::firestore::DocumentSnapshot::ServerTimestampBehavior:: kEstimate; - case ServerTimestampBehavior::previous: + case ServerTimestampBehavior::kPrevious: return firebase::firestore::DocumentSnapshot::ServerTimestampBehavior:: kPrevious; - case ServerTimestampBehavior::none: + case ServerTimestampBehavior::kNone: default: return firebase::firestore::DocumentSnapshot::ServerTimestampBehavior:: kNone; @@ -382,27 +382,27 @@ flutter::EncodableMap ConvertToEncodableMap( return convertedMap; } -PigeonSnapshotMetadata ParseSnapshotMetadata( +InternalSnapshotMetadata ParseSnapshotMetadata( const firebase::firestore::SnapshotMetadata& metadata) { - PigeonSnapshotMetadata pigeonSnapshotMetadata = PigeonSnapshotMetadata( + InternalSnapshotMetadata pigeonSnapshotMetadata = InternalSnapshotMetadata( metadata.has_pending_writes(), metadata.is_from_cache()); return pigeonSnapshotMetadata; } -PigeonDocumentSnapshot ParseDocumentSnapshot( +InternalDocumentSnapshot ParseDocumentSnapshot( DocumentSnapshot document, DocumentSnapshot::ServerTimestampBehavior serverTimestampBehavior) { flutter::EncodableMap tempMap = ConvertToEncodableMap(document.GetData(serverTimestampBehavior)); if (tempMap.empty()) { - return PigeonDocumentSnapshot(document.reference().path(), nullptr, - ParseSnapshotMetadata(document.metadata())); + return InternalDocumentSnapshot(document.reference().path(), nullptr, + ParseSnapshotMetadata(document.metadata())); } - PigeonDocumentSnapshot pigeonDocumentSnapshot = - PigeonDocumentSnapshot(document.reference().path(), &tempMap, - ParseSnapshotMetadata(document.metadata())); + InternalDocumentSnapshot pigeonDocumentSnapshot = + InternalDocumentSnapshot(document.reference().path(), &tempMap, + ParseSnapshotMetadata(document.metadata())); return pigeonDocumentSnapshot; } @@ -422,20 +422,20 @@ DocumentChangeType ParseDocumentChangeType( const firebase::firestore::DocumentChange::Type& type) { switch (type) { case firebase::firestore::DocumentChange::Type::kAdded: - return DocumentChangeType::added; + return DocumentChangeType::kAdded; case firebase::firestore::DocumentChange::Type::kRemoved: - return DocumentChangeType::removed; + return DocumentChangeType::kRemoved; case firebase::firestore::DocumentChange::Type::kModified: - return DocumentChangeType::modified; + return DocumentChangeType::kModified; } throw std::invalid_argument("Invalid DocumentChangeType"); } -PigeonDocumentChange ParseDocumentChange( +InternalDocumentChange ParseDocumentChange( const firebase::firestore::DocumentChange& document_change, DocumentSnapshot::ServerTimestampBehavior serverTimestampBehavior) { - PigeonDocumentChange pigeonDocumentChange = PigeonDocumentChange( + InternalDocumentChange pigeonDocumentChange = InternalDocumentChange( ParseDocumentChangeType(document_change.type()), ParseDocumentSnapshot(document_change.document(), serverTimestampBehavior), @@ -454,10 +454,10 @@ flutter::EncodableList ParseDocumentChanges( return pigeonDocumentChanges; } -PigeonQuerySnapshot ParseQuerySnapshot( +InternalQuerySnapshot ParseQuerySnapshot( const firebase::firestore::QuerySnapshot* query_snapshot, DocumentSnapshot::ServerTimestampBehavior serverTimestampBehavior) { - PigeonQuerySnapshot pigeonQuerySnapshot = PigeonQuerySnapshot( + InternalQuerySnapshot pigeonQuerySnapshot = InternalQuerySnapshot( ParseDocumentSnapshots(query_snapshot->documents(), serverTimestampBehavior), ParseDocumentChanges(query_snapshot->DocumentChanges(), @@ -625,8 +625,8 @@ using firebase::firestore::QuerySnapshot; void CloudFirestorePlugin::NamedQueryGet( const FirestorePigeonFirebaseApp& app, const std::string& name, - const PigeonGetOptions& options, - std::function reply)> result) { + const InternalGetOptions& options, + std::function reply)> result) { Firestore* firestore = GetFirestoreFromPigeon(app); Future future = firestore->NamedQuery(name.c_str()); @@ -825,8 +825,8 @@ class TransactionStreamHandler transactionId_(transactionId) {} void ReceiveTransactionResponse( - PigeonTransactionResult resultType, - std::vector commands) { + InternalTransactionResult resultType, + std::vector commands) { std::lock_guard lock(commands_mutex_); resultType_ = resultType; commands_ = commands; @@ -867,9 +867,9 @@ class TransactionStreamHandler std::lock_guard command_lock(commands_mutex_); if (commands_.empty()) return Error::kErrorOk; - for (PigeonTransactionCommand& command : commands_) { + for (InternalTransactionCommand& command : commands_) { std::string path = command.path(); - PigeonTransactionType type = command.type(); + InternalTransactionType type = command.type(); if (path.empty() /* or some other invalid condition */) { std::cerr << "Path is invalid: " << path << std::endl; continue; // Skip this iteration. @@ -882,7 +882,7 @@ class TransactionStreamHandler << std::endl; // debug print switch (type) { - case PigeonTransactionType::set: + case InternalTransactionType::kSet: std::cout << "Transaction set" << path << std::endl; // Debug print. @@ -902,14 +902,14 @@ class TransactionStreamHandler } break; - case PigeonTransactionType::update: + case InternalTransactionType::kUpdate: std::cout << "Transaction update" << path << std::endl; // Debug print. transaction.Update( reference, ConvertToMapFieldPathValue(*command.data())); break; - case PigeonTransactionType::deleteType: + case InternalTransactionType::kDeleteType: std::cout << "Transaction delete" << path << std::endl; // Debug print. @@ -948,8 +948,8 @@ class TransactionStreamHandler long timeout_; int maxAttempts_; std::string transactionId_; - std::vector commands_; - PigeonTransactionResult resultType_; + std::vector commands_; + InternalTransactionResult resultType_; std::mutex mtx_; std::mutex commands_mutex_; std::condition_variable cv_; @@ -990,16 +990,16 @@ using flutter::CustomEncodableValue; void CloudFirestorePlugin::TransactionStoreResult( const std::string& transaction_id, - const PigeonTransactionResult& result_type, + const InternalTransactionResult& result_type, const flutter::EncodableList* commands, std::function reply)> result) { if (CloudFirestorePlugin::transaction_handlers_[transaction_id]) { TransactionStreamHandler& handler = *static_cast( CloudFirestorePlugin::transaction_handlers_[transaction_id].get()); - std::vector commandVector; + std::vector commandVector; for (const auto& element : *commands) { - const PigeonTransactionCommand& command = - std::any_cast( + const InternalTransactionCommand& command = + std::any_cast( std::get(element)); commandVector.push_back(command); } @@ -1015,7 +1015,7 @@ void CloudFirestorePlugin::TransactionStoreResult( void CloudFirestorePlugin::TransactionGet( const FirestorePigeonFirebaseApp& app, const std::string& transaction_id, const std::string& path, - std::function reply)> result) { + std::function reply)> result) { Firestore* firestore = GetFirestoreFromPigeon(app); DocumentReference reference = firestore->Document(path); @@ -1114,7 +1114,7 @@ void CloudFirestorePlugin::DocumentReferenceUpdate( void CloudFirestorePlugin::DocumentReferenceGet( const FirestorePigeonFirebaseApp& app, const DocumentReferenceRequest& request, - std::function reply)> result) { + std::function reply)> result) { Firestore* firestore = GetFirestoreFromPigeon(app); DocumentReference document_reference = firestore->Document(request.path()); @@ -1249,10 +1249,9 @@ firebase::firestore::Filter filterFromJson(const EncodableMap& map) { throw std::runtime_error("Invalid operator"); } -firebase::firestore::Query ParseQuery(firebase::firestore::Firestore* firestore, - const std::string& path, - bool isCollectionGroup, - const PigeonQueryParameters& parameters) { +firebase::firestore::Query ParseQuery( + firebase::firestore::Firestore* firestore, const std::string& path, + bool isCollectionGroup, const InternalQueryParameters& parameters) { try { firebase::firestore::Query query; @@ -1369,9 +1368,9 @@ firebase::firestore::Query ParseQuery(firebase::firestore::Firestore* firestore, void CloudFirestorePlugin::QueryGet( const FirestorePigeonFirebaseApp& app, const std::string& path, - bool is_collection_group, const PigeonQueryParameters& parameters, - const PigeonGetOptions& options, - std::function reply)> result) { + bool is_collection_group, const InternalQueryParameters& parameters, + const InternalGetOptions& options, + std::function reply)> result) { Firestore* firestore = GetFirestoreFromPigeon(app); Query query = ParseQuery(firestore, path, is_collection_group, parameters); @@ -1397,7 +1396,7 @@ void CloudFirestorePlugin::QueryGet( firebase::firestore::AggregateSource GetAggregateSourceFromPigeon( const AggregateSource& source) { switch (source) { - case AggregateSource::server: + case AggregateSource::kServer: default: return firebase::firestore::AggregateSource::kServer; } @@ -1405,7 +1404,7 @@ firebase::firestore::AggregateSource GetAggregateSourceFromPigeon( void CloudFirestorePlugin::AggregateQuery( const FirestorePigeonFirebaseApp& app, const std::string& path, - const PigeonQueryParameters& parameters, const AggregateSource& source, + const InternalQueryParameters& parameters, const AggregateSource& source, const flutter::EncodableList& queries, bool is_collection_group, std::function reply)> result) { Firestore* firestore = GetFirestoreFromPigeon(app); @@ -1420,13 +1419,13 @@ void CloudFirestorePlugin::AggregateQuery( std::get(queryRequest)); switch (queryRequestTyped.type()) { - case AggregateType::count: + case AggregateType::kCount: aggregate_query = query.Count(); break; - case AggregateType::sum: + case AggregateType::kSum: std::cout << "Sum is not supported on C++" << std::endl; break; - case AggregateType::average: + case AggregateType::kAverage: std::cout << "Average is not supported on C++" << std::endl; break; } @@ -1449,20 +1448,20 @@ void CloudFirestorePlugin::AggregateQuery( std::get(queryRequest)); switch (queryRequestTyped.type()) { - case AggregateType::count: { + case AggregateType::kCount: { double doubleValue = static_cast(aggregateQuerySnapshot->count()); - AggregateQueryResponse aggregateResponse(AggregateType::count, + AggregateQueryResponse aggregateResponse(AggregateType::kCount, nullptr, &doubleValue); aggregateResponses.push_back( CustomEncodableValue(aggregateResponse)); break; } - case AggregateType::sum: { + case AggregateType::kSum: { std::cout << "Sum is not supported on C++" << std::endl; break; } - case AggregateType::average: { + case AggregateType::kAverage: { std::cout << "Average is not supported on C++" << std::endl; break; } @@ -1484,11 +1483,11 @@ void CloudFirestorePlugin::WriteBatchCommit( firebase::firestore::WriteBatch batch = firestore->batch(); for (const auto& write : writes) { - const PigeonTransactionCommand& transaction = - std::any_cast( + const InternalTransactionCommand& transaction = + std::any_cast( std::get(write)); - PigeonTransactionType type = transaction.type(); + InternalTransactionType type = transaction.type(); std::string path = transaction.path(); auto data = transaction.data(); @@ -1496,14 +1495,14 @@ void CloudFirestorePlugin::WriteBatchCommit( firestore->Document(path); switch (type) { - case PigeonTransactionType::deleteType: + case InternalTransactionType::kDeleteType: batch.Delete(documentReference); break; - case PigeonTransactionType::update: + case InternalTransactionType::kUpdate: batch.Update(documentReference, ConvertToMapFieldPathValue(*data)); break; - case PigeonTransactionType::set: - const PigeonDocumentOption* options = transaction.option(); + case InternalTransactionType::kSet: + const InternalDocumentOption* options = transaction.option(); if (options->merge()) { batch.Set(documentReference, ConvertToMapFieldValue(*data), @@ -1624,11 +1623,11 @@ class QuerySnapshotStreamHandler void CloudFirestorePlugin::QuerySnapshot( const FirestorePigeonFirebaseApp& app, const std::string& path, - bool is_collection_group, const PigeonQueryParameters& parameters, - const PigeonGetOptions& options, bool include_metadata_changes, + bool is_collection_group, const InternalQueryParameters& parameters, + const InternalGetOptions& options, bool include_metadata_changes, const ListenSource& source, std::function reply)> result) { - if (source == ListenSource::cache) { + if (source == ListenSource::kCache) { result(FlutterError("Listening from cache isn't supported on Windows")); return; } @@ -1717,7 +1716,7 @@ void CloudFirestorePlugin::DocumentReferenceSnapshot( const DocumentReferenceRequest& parameters, bool include_metadata_changes, const ListenSource& source, std::function reply)> result) { - if (source == ListenSource::cache) { + if (source == ListenSource::kCache) { result(FlutterError("Listening from cache isn't supported on Windows")); return; } @@ -1745,4 +1744,12 @@ void CloudFirestorePlugin::PersistenceCacheIndexManagerRequest( result(FlutterError("Not implemented on Windows")); } +void CloudFirestorePlugin::ExecutePipeline( + const FirestorePigeonFirebaseApp& app, + const ::flutter::EncodableList& stages, + const ::flutter::EncodableMap* options, + std::function reply)> result) { + result(FlutterError("Not implemented on Windows")); +} + } // namespace cloud_firestore_windows diff --git a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h index ee0dcb07e331..e99dac003c16 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h +++ b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h @@ -48,8 +48,9 @@ class CloudFirestorePlugin : public flutter::Plugin, std::function reply)> result) override; virtual void NamedQueryGet( const FirestorePigeonFirebaseApp& app, const std::string& name, - const PigeonGetOptions& options, - std::function reply)> result) override; + const InternalGetOptions& options, + std::function reply)> result) + override; virtual void ClearPersistence( const FirestorePigeonFirebaseApp& app, std::function reply)> result) override; @@ -81,13 +82,13 @@ class CloudFirestorePlugin : public flutter::Plugin, std::function reply)> result) override; virtual void TransactionStoreResult( const std::string& transaction_id, - const PigeonTransactionResult& result_type, + const InternalTransactionResult& result_type, const flutter::EncodableList* commands, std::function reply)> result) override; virtual void TransactionGet( const FirestorePigeonFirebaseApp& app, const std::string& transaction_id, const std::string& path, - std::function reply)> result) + std::function reply)> result) override; virtual void DocumentReferenceSet( const FirestorePigeonFirebaseApp& app, @@ -100,7 +101,7 @@ class CloudFirestorePlugin : public flutter::Plugin, virtual void DocumentReferenceGet( const FirestorePigeonFirebaseApp& app, const DocumentReferenceRequest& request, - std::function reply)> result) + std::function reply)> result) override; virtual void DocumentReferenceDelete( const FirestorePigeonFirebaseApp& app, @@ -108,12 +109,13 @@ class CloudFirestorePlugin : public flutter::Plugin, std::function reply)> result) override; virtual void QueryGet( const FirestorePigeonFirebaseApp& app, const std::string& path, - bool is_collection_group, const PigeonQueryParameters& parameters, - const PigeonGetOptions& options, - std::function reply)> result) override; + bool is_collection_group, const InternalQueryParameters& parameters, + const InternalGetOptions& options, + std::function reply)> result) + override; virtual void AggregateQuery( const FirestorePigeonFirebaseApp& app, const std::string& path, - const PigeonQueryParameters& parameters, const AggregateSource& source, + const InternalQueryParameters& parameters, const AggregateSource& source, const flutter::EncodableList& queries, bool is_collection_group, std::function reply)> result) override; @@ -123,8 +125,8 @@ class CloudFirestorePlugin : public flutter::Plugin, std::function reply)> result) override; virtual void QuerySnapshot( const FirestorePigeonFirebaseApp& app, const std::string& path, - bool is_collection_group, const PigeonQueryParameters& parameters, - const PigeonGetOptions& options, bool include_metadata_changes, + bool is_collection_group, const InternalQueryParameters& parameters, + const InternalGetOptions& options, bool include_metadata_changes, const ListenSource& source, std::function reply)> result) override; virtual void DocumentReferenceSnapshot( @@ -136,6 +138,12 @@ class CloudFirestorePlugin : public flutter::Plugin, const FirestorePigeonFirebaseApp& app, const PersistenceCacheIndexManagerRequestEnum& request, std::function reply)> result) override; + virtual void ExecutePipeline( + const FirestorePigeonFirebaseApp& app, + const ::flutter::EncodableList& stages, + const ::flutter::EncodableMap* options, + std::function reply)> result) + override; static flutter::BinaryMessenger* messenger_; static std::map< diff --git a/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp b/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp index bb9f58d5775d..9c3c6b9dceec 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp +++ b/packages/cloud_firestore/cloud_firestore/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,27 +13,242 @@ #include #include +#include +#include #include #include #include namespace cloud_firestore_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; -// PigeonFirebaseSettings +FlutterError CreateConnectionError(const std::string channel_name) { + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); +} + +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} -PigeonFirebaseSettings::PigeonFirebaseSettings(bool ignore_undefined_properties) +} // namespace +// InternalFirebaseSettings + +InternalFirebaseSettings::InternalFirebaseSettings( + bool ignore_undefined_properties) : ignore_undefined_properties_(ignore_undefined_properties) {} -PigeonFirebaseSettings::PigeonFirebaseSettings(const bool* persistence_enabled, - const std::string* host, - const bool* ssl_enabled, - const int64_t* cache_size_bytes, - bool ignore_undefined_properties) +InternalFirebaseSettings::InternalFirebaseSettings( + const bool* persistence_enabled, const std::string* host, + const bool* ssl_enabled, const int64_t* cache_size_bytes, + bool ignore_undefined_properties) : persistence_enabled_(persistence_enabled ? std::optional(*persistence_enabled) : std::nullopt), @@ -45,65 +260,65 @@ PigeonFirebaseSettings::PigeonFirebaseSettings(const bool* persistence_enabled, : std::nullopt), ignore_undefined_properties_(ignore_undefined_properties) {} -const bool* PigeonFirebaseSettings::persistence_enabled() const { +const bool* InternalFirebaseSettings::persistence_enabled() const { return persistence_enabled_ ? &(*persistence_enabled_) : nullptr; } -void PigeonFirebaseSettings::set_persistence_enabled(const bool* value_arg) { +void InternalFirebaseSettings::set_persistence_enabled(const bool* value_arg) { persistence_enabled_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseSettings::set_persistence_enabled(bool value_arg) { +void InternalFirebaseSettings::set_persistence_enabled(bool value_arg) { persistence_enabled_ = value_arg; } -const std::string* PigeonFirebaseSettings::host() const { +const std::string* InternalFirebaseSettings::host() const { return host_ ? &(*host_) : nullptr; } -void PigeonFirebaseSettings::set_host(const std::string_view* value_arg) { +void InternalFirebaseSettings::set_host(const std::string_view* value_arg) { host_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseSettings::set_host(std::string_view value_arg) { +void InternalFirebaseSettings::set_host(std::string_view value_arg) { host_ = value_arg; } -const bool* PigeonFirebaseSettings::ssl_enabled() const { +const bool* InternalFirebaseSettings::ssl_enabled() const { return ssl_enabled_ ? &(*ssl_enabled_) : nullptr; } -void PigeonFirebaseSettings::set_ssl_enabled(const bool* value_arg) { +void InternalFirebaseSettings::set_ssl_enabled(const bool* value_arg) { ssl_enabled_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseSettings::set_ssl_enabled(bool value_arg) { +void InternalFirebaseSettings::set_ssl_enabled(bool value_arg) { ssl_enabled_ = value_arg; } -const int64_t* PigeonFirebaseSettings::cache_size_bytes() const { +const int64_t* InternalFirebaseSettings::cache_size_bytes() const { return cache_size_bytes_ ? &(*cache_size_bytes_) : nullptr; } -void PigeonFirebaseSettings::set_cache_size_bytes(const int64_t* value_arg) { +void InternalFirebaseSettings::set_cache_size_bytes(const int64_t* value_arg) { cache_size_bytes_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseSettings::set_cache_size_bytes(int64_t value_arg) { +void InternalFirebaseSettings::set_cache_size_bytes(int64_t value_arg) { cache_size_bytes_ = value_arg; } -bool PigeonFirebaseSettings::ignore_undefined_properties() const { +bool InternalFirebaseSettings::ignore_undefined_properties() const { return ignore_undefined_properties_; } -void PigeonFirebaseSettings::set_ignore_undefined_properties(bool value_arg) { +void InternalFirebaseSettings::set_ignore_undefined_properties(bool value_arg) { ignore_undefined_properties_ = value_arg; } -EncodableList PigeonFirebaseSettings::ToEncodableList() const { +EncodableList InternalFirebaseSettings::ToEncodableList() const { EncodableList list; list.reserve(5); list.push_back(persistence_enabled_ ? EncodableValue(*persistence_enabled_) @@ -117,9 +332,9 @@ EncodableList PigeonFirebaseSettings::ToEncodableList() const { return list; } -PigeonFirebaseSettings PigeonFirebaseSettings::FromEncodableList( +InternalFirebaseSettings InternalFirebaseSettings::FromEncodableList( const EncodableList& list) { - PigeonFirebaseSettings decoded(std::get(list[4])); + InternalFirebaseSettings decoded(std::get(list[4])); auto& encodable_persistence_enabled = list[0]; if (!encodable_persistence_enabled.IsNull()) { decoded.set_persistence_enabled( @@ -135,20 +350,64 @@ PigeonFirebaseSettings PigeonFirebaseSettings::FromEncodableList( } auto& encodable_cache_size_bytes = list[3]; if (!encodable_cache_size_bytes.IsNull()) { - decoded.set_cache_size_bytes(encodable_cache_size_bytes.LongValue()); + decoded.set_cache_size_bytes(std::get(encodable_cache_size_bytes)); } return decoded; } +bool InternalFirebaseSettings::operator==( + const InternalFirebaseSettings& other) const { + return PigeonInternalDeepEquals(persistence_enabled_, + other.persistence_enabled_) && + PigeonInternalDeepEquals(host_, other.host_) && + PigeonInternalDeepEquals(ssl_enabled_, other.ssl_enabled_) && + PigeonInternalDeepEquals(cache_size_bytes_, other.cache_size_bytes_) && + PigeonInternalDeepEquals(ignore_undefined_properties_, + other.ignore_undefined_properties_); +} + +bool InternalFirebaseSettings::operator!=( + const InternalFirebaseSettings& other) const { + return !(*this == other); +} + +size_t InternalFirebaseSettings::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(persistence_enabled_); + result = result * 31 + PigeonInternalDeepHash(host_); + result = result * 31 + PigeonInternalDeepHash(ssl_enabled_); + result = result * 31 + PigeonInternalDeepHash(cache_size_bytes_); + result = result * 31 + PigeonInternalDeepHash(ignore_undefined_properties_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalFirebaseSettings& v) { + return v.Hash(); +} + // FirestorePigeonFirebaseApp FirestorePigeonFirebaseApp::FirestorePigeonFirebaseApp( - const std::string& app_name, const PigeonFirebaseSettings& settings, + const std::string& app_name, const InternalFirebaseSettings& settings, const std::string& database_u_r_l) : app_name_(app_name), - settings_(settings), + settings_(std::make_unique(settings)), database_u_r_l_(database_u_r_l) {} +FirestorePigeonFirebaseApp::FirestorePigeonFirebaseApp( + const FirestorePigeonFirebaseApp& other) + : app_name_(other.app_name_), + settings_(std::make_unique(*other.settings_)), + database_u_r_l_(other.database_u_r_l_) {} + +FirestorePigeonFirebaseApp& FirestorePigeonFirebaseApp::operator=( + const FirestorePigeonFirebaseApp& other) { + app_name_ = other.app_name_; + settings_ = std::make_unique(*other.settings_); + database_u_r_l_ = other.database_u_r_l_; + return *this; +} + const std::string& FirestorePigeonFirebaseApp::app_name() const { return app_name_; } @@ -157,13 +416,13 @@ void FirestorePigeonFirebaseApp::set_app_name(std::string_view value_arg) { app_name_ = value_arg; } -const PigeonFirebaseSettings& FirestorePigeonFirebaseApp::settings() const { - return settings_; +const InternalFirebaseSettings& FirestorePigeonFirebaseApp::settings() const { + return *settings_; } void FirestorePigeonFirebaseApp::set_settings( - const PigeonFirebaseSettings& value_arg) { - settings_ = value_arg; + const InternalFirebaseSettings& value_arg) { + settings_ = std::make_unique(value_arg); } const std::string& FirestorePigeonFirebaseApp::database_u_r_l() const { @@ -179,41 +438,66 @@ EncodableList FirestorePigeonFirebaseApp::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(EncodableValue(app_name_)); - list.push_back(EncodableValue(settings_.ToEncodableList())); + list.push_back(CustomEncodableValue(*settings_)); list.push_back(EncodableValue(database_u_r_l_)); return list; } FirestorePigeonFirebaseApp FirestorePigeonFirebaseApp::FromEncodableList( const EncodableList& list) { - FirestorePigeonFirebaseApp decoded(std::get(list[0]), - PigeonFirebaseSettings::FromEncodableList( - std::get(list[1])), - std::get(list[2])); + FirestorePigeonFirebaseApp decoded( + std::get(list[0]), + std::any_cast( + std::get(list[1])), + std::get(list[2])); return decoded; } -// PigeonSnapshotMetadata +bool FirestorePigeonFirebaseApp::operator==( + const FirestorePigeonFirebaseApp& other) const { + return PigeonInternalDeepEquals(app_name_, other.app_name_) && + PigeonInternalDeepEquals(settings_, other.settings_) && + PigeonInternalDeepEquals(database_u_r_l_, other.database_u_r_l_); +} -PigeonSnapshotMetadata::PigeonSnapshotMetadata(bool has_pending_writes, - bool is_from_cache) +bool FirestorePigeonFirebaseApp::operator!=( + const FirestorePigeonFirebaseApp& other) const { + return !(*this == other); +} + +size_t FirestorePigeonFirebaseApp::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(app_name_); + result = result * 31 + PigeonInternalDeepHash(settings_); + result = result * 31 + PigeonInternalDeepHash(database_u_r_l_); + return result; +} + +size_t PigeonInternalDeepHash(const FirestorePigeonFirebaseApp& v) { + return v.Hash(); +} + +// InternalSnapshotMetadata + +InternalSnapshotMetadata::InternalSnapshotMetadata(bool has_pending_writes, + bool is_from_cache) : has_pending_writes_(has_pending_writes), is_from_cache_(is_from_cache) {} -bool PigeonSnapshotMetadata::has_pending_writes() const { +bool InternalSnapshotMetadata::has_pending_writes() const { return has_pending_writes_; } -void PigeonSnapshotMetadata::set_has_pending_writes(bool value_arg) { +void InternalSnapshotMetadata::set_has_pending_writes(bool value_arg) { has_pending_writes_ = value_arg; } -bool PigeonSnapshotMetadata::is_from_cache() const { return is_from_cache_; } +bool InternalSnapshotMetadata::is_from_cache() const { return is_from_cache_; } -void PigeonSnapshotMetadata::set_is_from_cache(bool value_arg) { +void InternalSnapshotMetadata::set_is_from_cache(bool value_arg) { is_from_cache_ = value_arg; } -EncodableList PigeonSnapshotMetadata::ToEncodableList() const { +EncodableList InternalSnapshotMetadata::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(EncodableValue(has_pending_writes_)); @@ -221,67 +505,107 @@ EncodableList PigeonSnapshotMetadata::ToEncodableList() const { return list; } -PigeonSnapshotMetadata PigeonSnapshotMetadata::FromEncodableList( +InternalSnapshotMetadata InternalSnapshotMetadata::FromEncodableList( const EncodableList& list) { - PigeonSnapshotMetadata decoded(std::get(list[0]), - std::get(list[1])); + InternalSnapshotMetadata decoded(std::get(list[0]), + std::get(list[1])); return decoded; } -// PigeonDocumentSnapshot +bool InternalSnapshotMetadata::operator==( + const InternalSnapshotMetadata& other) const { + return PigeonInternalDeepEquals(has_pending_writes_, + other.has_pending_writes_) && + PigeonInternalDeepEquals(is_from_cache_, other.is_from_cache_); +} + +bool InternalSnapshotMetadata::operator!=( + const InternalSnapshotMetadata& other) const { + return !(*this == other); +} + +size_t InternalSnapshotMetadata::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(has_pending_writes_); + result = result * 31 + PigeonInternalDeepHash(is_from_cache_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalSnapshotMetadata& v) { + return v.Hash(); +} + +// InternalDocumentSnapshot -PigeonDocumentSnapshot::PigeonDocumentSnapshot( - const std::string& path, const PigeonSnapshotMetadata& metadata) - : path_(path), metadata_(metadata) {} +InternalDocumentSnapshot::InternalDocumentSnapshot( + const std::string& path, const InternalSnapshotMetadata& metadata) + : path_(path), + metadata_(std::make_unique(metadata)) {} -PigeonDocumentSnapshot::PigeonDocumentSnapshot( +InternalDocumentSnapshot::InternalDocumentSnapshot( const std::string& path, const EncodableMap* data, - const PigeonSnapshotMetadata& metadata) + const InternalSnapshotMetadata& metadata) : path_(path), data_(data ? std::optional(*data) : std::nullopt), - metadata_(metadata) {} + metadata_(std::make_unique(metadata)) {} -const std::string& PigeonDocumentSnapshot::path() const { return path_; } +InternalDocumentSnapshot::InternalDocumentSnapshot( + const InternalDocumentSnapshot& other) + : path_(other.path_), + data_(other.data_ ? std::optional(*other.data_) + : std::nullopt), + metadata_(std::make_unique(*other.metadata_)) {} -void PigeonDocumentSnapshot::set_path(std::string_view value_arg) { +InternalDocumentSnapshot& InternalDocumentSnapshot::operator=( + const InternalDocumentSnapshot& other) { + path_ = other.path_; + data_ = other.data_; + metadata_ = std::make_unique(*other.metadata_); + return *this; +} + +const std::string& InternalDocumentSnapshot::path() const { return path_; } + +void InternalDocumentSnapshot::set_path(std::string_view value_arg) { path_ = value_arg; } -const EncodableMap* PigeonDocumentSnapshot::data() const { +const EncodableMap* InternalDocumentSnapshot::data() const { return data_ ? &(*data_) : nullptr; } -void PigeonDocumentSnapshot::set_data(const EncodableMap* value_arg) { +void InternalDocumentSnapshot::set_data(const EncodableMap* value_arg) { data_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonDocumentSnapshot::set_data(const EncodableMap& value_arg) { +void InternalDocumentSnapshot::set_data(const EncodableMap& value_arg) { data_ = value_arg; } -const PigeonSnapshotMetadata& PigeonDocumentSnapshot::metadata() const { - return metadata_; +const InternalSnapshotMetadata& InternalDocumentSnapshot::metadata() const { + return *metadata_; } -void PigeonDocumentSnapshot::set_metadata( - const PigeonSnapshotMetadata& value_arg) { - metadata_ = value_arg; +void InternalDocumentSnapshot::set_metadata( + const InternalSnapshotMetadata& value_arg) { + metadata_ = std::make_unique(value_arg); } -EncodableList PigeonDocumentSnapshot::ToEncodableList() const { +EncodableList InternalDocumentSnapshot::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(EncodableValue(path_)); list.push_back(data_ ? EncodableValue(*data_) : EncodableValue()); - list.push_back(EncodableValue(metadata_.ToEncodableList())); + list.push_back(CustomEncodableValue(*metadata_)); return list; } -PigeonDocumentSnapshot PigeonDocumentSnapshot::FromEncodableList( +InternalDocumentSnapshot InternalDocumentSnapshot::FromEncodableList( const EncodableList& list) { - PigeonDocumentSnapshot decoded(std::get(list[0]), - PigeonSnapshotMetadata::FromEncodableList( - std::get(list[2]))); + InternalDocumentSnapshot decoded( + std::get(list[0]), + std::any_cast( + std::get(list[2]))); auto& encodable_data = list[1]; if (!encodable_data.IsNull()) { decoded.set_data(std::get(encodable_data)); @@ -289,187 +613,499 @@ PigeonDocumentSnapshot PigeonDocumentSnapshot::FromEncodableList( return decoded; } -// PigeonDocumentChange +bool InternalDocumentSnapshot::operator==( + const InternalDocumentSnapshot& other) const { + return PigeonInternalDeepEquals(path_, other.path_) && + PigeonInternalDeepEquals(data_, other.data_) && + PigeonInternalDeepEquals(metadata_, other.metadata_); +} + +bool InternalDocumentSnapshot::operator!=( + const InternalDocumentSnapshot& other) const { + return !(*this == other); +} + +size_t InternalDocumentSnapshot::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(path_); + result = result * 31 + PigeonInternalDeepHash(data_); + result = result * 31 + PigeonInternalDeepHash(metadata_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalDocumentSnapshot& v) { + return v.Hash(); +} + +// InternalDocumentChange -PigeonDocumentChange::PigeonDocumentChange( - const DocumentChangeType& type, const PigeonDocumentSnapshot& document, +InternalDocumentChange::InternalDocumentChange( + const DocumentChangeType& type, const InternalDocumentSnapshot& document, int64_t old_index, int64_t new_index) : type_(type), - document_(document), + document_(std::make_unique(document)), old_index_(old_index), new_index_(new_index) {} -const DocumentChangeType& PigeonDocumentChange::type() const { return type_; } +InternalDocumentChange::InternalDocumentChange( + const InternalDocumentChange& other) + : type_(other.type_), + document_(std::make_unique(*other.document_)), + old_index_(other.old_index_), + new_index_(other.new_index_) {} -void PigeonDocumentChange::set_type(const DocumentChangeType& value_arg) { +InternalDocumentChange& InternalDocumentChange::operator=( + const InternalDocumentChange& other) { + type_ = other.type_; + document_ = std::make_unique(*other.document_); + old_index_ = other.old_index_; + new_index_ = other.new_index_; + return *this; +} + +const DocumentChangeType& InternalDocumentChange::type() const { return type_; } + +void InternalDocumentChange::set_type(const DocumentChangeType& value_arg) { type_ = value_arg; } -const PigeonDocumentSnapshot& PigeonDocumentChange::document() const { - return document_; +const InternalDocumentSnapshot& InternalDocumentChange::document() const { + return *document_; } -void PigeonDocumentChange::set_document( - const PigeonDocumentSnapshot& value_arg) { - document_ = value_arg; +void InternalDocumentChange::set_document( + const InternalDocumentSnapshot& value_arg) { + document_ = std::make_unique(value_arg); } -int64_t PigeonDocumentChange::old_index() const { return old_index_; } +int64_t InternalDocumentChange::old_index() const { return old_index_; } -void PigeonDocumentChange::set_old_index(int64_t value_arg) { +void InternalDocumentChange::set_old_index(int64_t value_arg) { old_index_ = value_arg; } -int64_t PigeonDocumentChange::new_index() const { return new_index_; } +int64_t InternalDocumentChange::new_index() const { return new_index_; } -void PigeonDocumentChange::set_new_index(int64_t value_arg) { +void InternalDocumentChange::set_new_index(int64_t value_arg) { new_index_ = value_arg; } -EncodableList PigeonDocumentChange::ToEncodableList() const { +EncodableList InternalDocumentChange::ToEncodableList() const { EncodableList list; list.reserve(4); - list.push_back(EncodableValue((int)type_)); - list.push_back(EncodableValue(document_.ToEncodableList())); + list.push_back(CustomEncodableValue(type_)); + list.push_back(CustomEncodableValue(*document_)); list.push_back(EncodableValue(old_index_)); list.push_back(EncodableValue(new_index_)); return list; } -PigeonDocumentChange PigeonDocumentChange::FromEncodableList( +InternalDocumentChange InternalDocumentChange::FromEncodableList( const EncodableList& list) { - PigeonDocumentChange decoded((DocumentChangeType)(std::get(list[0])), - PigeonDocumentSnapshot::FromEncodableList( - std::get(list[1])), - list[2].LongValue(), list[3].LongValue()); + InternalDocumentChange decoded(std::any_cast( + std::get(list[0])), + std::any_cast( + std::get(list[1])), + std::get(list[2]), + std::get(list[3])); return decoded; } -// PigeonQuerySnapshot +bool InternalDocumentChange::operator==( + const InternalDocumentChange& other) const { + return PigeonInternalDeepEquals(type_, other.type_) && + PigeonInternalDeepEquals(document_, other.document_) && + PigeonInternalDeepEquals(old_index_, other.old_index_) && + PigeonInternalDeepEquals(new_index_, other.new_index_); +} -PigeonQuerySnapshot::PigeonQuerySnapshot(const EncodableList& documents, - const EncodableList& document_changes, - const PigeonSnapshotMetadata& metadata) +bool InternalDocumentChange::operator!=( + const InternalDocumentChange& other) const { + return !(*this == other); +} + +size_t InternalDocumentChange::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(type_); + result = result * 31 + PigeonInternalDeepHash(document_); + result = result * 31 + PigeonInternalDeepHash(old_index_); + result = result * 31 + PigeonInternalDeepHash(new_index_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalDocumentChange& v) { + return v.Hash(); +} + +// InternalQuerySnapshot + +InternalQuerySnapshot::InternalQuerySnapshot( + const EncodableList& documents, const EncodableList& document_changes, + const InternalSnapshotMetadata& metadata) : documents_(documents), document_changes_(document_changes), - metadata_(metadata) {} + metadata_(std::make_unique(metadata)) {} + +InternalQuerySnapshot::InternalQuerySnapshot(const InternalQuerySnapshot& other) + : documents_(other.documents_), + document_changes_(other.document_changes_), + metadata_(std::make_unique(*other.metadata_)) {} + +InternalQuerySnapshot& InternalQuerySnapshot::operator=( + const InternalQuerySnapshot& other) { + documents_ = other.documents_; + document_changes_ = other.document_changes_; + metadata_ = std::make_unique(*other.metadata_); + return *this; +} -const EncodableList& PigeonQuerySnapshot::documents() const { +const EncodableList& InternalQuerySnapshot::documents() const { return documents_; } -void PigeonQuerySnapshot::set_documents(const EncodableList& value_arg) { +void InternalQuerySnapshot::set_documents(const EncodableList& value_arg) { documents_ = value_arg; } -const EncodableList& PigeonQuerySnapshot::document_changes() const { +const EncodableList& InternalQuerySnapshot::document_changes() const { return document_changes_; } -void PigeonQuerySnapshot::set_document_changes(const EncodableList& value_arg) { +void InternalQuerySnapshot::set_document_changes( + const EncodableList& value_arg) { document_changes_ = value_arg; } -const PigeonSnapshotMetadata& PigeonQuerySnapshot::metadata() const { - return metadata_; +const InternalSnapshotMetadata& InternalQuerySnapshot::metadata() const { + return *metadata_; } -void PigeonQuerySnapshot::set_metadata( - const PigeonSnapshotMetadata& value_arg) { - metadata_ = value_arg; +void InternalQuerySnapshot::set_metadata( + const InternalSnapshotMetadata& value_arg) { + metadata_ = std::make_unique(value_arg); } -EncodableList PigeonQuerySnapshot::ToEncodableList() const { +EncodableList InternalQuerySnapshot::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(EncodableValue(documents_)); list.push_back(EncodableValue(document_changes_)); - list.push_back(EncodableValue(metadata_.ToEncodableList())); + list.push_back(CustomEncodableValue(*metadata_)); return list; } -PigeonQuerySnapshot PigeonQuerySnapshot::FromEncodableList( +InternalQuerySnapshot InternalQuerySnapshot::FromEncodableList( const EncodableList& list) { - PigeonQuerySnapshot decoded(std::get(list[0]), - std::get(list[1]), - PigeonSnapshotMetadata::FromEncodableList( - std::get(list[2]))); + InternalQuerySnapshot decoded(std::get(list[0]), + std::get(list[1]), + std::any_cast( + std::get(list[2]))); return decoded; } -// PigeonGetOptions +bool InternalQuerySnapshot::operator==( + const InternalQuerySnapshot& other) const { + return PigeonInternalDeepEquals(documents_, other.documents_) && + PigeonInternalDeepEquals(document_changes_, other.document_changes_) && + PigeonInternalDeepEquals(metadata_, other.metadata_); +} + +bool InternalQuerySnapshot::operator!=( + const InternalQuerySnapshot& other) const { + return !(*this == other); +} + +size_t InternalQuerySnapshot::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(documents_); + result = result * 31 + PigeonInternalDeepHash(document_changes_); + result = result * 31 + PigeonInternalDeepHash(metadata_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalQuerySnapshot& v) { + return v.Hash(); +} + +// InternalPipelineResult + +InternalPipelineResult::InternalPipelineResult() {} + +InternalPipelineResult::InternalPipelineResult(const std::string* document_path, + const int64_t* create_time, + const int64_t* update_time, + const EncodableMap* data) + : document_path_(document_path ? std::optional(*document_path) + : std::nullopt), + create_time_(create_time ? std::optional(*create_time) + : std::nullopt), + update_time_(update_time ? std::optional(*update_time) + : std::nullopt), + data_(data ? std::optional(*data) : std::nullopt) {} + +const std::string* InternalPipelineResult::document_path() const { + return document_path_ ? &(*document_path_) : nullptr; +} + +void InternalPipelineResult::set_document_path( + const std::string_view* value_arg) { + document_path_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void InternalPipelineResult::set_document_path(std::string_view value_arg) { + document_path_ = value_arg; +} + +const int64_t* InternalPipelineResult::create_time() const { + return create_time_ ? &(*create_time_) : nullptr; +} + +void InternalPipelineResult::set_create_time(const int64_t* value_arg) { + create_time_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void InternalPipelineResult::set_create_time(int64_t value_arg) { + create_time_ = value_arg; +} + +const int64_t* InternalPipelineResult::update_time() const { + return update_time_ ? &(*update_time_) : nullptr; +} -PigeonGetOptions::PigeonGetOptions( +void InternalPipelineResult::set_update_time(const int64_t* value_arg) { + update_time_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void InternalPipelineResult::set_update_time(int64_t value_arg) { + update_time_ = value_arg; +} + +const EncodableMap* InternalPipelineResult::data() const { + return data_ ? &(*data_) : nullptr; +} + +void InternalPipelineResult::set_data(const EncodableMap* value_arg) { + data_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void InternalPipelineResult::set_data(const EncodableMap& value_arg) { + data_ = value_arg; +} + +EncodableList InternalPipelineResult::ToEncodableList() const { + EncodableList list; + list.reserve(4); + list.push_back(document_path_ ? EncodableValue(*document_path_) + : EncodableValue()); + list.push_back(create_time_ ? EncodableValue(*create_time_) + : EncodableValue()); + list.push_back(update_time_ ? EncodableValue(*update_time_) + : EncodableValue()); + list.push_back(data_ ? EncodableValue(*data_) : EncodableValue()); + return list; +} + +InternalPipelineResult InternalPipelineResult::FromEncodableList( + const EncodableList& list) { + InternalPipelineResult decoded; + auto& encodable_document_path = list[0]; + if (!encodable_document_path.IsNull()) { + decoded.set_document_path(std::get(encodable_document_path)); + } + auto& encodable_create_time = list[1]; + if (!encodable_create_time.IsNull()) { + decoded.set_create_time(std::get(encodable_create_time)); + } + auto& encodable_update_time = list[2]; + if (!encodable_update_time.IsNull()) { + decoded.set_update_time(std::get(encodable_update_time)); + } + auto& encodable_data = list[3]; + if (!encodable_data.IsNull()) { + decoded.set_data(std::get(encodable_data)); + } + return decoded; +} + +bool InternalPipelineResult::operator==( + const InternalPipelineResult& other) const { + return PigeonInternalDeepEquals(document_path_, other.document_path_) && + PigeonInternalDeepEquals(create_time_, other.create_time_) && + PigeonInternalDeepEquals(update_time_, other.update_time_) && + PigeonInternalDeepEquals(data_, other.data_); +} + +bool InternalPipelineResult::operator!=( + const InternalPipelineResult& other) const { + return !(*this == other); +} + +size_t InternalPipelineResult::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(document_path_); + result = result * 31 + PigeonInternalDeepHash(create_time_); + result = result * 31 + PigeonInternalDeepHash(update_time_); + result = result * 31 + PigeonInternalDeepHash(data_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalPipelineResult& v) { + return v.Hash(); +} + +// InternalPipelineSnapshot + +InternalPipelineSnapshot::InternalPipelineSnapshot(const EncodableList& results, + int64_t execution_time) + : results_(results), execution_time_(execution_time) {} + +const EncodableList& InternalPipelineSnapshot::results() const { + return results_; +} + +void InternalPipelineSnapshot::set_results(const EncodableList& value_arg) { + results_ = value_arg; +} + +int64_t InternalPipelineSnapshot::execution_time() const { + return execution_time_; +} + +void InternalPipelineSnapshot::set_execution_time(int64_t value_arg) { + execution_time_ = value_arg; +} + +EncodableList InternalPipelineSnapshot::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(results_)); + list.push_back(EncodableValue(execution_time_)); + return list; +} + +InternalPipelineSnapshot InternalPipelineSnapshot::FromEncodableList( + const EncodableList& list) { + InternalPipelineSnapshot decoded(std::get(list[0]), + std::get(list[1])); + return decoded; +} + +bool InternalPipelineSnapshot::operator==( + const InternalPipelineSnapshot& other) const { + return PigeonInternalDeepEquals(results_, other.results_) && + PigeonInternalDeepEquals(execution_time_, other.execution_time_); +} + +bool InternalPipelineSnapshot::operator!=( + const InternalPipelineSnapshot& other) const { + return !(*this == other); +} + +size_t InternalPipelineSnapshot::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(results_); + result = result * 31 + PigeonInternalDeepHash(execution_time_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalPipelineSnapshot& v) { + return v.Hash(); +} + +// InternalGetOptions + +InternalGetOptions::InternalGetOptions( const Source& source, const ServerTimestampBehavior& server_timestamp_behavior) : source_(source), server_timestamp_behavior_(server_timestamp_behavior) {} -const Source& PigeonGetOptions::source() const { return source_; } +const Source& InternalGetOptions::source() const { return source_; } -void PigeonGetOptions::set_source(const Source& value_arg) { +void InternalGetOptions::set_source(const Source& value_arg) { source_ = value_arg; } -const ServerTimestampBehavior& PigeonGetOptions::server_timestamp_behavior() +const ServerTimestampBehavior& InternalGetOptions::server_timestamp_behavior() const { return server_timestamp_behavior_; } -void PigeonGetOptions::set_server_timestamp_behavior( +void InternalGetOptions::set_server_timestamp_behavior( const ServerTimestampBehavior& value_arg) { server_timestamp_behavior_ = value_arg; } -EncodableList PigeonGetOptions::ToEncodableList() const { +EncodableList InternalGetOptions::ToEncodableList() const { EncodableList list; list.reserve(2); - list.push_back(EncodableValue((int)source_)); - list.push_back(EncodableValue((int)server_timestamp_behavior_)); + list.push_back(CustomEncodableValue(source_)); + list.push_back(CustomEncodableValue(server_timestamp_behavior_)); return list; } -PigeonGetOptions PigeonGetOptions::FromEncodableList( +InternalGetOptions InternalGetOptions::FromEncodableList( const EncodableList& list) { - PigeonGetOptions decoded( - (Source)(std::get(list[0])), - (ServerTimestampBehavior)(std::get(list[1]))); + InternalGetOptions decoded( + std::any_cast(std::get(list[0])), + std::any_cast( + std::get(list[1]))); return decoded; } -// PigeonDocumentOption +bool InternalGetOptions::operator==(const InternalGetOptions& other) const { + return PigeonInternalDeepEquals(source_, other.source_) && + PigeonInternalDeepEquals(server_timestamp_behavior_, + other.server_timestamp_behavior_); +} + +bool InternalGetOptions::operator!=(const InternalGetOptions& other) const { + return !(*this == other); +} + +size_t InternalGetOptions::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(source_); + result = result * 31 + PigeonInternalDeepHash(server_timestamp_behavior_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalGetOptions& v) { return v.Hash(); } + +// InternalDocumentOption -PigeonDocumentOption::PigeonDocumentOption() {} +InternalDocumentOption::InternalDocumentOption() {} -PigeonDocumentOption::PigeonDocumentOption(const bool* merge, - const EncodableList* merge_fields) +InternalDocumentOption::InternalDocumentOption( + const bool* merge, const EncodableList* merge_fields) : merge_(merge ? std::optional(*merge) : std::nullopt), merge_fields_(merge_fields ? std::optional(*merge_fields) : std::nullopt) {} -const bool* PigeonDocumentOption::merge() const { +const bool* InternalDocumentOption::merge() const { return merge_ ? &(*merge_) : nullptr; } -void PigeonDocumentOption::set_merge(const bool* value_arg) { +void InternalDocumentOption::set_merge(const bool* value_arg) { merge_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonDocumentOption::set_merge(bool value_arg) { merge_ = value_arg; } +void InternalDocumentOption::set_merge(bool value_arg) { merge_ = value_arg; } -const EncodableList* PigeonDocumentOption::merge_fields() const { +const EncodableList* InternalDocumentOption::merge_fields() const { return merge_fields_ ? &(*merge_fields_) : nullptr; } -void PigeonDocumentOption::set_merge_fields(const EncodableList* value_arg) { +void InternalDocumentOption::set_merge_fields(const EncodableList* value_arg) { merge_fields_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonDocumentOption::set_merge_fields(const EncodableList& value_arg) { +void InternalDocumentOption::set_merge_fields(const EncodableList& value_arg) { merge_fields_ = value_arg; } -EncodableList PigeonDocumentOption::ToEncodableList() const { +EncodableList InternalDocumentOption::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(merge_ ? EncodableValue(*merge_) : EncodableValue()); @@ -478,9 +1114,9 @@ EncodableList PigeonDocumentOption::ToEncodableList() const { return list; } -PigeonDocumentOption PigeonDocumentOption::FromEncodableList( +InternalDocumentOption InternalDocumentOption::FromEncodableList( const EncodableList& list) { - PigeonDocumentOption decoded; + InternalDocumentOption decoded; auto& encodable_merge = list[0]; if (!encodable_merge.IsNull()) { decoded.set_merge(std::get(encodable_merge)); @@ -492,78 +1128,121 @@ PigeonDocumentOption PigeonDocumentOption::FromEncodableList( return decoded; } -// PigeonTransactionCommand +bool InternalDocumentOption::operator==( + const InternalDocumentOption& other) const { + return PigeonInternalDeepEquals(merge_, other.merge_) && + PigeonInternalDeepEquals(merge_fields_, other.merge_fields_); +} + +bool InternalDocumentOption::operator!=( + const InternalDocumentOption& other) const { + return !(*this == other); +} -PigeonTransactionCommand::PigeonTransactionCommand( - const PigeonTransactionType& type, const std::string& path) +size_t InternalDocumentOption::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(merge_); + result = result * 31 + PigeonInternalDeepHash(merge_fields_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalDocumentOption& v) { + return v.Hash(); +} + +// InternalTransactionCommand + +InternalTransactionCommand::InternalTransactionCommand( + const InternalTransactionType& type, const std::string& path) : type_(type), path_(path) {} -PigeonTransactionCommand::PigeonTransactionCommand( - const PigeonTransactionType& type, const std::string& path, - const EncodableMap* data, const PigeonDocumentOption* option) +InternalTransactionCommand::InternalTransactionCommand( + const InternalTransactionType& type, const std::string& path, + const EncodableMap* data, const InternalDocumentOption* option) : type_(type), path_(path), data_(data ? std::optional(*data) : std::nullopt), - option_(option ? std::optional(*option) - : std::nullopt) {} - -const PigeonTransactionType& PigeonTransactionCommand::type() const { + option_(option ? std::make_unique(*option) + : nullptr) {} + +InternalTransactionCommand::InternalTransactionCommand( + const InternalTransactionCommand& other) + : type_(other.type_), + path_(other.path_), + data_(other.data_ ? std::optional(*other.data_) + : std::nullopt), + option_(other.option_ + ? std::make_unique(*other.option_) + : nullptr) {} + +InternalTransactionCommand& InternalTransactionCommand::operator=( + const InternalTransactionCommand& other) { + type_ = other.type_; + path_ = other.path_; + data_ = other.data_; + option_ = other.option_ + ? std::make_unique(*other.option_) + : nullptr; + return *this; +} + +const InternalTransactionType& InternalTransactionCommand::type() const { return type_; } -void PigeonTransactionCommand::set_type( - const PigeonTransactionType& value_arg) { +void InternalTransactionCommand::set_type( + const InternalTransactionType& value_arg) { type_ = value_arg; } -const std::string& PigeonTransactionCommand::path() const { return path_; } +const std::string& InternalTransactionCommand::path() const { return path_; } -void PigeonTransactionCommand::set_path(std::string_view value_arg) { +void InternalTransactionCommand::set_path(std::string_view value_arg) { path_ = value_arg; } -const EncodableMap* PigeonTransactionCommand::data() const { +const EncodableMap* InternalTransactionCommand::data() const { return data_ ? &(*data_) : nullptr; } -void PigeonTransactionCommand::set_data(const EncodableMap* value_arg) { +void InternalTransactionCommand::set_data(const EncodableMap* value_arg) { data_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonTransactionCommand::set_data(const EncodableMap& value_arg) { +void InternalTransactionCommand::set_data(const EncodableMap& value_arg) { data_ = value_arg; } -const PigeonDocumentOption* PigeonTransactionCommand::option() const { - return option_ ? &(*option_) : nullptr; +const InternalDocumentOption* InternalTransactionCommand::option() const { + return option_.get(); } -void PigeonTransactionCommand::set_option( - const PigeonDocumentOption* value_arg) { - option_ = value_arg ? std::optional(*value_arg) - : std::nullopt; +void InternalTransactionCommand::set_option( + const InternalDocumentOption* value_arg) { + option_ = value_arg ? std::make_unique(*value_arg) + : nullptr; } -void PigeonTransactionCommand::set_option( - const PigeonDocumentOption& value_arg) { - option_ = value_arg; +void InternalTransactionCommand::set_option( + const InternalDocumentOption& value_arg) { + option_ = std::make_unique(value_arg); } -EncodableList PigeonTransactionCommand::ToEncodableList() const { +EncodableList InternalTransactionCommand::ToEncodableList() const { EncodableList list; list.reserve(4); - list.push_back(EncodableValue((int)type_)); + list.push_back(CustomEncodableValue(type_)); list.push_back(EncodableValue(path_)); list.push_back(data_ ? EncodableValue(*data_) : EncodableValue()); - list.push_back(option_ ? EncodableValue(option_->ToEncodableList()) - : EncodableValue()); + list.push_back(option_ ? CustomEncodableValue(*option_) : EncodableValue()); return list; } -PigeonTransactionCommand PigeonTransactionCommand::FromEncodableList( +InternalTransactionCommand InternalTransactionCommand::FromEncodableList( const EncodableList& list) { - PigeonTransactionCommand decoded( - (PigeonTransactionType)(std::get(list[0])), + InternalTransactionCommand decoded( + std::any_cast( + std::get(list[0])), std::get(list[1])); auto& encodable_data = list[2]; if (!encodable_data.IsNull()) { @@ -571,12 +1250,38 @@ PigeonTransactionCommand PigeonTransactionCommand::FromEncodableList( } auto& encodable_option = list[3]; if (!encodable_option.IsNull()) { - decoded.set_option(PigeonDocumentOption::FromEncodableList( - std::get(encodable_option))); + decoded.set_option(std::any_cast( + std::get(encodable_option))); } return decoded; } +bool InternalTransactionCommand::operator==( + const InternalTransactionCommand& other) const { + return PigeonInternalDeepEquals(type_, other.type_) && + PigeonInternalDeepEquals(path_, other.path_) && + PigeonInternalDeepEquals(data_, other.data_) && + PigeonInternalDeepEquals(option_, other.option_); +} + +bool InternalTransactionCommand::operator!=( + const InternalTransactionCommand& other) const { + return !(*this == other); +} + +size_t InternalTransactionCommand::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(type_); + result = result * 31 + PigeonInternalDeepHash(path_); + result = result * 31 + PigeonInternalDeepHash(data_); + result = result * 31 + PigeonInternalDeepHash(option_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalTransactionCommand& v) { + return v.Hash(); +} + // DocumentReferenceRequest DocumentReferenceRequest::DocumentReferenceRequest(const std::string& path) @@ -584,18 +1289,45 @@ DocumentReferenceRequest::DocumentReferenceRequest(const std::string& path) DocumentReferenceRequest::DocumentReferenceRequest( const std::string& path, const EncodableMap* data, - const PigeonDocumentOption* option, const Source* source, + const InternalDocumentOption* option, const Source* source, const ServerTimestampBehavior* server_timestamp_behavior) : path_(path), data_(data ? std::optional(*data) : std::nullopt), - option_(option ? std::optional(*option) - : std::nullopt), + option_(option ? std::make_unique(*option) + : nullptr), source_(source ? std::optional(*source) : std::nullopt), server_timestamp_behavior_(server_timestamp_behavior ? std::optional( *server_timestamp_behavior) : std::nullopt) {} +DocumentReferenceRequest::DocumentReferenceRequest( + const DocumentReferenceRequest& other) + : path_(other.path_), + data_(other.data_ ? std::optional(*other.data_) + : std::nullopt), + option_(other.option_ + ? std::make_unique(*other.option_) + : nullptr), + source_(other.source_ ? std::optional(*other.source_) + : std::nullopt), + server_timestamp_behavior_(other.server_timestamp_behavior_ + ? std::optional( + *other.server_timestamp_behavior_) + : std::nullopt) {} + +DocumentReferenceRequest& DocumentReferenceRequest::operator=( + const DocumentReferenceRequest& other) { + path_ = other.path_; + data_ = other.data_; + option_ = other.option_ + ? std::make_unique(*other.option_) + : nullptr; + source_ = other.source_; + server_timestamp_behavior_ = other.server_timestamp_behavior_; + return *this; +} + const std::string& DocumentReferenceRequest::path() const { return path_; } void DocumentReferenceRequest::set_path(std::string_view value_arg) { @@ -614,19 +1346,19 @@ void DocumentReferenceRequest::set_data(const EncodableMap& value_arg) { data_ = value_arg; } -const PigeonDocumentOption* DocumentReferenceRequest::option() const { - return option_ ? &(*option_) : nullptr; +const InternalDocumentOption* DocumentReferenceRequest::option() const { + return option_.get(); } void DocumentReferenceRequest::set_option( - const PigeonDocumentOption* value_arg) { - option_ = value_arg ? std::optional(*value_arg) - : std::nullopt; + const InternalDocumentOption* value_arg) { + option_ = value_arg ? std::make_unique(*value_arg) + : nullptr; } void DocumentReferenceRequest::set_option( - const PigeonDocumentOption& value_arg) { - option_ = value_arg; + const InternalDocumentOption& value_arg) { + option_ = std::make_unique(value_arg); } const Source* DocumentReferenceRequest::source() const { @@ -663,11 +1395,10 @@ EncodableList DocumentReferenceRequest::ToEncodableList() const { list.reserve(5); list.push_back(EncodableValue(path_)); list.push_back(data_ ? EncodableValue(*data_) : EncodableValue()); - list.push_back(option_ ? EncodableValue(option_->ToEncodableList()) - : EncodableValue()); - list.push_back(source_ ? EncodableValue((int)(*source_)) : EncodableValue()); + list.push_back(option_ ? CustomEncodableValue(*option_) : EncodableValue()); + list.push_back(source_ ? CustomEncodableValue(*source_) : EncodableValue()); list.push_back(server_timestamp_behavior_ - ? EncodableValue((int)(*server_timestamp_behavior_)) + ? CustomEncodableValue(*server_timestamp_behavior_) : EncodableValue()); return list; } @@ -681,27 +1412,58 @@ DocumentReferenceRequest DocumentReferenceRequest::FromEncodableList( } auto& encodable_option = list[2]; if (!encodable_option.IsNull()) { - decoded.set_option(PigeonDocumentOption::FromEncodableList( - std::get(encodable_option))); + decoded.set_option(std::any_cast( + std::get(encodable_option))); } auto& encodable_source = list[3]; if (!encodable_source.IsNull()) { - decoded.set_source((Source)(std::get(encodable_source))); + decoded.set_source(std::any_cast( + std::get(encodable_source))); } auto& encodable_server_timestamp_behavior = list[4]; if (!encodable_server_timestamp_behavior.IsNull()) { decoded.set_server_timestamp_behavior( - (ServerTimestampBehavior)(std::get( - encodable_server_timestamp_behavior))); + std::any_cast( + std::get( + encodable_server_timestamp_behavior))); } return decoded; } -// PigeonQueryParameters +bool DocumentReferenceRequest::operator==( + const DocumentReferenceRequest& other) const { + return PigeonInternalDeepEquals(path_, other.path_) && + PigeonInternalDeepEquals(data_, other.data_) && + PigeonInternalDeepEquals(option_, other.option_) && + PigeonInternalDeepEquals(source_, other.source_) && + PigeonInternalDeepEquals(server_timestamp_behavior_, + other.server_timestamp_behavior_); +} + +bool DocumentReferenceRequest::operator!=( + const DocumentReferenceRequest& other) const { + return !(*this == other); +} + +size_t DocumentReferenceRequest::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(path_); + result = result * 31 + PigeonInternalDeepHash(data_); + result = result * 31 + PigeonInternalDeepHash(option_); + result = result * 31 + PigeonInternalDeepHash(source_); + result = result * 31 + PigeonInternalDeepHash(server_timestamp_behavior_); + return result; +} + +size_t PigeonInternalDeepHash(const DocumentReferenceRequest& v) { + return v.Hash(); +} -PigeonQueryParameters::PigeonQueryParameters() {} +// InternalQueryParameters -PigeonQueryParameters::PigeonQueryParameters( +InternalQueryParameters::InternalQueryParameters() {} + +InternalQueryParameters::InternalQueryParameters( const EncodableList* where, const EncodableList* order_by, const int64_t* limit, const int64_t* limit_to_last, const EncodableList* start_at, const EncodableList* start_after, @@ -723,118 +1485,120 @@ PigeonQueryParameters::PigeonQueryParameters( filters_(filters ? std::optional(*filters) : std::nullopt) { } -const EncodableList* PigeonQueryParameters::where() const { +const EncodableList* InternalQueryParameters::where() const { return where_ ? &(*where_) : nullptr; } -void PigeonQueryParameters::set_where(const EncodableList* value_arg) { +void InternalQueryParameters::set_where(const EncodableList* value_arg) { where_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_where(const EncodableList& value_arg) { +void InternalQueryParameters::set_where(const EncodableList& value_arg) { where_ = value_arg; } -const EncodableList* PigeonQueryParameters::order_by() const { +const EncodableList* InternalQueryParameters::order_by() const { return order_by_ ? &(*order_by_) : nullptr; } -void PigeonQueryParameters::set_order_by(const EncodableList* value_arg) { +void InternalQueryParameters::set_order_by(const EncodableList* value_arg) { order_by_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_order_by(const EncodableList& value_arg) { +void InternalQueryParameters::set_order_by(const EncodableList& value_arg) { order_by_ = value_arg; } -const int64_t* PigeonQueryParameters::limit() const { +const int64_t* InternalQueryParameters::limit() const { return limit_ ? &(*limit_) : nullptr; } -void PigeonQueryParameters::set_limit(const int64_t* value_arg) { +void InternalQueryParameters::set_limit(const int64_t* value_arg) { limit_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_limit(int64_t value_arg) { limit_ = value_arg; } +void InternalQueryParameters::set_limit(int64_t value_arg) { + limit_ = value_arg; +} -const int64_t* PigeonQueryParameters::limit_to_last() const { +const int64_t* InternalQueryParameters::limit_to_last() const { return limit_to_last_ ? &(*limit_to_last_) : nullptr; } -void PigeonQueryParameters::set_limit_to_last(const int64_t* value_arg) { +void InternalQueryParameters::set_limit_to_last(const int64_t* value_arg) { limit_to_last_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_limit_to_last(int64_t value_arg) { +void InternalQueryParameters::set_limit_to_last(int64_t value_arg) { limit_to_last_ = value_arg; } -const EncodableList* PigeonQueryParameters::start_at() const { +const EncodableList* InternalQueryParameters::start_at() const { return start_at_ ? &(*start_at_) : nullptr; } -void PigeonQueryParameters::set_start_at(const EncodableList* value_arg) { +void InternalQueryParameters::set_start_at(const EncodableList* value_arg) { start_at_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_start_at(const EncodableList& value_arg) { +void InternalQueryParameters::set_start_at(const EncodableList& value_arg) { start_at_ = value_arg; } -const EncodableList* PigeonQueryParameters::start_after() const { +const EncodableList* InternalQueryParameters::start_after() const { return start_after_ ? &(*start_after_) : nullptr; } -void PigeonQueryParameters::set_start_after(const EncodableList* value_arg) { +void InternalQueryParameters::set_start_after(const EncodableList* value_arg) { start_after_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_start_after(const EncodableList& value_arg) { +void InternalQueryParameters::set_start_after(const EncodableList& value_arg) { start_after_ = value_arg; } -const EncodableList* PigeonQueryParameters::end_at() const { +const EncodableList* InternalQueryParameters::end_at() const { return end_at_ ? &(*end_at_) : nullptr; } -void PigeonQueryParameters::set_end_at(const EncodableList* value_arg) { +void InternalQueryParameters::set_end_at(const EncodableList* value_arg) { end_at_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_end_at(const EncodableList& value_arg) { +void InternalQueryParameters::set_end_at(const EncodableList& value_arg) { end_at_ = value_arg; } -const EncodableList* PigeonQueryParameters::end_before() const { +const EncodableList* InternalQueryParameters::end_before() const { return end_before_ ? &(*end_before_) : nullptr; } -void PigeonQueryParameters::set_end_before(const EncodableList* value_arg) { +void InternalQueryParameters::set_end_before(const EncodableList* value_arg) { end_before_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_end_before(const EncodableList& value_arg) { +void InternalQueryParameters::set_end_before(const EncodableList& value_arg) { end_before_ = value_arg; } -const EncodableMap* PigeonQueryParameters::filters() const { +const EncodableMap* InternalQueryParameters::filters() const { return filters_ ? &(*filters_) : nullptr; } -void PigeonQueryParameters::set_filters(const EncodableMap* value_arg) { +void InternalQueryParameters::set_filters(const EncodableMap* value_arg) { filters_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonQueryParameters::set_filters(const EncodableMap& value_arg) { +void InternalQueryParameters::set_filters(const EncodableMap& value_arg) { filters_ = value_arg; } -EncodableList PigeonQueryParameters::ToEncodableList() const { +EncodableList InternalQueryParameters::ToEncodableList() const { EncodableList list; list.reserve(9); list.push_back(where_ ? EncodableValue(*where_) : EncodableValue()); @@ -851,9 +1615,9 @@ EncodableList PigeonQueryParameters::ToEncodableList() const { return list; } -PigeonQueryParameters PigeonQueryParameters::FromEncodableList( +InternalQueryParameters InternalQueryParameters::FromEncodableList( const EncodableList& list) { - PigeonQueryParameters decoded; + InternalQueryParameters decoded; auto& encodable_where = list[0]; if (!encodable_where.IsNull()) { decoded.set_where(std::get(encodable_where)); @@ -864,11 +1628,11 @@ PigeonQueryParameters PigeonQueryParameters::FromEncodableList( } auto& encodable_limit = list[2]; if (!encodable_limit.IsNull()) { - decoded.set_limit(encodable_limit.LongValue()); + decoded.set_limit(std::get(encodable_limit)); } auto& encodable_limit_to_last = list[3]; if (!encodable_limit_to_last.IsNull()) { - decoded.set_limit_to_last(encodable_limit_to_last.LongValue()); + decoded.set_limit_to_last(std::get(encodable_limit_to_last)); } auto& encodable_start_at = list[4]; if (!encodable_start_at.IsNull()) { @@ -893,6 +1657,42 @@ PigeonQueryParameters PigeonQueryParameters::FromEncodableList( return decoded; } +bool InternalQueryParameters::operator==( + const InternalQueryParameters& other) const { + return PigeonInternalDeepEquals(where_, other.where_) && + PigeonInternalDeepEquals(order_by_, other.order_by_) && + PigeonInternalDeepEquals(limit_, other.limit_) && + PigeonInternalDeepEquals(limit_to_last_, other.limit_to_last_) && + PigeonInternalDeepEquals(start_at_, other.start_at_) && + PigeonInternalDeepEquals(start_after_, other.start_after_) && + PigeonInternalDeepEquals(end_at_, other.end_at_) && + PigeonInternalDeepEquals(end_before_, other.end_before_) && + PigeonInternalDeepEquals(filters_, other.filters_); +} + +bool InternalQueryParameters::operator!=( + const InternalQueryParameters& other) const { + return !(*this == other); +} + +size_t InternalQueryParameters::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(where_); + result = result * 31 + PigeonInternalDeepHash(order_by_); + result = result * 31 + PigeonInternalDeepHash(limit_); + result = result * 31 + PigeonInternalDeepHash(limit_to_last_); + result = result * 31 + PigeonInternalDeepHash(start_at_); + result = result * 31 + PigeonInternalDeepHash(start_after_); + result = result * 31 + PigeonInternalDeepHash(end_at_); + result = result * 31 + PigeonInternalDeepHash(end_before_); + result = result * 31 + PigeonInternalDeepHash(filters_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalQueryParameters& v) { + return v.Hash(); +} + // AggregateQuery AggregateQuery::AggregateQuery(const AggregateType& type) : type_(type) {} @@ -923,13 +1723,14 @@ void AggregateQuery::set_field(std::string_view value_arg) { EncodableList AggregateQuery::ToEncodableList() const { EncodableList list; list.reserve(2); - list.push_back(EncodableValue((int)type_)); + list.push_back(CustomEncodableValue(type_)); list.push_back(field_ ? EncodableValue(*field_) : EncodableValue()); return list; } AggregateQuery AggregateQuery::FromEncodableList(const EncodableList& list) { - AggregateQuery decoded((AggregateType)(std::get(list[0]))); + AggregateQuery decoded(std::any_cast( + std::get(list[0]))); auto& encodable_field = list[1]; if (!encodable_field.IsNull()) { decoded.set_field(std::get(encodable_field)); @@ -937,6 +1738,24 @@ AggregateQuery AggregateQuery::FromEncodableList(const EncodableList& list) { return decoded; } +bool AggregateQuery::operator==(const AggregateQuery& other) const { + return PigeonInternalDeepEquals(type_, other.type_) && + PigeonInternalDeepEquals(field_, other.field_); +} + +bool AggregateQuery::operator!=(const AggregateQuery& other) const { + return !(*this == other); +} + +size_t AggregateQuery::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(type_); + result = result * 31 + PigeonInternalDeepHash(field_); + return result; +} + +size_t PigeonInternalDeepHash(const AggregateQuery& v) { return v.Hash(); } + // AggregateQueryResponse AggregateQueryResponse::AggregateQueryResponse(const AggregateType& type) @@ -980,7 +1799,7 @@ void AggregateQueryResponse::set_value(double value_arg) { value_ = value_arg; } EncodableList AggregateQueryResponse::ToEncodableList() const { EncodableList list; list.reserve(3); - list.push_back(EncodableValue((int)type_)); + list.push_back(CustomEncodableValue(type_)); list.push_back(field_ ? EncodableValue(*field_) : EncodableValue()); list.push_back(value_ ? EncodableValue(*value_) : EncodableValue()); return list; @@ -988,7 +1807,8 @@ EncodableList AggregateQueryResponse::ToEncodableList() const { AggregateQueryResponse AggregateQueryResponse::FromEncodableList( const EncodableList& list) { - AggregateQueryResponse decoded((AggregateType)(std::get(list[0]))); + AggregateQueryResponse decoded(std::any_cast( + std::get(list[0]))); auto& encodable_field = list[1]; if (!encodable_field.IsNull()) { decoded.set_field(std::get(encodable_field)); @@ -1000,189 +1820,407 @@ AggregateQueryResponse AggregateQueryResponse::FromEncodableList( return decoded; } +bool AggregateQueryResponse::operator==( + const AggregateQueryResponse& other) const { + return PigeonInternalDeepEquals(type_, other.type_) && + PigeonInternalDeepEquals(field_, other.field_) && + PigeonInternalDeepEquals(value_, other.value_); +} + +bool AggregateQueryResponse::operator!=( + const AggregateQueryResponse& other) const { + return !(*this == other); +} + +size_t AggregateQueryResponse::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(type_); + result = result * 31 + PigeonInternalDeepHash(field_); + result = result * 31 + PigeonInternalDeepHash(value_); + return result; +} + +size_t PigeonInternalDeepHash(const AggregateQueryResponse& v) { + return v.Hash(); +} + FirebaseFirestoreHostApiCodecSerializer:: FirebaseFirestoreHostApiCodecSerializer() {} EncodableValue FirebaseFirestoreHostApiCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { - case 128: - return CustomEncodableValue(AggregateQuery::FromEncodableList( + case 129: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 130: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue(static_cast(enum_arg_value)); + } + case 131: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 132: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 133: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 134: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast( + enum_arg_value)); + } + case 135: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 136: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 137: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 138: { + return CustomEncodableValue(InternalFirebaseSettings::FromEncodableList( std::get(ReadValue(stream)))); - case 129: - return CustomEncodableValue(AggregateQueryResponse::FromEncodableList( + } + case 139: { + return CustomEncodableValue(FirestorePigeonFirebaseApp::FromEncodableList( std::get(ReadValue(stream)))); - case 130: - return CustomEncodableValue(DocumentReferenceRequest::FromEncodableList( + } + case 140: { + return CustomEncodableValue(InternalSnapshotMetadata::FromEncodableList( std::get(ReadValue(stream)))); - case 131: - return CustomEncodableValue(FirestorePigeonFirebaseApp::FromEncodableList( + } + case 141: { + return CustomEncodableValue(InternalDocumentSnapshot::FromEncodableList( std::get(ReadValue(stream)))); - case 132: - return CustomEncodableValue(PigeonDocumentChange::FromEncodableList( + } + case 142: { + return CustomEncodableValue(InternalDocumentChange::FromEncodableList( std::get(ReadValue(stream)))); - case 133: - return CustomEncodableValue(PigeonDocumentOption::FromEncodableList( + } + case 143: { + return CustomEncodableValue(InternalQuerySnapshot::FromEncodableList( std::get(ReadValue(stream)))); - case 134: - return CustomEncodableValue(PigeonDocumentSnapshot::FromEncodableList( + } + case 144: { + return CustomEncodableValue(InternalPipelineResult::FromEncodableList( std::get(ReadValue(stream)))); - case 135: - return CustomEncodableValue(PigeonFirebaseSettings::FromEncodableList( + } + case 145: { + return CustomEncodableValue(InternalPipelineSnapshot::FromEncodableList( std::get(ReadValue(stream)))); - case 136: - return CustomEncodableValue(PigeonGetOptions::FromEncodableList( + } + case 146: { + return CustomEncodableValue(InternalGetOptions::FromEncodableList( std::get(ReadValue(stream)))); - case 137: - return CustomEncodableValue(PigeonQueryParameters::FromEncodableList( + } + case 147: { + return CustomEncodableValue(InternalDocumentOption::FromEncodableList( std::get(ReadValue(stream)))); - case 138: - return CustomEncodableValue(PigeonQuerySnapshot::FromEncodableList( + } + case 148: { + return CustomEncodableValue(InternalTransactionCommand::FromEncodableList( std::get(ReadValue(stream)))); - case 139: - return CustomEncodableValue(PigeonSnapshotMetadata::FromEncodableList( + } + case 149: { + return CustomEncodableValue(DocumentReferenceRequest::FromEncodableList( std::get(ReadValue(stream)))); - case 140: - return CustomEncodableValue(PigeonTransactionCommand::FromEncodableList( + } + case 150: { + return CustomEncodableValue(InternalQueryParameters::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 151: { + return CustomEncodableValue(AggregateQuery::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 152: { + return CustomEncodableValue(AggregateQueryResponse::FromEncodableList( std::get(ReadValue(stream)))); + } default: - return cloud_firestore_windows::FirestoreCodec::ReadValueOfType(type, - stream); + return ::cloud_firestore_windows::FirestoreCodec::ReadValueOfType(type, + stream); } } void FirebaseFirestoreHostApiCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(AggregateQuery)) { - stream->WriteByte(128); - WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(AggregateQueryResponse)) { + if (custom_value->type() == typeid(DocumentChangeType)) { stream->WriteByte(129); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); return; } - if (custom_value->type() == typeid(DocumentReferenceRequest)) { + if (custom_value->type() == typeid(Source)) { stream->WriteByte(130); + WriteValue(EncodableValue( + static_cast(std::any_cast(*custom_value))), + stream); + return; + } + if (custom_value->type() == typeid(ListenSource)) { + stream->WriteByte(131); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); + return; + } + if (custom_value->type() == typeid(ServerTimestampBehavior)) { + stream->WriteByte(132); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); + return; + } + if (custom_value->type() == typeid(AggregateSource)) { + stream->WriteByte(133); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); + return; + } + if (custom_value->type() == + typeid(PersistenceCacheIndexManagerRequestEnum)) { + stream->WriteByte(134); + WriteValue(EncodableValue(static_cast( + std::any_cast( + *custom_value))), + stream); + return; + } + if (custom_value->type() == typeid(InternalTransactionResult)) { + stream->WriteByte(135); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); + return; + } + if (custom_value->type() == typeid(InternalTransactionType)) { + stream->WriteByte(136); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); + return; + } + if (custom_value->type() == typeid(AggregateType)) { + stream->WriteByte(137); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); + return; + } + if (custom_value->type() == typeid(InternalFirebaseSettings)) { + stream->WriteByte(138); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } if (custom_value->type() == typeid(FirestorePigeonFirebaseApp)) { - stream->WriteByte(131); + stream->WriteByte(139); WriteValue(EncodableValue( std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonDocumentChange)) { - stream->WriteByte(132); + if (custom_value->type() == typeid(InternalSnapshotMetadata)) { + stream->WriteByte(140); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonDocumentOption)) { - stream->WriteByte(133); + if (custom_value->type() == typeid(InternalDocumentSnapshot)) { + stream->WriteByte(141); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonDocumentSnapshot)) { - stream->WriteByte(134); + if (custom_value->type() == typeid(InternalDocumentChange)) { + stream->WriteByte(142); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonFirebaseSettings)) { - stream->WriteByte(135); + if (custom_value->type() == typeid(InternalQuerySnapshot)) { + stream->WriteByte(143); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonGetOptions)) { - stream->WriteByte(136); + if (custom_value->type() == typeid(InternalPipelineResult)) { + stream->WriteByte(144); WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonQueryParameters)) { - stream->WriteByte(137); + if (custom_value->type() == typeid(InternalPipelineSnapshot)) { + stream->WriteByte(145); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonQuerySnapshot)) { - stream->WriteByte(138); + if (custom_value->type() == typeid(InternalGetOptions)) { + stream->WriteByte(146); + WriteValue(EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(InternalDocumentOption)) { + stream->WriteByte(147); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonSnapshotMetadata)) { - stream->WriteByte(139); + if (custom_value->type() == typeid(InternalTransactionCommand)) { + stream->WriteByte(148); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(DocumentReferenceRequest)) { + stream->WriteByte(149); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonTransactionCommand)) { - stream->WriteByte(140); + if (custom_value->type() == typeid(InternalQueryParameters)) { + stream->WriteByte(150); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(AggregateQuery)) { + stream->WriteByte(151); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(AggregateQueryResponse)) { + stream->WriteByte(152); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } } - cloud_firestore_windows::FirestoreCodec::WriteValue(value, stream); + ::cloud_firestore_windows::FirestoreCodec::WriteValue(value, stream); } /// The codec used by FirebaseFirestoreHostApi. -const flutter::StandardMessageCodec& FirebaseFirestoreHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseFirestoreHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &FirebaseFirestoreHostApiCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseFirestoreHostApi` to handle messages through // the `binary_messenger`. -void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseFirestoreHostApi* api) { +void FirebaseFirestoreHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseFirestoreHostApi* api) { + FirebaseFirestoreHostApi::SetUp(binary_messenger, api, ""); +} + +void FirebaseFirestoreHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, FirebaseFirestoreHostApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = + message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : ""; { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.loadBundle", + "FirebaseFirestoreHostApi.loadBundle" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1216,19 +2254,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.namedQueryGet", + "FirebaseFirestoreHostApi.namedQueryGet" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1250,11 +2289,12 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("options_arg unexpectedly null.")); return; } - const auto& options_arg = std::any_cast( - std::get(encodable_options_arg)); + const auto& options_arg = + std::any_cast( + std::get(encodable_options_arg)); api->NamedQueryGet( app_arg, name_arg, options_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -1269,19 +2309,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.clearPersistence", + "FirebaseFirestoreHostApi.clearPersistence" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1307,19 +2348,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.disableNetwork", + "FirebaseFirestoreHostApi.disableNetwork" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1345,19 +2387,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.enableNetwork", + "FirebaseFirestoreHostApi.enableNetwork" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1383,19 +2426,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.terminate", + "FirebaseFirestoreHostApi.terminate" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1421,19 +2465,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.waitForPendingWrites", + "FirebaseFirestoreHostApi.waitForPendingWrites" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1459,19 +2504,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.setIndexConfiguration", + "FirebaseFirestoreHostApi.setIndexConfiguration" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1505,19 +2551,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.setLoggingEnabled", + "FirebaseFirestoreHostApi.setLoggingEnabled" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_logging_enabled_arg = args.at(0); @@ -1543,19 +2590,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.snapshotsInSyncSetup", + "FirebaseFirestoreHostApi.snapshotsInSyncSetup" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1582,19 +2630,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.transactionCreate", + "FirebaseFirestoreHostApi.transactionCreate" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1635,19 +2684,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.transactionStoreResult", + "FirebaseFirestoreHostApi.transactionStoreResult" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_transaction_id_arg = args.at(0); @@ -1662,9 +2712,10 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("result_type_arg unexpectedly null.")); return; } - const PigeonTransactionResult& result_type_arg = - (PigeonTransactionResult) - encodable_result_type_arg.LongValue(); + const auto& result_type_arg = + std::any_cast( + std::get( + encodable_result_type_arg)); const auto& encodable_commands_arg = args.at(2); const auto* commands_arg = std::get_if(&encodable_commands_arg); @@ -1684,19 +2735,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.transactionGet", + "FirebaseFirestoreHostApi.transactionGet" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1722,7 +2774,7 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& path_arg = std::get(encodable_path_arg); api->TransactionGet( app_arg, transaction_id_arg, path_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -1737,19 +2789,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.documentReferenceSet", + "FirebaseFirestoreHostApi.documentReferenceSet" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1784,19 +2837,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.documentReferenceUpdate", + "FirebaseFirestoreHostApi.documentReferenceUpdate" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1831,19 +2885,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.documentReferenceGet", + "FirebaseFirestoreHostApi.documentReferenceGet" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1864,7 +2919,7 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_request_arg)); api->DocumentReferenceGet( app_arg, request_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -1879,19 +2934,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.documentReferenceDelete", + "FirebaseFirestoreHostApi.documentReferenceDelete" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1926,19 +2982,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.queryGet", + "FirebaseFirestoreHostApi.queryGet" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1968,45 +3025,47 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& parameters_arg = - std::any_cast( + std::any_cast( std::get(encodable_parameters_arg)); const auto& encodable_options_arg = args.at(4); if (encodable_options_arg.IsNull()) { reply(WrapError("options_arg unexpectedly null.")); return; } - const auto& options_arg = std::any_cast( - std::get(encodable_options_arg)); - api->QueryGet( - app_arg, path_arg, is_collection_group_arg, parameters_arg, - options_arg, [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - CustomEncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); + const auto& options_arg = + std::any_cast( + std::get(encodable_options_arg)); + api->QueryGet(app_arg, path_arg, is_collection_group_arg, + parameters_arg, options_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(CustomEncodableValue( + std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); } catch (const std::exception& exception) { reply(WrapError(exception.what())); } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.aggregateQuery", + "FirebaseFirestoreHostApi.aggregateQuery" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2029,15 +3088,15 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& parameters_arg = - std::any_cast( + std::any_cast( std::get(encodable_parameters_arg)); const auto& encodable_source_arg = args.at(3); if (encodable_source_arg.IsNull()) { reply(WrapError("source_arg unexpectedly null.")); return; } - const AggregateSource& source_arg = - (AggregateSource)encodable_source_arg.LongValue(); + const auto& source_arg = std::any_cast( + std::get(encodable_source_arg)); const auto& encodable_queries_arg = args.at(4); if (encodable_queries_arg.IsNull()) { reply(WrapError("queries_arg unexpectedly null.")); @@ -2069,19 +3128,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.writeBatchCommit", + "FirebaseFirestoreHostApi.writeBatchCommit" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2115,19 +3175,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.querySnapshot", + "FirebaseFirestoreHostApi.querySnapshot" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2157,15 +3218,16 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& parameters_arg = - std::any_cast( + std::any_cast( std::get(encodable_parameters_arg)); const auto& encodable_options_arg = args.at(4); if (encodable_options_arg.IsNull()) { reply(WrapError("options_arg unexpectedly null.")); return; } - const auto& options_arg = std::any_cast( - std::get(encodable_options_arg)); + const auto& options_arg = + std::any_cast( + std::get(encodable_options_arg)); const auto& encodable_include_metadata_changes_arg = args.at(5); if (encodable_include_metadata_changes_arg.IsNull()) { reply(WrapError( @@ -2179,8 +3241,8 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("source_arg unexpectedly null.")); return; } - const ListenSource& source_arg = - (ListenSource)encodable_source_arg.LongValue(); + const auto& source_arg = std::any_cast( + std::get(encodable_source_arg)); api->QuerySnapshot( app_arg, path_arg, is_collection_group_arg, parameters_arg, options_arg, include_metadata_changes_arg, source_arg, @@ -2199,19 +3261,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.documentReferenceSnapshot", + "FirebaseFirestoreHostApi.documentReferenceSnapshot" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2243,8 +3306,8 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("source_arg unexpectedly null.")); return; } - const ListenSource& source_arg = - (ListenSource)encodable_source_arg.LongValue(); + const auto& source_arg = std::any_cast( + std::get(encodable_source_arg)); api->DocumentReferenceSnapshot( app_arg, parameters_arg, include_metadata_changes_arg, source_arg, [reply](ErrorOr&& output) { @@ -2262,19 +3325,20 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.cloud_firestore_platform_interface." - "FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest", + "FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2290,9 +3354,9 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("request_arg unexpectedly null.")); return; } - const PersistenceCacheIndexManagerRequestEnum& request_arg = - (PersistenceCacheIndexManagerRequestEnum) - encodable_request_arg.LongValue(); + const auto& request_arg = + std::any_cast( + std::get(encodable_request_arg)); api->PersistenceCacheIndexManagerRequest( app_arg, request_arg, [reply](std::optional&& output) { @@ -2309,7 +3373,58 @@ void FirebaseFirestoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.cloud_firestore_platform_interface." + "FirebaseFirestoreHostApi.executePipeline" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = + std::any_cast( + std::get(encodable_app_arg)); + const auto& encodable_stages_arg = args.at(1); + if (encodable_stages_arg.IsNull()) { + reply(WrapError("stages_arg unexpectedly null.")); + return; + } + const auto& stages_arg = + std::get(encodable_stages_arg); + const auto& encodable_options_arg = args.at(2); + const auto* options_arg = + std::get_if(&encodable_options_arg); + api->ExecutePipeline( + app_arg, stages_arg, options_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); } } } diff --git a/packages/cloud_firestore/cloud_firestore/windows/messages.g.h b/packages/cloud_firestore/cloud_firestore/windows/messages.g.h index 8aecb887facc..fcc6a5e80a11 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/messages.g.h +++ b/packages/cloud_firestore/cloud_firestore/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -27,17 +27,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -64,12 +64,12 @@ class ErrorOr { enum class DocumentChangeType { // Indicates a new document was added to the set of documents matching the // query. - added = 0, + kAdded = 0, // Indicates a document within the query was modified. - modified = 1, + kModified = 1, // Indicates a document within the query was removed (either deleted or no // longer matches the query. - removed = 2 + kRemoved = 2 }; // An enumeration of firestore source types. @@ -77,7 +77,7 @@ enum class Source { // Causes Firestore to try to retrieve an up-to-date (server-retrieved) // snapshot, but fall back to // returning cached data if the server can't be reached. - serverAndCache = 0, + kServerAndCache = 0, // Causes Firestore to avoid the cache, generating an error if the server // cannot be reached. Note // that the cache will still be updated if the server request succeeds. Also @@ -85,7 +85,7 @@ enum class Source { // latency-compensation still takes effect, so any pending write operations // will be visible in the // returned data (merged into the server-provided data). - server = 1, + kServer = 1, // Causes Firestore to immediately return a value from the cache, ignoring the // server completely // (implying that the returned value may be stale with respect to the value on @@ -93,7 +93,7 @@ enum class Source { // there is no data in the cache to satisfy the `get` call, // [DocumentReference.get] will throw a [FirebaseException] and // [Query.get] will return an empty [QuerySnapshotPlatform] with no documents. - cache = 2 + kCache = 2 }; // The listener retrieves data and listens to updates from the local Firestore @@ -108,63 +108,63 @@ enum class ListenSource { // cache and retrieve up-to-date snapshots from the Firestore server. // Snapshot events will be triggered on local mutations and server side // updates. - defaultSource = 0, + kDefaultSource = 0, // The listener retrieves data and listens to updates from the local Firestore // cache only. // If the cache is empty, an empty snapshot will be returned. // Snapshot events will be triggered on cache updates, like local mutations or // load bundles. - cache = 1 + kCache = 1 }; enum class ServerTimestampBehavior { // Return null for [FieldValue.serverTimestamp()] values that have not yet - none = 0, + kNone = 0, // Return local estimates for [FieldValue.serverTimestamp()] values that have // not yet been set to their final value. - estimate = 1, + kEstimate = 1, // Return the previous value for [FieldValue.serverTimestamp()] values that // have not yet been set to their final value. - previous = 2 + kPrevious = 2 }; // [AggregateSource] represents the source of data for an [AggregateQuery]. enum class AggregateSource { // Indicates that the data should be retrieved from the server. - server = 0 + kServer = 0 }; -// [PersistenceCacheIndexManagerRequest] represents the request types for the -// persistence cache index manager. +// [PersistenceCacheIndexManagerRequestEnum] represents the request types for +// the persistence cache index manager. enum class PersistenceCacheIndexManagerRequestEnum { - enableIndexAutoCreation = 0, - disableIndexAutoCreation = 1, - deleteAllIndexes = 2 + kEnableIndexAutoCreation = 0, + kDisableIndexAutoCreation = 1, + kDeleteAllIndexes = 2 }; -enum class PigeonTransactionResult { success = 0, failure = 1 }; +enum class InternalTransactionResult { kSuccess = 0, kFailure = 1 }; -enum class PigeonTransactionType { - get = 0, - update = 1, - set = 2, - deleteType = 3 +enum class InternalTransactionType { + kGet = 0, + kUpdate = 1, + kSet = 2, + kDeleteType = 3 }; -enum class AggregateType { count = 0, sum = 1, average = 2 }; +enum class AggregateType { kCount = 0, kSum = 1, kAverage = 2 }; // Generated class from Pigeon that represents data sent in messages. -class PigeonFirebaseSettings { +class InternalFirebaseSettings { public: // Constructs an object setting all non-nullable fields. - explicit PigeonFirebaseSettings(bool ignore_undefined_properties); + explicit InternalFirebaseSettings(bool ignore_undefined_properties); // Constructs an object setting all fields. - explicit PigeonFirebaseSettings(const bool* persistence_enabled, - const std::string* host, - const bool* ssl_enabled, - const int64_t* cache_size_bytes, - bool ignore_undefined_properties); + explicit InternalFirebaseSettings(const bool* persistence_enabled, + const std::string* host, + const bool* ssl_enabled, + const int64_t* cache_size_bytes, + bool ignore_undefined_properties); const bool* persistence_enabled() const; void set_persistence_enabled(const bool* value_arg); @@ -185,10 +185,22 @@ class PigeonFirebaseSettings { bool ignore_undefined_properties() const; void set_ignore_undefined_properties(bool value_arg); + bool operator==(const InternalFirebaseSettings& other) const; + bool operator!=(const InternalFirebaseSettings& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalFirebaseSettings FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static PigeonFirebaseSettings FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirestorePigeonFirebaseApp; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; @@ -204,34 +216,54 @@ class FirestorePigeonFirebaseApp { public: // Constructs an object setting all fields. explicit FirestorePigeonFirebaseApp(const std::string& app_name, - const PigeonFirebaseSettings& settings, + const InternalFirebaseSettings& settings, const std::string& database_u_r_l); + ~FirestorePigeonFirebaseApp() = default; + FirestorePigeonFirebaseApp(const FirestorePigeonFirebaseApp& other); + FirestorePigeonFirebaseApp& operator=( + const FirestorePigeonFirebaseApp& other); + FirestorePigeonFirebaseApp(FirestorePigeonFirebaseApp&& other) = default; + FirestorePigeonFirebaseApp& operator=( + FirestorePigeonFirebaseApp&& other) noexcept = default; const std::string& app_name() const; void set_app_name(std::string_view value_arg); - const PigeonFirebaseSettings& settings() const; - void set_settings(const PigeonFirebaseSettings& value_arg); + const InternalFirebaseSettings& settings() const; + void set_settings(const InternalFirebaseSettings& value_arg); const std::string& database_u_r_l() const; void set_database_u_r_l(std::string_view value_arg); + bool operator==(const FirestorePigeonFirebaseApp& other) const; + bool operator!=(const FirestorePigeonFirebaseApp& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static FirestorePigeonFirebaseApp FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; std::string app_name_; - PigeonFirebaseSettings settings_; + std::unique_ptr settings_; std::string database_u_r_l_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonSnapshotMetadata { +class InternalSnapshotMetadata { public: // Constructs an object setting all fields. - explicit PigeonSnapshotMetadata(bool has_pending_writes, bool is_from_cache); + explicit InternalSnapshotMetadata(bool has_pending_writes, + bool is_from_cache); bool has_pending_writes() const; void set_has_pending_writes(bool value_arg); @@ -239,13 +271,24 @@ class PigeonSnapshotMetadata { bool is_from_cache() const; void set_is_from_cache(bool value_arg); - static PigeonSnapshotMetadata FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + bool operator==(const InternalSnapshotMetadata& other) const; + bool operator!=(const InternalSnapshotMetadata& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + static InternalSnapshotMetadata FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: private: - friend class PigeonDocumentSnapshot; - friend class PigeonQuerySnapshot; + friend class InternalDocumentSnapshot; + friend class InternalQuerySnapshot; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; bool has_pending_writes_; @@ -253,53 +296,76 @@ class PigeonSnapshotMetadata { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonDocumentSnapshot { +class InternalDocumentSnapshot { public: // Constructs an object setting all non-nullable fields. - explicit PigeonDocumentSnapshot(const std::string& path, - const PigeonSnapshotMetadata& metadata); + explicit InternalDocumentSnapshot(const std::string& path, + const InternalSnapshotMetadata& metadata); // Constructs an object setting all fields. - explicit PigeonDocumentSnapshot(const std::string& path, - const flutter::EncodableMap* data, - const PigeonSnapshotMetadata& metadata); - + explicit InternalDocumentSnapshot(const std::string& path, + const ::flutter::EncodableMap* data, + const InternalSnapshotMetadata& metadata); + + ~InternalDocumentSnapshot() = default; + InternalDocumentSnapshot(const InternalDocumentSnapshot& other); + InternalDocumentSnapshot& operator=(const InternalDocumentSnapshot& other); + InternalDocumentSnapshot(InternalDocumentSnapshot&& other) = default; + InternalDocumentSnapshot& operator=( + InternalDocumentSnapshot&& other) noexcept = default; const std::string& path() const; void set_path(std::string_view value_arg); - const flutter::EncodableMap* data() const; - void set_data(const flutter::EncodableMap* value_arg); - void set_data(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* data() const; + void set_data(const ::flutter::EncodableMap* value_arg); + void set_data(const ::flutter::EncodableMap& value_arg); + + const InternalSnapshotMetadata& metadata() const; + void set_metadata(const InternalSnapshotMetadata& value_arg); - const PigeonSnapshotMetadata& metadata() const; - void set_metadata(const PigeonSnapshotMetadata& value_arg); + bool operator==(const InternalDocumentSnapshot& other) const; + bool operator!=(const InternalDocumentSnapshot& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; - static PigeonDocumentSnapshot FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + static InternalDocumentSnapshot FromEncodableList( + const ::flutter::EncodableList& list); + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - friend class PigeonDocumentChange; + private: + friend class InternalDocumentChange; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; std::string path_; - std::optional data_; - PigeonSnapshotMetadata metadata_; + std::optional<::flutter::EncodableMap> data_; + std::unique_ptr metadata_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonDocumentChange { +class InternalDocumentChange { public: // Constructs an object setting all fields. - explicit PigeonDocumentChange(const DocumentChangeType& type, - const PigeonDocumentSnapshot& document, - int64_t old_index, int64_t new_index); - + explicit InternalDocumentChange(const DocumentChangeType& type, + const InternalDocumentSnapshot& document, + int64_t old_index, int64_t new_index); + + ~InternalDocumentChange() = default; + InternalDocumentChange(const InternalDocumentChange& other); + InternalDocumentChange& operator=(const InternalDocumentChange& other); + InternalDocumentChange(InternalDocumentChange&& other) = default; + InternalDocumentChange& operator=(InternalDocumentChange&& other) noexcept = + default; const DocumentChangeType& type() const; void set_type(const DocumentChangeType& value_arg); - const PigeonDocumentSnapshot& document() const; - void set_document(const PigeonDocumentSnapshot& value_arg); + const InternalDocumentSnapshot& document() const; + void set_document(const InternalDocumentSnapshot& value_arg); int64_t old_index() const; void set_old_index(int64_t value_arg); @@ -307,52 +373,170 @@ class PigeonDocumentChange { int64_t new_index() const; void set_new_index(int64_t value_arg); - static PigeonDocumentChange FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + bool operator==(const InternalDocumentChange& other) const; + bool operator!=(const InternalDocumentChange& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + static InternalDocumentChange FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + private: + private: private: friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; DocumentChangeType type_; - PigeonDocumentSnapshot document_; + std::unique_ptr document_; int64_t old_index_; int64_t new_index_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonQuerySnapshot { +class InternalQuerySnapshot { public: // Constructs an object setting all fields. - explicit PigeonQuerySnapshot(const flutter::EncodableList& documents, - const flutter::EncodableList& document_changes, - const PigeonSnapshotMetadata& metadata); + explicit InternalQuerySnapshot( + const ::flutter::EncodableList& documents, + const ::flutter::EncodableList& document_changes, + const InternalSnapshotMetadata& metadata); + + ~InternalQuerySnapshot() = default; + InternalQuerySnapshot(const InternalQuerySnapshot& other); + InternalQuerySnapshot& operator=(const InternalQuerySnapshot& other); + InternalQuerySnapshot(InternalQuerySnapshot&& other) = default; + InternalQuerySnapshot& operator=(InternalQuerySnapshot&& other) noexcept = + default; + const ::flutter::EncodableList& documents() const; + void set_documents(const ::flutter::EncodableList& value_arg); + + const ::flutter::EncodableList& document_changes() const; + void set_document_changes(const ::flutter::EncodableList& value_arg); + + const InternalSnapshotMetadata& metadata() const; + void set_metadata(const InternalSnapshotMetadata& value_arg); + + bool operator==(const InternalQuerySnapshot& other) const; + bool operator!=(const InternalQuerySnapshot& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalQuerySnapshot FromEncodableList( + const ::flutter::EncodableList& list); - const flutter::EncodableList& documents() const; - void set_documents(const flutter::EncodableList& value_arg); + public: + public: + ::flutter::EncodableList ToEncodableList() const; - const flutter::EncodableList& document_changes() const; - void set_document_changes(const flutter::EncodableList& value_arg); + private: + private: + friend class FirebaseFirestoreHostApi; + friend class FirebaseFirestoreHostApiCodecSerializer; + ::flutter::EncodableList documents_; + ::flutter::EncodableList document_changes_; + std::unique_ptr metadata_; +}; - const PigeonSnapshotMetadata& metadata() const; - void set_metadata(const PigeonSnapshotMetadata& value_arg); +// Generated class from Pigeon that represents data sent in messages. +class InternalPipelineResult { + public: + // Constructs an object setting all non-nullable fields. + InternalPipelineResult(); + + // Constructs an object setting all fields. + explicit InternalPipelineResult(const std::string* document_path, + const int64_t* create_time, + const int64_t* update_time, + const ::flutter::EncodableMap* data); + + const std::string* document_path() const; + void set_document_path(const std::string_view* value_arg); + void set_document_path(std::string_view value_arg); + + const int64_t* create_time() const; + void set_create_time(const int64_t* value_arg); + void set_create_time(int64_t value_arg); + + const int64_t* update_time() const; + void set_update_time(const int64_t* value_arg); + void set_update_time(int64_t value_arg); + + // All fields in the result (from PipelineResult.data() on Android). + const ::flutter::EncodableMap* data() const; + void set_data(const ::flutter::EncodableMap* value_arg); + void set_data(const ::flutter::EncodableMap& value_arg); + + bool operator==(const InternalPipelineResult& other) const; + bool operator!=(const InternalPipelineResult& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalPipelineResult FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; private: - static PigeonQuerySnapshot FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + private: friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; - flutter::EncodableList documents_; - flutter::EncodableList document_changes_; - PigeonSnapshotMetadata metadata_; + std::optional document_path_; + std::optional create_time_; + std::optional update_time_; + std::optional<::flutter::EncodableMap> data_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonGetOptions { +class InternalPipelineSnapshot { public: // Constructs an object setting all fields. - explicit PigeonGetOptions( + explicit InternalPipelineSnapshot(const ::flutter::EncodableList& results, + int64_t execution_time); + + const ::flutter::EncodableList& results() const; + void set_results(const ::flutter::EncodableList& value_arg); + + int64_t execution_time() const; + void set_execution_time(int64_t value_arg); + + bool operator==(const InternalPipelineSnapshot& other) const; + bool operator!=(const InternalPipelineSnapshot& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalPipelineSnapshot FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: + friend class FirebaseFirestoreHostApi; + friend class FirebaseFirestoreHostApiCodecSerializer; + ::flutter::EncodableList results_; + int64_t execution_time_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class InternalGetOptions { + public: + // Constructs an object setting all fields. + explicit InternalGetOptions( const Source& source, const ServerTimestampBehavior& server_timestamp_behavior); @@ -362,9 +546,22 @@ class PigeonGetOptions { const ServerTimestampBehavior& server_timestamp_behavior() const; void set_server_timestamp_behavior(const ServerTimestampBehavior& value_arg); + bool operator==(const InternalGetOptions& other) const; + bool operator!=(const InternalGetOptions& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalGetOptions FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static PigeonGetOptions FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; Source source_; @@ -372,72 +569,103 @@ class PigeonGetOptions { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonDocumentOption { +class InternalDocumentOption { public: // Constructs an object setting all non-nullable fields. - PigeonDocumentOption(); + InternalDocumentOption(); // Constructs an object setting all fields. - explicit PigeonDocumentOption(const bool* merge, - const flutter::EncodableList* merge_fields); + explicit InternalDocumentOption(const bool* merge, + const ::flutter::EncodableList* merge_fields); const bool* merge() const; void set_merge(const bool* value_arg); void set_merge(bool value_arg); - const flutter::EncodableList* merge_fields() const; - void set_merge_fields(const flutter::EncodableList* value_arg); - void set_merge_fields(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList* merge_fields() const; + void set_merge_fields(const ::flutter::EncodableList* value_arg); + void set_merge_fields(const ::flutter::EncodableList& value_arg); + + bool operator==(const InternalDocumentOption& other) const; + bool operator!=(const InternalDocumentOption& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalDocumentOption FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; private: - static PigeonDocumentOption FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class PigeonTransactionCommand; + private: + friend class InternalTransactionCommand; friend class DocumentReferenceRequest; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; std::optional merge_; - std::optional merge_fields_; + std::optional<::flutter::EncodableList> merge_fields_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonTransactionCommand { +class InternalTransactionCommand { public: // Constructs an object setting all non-nullable fields. - explicit PigeonTransactionCommand(const PigeonTransactionType& type, - const std::string& path); + explicit InternalTransactionCommand(const InternalTransactionType& type, + const std::string& path); // Constructs an object setting all fields. - explicit PigeonTransactionCommand(const PigeonTransactionType& type, - const std::string& path, - const flutter::EncodableMap* data, - const PigeonDocumentOption* option); - - const PigeonTransactionType& type() const; - void set_type(const PigeonTransactionType& value_arg); + explicit InternalTransactionCommand(const InternalTransactionType& type, + const std::string& path, + const ::flutter::EncodableMap* data, + const InternalDocumentOption* option); + + ~InternalTransactionCommand() = default; + InternalTransactionCommand(const InternalTransactionCommand& other); + InternalTransactionCommand& operator=( + const InternalTransactionCommand& other); + InternalTransactionCommand(InternalTransactionCommand&& other) = default; + InternalTransactionCommand& operator=( + InternalTransactionCommand&& other) noexcept = default; + const InternalTransactionType& type() const; + void set_type(const InternalTransactionType& value_arg); const std::string& path() const; void set_path(std::string_view value_arg); - const flutter::EncodableMap* data() const; - void set_data(const flutter::EncodableMap* value_arg); - void set_data(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* data() const; + void set_data(const ::flutter::EncodableMap* value_arg); + void set_data(const ::flutter::EncodableMap& value_arg); + + const InternalDocumentOption* option() const; + void set_option(const InternalDocumentOption* value_arg); + void set_option(const InternalDocumentOption& value_arg); - const PigeonDocumentOption* option() const; - void set_option(const PigeonDocumentOption* value_arg); - void set_option(const PigeonDocumentOption& value_arg); + bool operator==(const InternalTransactionCommand& other) const; + bool operator!=(const InternalTransactionCommand& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalTransactionCommand FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; private: - static PigeonTransactionCommand FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + private: friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; - PigeonTransactionType type_; + InternalTransactionType type_; std::string path_; - std::optional data_; - std::optional option_; + std::optional<::flutter::EncodableMap> data_; + std::unique_ptr option_; }; // Generated class from Pigeon that represents data sent in messages. @@ -448,20 +676,26 @@ class DocumentReferenceRequest { // Constructs an object setting all fields. explicit DocumentReferenceRequest( - const std::string& path, const flutter::EncodableMap* data, - const PigeonDocumentOption* option, const Source* source, + const std::string& path, const ::flutter::EncodableMap* data, + const InternalDocumentOption* option, const Source* source, const ServerTimestampBehavior* server_timestamp_behavior); + ~DocumentReferenceRequest() = default; + DocumentReferenceRequest(const DocumentReferenceRequest& other); + DocumentReferenceRequest& operator=(const DocumentReferenceRequest& other); + DocumentReferenceRequest(DocumentReferenceRequest&& other) = default; + DocumentReferenceRequest& operator=( + DocumentReferenceRequest&& other) noexcept = default; const std::string& path() const; void set_path(std::string_view value_arg); - const flutter::EncodableMap* data() const; - void set_data(const flutter::EncodableMap* value_arg); - void set_data(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* data() const; + void set_data(const ::flutter::EncodableMap* value_arg); + void set_data(const ::flutter::EncodableMap& value_arg); - const PigeonDocumentOption* option() const; - void set_option(const PigeonDocumentOption* value_arg); - void set_option(const PigeonDocumentOption& value_arg); + const InternalDocumentOption* option() const; + void set_option(const InternalDocumentOption* value_arg); + void set_option(const InternalDocumentOption& value_arg); const Source* source() const; void set_source(const Source* value_arg); @@ -471,43 +705,55 @@ class DocumentReferenceRequest { void set_server_timestamp_behavior(const ServerTimestampBehavior* value_arg); void set_server_timestamp_behavior(const ServerTimestampBehavior& value_arg); + bool operator==(const DocumentReferenceRequest& other) const; + bool operator!=(const DocumentReferenceRequest& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static DocumentReferenceRequest FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; std::string path_; - std::optional data_; - std::optional option_; + std::optional<::flutter::EncodableMap> data_; + std::unique_ptr option_; std::optional source_; std::optional server_timestamp_behavior_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonQueryParameters { +class InternalQueryParameters { public: // Constructs an object setting all non-nullable fields. - PigeonQueryParameters(); + InternalQueryParameters(); // Constructs an object setting all fields. - explicit PigeonQueryParameters(const flutter::EncodableList* where, - const flutter::EncodableList* order_by, - const int64_t* limit, - const int64_t* limit_to_last, - const flutter::EncodableList* start_at, - const flutter::EncodableList* start_after, - const flutter::EncodableList* end_at, - const flutter::EncodableList* end_before, - const flutter::EncodableMap* filters); - - const flutter::EncodableList* where() const; - void set_where(const flutter::EncodableList* value_arg); - void set_where(const flutter::EncodableList& value_arg); - - const flutter::EncodableList* order_by() const; - void set_order_by(const flutter::EncodableList* value_arg); - void set_order_by(const flutter::EncodableList& value_arg); + explicit InternalQueryParameters(const ::flutter::EncodableList* where, + const ::flutter::EncodableList* order_by, + const int64_t* limit, + const int64_t* limit_to_last, + const ::flutter::EncodableList* start_at, + const ::flutter::EncodableList* start_after, + const ::flutter::EncodableList* end_at, + const ::flutter::EncodableList* end_before, + const ::flutter::EncodableMap* filters); + + const ::flutter::EncodableList* where() const; + void set_where(const ::flutter::EncodableList* value_arg); + void set_where(const ::flutter::EncodableList& value_arg); + + const ::flutter::EncodableList* order_by() const; + void set_order_by(const ::flutter::EncodableList* value_arg); + void set_order_by(const ::flutter::EncodableList& value_arg); const int64_t* limit() const; void set_limit(const int64_t* value_arg); @@ -517,41 +763,53 @@ class PigeonQueryParameters { void set_limit_to_last(const int64_t* value_arg); void set_limit_to_last(int64_t value_arg); - const flutter::EncodableList* start_at() const; - void set_start_at(const flutter::EncodableList* value_arg); - void set_start_at(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList* start_at() const; + void set_start_at(const ::flutter::EncodableList* value_arg); + void set_start_at(const ::flutter::EncodableList& value_arg); - const flutter::EncodableList* start_after() const; - void set_start_after(const flutter::EncodableList* value_arg); - void set_start_after(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList* start_after() const; + void set_start_after(const ::flutter::EncodableList* value_arg); + void set_start_after(const ::flutter::EncodableList& value_arg); - const flutter::EncodableList* end_at() const; - void set_end_at(const flutter::EncodableList* value_arg); - void set_end_at(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList* end_at() const; + void set_end_at(const ::flutter::EncodableList* value_arg); + void set_end_at(const ::flutter::EncodableList& value_arg); - const flutter::EncodableList* end_before() const; - void set_end_before(const flutter::EncodableList* value_arg); - void set_end_before(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList* end_before() const; + void set_end_before(const ::flutter::EncodableList* value_arg); + void set_end_before(const ::flutter::EncodableList& value_arg); - const flutter::EncodableMap* filters() const; - void set_filters(const flutter::EncodableMap* value_arg); - void set_filters(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* filters() const; + void set_filters(const ::flutter::EncodableMap* value_arg); + void set_filters(const ::flutter::EncodableMap& value_arg); + bool operator==(const InternalQueryParameters& other) const; + bool operator!=(const InternalQueryParameters& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalQueryParameters FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static PigeonQueryParameters FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; - std::optional where_; - std::optional order_by_; + std::optional<::flutter::EncodableList> where_; + std::optional<::flutter::EncodableList> order_by_; std::optional limit_; std::optional limit_to_last_; - std::optional start_at_; - std::optional start_after_; - std::optional end_at_; - std::optional end_before_; - std::optional filters_; + std::optional<::flutter::EncodableList> start_at_; + std::optional<::flutter::EncodableList> start_after_; + std::optional<::flutter::EncodableList> end_at_; + std::optional<::flutter::EncodableList> end_before_; + std::optional<::flutter::EncodableMap> filters_; }; // Generated class from Pigeon that represents data sent in messages. @@ -570,9 +828,21 @@ class AggregateQuery { void set_field(const std::string_view* value_arg); void set_field(std::string_view value_arg); + bool operator==(const AggregateQuery& other) const; + bool operator!=(const AggregateQuery& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static AggregateQuery FromEncodableList(const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static AggregateQuery FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; AggregateType type_; @@ -601,10 +871,22 @@ class AggregateQueryResponse { void set_value(const double* value_arg); void set_value(double value_arg); + bool operator==(const AggregateQueryResponse& other) const; + bool operator!=(const AggregateQueryResponse& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static AggregateQueryResponse FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseFirestoreHostApi; friend class FirebaseFirestoreHostApiCodecSerializer; AggregateType type_; @@ -621,12 +903,12 @@ class FirebaseFirestoreHostApiCodecSerializer return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -641,8 +923,8 @@ class FirebaseFirestoreHostApi { std::function reply)> result) = 0; virtual void NamedQueryGet( const FirestorePigeonFirebaseApp& app, const std::string& name, - const PigeonGetOptions& options, - std::function reply)> result) = 0; + const InternalGetOptions& options, + std::function reply)> result) = 0; virtual void ClearPersistence( const FirestorePigeonFirebaseApp& app, std::function reply)> result) = 0; @@ -674,13 +956,13 @@ class FirebaseFirestoreHostApi { std::function reply)> result) = 0; virtual void TransactionStoreResult( const std::string& transaction_id, - const PigeonTransactionResult& result_type, - const flutter::EncodableList* commands, + const InternalTransactionResult& result_type, + const ::flutter::EncodableList* commands, std::function reply)> result) = 0; virtual void TransactionGet( const FirestorePigeonFirebaseApp& app, const std::string& transaction_id, const std::string& path, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void DocumentReferenceSet( const FirestorePigeonFirebaseApp& app, const DocumentReferenceRequest& request, @@ -692,29 +974,29 @@ class FirebaseFirestoreHostApi { virtual void DocumentReferenceGet( const FirestorePigeonFirebaseApp& app, const DocumentReferenceRequest& request, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void DocumentReferenceDelete( const FirestorePigeonFirebaseApp& app, const DocumentReferenceRequest& request, std::function reply)> result) = 0; virtual void QueryGet( const FirestorePigeonFirebaseApp& app, const std::string& path, - bool is_collection_group, const PigeonQueryParameters& parameters, - const PigeonGetOptions& options, - std::function reply)> result) = 0; + bool is_collection_group, const InternalQueryParameters& parameters, + const InternalGetOptions& options, + std::function reply)> result) = 0; virtual void AggregateQuery( const FirestorePigeonFirebaseApp& app, const std::string& path, - const PigeonQueryParameters& parameters, const AggregateSource& source, - const flutter::EncodableList& queries, bool is_collection_group, - std::function reply)> result) = 0; + const InternalQueryParameters& parameters, const AggregateSource& source, + const ::flutter::EncodableList& queries, bool is_collection_group, + std::function reply)> result) = 0; virtual void WriteBatchCommit( const FirestorePigeonFirebaseApp& app, - const flutter::EncodableList& writes, + const ::flutter::EncodableList& writes, std::function reply)> result) = 0; virtual void QuerySnapshot( const FirestorePigeonFirebaseApp& app, const std::string& path, - bool is_collection_group, const PigeonQueryParameters& parameters, - const PigeonGetOptions& options, bool include_metadata_changes, + bool is_collection_group, const InternalQueryParameters& parameters, + const InternalGetOptions& options, bool include_metadata_changes, const ListenSource& source, std::function reply)> result) = 0; virtual void DocumentReferenceSnapshot( @@ -726,15 +1008,23 @@ class FirebaseFirestoreHostApi { const FirestorePigeonFirebaseApp& app, const PersistenceCacheIndexManagerRequestEnum& request, std::function reply)> result) = 0; + virtual void ExecutePipeline( + const FirestorePigeonFirebaseApp& app, + const ::flutter::EncodableList& stages, + const ::flutter::EncodableMap* options, + std::function reply)> result) = 0; // The codec used by FirebaseFirestoreHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseFirestoreHostApi` to handle messages // through the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseFirestoreHostApi* api); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static void SetUp(::flutter::BinaryMessenger* binary_messenger, + FirebaseFirestoreHostApi* api, + const std::string& message_channel_suffix); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseFirestoreHostApi() = default; diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_aggregate_query.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_aggregate_query.dart index ad54b1f6c018..ac3193875c3d 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_aggregate_query.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_aggregate_query.dart @@ -18,7 +18,7 @@ class MethodChannelAggregateQuery extends AggregateQueryPlatform { final FirestorePigeonFirebaseApp _pigeonApp; final String _path; - final PigeonQueryParameters _pigeonParameters; + final InternalQueryParameters _pigeonParameters; final bool _isCollectionGroupQuery; final List _aggregateQueries; diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_change.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_change.dart index 3d03a9d3edfa..0469941a7a35 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_change.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_change.dart @@ -9,8 +9,8 @@ import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_inte /// communicate with Firebase plugins. class MethodChannelDocumentChange extends DocumentChangePlatform { /// Creates a [MethodChannelDocumentChange] from the given [data] - MethodChannelDocumentChange( - FirebaseFirestorePlatform firestore, PigeonDocumentChange documentChange) + MethodChannelDocumentChange(FirebaseFirestorePlatform firestore, + InternalDocumentChange documentChange) : super( documentChange.type, documentChange.oldIndex, diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_reference.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_reference.dart index 4927de5c72e6..e957d4c63fbb 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_reference.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_document_reference.dart @@ -37,7 +37,7 @@ class MethodChannelDocumentReference extends DocumentReferencePlatform { DocumentReferenceRequest( path: _pointer.path, data: data, - option: PigeonDocumentOption( + option: InternalDocumentOption( merge: options?.merge, mergeFields: options?.mergeFields?.map((e) => e.components).toList(), @@ -137,8 +137,10 @@ class MethodChannelDocumentReference extends DocumentReferencePlatform { ) .listen( (snapshot) { - final PigeonDocumentSnapshot result = - PigeonDocumentSnapshot.decode(snapshot); + // With Pigeon 26, the native side emits the generated Pigeon class + // directly through the Pigeon-aware codec, so we receive a fully + // decoded `InternalDocumentSnapshot` here (no manual decode required). + final result = snapshot as InternalDocumentSnapshot; controller.add( DocumentSnapshotPlatform( firestore, diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart index 889ea4c5351b..33aefcfb42c0 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_firestore.dart @@ -21,7 +21,6 @@ import 'method_channel_query.dart'; import 'method_channel_transaction.dart'; import 'method_channel_write_batch.dart'; import 'utils/exception.dart'; -import 'utils/firestore_message_codec.dart'; /// The entry point for accessing a Firestore. /// @@ -39,7 +38,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { static EventChannel querySnapshotChannel(String id) { return EventChannel( 'plugins.flutter.io/firebase_firestore/query/$id', - const StandardMethodCodec(FirestoreMessageCodec()), + const StandardMethodCodec(PigeonCodec()), ); } @@ -47,7 +46,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { static EventChannel documentSnapshotChannel(String id) { return EventChannel( 'plugins.flutter.io/firebase_firestore/document/$id', - const StandardMethodCodec(FirestoreMessageCodec()), + const StandardMethodCodec(PigeonCodec()), ); } @@ -55,7 +54,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { static EventChannel snapshotsInSyncChannel(String id) { return EventChannel( 'plugins.flutter.io/firebase_firestore/snapshotsInSync/$id', - const StandardMethodCodec(FirestoreMessageCodec()), + const StandardMethodCodec(PigeonCodec()), ); } @@ -63,7 +62,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { static EventChannel loadBundleChannel(String id) { return EventChannel( 'plugins.flutter.io/firebase_firestore/loadBundle/$id', - const StandardMethodCodec(FirestoreMessageCodec()), + const StandardMethodCodec(PigeonCodec()), ); } @@ -72,7 +71,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { late final FirestorePigeonFirebaseApp pigeonApp = FirestorePigeonFirebaseApp( appName: appInstance!.name, databaseURL: databaseId, - settings: PigeonFirebaseSettings( + settings: InternalFirebaseSettings( persistenceEnabled: settings.persistenceEnabled, host: settings.host, sslEnabled: settings.sslEnabled, @@ -107,7 +106,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { final data = await pigeonChannel.namedQueryGet( pigeonApp, name, - PigeonGetOptions( + InternalGetOptions( source: options.source, serverTimestampBehavior: options.serverTimestampBehavior, ), @@ -233,7 +232,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { final eventChannel = EventChannel( 'plugins.flutter.io/firebase_firestore/transaction/$transactionId', - const StandardMethodCodec(FirestoreMessageCodec()), + const StandardMethodCodec(PigeonCodec()), ); final snapshotStreamSubscription = @@ -276,7 +275,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { // transaction await pigeonChannel.transactionStoreResult( transactionId, - PigeonTransactionResult.failure, + InternalTransactionResult.failure, null, ); @@ -290,7 +289,7 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { // Send the transaction commands to Dart. await pigeonChannel.transactionStoreResult( transactionId, - PigeonTransactionResult.success, + InternalTransactionResult.success, transaction.commands, ); }, @@ -374,7 +373,8 @@ class MethodChannelFirebaseFirestore extends FirebaseFirestorePlatform { MapEntry.new, ); - final PigeonPipelineSnapshot result = await pigeonChannel.executePipeline( + final InternalPipelineSnapshot result = + await pigeonChannel.executePipeline( pigeonApp, pigeonStages, pigeonOptions, diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart index c5f351ef88ed..a0b3a73d5bb3 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_pipeline_snapshot.dart @@ -16,9 +16,9 @@ class MethodChannelPipelineSnapshot extends PipelineSnapshotPlatform { MethodChannelPipelineSnapshot( FirebaseFirestorePlatform firestore, FirestorePigeonFirebaseApp pigeonApp, - PigeonPipelineSnapshot pigeonSnapshot, + InternalPipelineSnapshot pigeonSnapshot, ) : _results = pigeonSnapshot.results - .whereType() + .whereType() .map((result) => MethodChannelPipelineResult( firestore, pigeonApp, diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query.dart index 6ae2ec548688..12604b472d7c 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query.dart @@ -43,8 +43,8 @@ class MethodChannelQuery extends QueryPlatform { return _pointer.path; } - PigeonQueryParameters get _pigeonParameters { - return PigeonQueryParameters( + InternalQueryParameters get _pigeonParameters { + return InternalQueryParameters( where: parameters['where'], orderBy: parameters['orderBy'], limit: parameters['limit'], @@ -114,13 +114,13 @@ class MethodChannelQuery extends QueryPlatform { Future get( [GetOptions options = const GetOptions()]) async { try { - final PigeonQuerySnapshot result = + final InternalQuerySnapshot result = await MethodChannelFirebaseFirestore.pigeonChannel.queryGet( pigeonApp, _pointer.path, isCollectionGroupQuery, _pigeonParameters, - PigeonGetOptions( + InternalGetOptions( source: options.source, serverTimestampBehavior: options.serverTimestampBehavior, ), @@ -170,7 +170,7 @@ class MethodChannelQuery extends QueryPlatform { _pointer.path, isCollectionGroupQuery, _pigeonParameters, - PigeonGetOptions( + InternalGetOptions( source: Source.serverAndCache, serverTimestampBehavior: serverTimestampBehavior, ), @@ -185,21 +185,10 @@ class MethodChannelQuery extends QueryPlatform { ) .listen( (snapshot) { - final snapshotList = snapshot as List; - // We force the types here of list because they are not automatically - // decoded by the pigeon generated code. - final List documents = - (snapshotList[0]! as List) - .map((e) => PigeonDocumentSnapshot.decode(e)) - .toList() - .cast(); - final List changes = - (snapshotList[1]! as List) - .map((e) => PigeonDocumentChange.decode(e)) - .toList() - .cast(); - final PigeonQuerySnapshot result = PigeonQuerySnapshot.decode( - [documents, changes, snapshotList[2]]); + // With Pigeon 26, the native side emits the generated Pigeon class + // directly through the Pigeon-aware codec, so we receive a fully + // decoded `InternalQuerySnapshot` here (no manual decode required). + final result = snapshot as InternalQuerySnapshot; controller.add(MethodChannelQuerySnapshot(firestore, result)); }, onError: controller.addError, diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query_snapshot.dart index 204915caa160..72c61bd9e0db 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query_snapshot.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_query_snapshot.dart @@ -12,7 +12,7 @@ import 'method_channel_document_change.dart'; class MethodChannelQuerySnapshot extends QuerySnapshotPlatform { /// Creates a [MethodChannelQuerySnapshot] from the given [data] MethodChannelQuerySnapshot( - FirebaseFirestorePlatform firestore, PigeonQuerySnapshot data) + FirebaseFirestorePlatform firestore, InternalQuerySnapshot data) : super( data.documents .map((document) { diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_transaction.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_transaction.dart index 19b85bb93474..a4e75ad3d377 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_transaction.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_transaction.dart @@ -31,11 +31,11 @@ class MethodChannelTransaction extends TransactionPlatform { app: Firebase.app(appName), databaseId: databaseId); } - List _commands = []; + List _commands = []; /// Returns all transaction commands for the current instance. @override - List get commands { + List get commands { return _commands; } @@ -63,8 +63,8 @@ class MethodChannelTransaction extends TransactionPlatform { @override MethodChannelTransaction delete(String documentPath) { - _commands.add(PigeonTransactionCommand( - type: PigeonTransactionType.deleteType, + _commands.add(InternalTransactionCommand( + type: InternalTransactionType.deleteType, path: documentPath, )); @@ -76,8 +76,8 @@ class MethodChannelTransaction extends TransactionPlatform { String documentPath, Map data, ) { - _commands.add(PigeonTransactionCommand( - type: PigeonTransactionType.update, + _commands.add(InternalTransactionCommand( + type: InternalTransactionType.update, path: documentPath, data: data, )); @@ -88,11 +88,11 @@ class MethodChannelTransaction extends TransactionPlatform { @override MethodChannelTransaction set(String documentPath, Map data, [SetOptions? options]) { - _commands.add(PigeonTransactionCommand( - type: PigeonTransactionType.set, + _commands.add(InternalTransactionCommand( + type: InternalTransactionType.set, path: documentPath, data: data, - option: PigeonDocumentOption( + option: InternalDocumentOption( merge: options?.merge, mergeFields: options?.mergeFields?.map((e) => e.components).toList(), ))); diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_write_batch.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_write_batch.dart index bbdcbf3e678c..efd1de89fe6e 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_write_batch.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/method_channel/method_channel_write_batch.dart @@ -24,7 +24,7 @@ class MethodChannelWriteBatch extends WriteBatchPlatform { final FirestorePigeonFirebaseApp pigeonApp; /// Keeps track of all batch writes in order. - List _writes = []; + List _writes = []; /// The committed state of this batch. /// @@ -52,9 +52,9 @@ class MethodChannelWriteBatch extends WriteBatchPlatform { @override void delete(String documentPath) { _assertNotCommitted(); - _writes.add(PigeonTransactionCommand( + _writes.add(InternalTransactionCommand( path: documentPath, - type: PigeonTransactionType.deleteType, + type: InternalTransactionType.deleteType, )); } @@ -62,11 +62,11 @@ class MethodChannelWriteBatch extends WriteBatchPlatform { void set(String documentPath, Map data, [SetOptions? options]) { _assertNotCommitted(); - _writes.add(PigeonTransactionCommand( + _writes.add(InternalTransactionCommand( path: documentPath, - type: PigeonTransactionType.set, + type: InternalTransactionType.set, data: data, - option: PigeonDocumentOption( + option: InternalDocumentOption( merge: options?.merge, mergeFields: options?.mergeFields?.map((e) => e.components).toList(), ), @@ -79,9 +79,9 @@ class MethodChannelWriteBatch extends WriteBatchPlatform { Map data, ) { _assertNotCommitted(); - _writes.add(PigeonTransactionCommand( + _writes.add(InternalTransactionCommand( path: documentPath, - type: PigeonTransactionType.update, + type: InternalTransactionType.update, data: data, )); } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart index 662ed9358d9f..352fbf28fbed 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,16 +1,115 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; import 'package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart'; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; +} + +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + +bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } + if (a is List && b is List) { + return a.length == b.length && + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + } + if (a is Map && b is Map) { + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; + } + return a == b; +} + +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} /// An enumeration of document change types. enum DocumentChangeType { @@ -86,12 +185,12 @@ enum PersistenceCacheIndexManagerRequest { deleteAllIndexes, } -enum PigeonTransactionResult { +enum InternalTransactionResult { success, failure, } -enum PigeonTransactionType { +enum InternalTransactionType { get, update, set, @@ -104,8 +203,8 @@ enum AggregateType { average, } -class PigeonFirebaseSettings { - PigeonFirebaseSettings({ +class InternalFirebaseSettings { + InternalFirebaseSettings({ this.persistenceEnabled, this.host, this.sslEnabled, @@ -123,7 +222,7 @@ class PigeonFirebaseSettings { bool ignoreUndefinedProperties; - Object encode() { + List _toList() { return [ persistenceEnabled, host, @@ -133,9 +232,13 @@ class PigeonFirebaseSettings { ]; } - static PigeonFirebaseSettings decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalFirebaseSettings decode(Object result) { result as List; - return PigeonFirebaseSettings( + return InternalFirebaseSettings( persistenceEnabled: result[0] as bool?, host: result[1] as String?, sslEnabled: result[2] as bool?, @@ -143,6 +246,27 @@ class PigeonFirebaseSettings { ignoreUndefinedProperties: result[4]! as bool, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalFirebaseSettings || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(persistenceEnabled, other.persistenceEnabled) && + _deepEquals(host, other.host) && + _deepEquals(sslEnabled, other.sslEnabled) && + _deepEquals(cacheSizeBytes, other.cacheSizeBytes) && + _deepEquals(ignoreUndefinedProperties, other.ignoreUndefinedProperties); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class FirestorePigeonFirebaseApp { @@ -154,30 +278,53 @@ class FirestorePigeonFirebaseApp { String appName; - PigeonFirebaseSettings settings; + InternalFirebaseSettings settings; String databaseURL; - Object encode() { + List _toList() { return [ appName, - settings.encode(), + settings, databaseURL, ]; } + Object encode() { + return _toList(); + } + static FirestorePigeonFirebaseApp decode(Object result) { result as List; return FirestorePigeonFirebaseApp( appName: result[0]! as String, - settings: PigeonFirebaseSettings.decode(result[1]! as List), + settings: result[1]! as InternalFirebaseSettings, databaseURL: result[2]! as String, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! FirestorePigeonFirebaseApp || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(appName, other.appName) && + _deepEquals(settings, other.settings) && + _deepEquals(databaseURL, other.databaseURL); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonSnapshotMetadata { - PigeonSnapshotMetadata({ +class InternalSnapshotMetadata { + InternalSnapshotMetadata({ required this.hasPendingWrites, required this.isFromCache, }); @@ -186,24 +333,46 @@ class PigeonSnapshotMetadata { bool isFromCache; - Object encode() { + List _toList() { return [ hasPendingWrites, isFromCache, ]; } - static PigeonSnapshotMetadata decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalSnapshotMetadata decode(Object result) { result as List; - return PigeonSnapshotMetadata( + return InternalSnapshotMetadata( hasPendingWrites: result[0]! as bool, isFromCache: result[1]! as bool, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalSnapshotMetadata || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(hasPendingWrites, other.hasPendingWrites) && + _deepEquals(isFromCache, other.isFromCache); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonDocumentSnapshot { - PigeonDocumentSnapshot({ +class InternalDocumentSnapshot { + InternalDocumentSnapshot({ required this.path, this.data, required this.metadata, @@ -213,28 +382,51 @@ class PigeonDocumentSnapshot { Map? data; - PigeonSnapshotMetadata metadata; + InternalSnapshotMetadata metadata; - Object encode() { + List _toList() { return [ path, data, - metadata.encode(), + metadata, ]; } - static PigeonDocumentSnapshot decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalDocumentSnapshot decode(Object result) { result as List; - return PigeonDocumentSnapshot( + return InternalDocumentSnapshot( path: result[0]! as String, data: (result[1] as Map?)?.cast(), - metadata: PigeonSnapshotMetadata.decode(result[2]! as List), + metadata: result[2]! as InternalSnapshotMetadata, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalDocumentSnapshot || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(path, other.path) && + _deepEquals(data, other.data) && + _deepEquals(metadata, other.metadata); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonDocumentChange { - PigeonDocumentChange({ +class InternalDocumentChange { + InternalDocumentChange({ required this.type, required this.document, required this.oldIndex, @@ -243,66 +435,112 @@ class PigeonDocumentChange { DocumentChangeType type; - PigeonDocumentSnapshot document; + InternalDocumentSnapshot document; int oldIndex; int newIndex; - Object encode() { + List _toList() { return [ - type.index, - document.encode(), + type, + document, oldIndex, newIndex, ]; } - static PigeonDocumentChange decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalDocumentChange decode(Object result) { result as List; - return PigeonDocumentChange( - type: DocumentChangeType.values[result[0]! as int], - document: PigeonDocumentSnapshot.decode(result[1]! as List), + return InternalDocumentChange( + type: result[0]! as DocumentChangeType, + document: result[1]! as InternalDocumentSnapshot, oldIndex: result[2]! as int, newIndex: result[3]! as int, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalDocumentChange || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(type, other.type) && + _deepEquals(document, other.document) && + _deepEquals(oldIndex, other.oldIndex) && + _deepEquals(newIndex, other.newIndex); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonQuerySnapshot { - PigeonQuerySnapshot({ +class InternalQuerySnapshot { + InternalQuerySnapshot({ required this.documents, required this.documentChanges, required this.metadata, }); - List documents; + List documents; - List documentChanges; + List documentChanges; - PigeonSnapshotMetadata metadata; + InternalSnapshotMetadata metadata; - Object encode() { + List _toList() { return [ documents, documentChanges, - metadata.encode(), + metadata, ]; } - static PigeonQuerySnapshot decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalQuerySnapshot decode(Object result) { result as List; - return PigeonQuerySnapshot( - documents: (result[0] as List?)!.cast(), + return InternalQuerySnapshot( + documents: + (result[0]! as List).cast(), documentChanges: - (result[1] as List?)!.cast(), - metadata: PigeonSnapshotMetadata.decode(result[2]! as List), + (result[1]! as List).cast(), + metadata: result[2]! as InternalSnapshotMetadata, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalQuerySnapshot || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(documents, other.documents) && + _deepEquals(documentChanges, other.documentChanges) && + _deepEquals(metadata, other.metadata); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonPipelineResult { - PigeonPipelineResult({ +class InternalPipelineResult { + InternalPipelineResult({ this.documentPath, this.createTime, this.updateTime, @@ -318,7 +556,7 @@ class PigeonPipelineResult { /// All fields in the result (from PipelineResult.data() on Android). Map? data; - Object encode() { + List _toList() { return [ documentPath, createTime, @@ -327,45 +565,90 @@ class PigeonPipelineResult { ]; } - static PigeonPipelineResult decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalPipelineResult decode(Object result) { result as List; - return PigeonPipelineResult( + return InternalPipelineResult( documentPath: result[0] as String?, createTime: result[1] as int?, updateTime: result[2] as int?, data: (result[3] as Map?)?.cast(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalPipelineResult || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(documentPath, other.documentPath) && + _deepEquals(createTime, other.createTime) && + _deepEquals(updateTime, other.updateTime) && + _deepEquals(data, other.data); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonPipelineSnapshot { - PigeonPipelineSnapshot({ +class InternalPipelineSnapshot { + InternalPipelineSnapshot({ required this.results, required this.executionTime, }); - List results; + List results; int executionTime; - Object encode() { + List _toList() { return [ results, executionTime, ]; } - static PigeonPipelineSnapshot decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalPipelineSnapshot decode(Object result) { result as List; - return PigeonPipelineSnapshot( - results: (result[0] as List?)!.cast(), + return InternalPipelineSnapshot( + results: (result[0]! as List).cast(), executionTime: result[1]! as int, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalPipelineSnapshot || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(results, other.results) && + _deepEquals(executionTime, other.executionTime); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonGetOptions { - PigeonGetOptions({ +class InternalGetOptions { + InternalGetOptions({ required this.source, required this.serverTimestampBehavior, }); @@ -374,25 +657,45 @@ class PigeonGetOptions { ServerTimestampBehavior serverTimestampBehavior; - Object encode() { + List _toList() { return [ - source.index, - serverTimestampBehavior.index, + source, + serverTimestampBehavior, ]; } - static PigeonGetOptions decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalGetOptions decode(Object result) { result as List; - return PigeonGetOptions( - source: Source.values[result[0]! as int], - serverTimestampBehavior: - ServerTimestampBehavior.values[result[1]! as int], + return InternalGetOptions( + source: result[0]! as Source, + serverTimestampBehavior: result[1]! as ServerTimestampBehavior, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalGetOptions || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(source, other.source) && + _deepEquals(serverTimestampBehavior, other.serverTimestampBehavior); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonDocumentOption { - PigeonDocumentOption({ +class InternalDocumentOption { + InternalDocumentOption({ this.merge, this.mergeFields, }); @@ -401,58 +704,101 @@ class PigeonDocumentOption { List?>? mergeFields; - Object encode() { + List _toList() { return [ merge, mergeFields, ]; } - static PigeonDocumentOption decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalDocumentOption decode(Object result) { result as List; - return PigeonDocumentOption( + return InternalDocumentOption( merge: result[0] as bool?, mergeFields: (result[1] as List?)?.cast?>(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalDocumentOption || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(merge, other.merge) && + _deepEquals(mergeFields, other.mergeFields); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonTransactionCommand { - PigeonTransactionCommand({ +class InternalTransactionCommand { + InternalTransactionCommand({ required this.type, required this.path, this.data, this.option, }); - PigeonTransactionType type; + InternalTransactionType type; String path; Map? data; - PigeonDocumentOption? option; + InternalDocumentOption? option; - Object encode() { + List _toList() { return [ - type.index, + type, path, data, - option?.encode(), + option, ]; } - static PigeonTransactionCommand decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalTransactionCommand decode(Object result) { result as List; - return PigeonTransactionCommand( - type: PigeonTransactionType.values[result[0]! as int], + return InternalTransactionCommand( + type: result[0]! as InternalTransactionType, path: result[1]! as String, - data: (result[2] as Map?)?.cast(), - option: result[3] != null - ? PigeonDocumentOption.decode(result[3]! as List) - : null, + data: result[2] as Map?, + option: result[3] as InternalDocumentOption?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalTransactionCommand || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(type, other.type) && + _deepEquals(path, other.path) && + _deepEquals(data, other.data) && + _deepEquals(option, other.option); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class DocumentReferenceRequest { @@ -468,40 +814,61 @@ class DocumentReferenceRequest { Map? data; - PigeonDocumentOption? option; + InternalDocumentOption? option; Source? source; ServerTimestampBehavior? serverTimestampBehavior; - Object encode() { + List _toList() { return [ path, data, - option?.encode(), - source?.index, - serverTimestampBehavior?.index, + option, + source, + serverTimestampBehavior, ]; } + Object encode() { + return _toList(); + } + static DocumentReferenceRequest decode(Object result) { result as List; return DocumentReferenceRequest( path: result[0]! as String, - data: (result[1] as Map?)?.cast(), - option: result[2] != null - ? PigeonDocumentOption.decode(result[2]! as List) - : null, - source: result[3] != null ? Source.values[result[3]! as int] : null, - serverTimestampBehavior: result[4] != null - ? ServerTimestampBehavior.values[result[4]! as int] - : null, + data: result[1] as Map?, + option: result[2] as InternalDocumentOption?, + source: result[3] as Source?, + serverTimestampBehavior: result[4] as ServerTimestampBehavior?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! DocumentReferenceRequest || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(path, other.path) && + _deepEquals(data, other.data) && + _deepEquals(option, other.option) && + _deepEquals(source, other.source) && + _deepEquals(serverTimestampBehavior, other.serverTimestampBehavior); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonQueryParameters { - PigeonQueryParameters({ +class InternalQueryParameters { + InternalQueryParameters({ this.where, this.orderBy, this.limit, @@ -531,7 +898,7 @@ class PigeonQueryParameters { Map? filters; - Object encode() { + List _toList() { return [ where, orderBy, @@ -545,20 +912,48 @@ class PigeonQueryParameters { ]; } - static PigeonQueryParameters decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalQueryParameters decode(Object result) { result as List; - return PigeonQueryParameters( + return InternalQueryParameters( where: (result[0] as List?)?.cast?>(), orderBy: (result[1] as List?)?.cast?>(), limit: result[2] as int?, limitToLast: result[3] as int?, - startAt: (result[4] as List?)?.cast(), - startAfter: (result[5] as List?)?.cast(), - endAt: (result[6] as List?)?.cast(), - endBefore: (result[7] as List?)?.cast(), + startAt: result[4] as List?, + startAfter: result[5] as List?, + endAt: result[6] as List?, + endBefore: result[7] as List?, filters: (result[8] as Map?)?.cast(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalQueryParameters || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(where, other.where) && + _deepEquals(orderBy, other.orderBy) && + _deepEquals(limit, other.limit) && + _deepEquals(limitToLast, other.limitToLast) && + _deepEquals(startAt, other.startAt) && + _deepEquals(startAfter, other.startAfter) && + _deepEquals(endAt, other.endAt) && + _deepEquals(endBefore, other.endBefore) && + _deepEquals(filters, other.filters); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class AggregateQuery { @@ -571,20 +966,40 @@ class AggregateQuery { String? field; - Object encode() { + List _toList() { return [ - type.index, + type, field, ]; } + Object encode() { + return _toList(); + } + static AggregateQuery decode(Object result) { result as List; return AggregateQuery( - type: AggregateType.values[result[0]! as int], + type: result[0]! as AggregateType, field: result[1] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AggregateQuery || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(type, other.type) && _deepEquals(field, other.field); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class AggregateQueryResponse { @@ -600,73 +1015,125 @@ class AggregateQueryResponse { double? value; - Object encode() { + List _toList() { return [ - type.index, + type, field, value, ]; } + Object encode() { + return _toList(); + } + static AggregateQueryResponse decode(Object result) { result as List; return AggregateQueryResponse( - type: AggregateType.values[result[0]! as int], + type: result[0]! as AggregateType, field: result[1] as String?, value: result[2] as double?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AggregateQueryResponse || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(type, other.type) && + _deepEquals(field, other.field) && + _deepEquals(value, other.value); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec { - const _FirebaseFirestoreHostApiCodec(); +class PigeonCodec extends FirestoreMessageCodec { + const PigeonCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is AggregateQuery) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is AggregateQueryResponse) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is DocumentChangeType) { buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is DocumentReferenceRequest) { + writeValue(buffer, value.index); + } else if (value is Source) { buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is FirestorePigeonFirebaseApp) { + writeValue(buffer, value.index); + } else if (value is ListenSource) { buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else if (value is PigeonDocumentChange) { + writeValue(buffer, value.index); + } else if (value is ServerTimestampBehavior) { buffer.putUint8(132); - writeValue(buffer, value.encode()); - } else if (value is PigeonDocumentOption) { + writeValue(buffer, value.index); + } else if (value is AggregateSource) { buffer.putUint8(133); - writeValue(buffer, value.encode()); - } else if (value is PigeonDocumentSnapshot) { + writeValue(buffer, value.index); + } else if (value is PersistenceCacheIndexManagerRequest) { buffer.putUint8(134); - writeValue(buffer, value.encode()); - } else if (value is PigeonFirebaseSettings) { + writeValue(buffer, value.index); + } else if (value is InternalTransactionResult) { buffer.putUint8(135); - writeValue(buffer, value.encode()); - } else if (value is PigeonGetOptions) { + writeValue(buffer, value.index); + } else if (value is InternalTransactionType) { buffer.putUint8(136); - writeValue(buffer, value.encode()); - } else if (value is PigeonPipelineResult) { + writeValue(buffer, value.index); + } else if (value is AggregateType) { buffer.putUint8(137); - writeValue(buffer, value.encode()); - } else if (value is PigeonPipelineSnapshot) { + writeValue(buffer, value.index); + } else if (value is InternalFirebaseSettings) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonQueryParameters) { + } else if (value is FirestorePigeonFirebaseApp) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonQuerySnapshot) { + } else if (value is InternalSnapshotMetadata) { buffer.putUint8(140); writeValue(buffer, value.encode()); - } else if (value is PigeonSnapshotMetadata) { + } else if (value is InternalDocumentSnapshot) { buffer.putUint8(141); writeValue(buffer, value.encode()); - } else if (value is PigeonTransactionCommand) { + } else if (value is InternalDocumentChange) { buffer.putUint8(142); writeValue(buffer, value.encode()); + } else if (value is InternalQuerySnapshot) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is InternalPipelineResult) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else if (value is InternalPipelineSnapshot) { + buffer.putUint8(145); + writeValue(buffer, value.encode()); + } else if (value is InternalGetOptions) { + buffer.putUint8(146); + writeValue(buffer, value.encode()); + } else if (value is InternalDocumentOption) { + buffer.putUint8(147); + writeValue(buffer, value.encode()); + } else if (value is InternalTransactionCommand) { + buffer.putUint8(148); + writeValue(buffer, value.encode()); + } else if (value is DocumentReferenceRequest) { + buffer.putUint8(149); + writeValue(buffer, value.encode()); + } else if (value is InternalQueryParameters) { + buffer.putUint8(150); + writeValue(buffer, value.encode()); + } else if (value is AggregateQuery) { + buffer.putUint8(151); + writeValue(buffer, value.encode()); + } else if (value is AggregateQueryResponse) { + buffer.putUint8(152); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -675,36 +1142,65 @@ class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: - return AggregateQuery.decode(readValue(buffer)!); case 129: - return AggregateQueryResponse.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : DocumentChangeType.values[value]; case 130: - return DocumentReferenceRequest.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : Source.values[value]; case 131: - return FirestorePigeonFirebaseApp.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : ListenSource.values[value]; case 132: - return PigeonDocumentChange.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : ServerTimestampBehavior.values[value]; case 133: - return PigeonDocumentOption.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : AggregateSource.values[value]; case 134: - return PigeonDocumentSnapshot.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null + ? null + : PersistenceCacheIndexManagerRequest.values[value]; case 135: - return PigeonFirebaseSettings.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : InternalTransactionResult.values[value]; case 136: - return PigeonGetOptions.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : InternalTransactionType.values[value]; case 137: - return PigeonPipelineResult.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : AggregateType.values[value]; case 138: - return PigeonPipelineSnapshot.decode(readValue(buffer)!); + return InternalFirebaseSettings.decode(readValue(buffer)!); case 139: - return PigeonQueryParameters.decode(readValue(buffer)!); + return FirestorePigeonFirebaseApp.decode(readValue(buffer)!); case 140: - return PigeonQuerySnapshot.decode(readValue(buffer)!); + return InternalSnapshotMetadata.decode(readValue(buffer)!); case 141: - return PigeonSnapshotMetadata.decode(readValue(buffer)!); + return InternalDocumentSnapshot.decode(readValue(buffer)!); case 142: - return PigeonTransactionCommand.decode(readValue(buffer)!); + return InternalDocumentChange.decode(readValue(buffer)!); + case 143: + return InternalQuerySnapshot.decode(readValue(buffer)!); + case 144: + return InternalPipelineResult.decode(readValue(buffer)!); + case 145: + return InternalPipelineSnapshot.decode(readValue(buffer)!); + case 146: + return InternalGetOptions.decode(readValue(buffer)!); + case 147: + return InternalDocumentOption.decode(readValue(buffer)!); + case 148: + return InternalTransactionCommand.decode(readValue(buffer)!); + case 149: + return DocumentReferenceRequest.decode(readValue(buffer)!); + case 150: + return InternalQueryParameters.decode(readValue(buffer)!); + case 151: + return AggregateQuery.decode(readValue(buffer)!); + case 152: + return AggregateQueryResponse.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -715,737 +1211,530 @@ class FirebaseFirestoreHostApi { /// Constructor for [FirebaseFirestoreHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - FirebaseFirestoreHostApi({BinaryMessenger? binaryMessenger}) - : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; + FirebaseFirestoreHostApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = PigeonCodec(); - static const MessageCodec codec = _FirebaseFirestoreHostApiCodec(); + final String pigeonVar_messageChannelSuffix; Future loadBundle( - FirestorePigeonFirebaseApp arg_app, - Uint8List arg_bundle, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_bundle]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + FirestorePigeonFirebaseApp app, Uint8List bundle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, bundle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } - Future namedQueryGet( - FirestorePigeonFirebaseApp arg_app, - String arg_name, - PigeonGetOptions arg_options, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel - .send([arg_app, arg_name, arg_options]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonQuerySnapshot?)!; - } + Future namedQueryGet(FirestorePigeonFirebaseApp app, + String name, InternalGetOptions options) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, name, options]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalQuerySnapshot; } - Future clearPersistence(FirestorePigeonFirebaseApp arg_app) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future clearPersistence(FirestorePigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future disableNetwork(FirestorePigeonFirebaseApp arg_app) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future disableNetwork(FirestorePigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future enableNetwork(FirestorePigeonFirebaseApp arg_app) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future enableNetwork(FirestorePigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future terminate(FirestorePigeonFirebaseApp arg_app) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future terminate(FirestorePigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future waitForPendingWrites(FirestorePigeonFirebaseApp arg_app) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future waitForPendingWrites(FirestorePigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setIndexConfiguration( - FirestorePigeonFirebaseApp arg_app, - String arg_indexConfiguration, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel - .send([arg_app, arg_indexConfiguration]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + FirestorePigeonFirebaseApp app, String indexConfiguration) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, indexConfiguration]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future setLoggingEnabled(bool arg_loggingEnabled) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_loggingEnabled]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future setLoggingEnabled(bool loggingEnabled) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([loggingEnabled]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future snapshotsInSyncSetup( - FirestorePigeonFirebaseApp arg_app, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + Future snapshotsInSyncSetup(FirestorePigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future transactionCreate( - FirestorePigeonFirebaseApp arg_app, - int arg_timeout, - int arg_maxAttempts, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_timeout, arg_maxAttempts]) - as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + FirestorePigeonFirebaseApp app, int timeout, int maxAttempts) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, timeout, maxAttempts]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future transactionStoreResult( - String arg_transactionId, - PigeonTransactionResult arg_resultType, - List? arg_commands, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel.send( - [arg_transactionId, arg_resultType.index, arg_commands], - ) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + String transactionId, + InternalTransactionResult resultType, + List? commands) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([transactionId, resultType, commands]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future transactionGet( - FirestorePigeonFirebaseApp arg_app, - String arg_transactionId, - String arg_path, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_transactionId, arg_path]) - as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonDocumentSnapshot?)!; - } + Future transactionGet( + FirestorePigeonFirebaseApp app, String transactionId, String path) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, transactionId, path]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalDocumentSnapshot; } Future documentReferenceSet( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_request]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, request]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future documentReferenceUpdate( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_request]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, request]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future documentReferenceGet( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_request]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonDocumentSnapshot?)!; - } + Future documentReferenceGet( + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, request]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalDocumentSnapshot; } Future documentReferenceDelete( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_request, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_request]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + FirestorePigeonFirebaseApp app, DocumentReferenceRequest request) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, request]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future queryGet( - FirestorePigeonFirebaseApp arg_app, - String arg_path, - bool arg_isCollectionGroup, - PigeonQueryParameters arg_parameters, - PigeonGetOptions arg_options, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel.send([ - arg_app, - arg_path, - arg_isCollectionGroup, - arg_parameters, - arg_options, - ]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonQuerySnapshot?)!; - } + Future queryGet( + FirestorePigeonFirebaseApp app, + String path, + bool isCollectionGroup, + InternalQueryParameters parameters, + InternalGetOptions options) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([app, path, isCollectionGroup, parameters, options]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalQuerySnapshot; } Future> aggregateQuery( - FirestorePigeonFirebaseApp arg_app, - String arg_path, - PigeonQueryParameters arg_parameters, - AggregateSource arg_source, - List arg_queries, - bool arg_isCollectionGroup, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel.send([ - arg_app, - arg_path, - arg_parameters, - arg_source.index, - arg_queries, - arg_isCollectionGroup, - ]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as List?)!.cast(); - } + FirestorePigeonFirebaseApp app, + String path, + InternalQueryParameters parameters, + AggregateSource source, + List queries, + bool isCollectionGroup) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [app, path, parameters, source, queries, isCollectionGroup]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List) + .cast(); } - Future writeBatchCommit( - FirestorePigeonFirebaseApp arg_app, - List arg_writes, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = - await channel.send([arg_app, arg_writes]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future writeBatchCommit(FirestorePigeonFirebaseApp app, + List writes) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, writes]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future querySnapshot( - FirestorePigeonFirebaseApp arg_app, - String arg_path, - bool arg_isCollectionGroup, - PigeonQueryParameters arg_parameters, - PigeonGetOptions arg_options, - bool arg_includeMetadataChanges, - ListenSource arg_source, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel.send([ - arg_app, - arg_path, - arg_isCollectionGroup, - arg_parameters, - arg_options, - arg_includeMetadataChanges, - arg_source.index, - ]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + FirestorePigeonFirebaseApp app, + String path, + bool isCollectionGroup, + InternalQueryParameters parameters, + InternalGetOptions options, + bool includeMetadataChanges, + ListenSource source) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([ + app, + path, + isCollectionGroup, + parameters, + options, + includeMetadataChanges, + source + ]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future documentReferenceSnapshot( - FirestorePigeonFirebaseApp arg_app, - DocumentReferenceRequest arg_parameters, - bool arg_includeMetadataChanges, - ListenSource arg_source, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel.send([ - arg_app, - arg_parameters, - arg_includeMetadataChanges, - arg_source.index, - ]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + FirestorePigeonFirebaseApp app, + DocumentReferenceRequest parameters, + bool includeMetadataChanges, + ListenSource source) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([app, parameters, includeMetadataChanges, source]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future persistenceCacheIndexManagerRequest( - FirestorePigeonFirebaseApp arg_app, - PersistenceCacheIndexManagerRequest arg_request, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel - .send([arg_app, arg_request.index]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + FirestorePigeonFirebaseApp app, + PersistenceCacheIndexManagerRequest request) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, request]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future executePipeline( - FirestorePigeonFirebaseApp arg_app, - List?> arg_stages, - Map? arg_options, - ) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline', - codec, - binaryMessenger: _binaryMessenger, - ); - final List? replyList = await channel - .send([arg_app, arg_stages, arg_options]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonPipelineSnapshot?)!; - } + Future executePipeline( + FirestorePigeonFirebaseApp app, + List?> stages, + Map? options) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, stages, options]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalPipelineSnapshot; } } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_document_snapshot.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_document_snapshot.dart index 05f7ada727e8..3fce79a77f10 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_document_snapshot.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_document_snapshot.dart @@ -38,7 +38,7 @@ class DocumentSnapshotPlatform extends PlatformInterface { final Map? _data; - final PigeonSnapshotMetadata _metadata; + final InternalSnapshotMetadata _metadata; /// The database ID of the snapshot's document. String get id => _pointer.id; diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_transaction.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_transaction.dart index e6648db2aea2..64ae9fef837e 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_transaction.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/platform_interface/platform_interface_transaction.dart @@ -31,7 +31,7 @@ abstract class TransactionPlatform extends PlatformInterface { } /// Returns all transaction commands for the current instance. - List get commands { + List get commands { throw UnimplementedError('commands is not implemented'); } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh index e8950e42ef53..0bf9dabad9d7 100755 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/generate_pigeon.sh @@ -1,4 +1,5 @@ # Objective of this script is to fix some files generated by Pigeon because Pigeon does not support Custom Codecs. +# These transformations are tuned for Pigeon 26.x. If you bump Pigeon, re-verify every sed/perl below. echo "Generate Pigeon Files." (cd .. && dart run pigeon --input ./pigeons/messages.dart) @@ -9,8 +10,13 @@ echo "Formatting complete." # # Fix Java files FILE_NAME="../../cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java" +# Expose toList() so plugin code can serialize generated classes outside of the pigeon codec. sed -i '' 's/ArrayList toList() {/public ArrayList toList() {/' "$FILE_NAME" -sed -i '' 's/private static class FirebaseFirestoreHostApiCodec extends StandardMessageCodec {/private static class FirebaseFirestoreHostApiCodec extends FlutterFirebaseFirestoreMessageCodec {/' "$FILE_NAME" +# Pigeon 26 emits a single `PigeonCodec` per file (was `FirebaseFirestoreHostApiCodec` in older versions). +# Swap its base class to the custom Firestore codec so Firestore types are encoded/decoded, and +# expose it publicly so the plugin can reuse it on EventChannel/MethodChannel instances (those +# must serialize Pigeon-generated types like `InternalDocumentSnapshot` emitted via stream handlers). +sed -i '' 's/private static class PigeonCodec extends StandardMessageCodec {/public static class PigeonCodec extends FlutterFirebaseFirestoreMessageCodec {/' "$FILE_NAME" echo "Android modification complete." @@ -20,15 +26,20 @@ sed -i '' '/#import "FirestoreMessages.g.h"/a\ #import "FLTFirebaseFirestoreReader.h"\ #import "FLTFirebaseFirestoreWriter.h" ' $FILE_NAME -sed -i '' 's/pigeonResult.newIndex = newIndex;/pigeonResult.index = newIndex;/' $FILE_NAME -sed -i '' -e 's/pigeonResult.newIndex = GetNullableObjectAtIndex(list, 3);/pigeonResult.index = GetNullableObjectAtIndex(list, 3);/' -e 's/NSAssert(pigeonResult.newIndex != nil, @"");/NSAssert(pigeonResult.index != nil, @"");/' $FILE_NAME -sed -i '' 's/(self\.newIndex \?: \[NSNull null\]),/(self.index ?: [NSNull null]),/' $FILE_NAME +# Pigeon 26 generates ObjC codec classes with a `nullPigeonCodec*` prefix when no +# ObjcOptions prefix is configured. Rename them to stable, readable names first. +sed -i '' 's/nullFirestoreMessagesPigeonCodecReaderWriter/FirebaseFirestoreHostApiCodecReaderWriter/g' $FILE_NAME +sed -i '' 's/nullFirestoreMessagesPigeonCodecReader/FirebaseFirestoreHostApiCodecReader/g' $FILE_NAME +sed -i '' 's/nullFirestoreMessagesPigeonCodecWriter/FirebaseFirestoreHostApiCodecWriter/g' $FILE_NAME +# Rename the public codec getter from `nullGetFirestoreMessagesCodec` so the plugin can reuse +# it on EventChannels without an awkward `null` prefix. +sed -i '' 's/nullGetFirestoreMessagesCodec/GetFirebaseFirestoreHostApiCodec/g' $FILE_NAME +sed -i '' 's/nullGetFirestoreMessagesCodec/GetFirebaseFirestoreHostApiCodec/g' ../../cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h +# Reparent the reader/writer onto our custom Firestore reader/writer so Firestore-specific +# types (Timestamp, GeoPoint, FieldValue, DocumentReference, FieldPath, ...) round-trip. sed -i '' 's/@interface FirebaseFirestoreHostApiCodecReader : FlutterStandardReader/@interface FirebaseFirestoreHostApiCodecReader : FLTFirebaseFirestoreReader/' $FILE_NAME sed -i '' 's/@interface FirebaseFirestoreHostApiCodecWriter : FlutterStandardWriter/@interface FirebaseFirestoreHostApiCodecWriter : FLTFirebaseFirestoreWriter/' $FILE_NAME -FILE_NAME="../../cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/include/cloud_firestore/Public/FirestoreMessages.g.h" -sed -i '' 's/@property(nonatomic, strong) NSNumber \*newIndex;/@property(nonatomic, strong) NSNumber \*index;/' $FILE_NAME - echo "iOS modification complete." # Fix Windows files @@ -36,25 +47,49 @@ FILE_NAME="../../cloud_firestore/windows/messages.g.h" sed -i '' '/#include /a\ #include "firestore_codec.h" ' $FILE_NAME -perl -i -0777 -pe 's|private:\n(\s+static PigeonSnapshotMetadata FromEncodableList\(\n\s+const flutter::EncodableList& list\);\n\s+flutter::EncodableList ToEncodableList\(\) const;)|\1\n\n private:|gs' $FILE_NAME -perl -0777 -i -pe 's/private:\n(\x20{2}static PigeonDocumentSnapshot FromEncodableList\(\n\x20{6}const flutter::EncodableList& list\);\n\x20{2}flutter::EncodableList ToEncodableList\(\) const;)/\1\n\n private:/gs' $FILE_NAME -perl -0777 -i -pe 's/private:\n(\x20{2}static PigeonDocumentChange FromEncodableList\(\n\x20{6}const flutter::EncodableList& list\);\n\x20{2}flutter::EncodableList ToEncodableList\(\) const;)/\1\n\n private:/gs' $FILE_NAME +# Make FromEncodableList / ToEncodableList accessible from plugin code (they're used directly +# to serialize stream events). Pigeon 26 qualifies EncodableList with a leading `::`, hence the +# `::flutter::EncodableList` pattern below. +perl -i -0777 -pe 's|private:\n(\s+static InternalSnapshotMetadata FromEncodableList\(\n\s+const ::flutter::EncodableList& list\);\n\s+::flutter::EncodableList ToEncodableList\(\) const;)|\1\n\n private:|gs' $FILE_NAME +perl -0777 -i -pe 's/private:\n(\x20{2}static InternalDocumentSnapshot FromEncodableList\(\n\x20{6}const ::flutter::EncodableList& list\);\n\x20{2}::flutter::EncodableList ToEncodableList\(\) const;)/\1\n\n private:/gs' $FILE_NAME +perl -0777 -i -pe 's/private:\n(\x20{2}static InternalDocumentChange FromEncodableList\(\n\x20{6}const ::flutter::EncodableList& list\);\n\x20{2}::flutter::EncodableList ToEncodableList\(\) const;)/\1\n\n private:/gs' $FILE_NAME -sed -i '' 's/: public flutter::StandardCodecSerializer {/: public cloud_firestore_windows::FirestoreCodec {/' $FILE_NAME +# Pigeon 26 renamed the generated C++ codec class to `PigeonInternalCodecSerializer`. The Windows +# plugin code historically references `FirebaseFirestoreHostApiCodecSerializer`, so keep that +# stable name and reparent the class onto our custom Firestore codec. +sed -i '' 's/PigeonInternalCodecSerializer/FirebaseFirestoreHostApiCodecSerializer/g' $FILE_NAME +sed -i '' 's|: public ::flutter::StandardCodecSerializer {|: public cloud_firestore_windows::FirestoreCodec {|' $FILE_NAME FILE_NAME="../../cloud_firestore/windows/messages.g.cpp" -sed -i '' 's/flutter::StandardCodecSerializer::WriteValue(value, stream);/cloud_firestore_windows::FirestoreCodec::WriteValue(value, stream);/' $FILE_NAME -sed -i '' 's/return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);/return cloud_firestore_windows::FirestoreCodec::ReadValueOfType(type, stream);/' $FILE_NAME +sed -i '' 's/PigeonInternalCodecSerializer/FirebaseFirestoreHostApiCodecSerializer/g' $FILE_NAME +sed -i '' 's|::flutter::StandardCodecSerializer::WriteValue(value, stream)|::cloud_firestore_windows::FirestoreCodec::WriteValue(value, stream)|' $FILE_NAME +sed -i '' 's|::flutter::StandardCodecSerializer::ReadValueOfType(type, stream)|::cloud_firestore_windows::FirestoreCodec::ReadValueOfType(type, stream)|' $FILE_NAME + +# Pigeon 26 no longer auto-renames a C++ enum whose identifier collides with a method in the same +# scope. The `PersistenceCacheIndexManagerRequest` enum collides with the host API method of the +# same name, which fails to compile on MSVC. Rename every *usage* of the enum type (but keep the +# method name intact) by first renaming the identifier globally and then restoring call/method +# sites that are followed by `(`. +for FILE_NAME in "../../cloud_firestore/windows/messages.g.h" "../../cloud_firestore/windows/messages.g.cpp"; do + sed -i '' 's/PersistenceCacheIndexManagerRequest/PersistenceCacheIndexManagerRequestEnum/g' $FILE_NAME + sed -i '' 's/PersistenceCacheIndexManagerRequestEnum(/PersistenceCacheIndexManagerRequest(/g' $FILE_NAME +done echo "Windows modification complete." # Fix Dart files FILE_NAME="../lib/src/pigeon/messages.pigeon.dart" -sed -i '' '/import '\''package:flutter\/foundation\.dart'\'' show ReadBuffer, WriteBuffer;/i\ +# Pigeon 26 no longer imports flutter/foundation.dart, so anchor on flutter/services.dart instead. +sed -i '' '/import '\''package:flutter\/services\.dart'\'';/i\ import '\''package:cloud_firestore_platform_interface/src/method_channel/utils/firestore_message_codec.dart'\''; ' $FILE_NAME -sed -i '' 's/class _FirebaseFirestoreHostApiCodec extends StandardMessageCodec {/class _FirebaseFirestoreHostApiCodec extends FirestoreMessageCodec {/' $FILE_NAME -(cd .. && dart fix --apply > /dev/null) +# Pigeon 26 renamed the private codec to `_PigeonCodec`. Swap its base class to our custom one +# and expose it publicly (as `PigeonCodec`) so the plugin's EventChannels can reuse it to decode +# Pigeon-generated types like `InternalDocumentSnapshot` emitted via stream handlers. +sed -i '' 's/class _PigeonCodec extends StandardMessageCodec {/class PigeonCodec extends FirestoreMessageCodec {/' $FILE_NAME +sed -i '' 's/const _PigeonCodec();/const PigeonCodec();/' $FILE_NAME +sed -i '' 's/pigeonChannelCodec = _PigeonCodec();/pigeonChannelCodec = PigeonCodec();/' $FILE_NAME +(cd .. && dart fix --apply > /dev/null) FILE_NAME="../test/pigeon/test_api.dart" sed -i '' -E 's/import '\''dart:typed_data'\'' show Float64List, Int32List, Int64List, Uint8List;/import '\''dart:typed_data'\'' show Uint8List;/' $FILE_NAME diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart index a84c58f7af56..27a61ef98f0d 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pigeons/messages.dart @@ -26,8 +26,8 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) -class PigeonFirebaseSettings { - const PigeonFirebaseSettings({ +class InternalFirebaseSettings { + const InternalFirebaseSettings({ required this.persistenceEnabled, required this.host, required this.sslEnabled, @@ -52,12 +52,12 @@ class FirestorePigeonFirebaseApp { }); final String appName; - final PigeonFirebaseSettings settings; + final InternalFirebaseSettings settings; final String databaseURL; } -class PigeonSnapshotMetadata { - const PigeonSnapshotMetadata({ +class InternalSnapshotMetadata { + const InternalSnapshotMetadata({ required this.hasPendingWrites, required this.isFromCache, }); @@ -66,8 +66,8 @@ class PigeonSnapshotMetadata { final bool isFromCache; } -class PigeonDocumentSnapshot { - const PigeonDocumentSnapshot({ +class InternalDocumentSnapshot { + const InternalDocumentSnapshot({ required this.path, required this.data, required this.metadata, @@ -75,7 +75,7 @@ class PigeonDocumentSnapshot { final String path; final Map? data; - final PigeonSnapshotMetadata metadata; + final InternalSnapshotMetadata metadata; } /// An enumeration of document change types. @@ -92,8 +92,8 @@ enum DocumentChangeType { removed, } -class PigeonDocumentChange { - const PigeonDocumentChange({ +class InternalDocumentChange { + const InternalDocumentChange({ required this.type, required this.document, required this.oldIndex, @@ -101,25 +101,25 @@ class PigeonDocumentChange { }); final DocumentChangeType type; - final PigeonDocumentSnapshot document; + final InternalDocumentSnapshot document; final int oldIndex; final int newIndex; } -class PigeonQuerySnapshot { - const PigeonQuerySnapshot({ +class InternalQuerySnapshot { + const InternalQuerySnapshot({ required this.documents, required this.documentChanges, required this.metadata, }); - final List documents; - final List documentChanges; - final PigeonSnapshotMetadata metadata; + final List documents; + final List documentChanges; + final InternalSnapshotMetadata metadata; } -class PigeonPipelineResult { - const PigeonPipelineResult({ +class InternalPipelineResult { + const InternalPipelineResult({ this.documentPath, this.createTime, this.updateTime, @@ -133,13 +133,13 @@ class PigeonPipelineResult { final Map? data; } -class PigeonPipelineSnapshot { - const PigeonPipelineSnapshot({ +class InternalPipelineSnapshot { + const InternalPipelineSnapshot({ required this.results, required this.executionTime, }); - final List results; + final List results; final int executionTime; // Timestamp in milliseconds since epoch } @@ -203,8 +203,8 @@ enum PersistenceCacheIndexManagerRequest { deleteAllIndexes } -class PigeonGetOptions { - const PigeonGetOptions({ +class InternalGetOptions { + const InternalGetOptions({ required this.source, required this.serverTimestampBehavior, }); @@ -213,12 +213,12 @@ class PigeonGetOptions { final ServerTimestampBehavior serverTimestampBehavior; } -enum PigeonTransactionResult { +enum InternalTransactionResult { success, failure, } -enum PigeonTransactionType { +enum InternalTransactionType { get, update, set, @@ -226,8 +226,8 @@ enum PigeonTransactionType { deleteType, } -class PigeonDocumentOption { - const PigeonDocumentOption({ +class InternalDocumentOption { + const InternalDocumentOption({ required this.merge, required this.mergeFields, }); @@ -236,18 +236,18 @@ class PigeonDocumentOption { final List?>? mergeFields; } -class PigeonTransactionCommand { - const PigeonTransactionCommand({ +class InternalTransactionCommand { + const InternalTransactionCommand({ required this.type, required this.path, required this.data, this.option, }); - final PigeonTransactionType type; + final InternalTransactionType type; final String path; final Map? data; - final PigeonDocumentOption? option; + final InternalDocumentOption? option; } class DocumentReferenceRequest { @@ -260,13 +260,13 @@ class DocumentReferenceRequest { }); final String path; final Map? data; - final PigeonDocumentOption? option; + final InternalDocumentOption? option; final Source? source; final ServerTimestampBehavior? serverTimestampBehavior; } -class PigeonQueryParameters { - const PigeonQueryParameters({ +class InternalQueryParameters { + const InternalQueryParameters({ this.where, this.orderBy, this.limit, @@ -326,10 +326,10 @@ abstract class FirebaseFirestoreHostApi { ); @async - PigeonQuerySnapshot namedQueryGet( + InternalQuerySnapshot namedQueryGet( FirestorePigeonFirebaseApp app, String name, - PigeonGetOptions options, + InternalGetOptions options, ); @async @@ -383,12 +383,12 @@ abstract class FirebaseFirestoreHostApi { @async void transactionStoreResult( String transactionId, - PigeonTransactionResult resultType, - List? commands, + InternalTransactionResult resultType, + List? commands, ); @async - PigeonDocumentSnapshot transactionGet( + InternalDocumentSnapshot transactionGet( FirestorePigeonFirebaseApp app, String transactionId, String path, @@ -407,7 +407,7 @@ abstract class FirebaseFirestoreHostApi { ); @async - PigeonDocumentSnapshot documentReferenceGet( + InternalDocumentSnapshot documentReferenceGet( FirestorePigeonFirebaseApp app, DocumentReferenceRequest request, ); @@ -419,19 +419,19 @@ abstract class FirebaseFirestoreHostApi { ); @async - PigeonQuerySnapshot queryGet( + InternalQuerySnapshot queryGet( FirestorePigeonFirebaseApp app, String path, bool isCollectionGroup, - PigeonQueryParameters parameters, - PigeonGetOptions options, + InternalQueryParameters parameters, + InternalGetOptions options, ); @async List aggregateQuery( FirestorePigeonFirebaseApp app, String path, - PigeonQueryParameters parameters, + InternalQueryParameters parameters, AggregateSource source, List queries, bool isCollectionGroup, @@ -440,7 +440,7 @@ abstract class FirebaseFirestoreHostApi { @async void writeBatchCommit( FirestorePigeonFirebaseApp app, - List writes, + List writes, ); @async @@ -448,8 +448,8 @@ abstract class FirebaseFirestoreHostApi { FirestorePigeonFirebaseApp app, String path, bool isCollectionGroup, - PigeonQueryParameters parameters, - PigeonGetOptions options, + InternalQueryParameters parameters, + InternalGetOptions options, bool includeMetadataChanges, ListenSource source, ); @@ -469,7 +469,7 @@ abstract class FirebaseFirestoreHostApi { ); @async - PigeonPipelineSnapshot executePipeline( + InternalPipelineSnapshot executePipeline( FirestorePigeonFirebaseApp app, List?> stages, Map? options, diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml index 72dd614e2e7c..c73118f38741 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml @@ -22,7 +22,7 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 - pigeon: 11.0.1 + pigeon: 26.3.4 watcher: ^1.1.0 dependency_overrides: diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart index e9ed58eafc5c..726d510a1f69 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/test/pigeon/test_api.dart @@ -1,9 +1,9 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Uint8List; @@ -13,55 +13,85 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:cloud_firestore_platform_interface/src/pigeon/messages.pigeon.dart'; -class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { - const _TestFirebaseFirestoreHostApiCodec(); +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is AggregateQuery) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is AggregateQueryResponse) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is DocumentChangeType) { buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is DocumentReferenceRequest) { + writeValue(buffer, value.index); + } else if (value is Source) { buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is FirestorePigeonFirebaseApp) { + writeValue(buffer, value.index); + } else if (value is ListenSource) { buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else if (value is PigeonDocumentChange) { + writeValue(buffer, value.index); + } else if (value is ServerTimestampBehavior) { buffer.putUint8(132); - writeValue(buffer, value.encode()); - } else if (value is PigeonDocumentOption) { + writeValue(buffer, value.index); + } else if (value is AggregateSource) { buffer.putUint8(133); - writeValue(buffer, value.encode()); - } else if (value is PigeonDocumentSnapshot) { + writeValue(buffer, value.index); + } else if (value is PersistenceCacheIndexManagerRequest) { buffer.putUint8(134); - writeValue(buffer, value.encode()); - } else if (value is PigeonFirebaseSettings) { + writeValue(buffer, value.index); + } else if (value is InternalTransactionResult) { buffer.putUint8(135); - writeValue(buffer, value.encode()); - } else if (value is PigeonGetOptions) { + writeValue(buffer, value.index); + } else if (value is InternalTransactionType) { buffer.putUint8(136); - writeValue(buffer, value.encode()); - } else if (value is PigeonPipelineResult) { + writeValue(buffer, value.index); + } else if (value is AggregateType) { buffer.putUint8(137); - writeValue(buffer, value.encode()); - } else if (value is PigeonPipelineSnapshot) { + writeValue(buffer, value.index); + } else if (value is InternalFirebaseSettings) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonQueryParameters) { + } else if (value is FirestorePigeonFirebaseApp) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonQuerySnapshot) { + } else if (value is InternalSnapshotMetadata) { buffer.putUint8(140); writeValue(buffer, value.encode()); - } else if (value is PigeonSnapshotMetadata) { + } else if (value is InternalDocumentSnapshot) { buffer.putUint8(141); writeValue(buffer, value.encode()); - } else if (value is PigeonTransactionCommand) { + } else if (value is InternalDocumentChange) { buffer.putUint8(142); writeValue(buffer, value.encode()); + } else if (value is InternalQuerySnapshot) { + buffer.putUint8(143); + writeValue(buffer, value.encode()); + } else if (value is InternalPipelineResult) { + buffer.putUint8(144); + writeValue(buffer, value.encode()); + } else if (value is InternalPipelineSnapshot) { + buffer.putUint8(145); + writeValue(buffer, value.encode()); + } else if (value is InternalGetOptions) { + buffer.putUint8(146); + writeValue(buffer, value.encode()); + } else if (value is InternalDocumentOption) { + buffer.putUint8(147); + writeValue(buffer, value.encode()); + } else if (value is InternalTransactionCommand) { + buffer.putUint8(148); + writeValue(buffer, value.encode()); + } else if (value is DocumentReferenceRequest) { + buffer.putUint8(149); + writeValue(buffer, value.encode()); + } else if (value is InternalQueryParameters) { + buffer.putUint8(150); + writeValue(buffer, value.encode()); + } else if (value is AggregateQuery) { + buffer.putUint8(151); + writeValue(buffer, value.encode()); + } else if (value is AggregateQueryResponse) { + buffer.putUint8(152); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -70,36 +100,65 @@ class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: - return AggregateQuery.decode(readValue(buffer)!); case 129: - return AggregateQueryResponse.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : DocumentChangeType.values[value]; case 130: - return DocumentReferenceRequest.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : Source.values[value]; case 131: - return FirestorePigeonFirebaseApp.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : ListenSource.values[value]; case 132: - return PigeonDocumentChange.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : ServerTimestampBehavior.values[value]; case 133: - return PigeonDocumentOption.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : AggregateSource.values[value]; case 134: - return PigeonDocumentSnapshot.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null + ? null + : PersistenceCacheIndexManagerRequest.values[value]; case 135: - return PigeonFirebaseSettings.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : InternalTransactionResult.values[value]; case 136: - return PigeonGetOptions.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : InternalTransactionType.values[value]; case 137: - return PigeonPipelineResult.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : AggregateType.values[value]; case 138: - return PigeonPipelineSnapshot.decode(readValue(buffer)!); + return InternalFirebaseSettings.decode(readValue(buffer)!); case 139: - return PigeonQueryParameters.decode(readValue(buffer)!); + return FirestorePigeonFirebaseApp.decode(readValue(buffer)!); case 140: - return PigeonQuerySnapshot.decode(readValue(buffer)!); + return InternalSnapshotMetadata.decode(readValue(buffer)!); case 141: - return PigeonSnapshotMetadata.decode(readValue(buffer)!); + return InternalDocumentSnapshot.decode(readValue(buffer)!); case 142: - return PigeonTransactionCommand.decode(readValue(buffer)!); + return InternalDocumentChange.decode(readValue(buffer)!); + case 143: + return InternalQuerySnapshot.decode(readValue(buffer)!); + case 144: + return InternalPipelineResult.decode(readValue(buffer)!); + case 145: + return InternalPipelineSnapshot.decode(readValue(buffer)!); + case 146: + return InternalGetOptions.decode(readValue(buffer)!); + case 147: + return InternalDocumentOption.decode(readValue(buffer)!); + case 148: + return InternalTransactionCommand.decode(readValue(buffer)!); + case 149: + return DocumentReferenceRequest.decode(readValue(buffer)!); + case 150: + return InternalQueryParameters.decode(readValue(buffer)!); + case 151: + return AggregateQuery.decode(readValue(buffer)!); + case 152: + return AggregateQueryResponse.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -109,15 +168,14 @@ class _TestFirebaseFirestoreHostApiCodec extends StandardMessageCodec { abstract class TestFirebaseFirestoreHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec codec = - _TestFirebaseFirestoreHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); Future loadBundle(FirestorePigeonFirebaseApp app, Uint8List bundle); - Future namedQueryGet( + Future namedQueryGet( FirestorePigeonFirebaseApp app, String name, - PigeonGetOptions options, + InternalGetOptions options, ); Future clearPersistence(FirestorePigeonFirebaseApp app); @@ -147,11 +205,11 @@ abstract class TestFirebaseFirestoreHostApi { Future transactionStoreResult( String transactionId, - PigeonTransactionResult resultType, - List? commands, + InternalTransactionResult resultType, + List? commands, ); - Future transactionGet( + Future transactionGet( FirestorePigeonFirebaseApp app, String transactionId, String path, @@ -167,7 +225,7 @@ abstract class TestFirebaseFirestoreHostApi { DocumentReferenceRequest request, ); - Future documentReferenceGet( + Future documentReferenceGet( FirestorePigeonFirebaseApp app, DocumentReferenceRequest request, ); @@ -177,18 +235,18 @@ abstract class TestFirebaseFirestoreHostApi { DocumentReferenceRequest request, ); - Future queryGet( + Future queryGet( FirestorePigeonFirebaseApp app, String path, bool isCollectionGroup, - PigeonQueryParameters parameters, - PigeonGetOptions options, + InternalQueryParameters parameters, + InternalGetOptions options, ); Future> aggregateQuery( FirestorePigeonFirebaseApp app, String path, - PigeonQueryParameters parameters, + InternalQueryParameters parameters, AggregateSource source, List queries, bool isCollectionGroup, @@ -196,15 +254,15 @@ abstract class TestFirebaseFirestoreHostApi { Future writeBatchCommit( FirestorePigeonFirebaseApp app, - List writes, + List writes, ); Future querySnapshot( FirestorePigeonFirebaseApp app, String path, bool isCollectionGroup, - PigeonQueryParameters parameters, - PigeonGetOptions options, + InternalQueryParameters parameters, + InternalGetOptions options, bool includeMetadataChanges, ListenSource source, ); @@ -221,938 +279,800 @@ abstract class TestFirebaseFirestoreHostApi { PersistenceCacheIndexManagerRequest request, ); - Future executePipeline( + Future executePipeline( FirestorePigeonFirebaseApp app, List?> stages, Map? options, ); - static void setup( + static void setUp( TestFirebaseFirestoreHostApi? api, { BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', }) { + messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final Uint8List? arg_bundle = (args[1] as Uint8List?); - assert( - arg_bundle != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.loadBundle was null, expected non-null Uint8List.', - ); - final String output = await api.loadBundle(arg_app!, arg_bundle!); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final Uint8List arg_bundle = args[1]! as Uint8List; + try { + final String output = await api.loadBundle(arg_app, arg_bundle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final String? arg_name = (args[1] as String?); - assert( - arg_name != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null String.', - ); - final PigeonGetOptions? arg_options = (args[2] as PigeonGetOptions?); - assert( - arg_options != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.namedQueryGet was null, expected non-null PigeonGetOptions.', - ); - final PigeonQuerySnapshot output = - await api.namedQueryGet(arg_app!, arg_name!, arg_options!); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final String arg_name = args[1]! as String; + final InternalGetOptions arg_options = args[2]! as InternalGetOptions; + try { + final InternalQuerySnapshot output = + await api.namedQueryGet(arg_app, arg_name, arg_options); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.clearPersistence was null, expected non-null FirestorePigeonFirebaseApp.', - ); - await api.clearPersistence(arg_app!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + try { + await api.clearPersistence(arg_app); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.disableNetwork was null, expected non-null FirestorePigeonFirebaseApp.', - ); - await api.disableNetwork(arg_app!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + try { + await api.disableNetwork(arg_app); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.enableNetwork was null, expected non-null FirestorePigeonFirebaseApp.', - ); - await api.enableNetwork(arg_app!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + try { + await api.enableNetwork(arg_app); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.terminate was null, expected non-null FirestorePigeonFirebaseApp.', - ); - await api.terminate(arg_app!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + try { + await api.terminate(arg_app); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.waitForPendingWrites was null, expected non-null FirestorePigeonFirebaseApp.', - ); - await api.waitForPendingWrites(arg_app!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + try { + await api.waitForPendingWrites(arg_app); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final String? arg_indexConfiguration = (args[1] as String?); - assert( - arg_indexConfiguration != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setIndexConfiguration was null, expected non-null String.', - ); - await api.setIndexConfiguration(arg_app!, arg_indexConfiguration!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final String arg_indexConfiguration = args[1]! as String; + try { + await api.setIndexConfiguration(arg_app, arg_indexConfiguration); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled was null.', - ); - final List args = (message as List?)!; - final bool? arg_loggingEnabled = (args[0] as bool?); - assert( - arg_loggingEnabled != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.setLoggingEnabled was null, expected non-null bool.', - ); - await api.setLoggingEnabled(arg_loggingEnabled!); - return []; + final List args = message! as List; + final bool arg_loggingEnabled = args[0]! as bool; + try { + await api.setLoggingEnabled(arg_loggingEnabled); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.snapshotsInSyncSetup was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final String output = await api.snapshotsInSyncSetup(arg_app!); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + try { + final String output = await api.snapshotsInSyncSetup(arg_app); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final int? arg_timeout = (args[1] as int?); - assert( - arg_timeout != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null int.', - ); - final int? arg_maxAttempts = (args[2] as int?); - assert( - arg_maxAttempts != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionCreate was null, expected non-null int.', - ); - final String output = await api.transactionCreate( - arg_app!, - arg_timeout!, - arg_maxAttempts!, - ); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final int arg_timeout = args[1]! as int; + final int arg_maxAttempts = args[2]! as int; + try { + final String output = await api.transactionCreate( + arg_app, + arg_timeout, + arg_maxAttempts, + ); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null.', - ); - final List args = (message as List?)!; - final String? arg_transactionId = (args[0] as String?); - assert( - arg_transactionId != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null, expected non-null String.', - ); - final PigeonTransactionResult? arg_resultType = args[1] == null - ? null - : PigeonTransactionResult.values[args[1]! as int]; - assert( - arg_resultType != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionStoreResult was null, expected non-null PigeonTransactionResult.', - ); - final List? arg_commands = - (args[2] as List?)?.cast(); - await api.transactionStoreResult( - arg_transactionId!, - arg_resultType!, - arg_commands, - ); - return []; + final List args = message! as List; + final String arg_transactionId = args[0]! as String; + final InternalTransactionResult arg_resultType = + args[1]! as InternalTransactionResult; + final List? arg_commands = + (args[2] as List?)?.cast(); + try { + await api.transactionStoreResult( + arg_transactionId, + arg_resultType, + arg_commands, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final String? arg_transactionId = (args[1] as String?); - assert( - arg_transactionId != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null String.', - ); - final String? arg_path = (args[2] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.transactionGet was null, expected non-null String.', - ); - final PigeonDocumentSnapshot output = - await api.transactionGet(arg_app!, arg_transactionId!, arg_path!); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final String arg_transactionId = args[1]! as String; + final String arg_path = args[2]! as String; + try { + final InternalDocumentSnapshot output = + await api.transactionGet(arg_app, arg_transactionId, arg_path); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final DocumentReferenceRequest? arg_request = - (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSet was null, expected non-null DocumentReferenceRequest.', - ); - await api.documentReferenceSet(arg_app!, arg_request!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final DocumentReferenceRequest arg_request = + args[1]! as DocumentReferenceRequest; + try { + await api.documentReferenceSet(arg_app, arg_request); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final DocumentReferenceRequest? arg_request = - (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceUpdate was null, expected non-null DocumentReferenceRequest.', - ); - await api.documentReferenceUpdate(arg_app!, arg_request!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final DocumentReferenceRequest arg_request = + args[1]! as DocumentReferenceRequest; + try { + await api.documentReferenceUpdate(arg_app, arg_request); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final DocumentReferenceRequest? arg_request = - (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceGet was null, expected non-null DocumentReferenceRequest.', - ); - final PigeonDocumentSnapshot output = - await api.documentReferenceGet(arg_app!, arg_request!); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final DocumentReferenceRequest arg_request = + args[1]! as DocumentReferenceRequest; + try { + final InternalDocumentSnapshot output = + await api.documentReferenceGet(arg_app, arg_request); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final DocumentReferenceRequest? arg_request = - (args[1] as DocumentReferenceRequest?); - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceDelete was null, expected non-null DocumentReferenceRequest.', - ); - await api.documentReferenceDelete(arg_app!, arg_request!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final DocumentReferenceRequest arg_request = + args[1]! as DocumentReferenceRequest; + try { + await api.documentReferenceDelete(arg_app, arg_request); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final String? arg_path = (args[1] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null String.', - ); - final bool? arg_isCollectionGroup = (args[2] as bool?); - assert( - arg_isCollectionGroup != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null bool.', - ); - final PigeonQueryParameters? arg_parameters = - (args[3] as PigeonQueryParameters?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null PigeonQueryParameters.', - ); - final PigeonGetOptions? arg_options = (args[4] as PigeonGetOptions?); - assert( - arg_options != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.queryGet was null, expected non-null PigeonGetOptions.', - ); - final PigeonQuerySnapshot output = await api.queryGet( - arg_app!, - arg_path!, - arg_isCollectionGroup!, - arg_parameters!, - arg_options!, - ); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final String arg_path = args[1]! as String; + final bool arg_isCollectionGroup = args[2]! as bool; + final InternalQueryParameters arg_parameters = + args[3]! as InternalQueryParameters; + final InternalGetOptions arg_options = args[4]! as InternalGetOptions; + try { + final InternalQuerySnapshot output = await api.queryGet( + arg_app, + arg_path, + arg_isCollectionGroup, + arg_parameters, + arg_options, + ); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final String? arg_path = (args[1] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null String.', - ); - final PigeonQueryParameters? arg_parameters = - (args[2] as PigeonQueryParameters?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null PigeonQueryParameters.', - ); - final AggregateSource? arg_source = - args[3] == null ? null : AggregateSource.values[args[3]! as int]; - assert( - arg_source != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null AggregateSource.', - ); - final List? arg_queries = - (args[4] as List?)?.cast(); - assert( - arg_queries != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null List.', - ); - final bool? arg_isCollectionGroup = (args[5] as bool?); - assert( - arg_isCollectionGroup != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.aggregateQuery was null, expected non-null bool.', - ); - final List output = await api.aggregateQuery( - arg_app!, - arg_path!, - arg_parameters!, - arg_source!, - arg_queries!, - arg_isCollectionGroup!, - ); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final String arg_path = args[1]! as String; + final InternalQueryParameters arg_parameters = + args[2]! as InternalQueryParameters; + final AggregateSource arg_source = args[3]! as AggregateSource; + final List arg_queries = + (args[4]! as List).cast(); + final bool arg_isCollectionGroup = args[5]! as bool; + try { + final List output = + await api.aggregateQuery( + arg_app, + arg_path, + arg_parameters, + arg_source, + arg_queries, + arg_isCollectionGroup, + ); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final List? arg_writes = - (args[1] as List?)?.cast(); - assert( - arg_writes != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.writeBatchCommit was null, expected non-null List.', - ); - await api.writeBatchCommit(arg_app!, arg_writes!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final List arg_writes = + (args[1]! as List).cast(); + try { + await api.writeBatchCommit(arg_app, arg_writes); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final String? arg_path = (args[1] as String?); - assert( - arg_path != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null String.', - ); - final bool? arg_isCollectionGroup = (args[2] as bool?); - assert( - arg_isCollectionGroup != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null bool.', - ); - final PigeonQueryParameters? arg_parameters = - (args[3] as PigeonQueryParameters?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null PigeonQueryParameters.', - ); - final PigeonGetOptions? arg_options = (args[4] as PigeonGetOptions?); - assert( - arg_options != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null PigeonGetOptions.', - ); - final bool? arg_includeMetadataChanges = (args[5] as bool?); - assert( - arg_includeMetadataChanges != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null bool.', - ); - final ListenSource? arg_source = - args[6] == null ? null : ListenSource.values[args[6]! as int]; - assert( - arg_source != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.querySnapshot was null, expected non-null ListenSource.', - ); - final String output = await api.querySnapshot( - arg_app!, - arg_path!, - arg_isCollectionGroup!, - arg_parameters!, - arg_options!, - arg_includeMetadataChanges!, - arg_source!, - ); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final String arg_path = args[1]! as String; + final bool arg_isCollectionGroup = args[2]! as bool; + final InternalQueryParameters arg_parameters = + args[3]! as InternalQueryParameters; + final InternalGetOptions arg_options = args[4]! as InternalGetOptions; + final bool arg_includeMetadataChanges = args[5]! as bool; + final ListenSource arg_source = args[6]! as ListenSource; + try { + final String output = await api.querySnapshot( + arg_app, + arg_path, + arg_isCollectionGroup, + arg_parameters, + arg_options, + arg_includeMetadataChanges, + arg_source, + ); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final DocumentReferenceRequest? arg_parameters = - (args[1] as DocumentReferenceRequest?); - assert( - arg_parameters != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null DocumentReferenceRequest.', - ); - final bool? arg_includeMetadataChanges = (args[2] as bool?); - assert( - arg_includeMetadataChanges != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null bool.', - ); - final ListenSource? arg_source = - args[3] == null ? null : ListenSource.values[args[3]! as int]; - assert( - arg_source != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.documentReferenceSnapshot was null, expected non-null ListenSource.', - ); - final String output = await api.documentReferenceSnapshot( - arg_app!, - arg_parameters!, - arg_includeMetadataChanges!, - arg_source!, - ); - return [output]; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final DocumentReferenceRequest arg_parameters = + args[1]! as DocumentReferenceRequest; + final bool arg_includeMetadataChanges = args[2]! as bool; + final ListenSource arg_source = args[3]! as ListenSource; + try { + final String output = await api.documentReferenceSnapshot( + arg_app, + arg_parameters, + arg_includeMetadataChanges, + arg_source, + ); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final PersistenceCacheIndexManagerRequest? arg_request = - args[1] == null - ? null - : PersistenceCacheIndexManagerRequest.values[args[1]! as int]; - assert( - arg_request != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.persistenceCacheIndexManagerRequest was null, expected non-null PersistenceCacheIndexManagerRequest.', - ); - await api.persistenceCacheIndexManagerRequest(arg_app!, arg_request!); - return []; + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final PersistenceCacheIndexManagerRequest arg_request = + args[1]! as PersistenceCacheIndexManagerRequest; + try { + await api.persistenceCacheIndexManagerRequest(arg_app, arg_request); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger, ); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null.', - ); - final List args = (message as List?)!; - final FirestorePigeonFirebaseApp? arg_app = - (args[0] as FirestorePigeonFirebaseApp?); - assert( - arg_app != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null, expected non-null FirestorePigeonFirebaseApp.', - ); - final List?>? arg_stages = - (args[1] as List?)?.cast?>(); - assert( - arg_stages != null, - 'Argument for dev.flutter.pigeon.cloud_firestore_platform_interface.FirebaseFirestoreHostApi.executePipeline was null, expected non-null List?>.', - ); + final List args = message! as List; + final FirestorePigeonFirebaseApp arg_app = + args[0]! as FirestorePigeonFirebaseApp; + final List?> arg_stages = + (args[1]! as List).cast?>(); final Map? arg_options = (args[2] as Map?)?.cast(); - final PigeonPipelineSnapshot output = - await api.executePipeline(arg_app!, arg_stages!, arg_options); - return [output]; + try { + final InternalPipelineSnapshot output = + await api.executePipeline(arg_app, arg_stages, arg_options); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } }); } } diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/test/utils/test_firestore_message_codec.dart b/packages/cloud_firestore/cloud_firestore_platform_interface/test/utils/test_firestore_message_codec.dart index 12b7b5bb1c27..d17c62a8ecf1 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/test/utils/test_firestore_message_codec.dart +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/test/utils/test_firestore_message_codec.dart @@ -73,7 +73,7 @@ class TestFirestoreMessageCodec extends FirestoreMessageCodec { values['path'], FirestorePigeonFirebaseApp( appName: 'test', - settings: PigeonFirebaseSettings( + settings: InternalFirebaseSettings( ignoreUndefinedProperties: false, ), databaseURL: '', diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/web_utils.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/web_utils.dart index 43d3b07cb1a8..c92ef6b73fb8 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/web_utils.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/web_utils.dart @@ -67,7 +67,7 @@ DocumentSnapshotPlatform convertWebDocumentSnapshot( )), firestore, ), - PigeonSnapshotMetadata( + InternalSnapshotMetadata( hasPendingWrites: webSnapshot.metadata.hasPendingWrites.toDart, isFromCache: webSnapshot.metadata.fromCache.toDart, ), diff --git a/packages/cloud_functions/analysis_options.yaml b/packages/cloud_functions/analysis_options.yaml index 1597da232319..b8c16f67fb33 100644 --- a/packages/cloud_functions/analysis_options.yaml +++ b/packages/cloud_functions/analysis_options.yaml @@ -7,4 +7,5 @@ include: ../../analysis_options.yaml analyzer: exclude: - cloud_functions_platform_interface/lib/src/pigeon/messages.pigeon.dart - - cloud_functions_platform_interface/test/pigeon/test_api.dart \ No newline at end of file + - cloud_functions_platform_interface/test/pigeon/test_api.dart + - cloud_functions_platform_interface/pigeons/messages.dart \ No newline at end of file diff --git a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt index ed7f4b3c90fc..7b5c2181da86 100644 --- a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt +++ b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -49,7 +49,7 @@ class FlutterError ( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() private open class GeneratedAndroidCloudFunctionsPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return super.readValueOfType(type, buffer) diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift index a24439b9a7c3..fca2234a4060 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -52,7 +52,7 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } diff --git a/packages/cloud_functions/cloud_functions/windows/messages.g.cpp b/packages/cloud_functions/cloud_functions/windows/messages.g.cpp index 31724f26c541..50ab69ead469 100644 --- a/packages/cloud_functions/cloud_functions/windows/messages.g.cpp +++ b/packages/cloud_functions/cloud_functions/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace cloud_functions_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,32 +33,239 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + uint8_t type, ::flutter::ByteStreamReader* stream) const { + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - flutter::StandardCodecSerializer::WriteValue(value, stream); + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by CloudFunctionsHostApi. -const flutter::StandardMessageCodec& CloudFunctionsHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& CloudFunctionsHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `CloudFunctionsHostApi` to handle messages through the // `binary_messenger`. -void CloudFunctionsHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void CloudFunctionsHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, CloudFunctionsHostApi* api) { CloudFunctionsHostApi::SetUp(binary_messenger, api, ""); } -void CloudFunctionsHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void CloudFunctionsHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, CloudFunctionsHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -72,7 +281,7 @@ void CloudFunctionsHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_arguments_arg = args.at(0); @@ -117,7 +326,7 @@ void CloudFunctionsHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_arguments_arg = args.at(0); diff --git a/packages/cloud_functions/cloud_functions/windows/messages.g.h b/packages/cloud_functions/cloud_functions/windows/messages.g.h index 7648ad06af7f..6f537decbd12 100644 --- a/packages/cloud_functions/cloud_functions/windows/messages.g.h +++ b/packages/cloud_functions/cloud_functions/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -58,7 +58,8 @@ class ErrorOr { std::variant v_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -66,12 +67,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -82,24 +83,25 @@ class CloudFunctionsHostApi { CloudFunctionsHostApi& operator=(const CloudFunctionsHostApi&) = delete; virtual ~CloudFunctionsHostApi() {} virtual void Call( - const flutter::EncodableMap& arguments, - std::function> reply)> + const ::flutter::EncodableMap& arguments, + std::function< + void(ErrorOr> reply)> result) = 0; virtual void RegisterEventChannel( - const flutter::EncodableMap& arguments, + const ::flutter::EncodableMap& arguments, std::function reply)> result) = 0; // The codec used by CloudFunctionsHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `CloudFunctionsHostApi` to handle messages through // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, CloudFunctionsHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, CloudFunctionsHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: CloudFunctionsHostApi() = default; diff --git a/packages/cloud_functions/cloud_functions_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/cloud_functions/cloud_functions_platform_interface/lib/src/pigeon/messages.pigeon.dart index 5249dd1cd031..ed2a18de54a0 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/cloud_functions/cloud_functions_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,21 +1,40 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } List wrapResponse( @@ -66,54 +85,41 @@ class CloudFunctionsHostApi { final String pigeonVar_messageChannelSuffix; Future call(Map arguments) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([arguments]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return pigeonVar_replyList[0]; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); + return pigeonVar_replyValue; } Future registerEventChannel(Map arguments) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([arguments]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } diff --git a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml index 0e1e096a2c5c..4be0404452de 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml @@ -23,4 +23,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 - pigeon: 25.3.2 + pigeon: 26.3.4 diff --git a/packages/cloud_functions/cloud_functions_platform_interface/test/pigeon/test_api.dart b/packages/cloud_functions/cloud_functions_platform_interface/test/pigeon/test_api.dart index 085dfc1a66de..3583ef25e17d 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/test/pigeon/test_api.dart +++ b/packages/cloud_functions/cloud_functions_platform_interface/test/pigeon/test_api.dart @@ -1,9 +1,9 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; @@ -51,9 +51,7 @@ abstract class TestCloudFunctionsHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -64,15 +62,11 @@ abstract class TestCloudFunctionsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call was null.'); - final List args = (message as List?)!; - final Map? arg_arguments = - (args[0] as Map?)?.cast(); - assert(arg_arguments != null, - 'Argument for dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call was null, expected non-null Map.'); + final List args = message! as List; + final Map arg_arguments = + (args[0]! as Map).cast(); try { - final Object? output = await api.call(arg_arguments!); + final Object? output = await api.call(arg_arguments); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -84,9 +78,7 @@ abstract class TestCloudFunctionsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -97,15 +89,11 @@ abstract class TestCloudFunctionsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel was null.'); - final List args = (message as List?)!; - final Map? arg_arguments = - (args[0] as Map?)?.cast(); - assert(arg_arguments != null, - 'Argument for dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel was null, expected non-null Map.'); + final List args = message! as List; + final Map arg_arguments = + (args[0]! as Map).cast(); try { - await api.registerEventChannel(arg_arguments!); + await api.registerEventChannel(arg_arguments); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); diff --git a/packages/firebase_analytics/analysis_options.yaml b/packages/firebase_analytics/analysis_options.yaml index 478fde4d9c56..f67ba3d72398 100644 --- a/packages/firebase_analytics/analysis_options.yaml +++ b/packages/firebase_analytics/analysis_options.yaml @@ -8,3 +8,4 @@ analyzer: exclude: - firebase_analytics_platform_interface/lib/src/pigeon/messages.pigeon.dart - firebase_analytics_platform_interface/test/pigeon/test_api.dart + - firebase_analytics_platform_interface/pigeons/messages.dart diff --git a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt index fdfc88dc8f42..e2dd133d1e21 100644 --- a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt +++ b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -37,36 +37,150 @@ private object GeneratedAndroidFirebaseAnalyticsPigeonUtils { ) } } + fun doubleEquals(a: Double, b: Double): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) + } + + fun floatEquals(a: Float, b: Float): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN()) + } + + fun doubleHash(d: Double): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (d == 0.0) 0.0 else d + val bits = java.lang.Double.doubleToLongBits(normalized) + return (bits xor (bits ushr 32)).toInt() + } + + fun floatHash(f: Float): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (f == 0.0f) 0.0f else f + return java.lang.Float.floatToIntBits(normalized) + } + fun deepEquals(a: Any?, b: Any?): Boolean { + if (a === b) { + return true + } + if (a == null || b == null) { + return false + } if (a is ByteArray && b is ByteArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is IntArray && b is IntArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is LongArray && b is LongArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is DoubleArray && b is DoubleArray) { - return a.contentEquals(b) + if (a.size != b.size) return false + for (i in a.indices) { + if (!doubleEquals(a[i], b[i])) return false + } + return true + } + if (a is FloatArray && b is FloatArray) { + if (a.size != b.size) return false + for (i in a.indices) { + if (!floatEquals(a[i], b[i])) return false + } + return true } if (a is Array<*> && b is Array<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + for (i in a.indices) { + if (!deepEquals(a[i], b[i])) return false + } + return true } if (a is List<*> && b is List<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + val iterA = a.iterator() + val iterB = b.iterator() + while (iterA.hasNext() && iterB.hasNext()) { + if (!deepEquals(iterA.next(), iterB.next())) return false + } + return true } if (a is Map<*, *> && b is Map<*, *>) { - return a.size == b.size && a.all { - (b as Map).containsKey(it.key) && - deepEquals(it.value, b[it.key]) + if (a.size != b.size) return false + for (entry in a) { + val key = entry.key + var found = false + for (bEntry in b) { + if (deepEquals(key, bEntry.key)) { + if (deepEquals(entry.value, bEntry.value)) { + found = true + break + } else { + return false + } + } + } + if (!found) return false } + return true + } + if (a is Double && b is Double) { + return doubleEquals(a, b) + } + if (a is Float && b is Float) { + return floatEquals(a, b) } return a == b } - + + fun deepHash(value: Any?): Int { + return when (value) { + null -> 0 + is ByteArray -> value.contentHashCode() + is IntArray -> value.contentHashCode() + is LongArray -> value.contentHashCode() + is DoubleArray -> { + var result = 1 + for (item in value) { + result = 31 * result + doubleHash(item) + } + result + } + is FloatArray -> { + var result = 1 + for (item in value) { + result = 31 * result + floatHash(item) + } + result + } + is Array<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is List<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is Map<*, *> -> { + var result = 0 + for (entry in value) { + result += ((deepHash(entry.key) * 31) xor deepHash(entry.value)) + } + result + } + is Double -> doubleHash(value) + is Float -> floatHash(value) + else -> value.hashCode() + } + } + } /** @@ -79,7 +193,7 @@ class FlutterError ( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() /** Generated class from Pigeon that represents data sent in messages. */ data class AnalyticsEvent ( @@ -101,15 +215,22 @@ data class AnalyticsEvent ( ) } override fun equals(other: Any?): Boolean { - if (other !is AnalyticsEvent) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as AnalyticsEvent + return GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepEquals(this.name, other.name) && GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepEquals(this.parameters, other.parameters) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepHash(this.name) + result = 31 * result + GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepHash(this.parameters) + return result + } } private open class GeneratedAndroidFirebaseAnalyticsPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift index d8b175ba6e20..e0f11296f10a 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -52,7 +52,7 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } @@ -66,6 +66,19 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } +private func doubleEqualsFirebaseAnalyticsMessages(_ lhs: Double, _ rhs: Double) -> Bool { + (lhs.isNaN && rhs.isNaN) || lhs == rhs +} + +private func doubleHashFirebaseAnalyticsMessages(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } +} + func deepEqualsFirebaseAnalyticsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { let cleanLhs = nilOrValue(lhs) as Any? let cleanRhs = nilOrValue(rhs) as Any? @@ -76,59 +89,90 @@ func deepEqualsFirebaseAnalyticsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case is (Void, Void): + case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: return true - case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): - return cleanLhsHashable == cleanRhsHashable + case is (Void, Void): + return true - case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): - guard cleanLhsArray.count == cleanRhsArray.count else { return false } - for (index, element) in cleanLhsArray.enumerated() { - if !deepEqualsFirebaseAnalyticsMessages(element, cleanRhsArray[index]) { + case let (lhsArray, rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEqualsFirebaseAnalyticsMessages(element, rhsArray[index]) { return false } } return true - case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } - for (key, cleanLhsValue) in cleanLhsDictionary { - guard cleanRhsDictionary.index(forKey: key) != nil else { return false } - if !deepEqualsFirebaseAnalyticsMessages(cleanLhsValue, cleanRhsDictionary[key]!) { + case let (lhsArray, rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEqualsFirebaseAnalyticsMessages(element, rhsArray[index]) { return false } } return true + case let (lhsDictionary, rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEqualsFirebaseAnalyticsMessages(lhsKey, rhsKey) { + if deepEqualsFirebaseAnalyticsMessages(lhsValue, rhsValue) { + found = true + break + } else { + return false + } + } + } + if !found { return false } + } + return true + + case let (lhs as Double, rhs as Double): + return doubleEqualsFirebaseAnalyticsMessages(lhs, rhs) + + case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable + default: - // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be - // untrue. return false } } func deepHashFirebaseAnalyticsMessages(value: Any?, hasher: inout Hasher) { - if let valueList = value as? [AnyHashable] { - for item in valueList { - deepHashFirebaseAnalyticsMessages(value: item, hasher: &hasher) - } - return - } - - if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { - hasher.combine(key) - deepHashFirebaseAnalyticsMessages(value: valueDict[key]!, hasher: &hasher) + let cleanValue = nilOrValue(value) as Any? + if let cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHashFirebaseAnalyticsMessages(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHashFirebaseAnalyticsMessages(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHashFirebaseAnalyticsMessages(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHashFirebaseAnalyticsMessages(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHashFirebaseAnalyticsMessages(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) } - return - } - - if let hashableValue = value as? AnyHashable { - hasher.combine(hashableValue.hashValue) + } else { + hasher.combine(0) } - - return hasher.combine(String(describing: value)) } /// Generated class from Pigeon that represents data sent in messages. @@ -155,11 +199,20 @@ struct AnalyticsEvent: Hashable { } static func == (lhs: AnalyticsEvent, rhs: AnalyticsEvent) -> Bool { - deepEqualsFirebaseAnalyticsMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseAnalyticsMessages(lhs.name, rhs.name) && + deepEqualsFirebaseAnalyticsMessages( + lhs.parameters, + rhs.parameters + ) } func hash(into hasher: inout Hasher) { - deepHashFirebaseAnalyticsMessages(value: toList(), hasher: &hasher) + hasher.combine("AnalyticsEvent") + deepHashFirebaseAnalyticsMessages(value: name, hasher: &hasher) + deepHashFirebaseAnalyticsMessages(value: parameters, hasher: &hasher) } } diff --git a/packages/firebase_analytics/firebase_analytics/windows/messages.g.cpp b/packages/firebase_analytics/firebase_analytics/windows/messages.g.cpp index 14a92edf1452..8da8a92f2b39 100644 --- a/packages/firebase_analytics/firebase_analytics/windows/messages.g.cpp +++ b/packages/firebase_analytics/firebase_analytics/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_analytics_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,6 +33,212 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace // AnalyticsEvent AnalyticsEvent::AnalyticsEvent(const std::string& name) : name_(name) {} @@ -75,22 +283,40 @@ AnalyticsEvent AnalyticsEvent::FromEncodableList(const EncodableList& list) { return decoded; } +bool AnalyticsEvent::operator==(const AnalyticsEvent& other) const { + return PigeonInternalDeepEquals(name_, other.name_) && + PigeonInternalDeepEquals(parameters_, other.parameters_); +} + +bool AnalyticsEvent::operator!=(const AnalyticsEvent& other) const { + return !(*this == other); +} + +size_t AnalyticsEvent::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(name_); + result = result * 31 + PigeonInternalDeepHash(parameters_); + return result; +} + +size_t PigeonInternalDeepHash(const AnalyticsEvent& v) { return v.Hash(); } + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { case 129: { return CustomEncodableValue(AnalyticsEvent::FromEncodableList( std::get(ReadValue(stream)))); } default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { if (custom_value->type() == typeid(AnalyticsEvent)) { @@ -102,24 +328,25 @@ void PigeonInternalCodecSerializer::WriteValue( return; } } - flutter::StandardCodecSerializer::WriteValue(value, stream); + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseAnalyticsHostApi. -const flutter::StandardMessageCodec& FirebaseAnalyticsHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseAnalyticsHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseAnalyticsHostApi` to handle messages through // the `binary_messenger`. -void FirebaseAnalyticsHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAnalyticsHostApi* api) { +void FirebaseAnalyticsHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAnalyticsHostApi* api) { FirebaseAnalyticsHostApi::SetUp(binary_messenger, api, ""); } void FirebaseAnalyticsHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, FirebaseAnalyticsHostApi* api, + ::flutter::BinaryMessenger* binary_messenger, FirebaseAnalyticsHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = message_channel_suffix.length() > 0 @@ -135,7 +362,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_event_arg = args.at(0); @@ -173,7 +400,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_user_id_arg = args.at(0); @@ -207,7 +434,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_name_arg = args.at(0); @@ -248,7 +475,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_enabled_arg = args.at(0); @@ -285,7 +512,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { api->ResetAnalyticsData( [reply](std::optional&& output) { @@ -315,7 +542,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_timeout_arg = args.at(0); @@ -352,7 +579,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_consent_arg = args.at(0); @@ -390,7 +617,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_parameters_arg = args.at(0); @@ -425,7 +652,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { api->GetAppInstanceId( [reply](ErrorOr>&& output) { @@ -461,7 +688,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { api->GetSessionId( [reply](ErrorOr>&& output) { @@ -497,7 +724,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_arguments_arg = args.at(0); @@ -535,7 +762,7 @@ void FirebaseAnalyticsHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_transaction_id_arg = args.at(0); diff --git a/packages/firebase_analytics/firebase_analytics/windows/messages.g.h b/packages/firebase_analytics/firebase_analytics/windows/messages.g.h index b755d9ef6045..7c22489d9c28 100644 --- a/packages/firebase_analytics/firebase_analytics/windows/messages.g.h +++ b/packages/firebase_analytics/firebase_analytics/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -66,25 +66,38 @@ class AnalyticsEvent { // Constructs an object setting all fields. explicit AnalyticsEvent(const std::string& name, - const flutter::EncodableMap* parameters); + const ::flutter::EncodableMap* parameters); const std::string& name() const; void set_name(std::string_view value_arg); - const flutter::EncodableMap* parameters() const; - void set_parameters(const flutter::EncodableMap* value_arg); - void set_parameters(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* parameters() const; + void set_parameters(const ::flutter::EncodableMap* value_arg); + void set_parameters(const ::flutter::EncodableMap& value_arg); + bool operator==(const AnalyticsEvent& other) const; + bool operator!=(const AnalyticsEvent& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static AnalyticsEvent FromEncodableList(const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static AnalyticsEvent FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAnalyticsHostApi; friend class PigeonInternalCodecSerializer; std::string name_; - std::optional parameters_; + std::optional<::flutter::EncodableMap> parameters_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -92,12 +105,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -108,7 +121,7 @@ class FirebaseAnalyticsHostApi { FirebaseAnalyticsHostApi& operator=(const FirebaseAnalyticsHostApi&) = delete; virtual ~FirebaseAnalyticsHostApi() {} virtual void LogEvent( - const flutter::EncodableMap& event, + const ::flutter::EncodableMap& event, std::function reply)> result) = 0; virtual void SetUserId( const std::string* user_id, @@ -125,10 +138,10 @@ class FirebaseAnalyticsHostApi { int64_t timeout, std::function reply)> result) = 0; virtual void SetConsent( - const flutter::EncodableMap& consent, + const ::flutter::EncodableMap& consent, std::function reply)> result) = 0; virtual void SetDefaultEventParameters( - const flutter::EncodableMap* parameters, + const ::flutter::EncodableMap* parameters, std::function reply)> result) = 0; virtual void GetAppInstanceId( std::function> reply)> @@ -136,23 +149,23 @@ class FirebaseAnalyticsHostApi { virtual void GetSessionId( std::function> reply)> result) = 0; virtual void InitiateOnDeviceConversionMeasurement( - const flutter::EncodableMap& arguments, + const ::flutter::EncodableMap& arguments, std::function reply)> result) = 0; virtual void LogTransaction( const std::string& transaction_id, std::function reply)> result) = 0; // The codec used by FirebaseAnalyticsHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseAnalyticsHostApi` to handle messages // through the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAnalyticsHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAnalyticsHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseAnalyticsHostApi() = default; diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_analytics/firebase_analytics_platform_interface/lib/src/pigeon/messages.pigeon.dart index 003dd773639e..b61f5de91985 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,21 +1,40 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } List wrapResponse( @@ -30,20 +49,67 @@ List wrapResponse( } bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } if (a is List && b is List) { return a.length == b.length && a.indexed .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; } return a == b; } +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} + class AnalyticsEvent { AnalyticsEvent({ required this.name, @@ -83,12 +149,13 @@ class AnalyticsEvent { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(name, other.name) && + _deepEquals(parameters, other.parameters); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class _PigeonCodec extends StandardMessageCodec { @@ -133,313 +200,231 @@ class FirebaseAnalyticsHostApi { final String pigeonVar_messageChannelSuffix; Future logEvent(Map event) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([event]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setUserId(String? userId) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserId$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([userId]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setUserProperty(String name, String? value) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([name, value]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setAnalyticsCollectionEnabled(bool enabled) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([enabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future resetAnalyticsData() async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.resetAnalyticsData$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setSessionTimeoutDuration(int timeout) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([timeout]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setConsent(Map consent) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([consent]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setDefaultEventParameters( Map? parameters) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setDefaultEventParameters$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([parameters]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future getAppInstanceId() async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getAppInstanceId$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as String?); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); + return pigeonVar_replyValue as String?; } Future getSessionId() async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getSessionId$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as int?); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); + return pigeonVar_replyValue as int?; } Future initiateOnDeviceConversionMeasurement( Map arguments) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([arguments]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future logTransaction(String transactionId) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([transactionId]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml index ad780d100a1d..d21a75f0cb4e 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml @@ -20,4 +20,4 @@ dev_dependencies: firebase_core_platform_interface: ^6.0.3 flutter_test: sdk: flutter - pigeon: 25.3.2 + pigeon: 26.3.4 diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/test/pigeon/test_api.dart b/packages/firebase_analytics/firebase_analytics_platform_interface/test/pigeon/test_api.dart index 591cce9f19e2..830f97b9696d 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/test/pigeon/test_api.dart +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/test/pigeon/test_api.dart @@ -1,9 +1,9 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; @@ -77,9 +77,7 @@ abstract class TestFirebaseAnalyticsHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -90,15 +88,11 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent was null.'); - final List args = (message as List?)!; - final Map? arg_event = - (args[0] as Map?)?.cast(); - assert(arg_event != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent was null, expected non-null Map.'); + final List args = message! as List; + final Map arg_event = + (args[0]! as Map).cast(); try { - await api.logEvent(arg_event!); + await api.logEvent(arg_event); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -110,9 +104,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserId$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -123,10 +115,8 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserId was null.'); - final List args = (message as List?)!; - final String? arg_userId = (args[0] as String?); + final List args = message! as List; + final String? arg_userId = args[0] as String?; try { await api.setUserId(arg_userId); return wrapResponse(empty: true); @@ -140,9 +130,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -153,15 +141,11 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty was null.'); - final List args = (message as List?)!; - final String? arg_name = (args[0] as String?); - assert(arg_name != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty was null, expected non-null String.'); - final String? arg_value = (args[1] as String?); + final List args = message! as List; + final String arg_name = args[0]! as String; + final String? arg_value = args[1] as String?; try { - await api.setUserProperty(arg_name!, arg_value); + await api.setUserProperty(arg_name, arg_value); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -173,9 +157,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -186,14 +168,10 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled was null.'); - final List args = (message as List?)!; - final bool? arg_enabled = (args[0] as bool?); - assert(arg_enabled != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled was null, expected non-null bool.'); + final List args = message! as List; + final bool arg_enabled = args[0]! as bool; try { - await api.setAnalyticsCollectionEnabled(arg_enabled!); + await api.setAnalyticsCollectionEnabled(arg_enabled); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -205,9 +183,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.resetAnalyticsData$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -231,9 +207,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -244,14 +218,10 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration was null.'); - final List args = (message as List?)!; - final int? arg_timeout = (args[0] as int?); - assert(arg_timeout != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration was null, expected non-null int.'); + final List args = message! as List; + final int arg_timeout = args[0]! as int; try { - await api.setSessionTimeoutDuration(arg_timeout!); + await api.setSessionTimeoutDuration(arg_timeout); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -263,9 +233,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -276,15 +244,11 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent was null.'); - final List args = (message as List?)!; - final Map? arg_consent = - (args[0] as Map?)?.cast(); - assert(arg_consent != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent was null, expected non-null Map.'); + final List args = message! as List; + final Map arg_consent = + (args[0]! as Map).cast(); try { - await api.setConsent(arg_consent!); + await api.setConsent(arg_consent); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -296,9 +260,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setDefaultEventParameters$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -309,9 +271,7 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setDefaultEventParameters was null.'); - final List args = (message as List?)!; + final List args = message! as List; final Map? arg_parameters = (args[0] as Map?)?.cast(); try { @@ -327,9 +287,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getAppInstanceId$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -353,9 +311,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getSessionId$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -379,9 +335,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -392,15 +346,11 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement was null.'); - final List args = (message as List?)!; - final Map? arg_arguments = - (args[0] as Map?)?.cast(); - assert(arg_arguments != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement was null, expected non-null Map.'); + final List args = message! as List; + final Map arg_arguments = + (args[0]! as Map).cast(); try { - await api.initiateOnDeviceConversionMeasurement(arg_arguments!); + await api.initiateOnDeviceConversionMeasurement(arg_arguments); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -412,9 +362,7 @@ abstract class TestFirebaseAnalyticsHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -425,14 +373,10 @@ abstract class TestFirebaseAnalyticsHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction was null.'); - final List args = (message as List?)!; - final String? arg_transactionId = (args[0] as String?); - assert(arg_transactionId != null, - 'Argument for dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction was null, expected non-null String.'); + final List args = message! as List; + final String arg_transactionId = args[0]! as String; try { - await api.logTransaction(arg_transactionId!); + await api.logTransaction(arg_transactionId); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); diff --git a/packages/firebase_app_check/analysis_options.yaml b/packages/firebase_app_check/analysis_options.yaml new file mode 100644 index 000000000000..0a5c260b3115 --- /dev/null +++ b/packages/firebase_app_check/analysis_options.yaml @@ -0,0 +1,10 @@ +# Copyright 2026 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# in the LICENSE file. + +include: ../../analysis_options.yaml + +analyzer: + exclude: + - firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart + - firebase_app_check_platform_interface/pigeons/messages.dart diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart index fab0d53008a2..8916928599ce 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. // Autogenerated from Pigeon (v25.3.2), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers, require_trailing_commas +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 863fa956cacf..3d90b2b238c5 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -20,4 +20,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 - pigeon: 25.3.2 + pigeon: 26.3.4 diff --git a/packages/firebase_auth/analysis_options.yaml b/packages/firebase_auth/analysis_options.yaml index 8b3451b56a01..6aa2853bfc0a 100644 --- a/packages/firebase_auth/analysis_options.yaml +++ b/packages/firebase_auth/analysis_options.yaml @@ -9,3 +9,4 @@ analyzer: exclude: - firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart - firebase_auth_platform_interface/test/pigeon/test_api.dart + - firebase_auth_platform_interface/pigeons/messages.dart diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java index 74ee8c89aa14..890fbca4c32d 100755 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java @@ -224,7 +224,7 @@ public void checkActionCode( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String code, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); firebaseAuth @@ -270,7 +270,7 @@ public void createUserWithEmailAndPassword( @NonNull String email, @NonNull String password, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); @@ -293,7 +293,7 @@ public void createUserWithEmailAndPassword( public void signInAnonymously( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); firebaseAuth @@ -316,7 +316,7 @@ public void signInWithCredential( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull Map input, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); AuthCredential credential = PigeonParser.getCredential(input); @@ -344,7 +344,7 @@ public void signInWithCustomToken( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String token, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); @@ -369,7 +369,7 @@ public void signInWithEmailAndPassword( @NonNull String email, @NonNull String password, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); firebaseAuth @@ -392,7 +392,7 @@ public void signInWithEmailLink( @NonNull String email, @NonNull String emailLink, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); firebaseAuth @@ -413,9 +413,9 @@ public void signInWithEmailLink( @Override public void signInWithProvider( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonSignInProvider signInProvider, + @NonNull GeneratedAndroidFirebaseAuth.InternalSignInProvider signInProvider, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); @@ -489,7 +489,7 @@ public void fetchSignInMethodsForEmail( public void sendPasswordResetEmail( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String email, - @Nullable GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @Nullable GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings, @NonNull GeneratedAndroidFirebaseAuth.VoidResult result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); @@ -527,7 +527,7 @@ public void sendPasswordResetEmail( public void sendSignInLinkToEmail( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String email, - @NonNull GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @NonNull GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings, @NonNull GeneratedAndroidFirebaseAuth.VoidResult result) { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); @@ -568,7 +568,7 @@ public void setLanguageCode( @Override public void setSettings( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonFirebaseAuthSettings settings, + @NonNull GeneratedAndroidFirebaseAuth.InternalFirebaseAuthSettings settings, @NonNull GeneratedAndroidFirebaseAuth.VoidResult result) { try { FirebaseAuth firebaseAuth = getAuthFromPigeon(app); @@ -620,7 +620,7 @@ public void verifyPasswordResetCode( @Override public void verifyPhoneNumber( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonVerifyPhoneNumberRequest request, + @NonNull GeneratedAndroidFirebaseAuth.InternalVerifyPhoneNumberRequest request, @NonNull GeneratedAndroidFirebaseAuth.Result result) { try { String eventChannelName = METHOD_CHANNEL_NAME + "/phone/" + UUID.randomUUID().toString(); @@ -730,7 +730,7 @@ public Task> getPluginConstantsForFirebaseApp(FirebaseApp fi FirebaseUser firebaseUser = firebaseAuth.getCurrentUser(); String languageCode = firebaseAuth.getLanguageCode(); - GeneratedAndroidFirebaseAuth.PigeonUserDetails user = + GeneratedAndroidFirebaseAuth.InternalUserDetails user = firebaseUser == null ? null : PigeonParser.parseFirebaseUser(firebaseUser); if (languageCode != null) { diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthUser.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthUser.java index 9f84d832c419..7039a38f18e8 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthUser.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthUser.java @@ -73,7 +73,7 @@ public void getIdToken( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull Boolean forceRefresh, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { cachedThreadPool.execute( () -> { @@ -97,7 +97,7 @@ public void linkWithCredential( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull Map input, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); AuthCredential credential = PigeonParser.getCredential(input); @@ -129,9 +129,9 @@ public void linkWithCredential( @Override public void linkWithProvider( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonSignInProvider signInProvider, + @NonNull GeneratedAndroidFirebaseAuth.InternalSignInProvider signInProvider, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -162,7 +162,7 @@ public void reauthenticateWithCredential( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull Map input, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); AuthCredential credential = PigeonParser.getCredential(input); @@ -194,9 +194,9 @@ public void reauthenticateWithCredential( @Override public void reauthenticateWithProvider( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonSignInProvider signInProvider, + @NonNull GeneratedAndroidFirebaseAuth.InternalSignInProvider signInProvider, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -226,7 +226,7 @@ public void reauthenticateWithProvider( public void reload( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -252,7 +252,7 @@ public void reload( @Override public void sendEmailVerification( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @Nullable GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @Nullable GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings, @NonNull GeneratedAndroidFirebaseAuth.VoidResult result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -296,7 +296,7 @@ public void unlink( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String providerId, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -330,7 +330,7 @@ public void updateEmail( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String newEmail, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -369,7 +369,7 @@ public void updatePassword( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String newPassword, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -408,7 +408,7 @@ public void updatePhoneNumber( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull Map input, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -453,9 +453,9 @@ public void updatePhoneNumber( @Override public void updateProfile( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonUserProfile profile, + @NonNull GeneratedAndroidFirebaseAuth.InternalUserProfile profile, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); @@ -507,7 +507,7 @@ public void updateProfile( public void verifyBeforeUpdateEmail( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull String newEmail, - @Nullable GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings actionCodeSettings, + @Nullable GeneratedAndroidFirebaseAuth.InternalActionCodeSettings actionCodeSettings, @NonNull GeneratedAndroidFirebaseAuth.VoidResult result) { FirebaseUser firebaseUser = getCurrentUserFromPigeon(app); diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseMultiFactor.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseMultiFactor.java index f2d1ed575ca6..1ba51914254e 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseMultiFactor.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseMultiFactor.java @@ -60,7 +60,7 @@ MultiFactor getAppMultiFactor(@NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFi @Override public void enrollPhone( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonPhoneMultiFactorAssertion assertion, + @NonNull GeneratedAndroidFirebaseAuth.InternalPhoneMultiFactorAssertion assertion, @Nullable String displayName, @NonNull GeneratedAndroidFirebaseAuth.VoidResult result) { final MultiFactor multiFactor; @@ -126,7 +126,8 @@ public void enrollTotp( public void getSession( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result< + GeneratedAndroidFirebaseAuth.InternalMultiFactorSession> result) { final MultiFactor multiFactor; try { @@ -145,7 +146,7 @@ public void getSession( final String id = UUID.randomUUID().toString(); multiFactorSessionMap.put(id, sessionResult); result.success( - new GeneratedAndroidFirebaseAuth.PigeonMultiFactorSession.Builder() + new GeneratedAndroidFirebaseAuth.InternalMultiFactorSession.Builder() .setId(id) .build()); } else { @@ -188,7 +189,7 @@ public void getEnrolledFactors( @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, @NonNull GeneratedAndroidFirebaseAuth.Result< - List> + List> result) { final MultiFactor multiFactor; try { @@ -200,7 +201,7 @@ public void getEnrolledFactors( final List factors = multiFactor.getEnrolledFactors(); - final List resultFactors = + final List resultFactors = PigeonParser.multiFactorInfoToPigeon(factors); result.success(resultFactors); @@ -209,10 +210,10 @@ public void getEnrolledFactors( @Override public void resolveSignIn( @NonNull String resolverId, - @Nullable GeneratedAndroidFirebaseAuth.PigeonPhoneMultiFactorAssertion assertion, + @Nullable GeneratedAndroidFirebaseAuth.InternalPhoneMultiFactorAssertion assertion, @Nullable String totpAssertionId, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { final MultiFactorResolver resolver = multiFactorResolverMap.get(resolverId); diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseTotpMultiFactor.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseTotpMultiFactor.java index c766b9598ed4..9761a5df73f2 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseTotpMultiFactor.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseTotpMultiFactor.java @@ -25,7 +25,7 @@ public class FlutterFirebaseTotpMultiFactor public void generateSecret( @NonNull String sessionId, @NonNull - GeneratedAndroidFirebaseAuth.Result + GeneratedAndroidFirebaseAuth.Result result) { MultiFactorSession multiFactorSession = FlutterFirebaseMultiFactor.multiFactorSessionMap.get(sessionId); @@ -38,7 +38,7 @@ public void generateSecret( TotpSecret secret = task.getResult(); multiFactorSecret.put(secret.getSharedSecretKey(), secret); result.success( - new GeneratedAndroidFirebaseAuth.PigeonTotpSecret.Builder() + new GeneratedAndroidFirebaseAuth.InternalTotpSecret.Builder() .setCodeIntervalSeconds((long) secret.getCodeIntervalSeconds()) .setCodeLength((long) secret.getCodeLength()) .setSecretKey(secret.getSharedSecretKey()) diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java index 19545ba97da0..ee16c9973a33 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v19.0.0), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon package io.flutter.plugins.firebase.auth; @@ -21,12 +21,170 @@ import java.lang.annotation.Target; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; /** Generated class from Pigeon. */ @SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) public class GeneratedAndroidFirebaseAuth { + static boolean pigeonDoubleEquals(double a, double b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == 0.0 ? 0.0 : a) == (b == 0.0 ? 0.0 : b) || (Double.isNaN(a) && Double.isNaN(b)); + } + + static boolean pigeonFloatEquals(float a, float b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == 0.0f ? 0.0f : a) == (b == 0.0f ? 0.0f : b) || (Float.isNaN(a) && Float.isNaN(b)); + } + + static int pigeonDoubleHashCode(double d) { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + if (d == 0.0) { + d = 0.0; + } + long bits = Double.doubleToLongBits(d); + return (int) (bits ^ (bits >>> 32)); + } + + static int pigeonFloatHashCode(float f) { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + if (f == 0.0f) { + f = 0.0f; + } + return Float.floatToIntBits(f); + } + + static boolean pigeonDeepEquals(Object a, Object b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a instanceof byte[] && b instanceof byte[]) { + return Arrays.equals((byte[]) a, (byte[]) b); + } + if (a instanceof int[] && b instanceof int[]) { + return Arrays.equals((int[]) a, (int[]) b); + } + if (a instanceof long[] && b instanceof long[]) { + return Arrays.equals((long[]) a, (long[]) b); + } + if (a instanceof double[] && b instanceof double[]) { + double[] da = (double[]) a; + double[] db = (double[]) b; + if (da.length != db.length) { + return false; + } + for (int i = 0; i < da.length; i++) { + if (!pigeonDoubleEquals(da[i], db[i])) { + return false; + } + } + return true; + } + if (a instanceof List && b instanceof List) { + List listA = (List) a; + List listB = (List) b; + if (listA.size() != listB.size()) { + return false; + } + for (int i = 0; i < listA.size(); i++) { + if (!pigeonDeepEquals(listA.get(i), listB.get(i))) { + return false; + } + } + return true; + } + if (a instanceof Map && b instanceof Map) { + Map mapA = (Map) a; + Map mapB = (Map) b; + if (mapA.size() != mapB.size()) { + return false; + } + for (Map.Entry entryA : mapA.entrySet()) { + Object keyA = entryA.getKey(); + Object valueA = entryA.getValue(); + boolean found = false; + for (Map.Entry entryB : mapB.entrySet()) { + Object keyB = entryB.getKey(); + if (pigeonDeepEquals(keyA, keyB)) { + Object valueB = entryB.getValue(); + if (pigeonDeepEquals(valueA, valueB)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; + } + if (a instanceof Double && b instanceof Double) { + return pigeonDoubleEquals((double) a, (double) b); + } + if (a instanceof Float && b instanceof Float) { + return pigeonFloatEquals((float) a, (float) b); + } + return a.equals(b); + } + + static int pigeonDeepHashCode(Object value) { + if (value == null) { + return 0; + } + if (value instanceof byte[]) { + return Arrays.hashCode((byte[]) value); + } + if (value instanceof int[]) { + return Arrays.hashCode((int[]) value); + } + if (value instanceof long[]) { + return Arrays.hashCode((long[]) value); + } + if (value instanceof double[]) { + double[] da = (double[]) value; + int result = 1; + for (double d : da) { + result = 31 * result + pigeonDoubleHashCode(d); + } + return result; + } + if (value instanceof List) { + int result = 1; + for (Object item : (List) value) { + result = 31 * result + pigeonDeepHashCode(item); + } + return result; + } + if (value instanceof Map) { + int result = 0; + for (Map.Entry entry : ((Map) value).entrySet()) { + result += + ((pigeonDeepHashCode(entry.getKey()) * 31) ^ pigeonDeepHashCode(entry.getValue())); + } + return result; + } + if (value instanceof Object[]) { + int result = 1; + for (Object item : (Object[]) value) { + result = 31 * result + pigeonDeepHashCode(item); + } + return result; + } + if (value instanceof Double) { + return pigeonDoubleHashCode((double) value); + } + if (value instanceof Float) { + return pigeonFloatHashCode((float) value); + } + return value.hashCode(); + } /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ public static class FlutterError extends RuntimeException { @@ -46,7 +204,7 @@ public FlutterError(@NonNull String code, @Nullable String message, @Nullable Ob @NonNull protected static ArrayList wrapError(@NonNull Throwable exception) { - ArrayList errorList = new ArrayList(3); + ArrayList errorList = new ArrayList<>(3); if (exception instanceof FlutterError) { FlutterError error = (FlutterError) exception; errorList.add(error.code); @@ -84,13 +242,13 @@ public enum ActionCodeInfoOperation { final int index; - private ActionCodeInfoOperation(final int index) { + ActionCodeInfoOperation(final int index) { this.index = index; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonMultiFactorSession { + public static final class InternalMultiFactorSession { private @NonNull String id; public @NonNull String getId() { @@ -105,7 +263,25 @@ public void setId(@NonNull String setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonMultiFactorSession() {} + InternalMultiFactorSession() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalMultiFactorSession that = (InternalMultiFactorSession) o; + return pigeonDeepEquals(id, that.id); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), id}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -117,30 +293,30 @@ public static final class Builder { return this; } - public @NonNull PigeonMultiFactorSession build() { - PigeonMultiFactorSession pigeonReturn = new PigeonMultiFactorSession(); + public @NonNull InternalMultiFactorSession build() { + InternalMultiFactorSession pigeonReturn = new InternalMultiFactorSession(); pigeonReturn.setId(id); return pigeonReturn; } } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(1); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(1); toListResult.add(id); return toListResult; } - static @NonNull PigeonMultiFactorSession fromList(@NonNull ArrayList __pigeon_list) { - PigeonMultiFactorSession pigeonResult = new PigeonMultiFactorSession(); - Object id = __pigeon_list.get(0); + static @NonNull InternalMultiFactorSession fromList(@NonNull ArrayList pigeonVar_list) { + InternalMultiFactorSession pigeonResult = new InternalMultiFactorSession(); + Object id = pigeonVar_list.get(0); pigeonResult.setId((String) id); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonPhoneMultiFactorAssertion { + public static final class InternalPhoneMultiFactorAssertion { private @NonNull String verificationId; public @NonNull String getVerificationId() { @@ -168,7 +344,26 @@ public void setVerificationCode(@NonNull String setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonPhoneMultiFactorAssertion() {} + InternalPhoneMultiFactorAssertion() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalPhoneMultiFactorAssertion that = (InternalPhoneMultiFactorAssertion) o; + return pigeonDeepEquals(verificationId, that.verificationId) + && pigeonDeepEquals(verificationCode, that.verificationCode); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), verificationId, verificationCode}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -188,8 +383,8 @@ public static final class Builder { return this; } - public @NonNull PigeonPhoneMultiFactorAssertion build() { - PigeonPhoneMultiFactorAssertion pigeonReturn = new PigeonPhoneMultiFactorAssertion(); + public @NonNull InternalPhoneMultiFactorAssertion build() { + InternalPhoneMultiFactorAssertion pigeonReturn = new InternalPhoneMultiFactorAssertion(); pigeonReturn.setVerificationId(verificationId); pigeonReturn.setVerificationCode(verificationCode); return pigeonReturn; @@ -197,26 +392,26 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(2); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(2); toListResult.add(verificationId); toListResult.add(verificationCode); return toListResult; } - static @NonNull PigeonPhoneMultiFactorAssertion fromList( - @NonNull ArrayList __pigeon_list) { - PigeonPhoneMultiFactorAssertion pigeonResult = new PigeonPhoneMultiFactorAssertion(); - Object verificationId = __pigeon_list.get(0); + static @NonNull InternalPhoneMultiFactorAssertion fromList( + @NonNull ArrayList pigeonVar_list) { + InternalPhoneMultiFactorAssertion pigeonResult = new InternalPhoneMultiFactorAssertion(); + Object verificationId = pigeonVar_list.get(0); pigeonResult.setVerificationId((String) verificationId); - Object verificationCode = __pigeon_list.get(1); + Object verificationCode = pigeonVar_list.get(1); pigeonResult.setVerificationCode((String) verificationCode); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonMultiFactorInfo { + public static final class InternalMultiFactorInfo { private @Nullable String displayName; public @Nullable String getDisplayName() { @@ -274,7 +469,30 @@ public void setPhoneNumber(@Nullable String setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonMultiFactorInfo() {} + InternalMultiFactorInfo() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalMultiFactorInfo that = (InternalMultiFactorInfo) o; + return pigeonDeepEquals(displayName, that.displayName) + && pigeonDeepEquals(enrollmentTimestamp, that.enrollmentTimestamp) + && pigeonDeepEquals(factorId, that.factorId) + && pigeonDeepEquals(uid, that.uid) + && pigeonDeepEquals(phoneNumber, that.phoneNumber); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] {getClass(), displayName, enrollmentTimestamp, factorId, uid, phoneNumber}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -318,8 +536,8 @@ public static final class Builder { return this; } - public @NonNull PigeonMultiFactorInfo build() { - PigeonMultiFactorInfo pigeonReturn = new PigeonMultiFactorInfo(); + public @NonNull InternalMultiFactorInfo build() { + InternalMultiFactorInfo pigeonReturn = new InternalMultiFactorInfo(); pigeonReturn.setDisplayName(displayName); pigeonReturn.setEnrollmentTimestamp(enrollmentTimestamp); pigeonReturn.setFactorId(factorId); @@ -330,8 +548,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(5); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(5); toListResult.add(displayName); toListResult.add(enrollmentTimestamp); toListResult.add(factorId); @@ -340,17 +558,17 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonMultiFactorInfo fromList(@NonNull ArrayList __pigeon_list) { - PigeonMultiFactorInfo pigeonResult = new PigeonMultiFactorInfo(); - Object displayName = __pigeon_list.get(0); + static @NonNull InternalMultiFactorInfo fromList(@NonNull ArrayList pigeonVar_list) { + InternalMultiFactorInfo pigeonResult = new InternalMultiFactorInfo(); + Object displayName = pigeonVar_list.get(0); pigeonResult.setDisplayName((String) displayName); - Object enrollmentTimestamp = __pigeon_list.get(1); + Object enrollmentTimestamp = pigeonVar_list.get(1); pigeonResult.setEnrollmentTimestamp((Double) enrollmentTimestamp); - Object factorId = __pigeon_list.get(2); + Object factorId = pigeonVar_list.get(2); pigeonResult.setFactorId((String) factorId); - Object uid = __pigeon_list.get(3); + Object uid = pigeonVar_list.get(3); pigeonResult.setUid((String) uid); - Object phoneNumber = __pigeon_list.get(4); + Object phoneNumber = pigeonVar_list.get(4); pigeonResult.setPhoneNumber((String) phoneNumber); return pigeonResult; } @@ -394,6 +612,26 @@ public void setCustomAuthDomain(@Nullable String setterArg) { /** Constructor is non-public to enforce null safety; use Builder. */ AuthPigeonFirebaseApp() {} + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuthPigeonFirebaseApp that = (AuthPigeonFirebaseApp) o; + return pigeonDeepEquals(appName, that.appName) + && pigeonDeepEquals(tenantId, that.tenantId) + && pigeonDeepEquals(customAuthDomain, that.customAuthDomain); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), appName, tenantId, customAuthDomain}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable String appName; @@ -430,28 +668,28 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(3); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(3); toListResult.add(appName); toListResult.add(tenantId); toListResult.add(customAuthDomain); return toListResult; } - static @NonNull AuthPigeonFirebaseApp fromList(@NonNull ArrayList __pigeon_list) { + static @NonNull AuthPigeonFirebaseApp fromList(@NonNull ArrayList pigeonVar_list) { AuthPigeonFirebaseApp pigeonResult = new AuthPigeonFirebaseApp(); - Object appName = __pigeon_list.get(0); + Object appName = pigeonVar_list.get(0); pigeonResult.setAppName((String) appName); - Object tenantId = __pigeon_list.get(1); + Object tenantId = pigeonVar_list.get(1); pigeonResult.setTenantId((String) tenantId); - Object customAuthDomain = __pigeon_list.get(2); + Object customAuthDomain = pigeonVar_list.get(2); pigeonResult.setCustomAuthDomain((String) customAuthDomain); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonActionCodeInfoData { + public static final class InternalActionCodeInfoData { private @Nullable String email; public @Nullable String getEmail() { @@ -472,6 +710,25 @@ public void setPreviousEmail(@Nullable String setterArg) { this.previousEmail = setterArg; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalActionCodeInfoData that = (InternalActionCodeInfoData) o; + return pigeonDeepEquals(email, that.email) + && pigeonDeepEquals(previousEmail, that.previousEmail); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), email, previousEmail}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable String email; @@ -490,8 +747,8 @@ public static final class Builder { return this; } - public @NonNull PigeonActionCodeInfoData build() { - PigeonActionCodeInfoData pigeonReturn = new PigeonActionCodeInfoData(); + public @NonNull InternalActionCodeInfoData build() { + InternalActionCodeInfoData pigeonReturn = new InternalActionCodeInfoData(); pigeonReturn.setEmail(email); pigeonReturn.setPreviousEmail(previousEmail); return pigeonReturn; @@ -499,25 +756,25 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(2); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(2); toListResult.add(email); toListResult.add(previousEmail); return toListResult; } - static @NonNull PigeonActionCodeInfoData fromList(@NonNull ArrayList __pigeon_list) { - PigeonActionCodeInfoData pigeonResult = new PigeonActionCodeInfoData(); - Object email = __pigeon_list.get(0); + static @NonNull InternalActionCodeInfoData fromList(@NonNull ArrayList pigeonVar_list) { + InternalActionCodeInfoData pigeonResult = new InternalActionCodeInfoData(); + Object email = pigeonVar_list.get(0); pigeonResult.setEmail((String) email); - Object previousEmail = __pigeon_list.get(1); + Object previousEmail = pigeonVar_list.get(1); pigeonResult.setPreviousEmail((String) previousEmail); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonActionCodeInfo { + public static final class InternalActionCodeInfo { private @NonNull ActionCodeInfoOperation operation; public @NonNull ActionCodeInfoOperation getOperation() { @@ -531,13 +788,13 @@ public void setOperation(@NonNull ActionCodeInfoOperation setterArg) { this.operation = setterArg; } - private @NonNull PigeonActionCodeInfoData data; + private @NonNull InternalActionCodeInfoData data; - public @NonNull PigeonActionCodeInfoData getData() { + public @NonNull InternalActionCodeInfoData getData() { return data; } - public void setData(@NonNull PigeonActionCodeInfoData setterArg) { + public void setData(@NonNull InternalActionCodeInfoData setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"data\" is null."); } @@ -545,7 +802,25 @@ public void setData(@NonNull PigeonActionCodeInfoData setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonActionCodeInfo() {} + InternalActionCodeInfo() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalActionCodeInfo that = (InternalActionCodeInfo) o; + return pigeonDeepEquals(operation, that.operation) && pigeonDeepEquals(data, that.data); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), operation, data}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -557,16 +832,16 @@ public static final class Builder { return this; } - private @Nullable PigeonActionCodeInfoData data; + private @Nullable InternalActionCodeInfoData data; @CanIgnoreReturnValue - public @NonNull Builder setData(@NonNull PigeonActionCodeInfoData setterArg) { + public @NonNull Builder setData(@NonNull InternalActionCodeInfoData setterArg) { this.data = setterArg; return this; } - public @NonNull PigeonActionCodeInfo build() { - PigeonActionCodeInfo pigeonReturn = new PigeonActionCodeInfo(); + public @NonNull InternalActionCodeInfo build() { + InternalActionCodeInfo pigeonReturn = new InternalActionCodeInfo(); pigeonReturn.setOperation(operation); pigeonReturn.setData(data); return pigeonReturn; @@ -574,25 +849,25 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(2); - toListResult.add(operation == null ? null : operation.index); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(2); + toListResult.add(operation); toListResult.add(data); return toListResult; } - static @NonNull PigeonActionCodeInfo fromList(@NonNull ArrayList __pigeon_list) { - PigeonActionCodeInfo pigeonResult = new PigeonActionCodeInfo(); - Object operation = __pigeon_list.get(0); - pigeonResult.setOperation(ActionCodeInfoOperation.values()[(int) operation]); - Object data = __pigeon_list.get(1); - pigeonResult.setData((PigeonActionCodeInfoData) data); + static @NonNull InternalActionCodeInfo fromList(@NonNull ArrayList pigeonVar_list) { + InternalActionCodeInfo pigeonResult = new InternalActionCodeInfo(); + Object operation = pigeonVar_list.get(0); + pigeonResult.setOperation((ActionCodeInfoOperation) operation); + Object data = pigeonVar_list.get(1); + pigeonResult.setData((InternalActionCodeInfoData) data); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonAdditionalUserInfo { + public static final class InternalAdditionalUserInfo { private @NonNull Boolean isNewUser; public @NonNull Boolean getIsNewUser() { @@ -647,7 +922,30 @@ public void setProfile(@Nullable Map setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonAdditionalUserInfo() {} + InternalAdditionalUserInfo() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalAdditionalUserInfo that = (InternalAdditionalUserInfo) o; + return pigeonDeepEquals(isNewUser, that.isNewUser) + && pigeonDeepEquals(providerId, that.providerId) + && pigeonDeepEquals(username, that.username) + && pigeonDeepEquals(authorizationCode, that.authorizationCode) + && pigeonDeepEquals(profile, that.profile); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] {getClass(), isNewUser, providerId, username, authorizationCode, profile}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -691,8 +989,8 @@ public static final class Builder { return this; } - public @NonNull PigeonAdditionalUserInfo build() { - PigeonAdditionalUserInfo pigeonReturn = new PigeonAdditionalUserInfo(); + public @NonNull InternalAdditionalUserInfo build() { + InternalAdditionalUserInfo pigeonReturn = new InternalAdditionalUserInfo(); pigeonReturn.setIsNewUser(isNewUser); pigeonReturn.setProviderId(providerId); pigeonReturn.setUsername(username); @@ -703,8 +1001,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(5); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(5); toListResult.add(isNewUser); toListResult.add(providerId); toListResult.add(username); @@ -713,24 +1011,24 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonAdditionalUserInfo fromList(@NonNull ArrayList __pigeon_list) { - PigeonAdditionalUserInfo pigeonResult = new PigeonAdditionalUserInfo(); - Object isNewUser = __pigeon_list.get(0); + static @NonNull InternalAdditionalUserInfo fromList(@NonNull ArrayList pigeonVar_list) { + InternalAdditionalUserInfo pigeonResult = new InternalAdditionalUserInfo(); + Object isNewUser = pigeonVar_list.get(0); pigeonResult.setIsNewUser((Boolean) isNewUser); - Object providerId = __pigeon_list.get(1); + Object providerId = pigeonVar_list.get(1); pigeonResult.setProviderId((String) providerId); - Object username = __pigeon_list.get(2); + Object username = pigeonVar_list.get(2); pigeonResult.setUsername((String) username); - Object authorizationCode = __pigeon_list.get(3); + Object authorizationCode = pigeonVar_list.get(3); pigeonResult.setAuthorizationCode((String) authorizationCode); - Object profile = __pigeon_list.get(4); + Object profile = pigeonVar_list.get(4); pigeonResult.setProfile((Map) profile); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonAuthCredential { + public static final class InternalAuthCredential { private @NonNull String providerId; public @NonNull String getProviderId() { @@ -781,7 +1079,28 @@ public void setAccessToken(@Nullable String setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonAuthCredential() {} + InternalAuthCredential() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalAuthCredential that = (InternalAuthCredential) o; + return pigeonDeepEquals(providerId, that.providerId) + && pigeonDeepEquals(signInMethod, that.signInMethod) + && pigeonDeepEquals(nativeId, that.nativeId) + && pigeonDeepEquals(accessToken, that.accessToken); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), providerId, signInMethod, nativeId, accessToken}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -817,8 +1136,8 @@ public static final class Builder { return this; } - public @NonNull PigeonAuthCredential build() { - PigeonAuthCredential pigeonReturn = new PigeonAuthCredential(); + public @NonNull InternalAuthCredential build() { + InternalAuthCredential pigeonReturn = new InternalAuthCredential(); pigeonReturn.setProviderId(providerId); pigeonReturn.setSignInMethod(signInMethod); pigeonReturn.setNativeId(nativeId); @@ -828,8 +1147,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(4); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(4); toListResult.add(providerId); toListResult.add(signInMethod); toListResult.add(nativeId); @@ -837,25 +1156,22 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonAuthCredential fromList(@NonNull ArrayList __pigeon_list) { - PigeonAuthCredential pigeonResult = new PigeonAuthCredential(); - Object providerId = __pigeon_list.get(0); + static @NonNull InternalAuthCredential fromList(@NonNull ArrayList pigeonVar_list) { + InternalAuthCredential pigeonResult = new InternalAuthCredential(); + Object providerId = pigeonVar_list.get(0); pigeonResult.setProviderId((String) providerId); - Object signInMethod = __pigeon_list.get(1); + Object signInMethod = pigeonVar_list.get(1); pigeonResult.setSignInMethod((String) signInMethod); - Object nativeId = __pigeon_list.get(2); - pigeonResult.setNativeId( - (nativeId == null) - ? null - : ((nativeId instanceof Integer) ? (Integer) nativeId : (Long) nativeId)); - Object accessToken = __pigeon_list.get(3); + Object nativeId = pigeonVar_list.get(2); + pigeonResult.setNativeId((Long) nativeId); + Object accessToken = pigeonVar_list.get(3); pigeonResult.setAccessToken((String) accessToken); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonUserInfo { + public static final class InternalUserInfo { private @NonNull String uid; public @NonNull String getUid() { @@ -986,7 +1302,51 @@ public void setLastSignInTimestamp(@Nullable Long setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonUserInfo() {} + InternalUserInfo() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalUserInfo that = (InternalUserInfo) o; + return pigeonDeepEquals(uid, that.uid) + && pigeonDeepEquals(email, that.email) + && pigeonDeepEquals(displayName, that.displayName) + && pigeonDeepEquals(photoUrl, that.photoUrl) + && pigeonDeepEquals(phoneNumber, that.phoneNumber) + && pigeonDeepEquals(isAnonymous, that.isAnonymous) + && pigeonDeepEquals(isEmailVerified, that.isEmailVerified) + && pigeonDeepEquals(providerId, that.providerId) + && pigeonDeepEquals(tenantId, that.tenantId) + && pigeonDeepEquals(refreshToken, that.refreshToken) + && pigeonDeepEquals(creationTimestamp, that.creationTimestamp) + && pigeonDeepEquals(lastSignInTimestamp, that.lastSignInTimestamp); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + uid, + email, + displayName, + photoUrl, + phoneNumber, + isAnonymous, + isEmailVerified, + providerId, + tenantId, + refreshToken, + creationTimestamp, + lastSignInTimestamp + }; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -1086,8 +1446,8 @@ public static final class Builder { return this; } - public @NonNull PigeonUserInfo build() { - PigeonUserInfo pigeonReturn = new PigeonUserInfo(); + public @NonNull InternalUserInfo build() { + InternalUserInfo pigeonReturn = new InternalUserInfo(); pigeonReturn.setUid(uid); pigeonReturn.setEmail(email); pigeonReturn.setDisplayName(displayName); @@ -1105,8 +1465,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(12); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(12); toListResult.add(uid); toListResult.add(email); toListResult.add(displayName); @@ -1122,55 +1482,45 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonUserInfo fromList(@NonNull ArrayList __pigeon_list) { - PigeonUserInfo pigeonResult = new PigeonUserInfo(); - Object uid = __pigeon_list.get(0); + static @NonNull InternalUserInfo fromList(@NonNull ArrayList pigeonVar_list) { + InternalUserInfo pigeonResult = new InternalUserInfo(); + Object uid = pigeonVar_list.get(0); pigeonResult.setUid((String) uid); - Object email = __pigeon_list.get(1); + Object email = pigeonVar_list.get(1); pigeonResult.setEmail((String) email); - Object displayName = __pigeon_list.get(2); + Object displayName = pigeonVar_list.get(2); pigeonResult.setDisplayName((String) displayName); - Object photoUrl = __pigeon_list.get(3); + Object photoUrl = pigeonVar_list.get(3); pigeonResult.setPhotoUrl((String) photoUrl); - Object phoneNumber = __pigeon_list.get(4); + Object phoneNumber = pigeonVar_list.get(4); pigeonResult.setPhoneNumber((String) phoneNumber); - Object isAnonymous = __pigeon_list.get(5); + Object isAnonymous = pigeonVar_list.get(5); pigeonResult.setIsAnonymous((Boolean) isAnonymous); - Object isEmailVerified = __pigeon_list.get(6); + Object isEmailVerified = pigeonVar_list.get(6); pigeonResult.setIsEmailVerified((Boolean) isEmailVerified); - Object providerId = __pigeon_list.get(7); + Object providerId = pigeonVar_list.get(7); pigeonResult.setProviderId((String) providerId); - Object tenantId = __pigeon_list.get(8); + Object tenantId = pigeonVar_list.get(8); pigeonResult.setTenantId((String) tenantId); - Object refreshToken = __pigeon_list.get(9); + Object refreshToken = pigeonVar_list.get(9); pigeonResult.setRefreshToken((String) refreshToken); - Object creationTimestamp = __pigeon_list.get(10); - pigeonResult.setCreationTimestamp( - (creationTimestamp == null) - ? null - : ((creationTimestamp instanceof Integer) - ? (Integer) creationTimestamp - : (Long) creationTimestamp)); - Object lastSignInTimestamp = __pigeon_list.get(11); - pigeonResult.setLastSignInTimestamp( - (lastSignInTimestamp == null) - ? null - : ((lastSignInTimestamp instanceof Integer) - ? (Integer) lastSignInTimestamp - : (Long) lastSignInTimestamp)); + Object creationTimestamp = pigeonVar_list.get(10); + pigeonResult.setCreationTimestamp((Long) creationTimestamp); + Object lastSignInTimestamp = pigeonVar_list.get(11); + pigeonResult.setLastSignInTimestamp((Long) lastSignInTimestamp); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonUserDetails { - private @NonNull PigeonUserInfo userInfo; + public static final class InternalUserDetails { + private @NonNull InternalUserInfo userInfo; - public @NonNull PigeonUserInfo getUserInfo() { + public @NonNull InternalUserInfo getUserInfo() { return userInfo; } - public void setUserInfo(@NonNull PigeonUserInfo setterArg) { + public void setUserInfo(@NonNull InternalUserInfo setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"userInfo\" is null."); } @@ -1191,14 +1541,33 @@ public void setProviderData(@NonNull List> setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonUserDetails() {} + InternalUserDetails() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalUserDetails that = (InternalUserDetails) o; + return pigeonDeepEquals(userInfo, that.userInfo) + && pigeonDeepEquals(providerData, that.providerData); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), userInfo, providerData}; + return pigeonDeepHashCode(fields); + } public static final class Builder { - private @Nullable PigeonUserInfo userInfo; + private @Nullable InternalUserInfo userInfo; @CanIgnoreReturnValue - public @NonNull Builder setUserInfo(@NonNull PigeonUserInfo setterArg) { + public @NonNull Builder setUserInfo(@NonNull InternalUserInfo setterArg) { this.userInfo = setterArg; return this; } @@ -1211,8 +1580,8 @@ public static final class Builder { return this; } - public @NonNull PigeonUserDetails build() { - PigeonUserDetails pigeonReturn = new PigeonUserDetails(); + public @NonNull InternalUserDetails build() { + InternalUserDetails pigeonReturn = new InternalUserDetails(); pigeonReturn.setUserInfo(userInfo); pigeonReturn.setProviderData(providerData); return pigeonReturn; @@ -1220,83 +1589,104 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(2); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(2); toListResult.add(userInfo); toListResult.add(providerData); return toListResult; } - static @NonNull PigeonUserDetails fromList(@NonNull ArrayList __pigeon_list) { - PigeonUserDetails pigeonResult = new PigeonUserDetails(); - Object userInfo = __pigeon_list.get(0); - pigeonResult.setUserInfo((PigeonUserInfo) userInfo); - Object providerData = __pigeon_list.get(1); + static @NonNull InternalUserDetails fromList(@NonNull ArrayList pigeonVar_list) { + InternalUserDetails pigeonResult = new InternalUserDetails(); + Object userInfo = pigeonVar_list.get(0); + pigeonResult.setUserInfo((InternalUserInfo) userInfo); + Object providerData = pigeonVar_list.get(1); pigeonResult.setProviderData((List>) providerData); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonUserCredential { - private @Nullable PigeonUserDetails user; + public static final class InternalUserCredential { + private @Nullable InternalUserDetails user; - public @Nullable PigeonUserDetails getUser() { + public @Nullable InternalUserDetails getUser() { return user; } - public void setUser(@Nullable PigeonUserDetails setterArg) { + public void setUser(@Nullable InternalUserDetails setterArg) { this.user = setterArg; } - private @Nullable PigeonAdditionalUserInfo additionalUserInfo; + private @Nullable InternalAdditionalUserInfo additionalUserInfo; - public @Nullable PigeonAdditionalUserInfo getAdditionalUserInfo() { + public @Nullable InternalAdditionalUserInfo getAdditionalUserInfo() { return additionalUserInfo; } - public void setAdditionalUserInfo(@Nullable PigeonAdditionalUserInfo setterArg) { + public void setAdditionalUserInfo(@Nullable InternalAdditionalUserInfo setterArg) { this.additionalUserInfo = setterArg; } - private @Nullable PigeonAuthCredential credential; + private @Nullable InternalAuthCredential credential; - public @Nullable PigeonAuthCredential getCredential() { + public @Nullable InternalAuthCredential getCredential() { return credential; } - public void setCredential(@Nullable PigeonAuthCredential setterArg) { + public void setCredential(@Nullable InternalAuthCredential setterArg) { this.credential = setterArg; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalUserCredential that = (InternalUserCredential) o; + return pigeonDeepEquals(user, that.user) + && pigeonDeepEquals(additionalUserInfo, that.additionalUserInfo) + && pigeonDeepEquals(credential, that.credential); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), user, additionalUserInfo, credential}; + return pigeonDeepHashCode(fields); + } + public static final class Builder { - private @Nullable PigeonUserDetails user; + private @Nullable InternalUserDetails user; @CanIgnoreReturnValue - public @NonNull Builder setUser(@Nullable PigeonUserDetails setterArg) { + public @NonNull Builder setUser(@Nullable InternalUserDetails setterArg) { this.user = setterArg; return this; } - private @Nullable PigeonAdditionalUserInfo additionalUserInfo; + private @Nullable InternalAdditionalUserInfo additionalUserInfo; @CanIgnoreReturnValue - public @NonNull Builder setAdditionalUserInfo(@Nullable PigeonAdditionalUserInfo setterArg) { + public @NonNull Builder setAdditionalUserInfo( + @Nullable InternalAdditionalUserInfo setterArg) { this.additionalUserInfo = setterArg; return this; } - private @Nullable PigeonAuthCredential credential; + private @Nullable InternalAuthCredential credential; @CanIgnoreReturnValue - public @NonNull Builder setCredential(@Nullable PigeonAuthCredential setterArg) { + public @NonNull Builder setCredential(@Nullable InternalAuthCredential setterArg) { this.credential = setterArg; return this; } - public @NonNull PigeonUserCredential build() { - PigeonUserCredential pigeonReturn = new PigeonUserCredential(); + public @NonNull InternalUserCredential build() { + InternalUserCredential pigeonReturn = new InternalUserCredential(); pigeonReturn.setUser(user); pigeonReturn.setAdditionalUserInfo(additionalUserInfo); pigeonReturn.setCredential(credential); @@ -1305,28 +1695,169 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(3); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(3); toListResult.add(user); toListResult.add(additionalUserInfo); toListResult.add(credential); return toListResult; } - static @NonNull PigeonUserCredential fromList(@NonNull ArrayList __pigeon_list) { - PigeonUserCredential pigeonResult = new PigeonUserCredential(); - Object user = __pigeon_list.get(0); - pigeonResult.setUser((PigeonUserDetails) user); - Object additionalUserInfo = __pigeon_list.get(1); - pigeonResult.setAdditionalUserInfo((PigeonAdditionalUserInfo) additionalUserInfo); - Object credential = __pigeon_list.get(2); - pigeonResult.setCredential((PigeonAuthCredential) credential); + static @NonNull InternalUserCredential fromList(@NonNull ArrayList pigeonVar_list) { + InternalUserCredential pigeonResult = new InternalUserCredential(); + Object user = pigeonVar_list.get(0); + pigeonResult.setUser((InternalUserDetails) user); + Object additionalUserInfo = pigeonVar_list.get(1); + pigeonResult.setAdditionalUserInfo((InternalAdditionalUserInfo) additionalUserInfo); + Object credential = pigeonVar_list.get(2); + pigeonResult.setCredential((InternalAuthCredential) credential); + return pigeonResult; + } + } + + /** Generated class from Pigeon that represents data sent in messages. */ + public static final class InternalAuthCredentialInput { + private @NonNull String providerId; + + public @NonNull String getProviderId() { + return providerId; + } + + public void setProviderId(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"providerId\" is null."); + } + this.providerId = setterArg; + } + + private @NonNull String signInMethod; + + public @NonNull String getSignInMethod() { + return signInMethod; + } + + public void setSignInMethod(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"signInMethod\" is null."); + } + this.signInMethod = setterArg; + } + + private @Nullable String token; + + public @Nullable String getToken() { + return token; + } + + public void setToken(@Nullable String setterArg) { + this.token = setterArg; + } + + private @Nullable String accessToken; + + public @Nullable String getAccessToken() { + return accessToken; + } + + public void setAccessToken(@Nullable String setterArg) { + this.accessToken = setterArg; + } + + /** Constructor is non-public to enforce null safety; use Builder. */ + InternalAuthCredentialInput() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalAuthCredentialInput that = (InternalAuthCredentialInput) o; + return pigeonDeepEquals(providerId, that.providerId) + && pigeonDeepEquals(signInMethod, that.signInMethod) + && pigeonDeepEquals(token, that.token) + && pigeonDeepEquals(accessToken, that.accessToken); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), providerId, signInMethod, token, accessToken}; + return pigeonDeepHashCode(fields); + } + + public static final class Builder { + + private @Nullable String providerId; + + @CanIgnoreReturnValue + public @NonNull Builder setProviderId(@NonNull String setterArg) { + this.providerId = setterArg; + return this; + } + + private @Nullable String signInMethod; + + @CanIgnoreReturnValue + public @NonNull Builder setSignInMethod(@NonNull String setterArg) { + this.signInMethod = setterArg; + return this; + } + + private @Nullable String token; + + @CanIgnoreReturnValue + public @NonNull Builder setToken(@Nullable String setterArg) { + this.token = setterArg; + return this; + } + + private @Nullable String accessToken; + + @CanIgnoreReturnValue + public @NonNull Builder setAccessToken(@Nullable String setterArg) { + this.accessToken = setterArg; + return this; + } + + public @NonNull InternalAuthCredentialInput build() { + InternalAuthCredentialInput pigeonReturn = new InternalAuthCredentialInput(); + pigeonReturn.setProviderId(providerId); + pigeonReturn.setSignInMethod(signInMethod); + pigeonReturn.setToken(token); + pigeonReturn.setAccessToken(accessToken); + return pigeonReturn; + } + } + + @NonNull + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(4); + toListResult.add(providerId); + toListResult.add(signInMethod); + toListResult.add(token); + toListResult.add(accessToken); + return toListResult; + } + + static @NonNull InternalAuthCredentialInput fromList( + @NonNull ArrayList pigeonVar_list) { + InternalAuthCredentialInput pigeonResult = new InternalAuthCredentialInput(); + Object providerId = pigeonVar_list.get(0); + pigeonResult.setProviderId((String) providerId); + Object signInMethod = pigeonVar_list.get(1); + pigeonResult.setSignInMethod((String) signInMethod); + Object token = pigeonVar_list.get(2); + pigeonResult.setToken((String) token); + Object accessToken = pigeonVar_list.get(3); + pigeonResult.setAccessToken((String) accessToken); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonActionCodeSettings { + public static final class InternalActionCodeSettings { private @NonNull String url; public @NonNull String getUrl() { @@ -1417,7 +1948,43 @@ public void setLinkDomain(@Nullable String setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonActionCodeSettings() {} + InternalActionCodeSettings() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalActionCodeSettings that = (InternalActionCodeSettings) o; + return pigeonDeepEquals(url, that.url) + && pigeonDeepEquals(dynamicLinkDomain, that.dynamicLinkDomain) + && pigeonDeepEquals(handleCodeInApp, that.handleCodeInApp) + && pigeonDeepEquals(iOSBundleId, that.iOSBundleId) + && pigeonDeepEquals(androidPackageName, that.androidPackageName) + && pigeonDeepEquals(androidInstallApp, that.androidInstallApp) + && pigeonDeepEquals(androidMinimumVersion, that.androidMinimumVersion) + && pigeonDeepEquals(linkDomain, that.linkDomain); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + url, + dynamicLinkDomain, + handleCodeInApp, + iOSBundleId, + androidPackageName, + androidInstallApp, + androidMinimumVersion, + linkDomain + }; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -1485,8 +2052,8 @@ public static final class Builder { return this; } - public @NonNull PigeonActionCodeSettings build() { - PigeonActionCodeSettings pigeonReturn = new PigeonActionCodeSettings(); + public @NonNull InternalActionCodeSettings build() { + InternalActionCodeSettings pigeonReturn = new InternalActionCodeSettings(); pigeonReturn.setUrl(url); pigeonReturn.setDynamicLinkDomain(dynamicLinkDomain); pigeonReturn.setHandleCodeInApp(handleCodeInApp); @@ -1500,8 +2067,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(8); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(8); toListResult.add(url); toListResult.add(dynamicLinkDomain); toListResult.add(handleCodeInApp); @@ -1513,30 +2080,30 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonActionCodeSettings fromList(@NonNull ArrayList __pigeon_list) { - PigeonActionCodeSettings pigeonResult = new PigeonActionCodeSettings(); - Object url = __pigeon_list.get(0); + static @NonNull InternalActionCodeSettings fromList(@NonNull ArrayList pigeonVar_list) { + InternalActionCodeSettings pigeonResult = new InternalActionCodeSettings(); + Object url = pigeonVar_list.get(0); pigeonResult.setUrl((String) url); - Object dynamicLinkDomain = __pigeon_list.get(1); + Object dynamicLinkDomain = pigeonVar_list.get(1); pigeonResult.setDynamicLinkDomain((String) dynamicLinkDomain); - Object handleCodeInApp = __pigeon_list.get(2); + Object handleCodeInApp = pigeonVar_list.get(2); pigeonResult.setHandleCodeInApp((Boolean) handleCodeInApp); - Object iOSBundleId = __pigeon_list.get(3); + Object iOSBundleId = pigeonVar_list.get(3); pigeonResult.setIOSBundleId((String) iOSBundleId); - Object androidPackageName = __pigeon_list.get(4); + Object androidPackageName = pigeonVar_list.get(4); pigeonResult.setAndroidPackageName((String) androidPackageName); - Object androidInstallApp = __pigeon_list.get(5); + Object androidInstallApp = pigeonVar_list.get(5); pigeonResult.setAndroidInstallApp((Boolean) androidInstallApp); - Object androidMinimumVersion = __pigeon_list.get(6); + Object androidMinimumVersion = pigeonVar_list.get(6); pigeonResult.setAndroidMinimumVersion((String) androidMinimumVersion); - Object linkDomain = __pigeon_list.get(7); + Object linkDomain = pigeonVar_list.get(7); pigeonResult.setLinkDomain((String) linkDomain); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonFirebaseAuthSettings { + public static final class InternalFirebaseAuthSettings { private @NonNull Boolean appVerificationDisabledForTesting; public @NonNull Boolean getAppVerificationDisabledForTesting() { @@ -1592,7 +2159,38 @@ public void setForceRecaptchaFlow(@Nullable Boolean setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonFirebaseAuthSettings() {} + InternalFirebaseAuthSettings() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalFirebaseAuthSettings that = (InternalFirebaseAuthSettings) o; + return pigeonDeepEquals( + appVerificationDisabledForTesting, that.appVerificationDisabledForTesting) + && pigeonDeepEquals(userAccessGroup, that.userAccessGroup) + && pigeonDeepEquals(phoneNumber, that.phoneNumber) + && pigeonDeepEquals(smsCode, that.smsCode) + && pigeonDeepEquals(forceRecaptchaFlow, that.forceRecaptchaFlow); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + appVerificationDisabledForTesting, + userAccessGroup, + phoneNumber, + smsCode, + forceRecaptchaFlow + }; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -1636,8 +2234,8 @@ public static final class Builder { return this; } - public @NonNull PigeonFirebaseAuthSettings build() { - PigeonFirebaseAuthSettings pigeonReturn = new PigeonFirebaseAuthSettings(); + public @NonNull InternalFirebaseAuthSettings build() { + InternalFirebaseAuthSettings pigeonReturn = new InternalFirebaseAuthSettings(); pigeonReturn.setAppVerificationDisabledForTesting(appVerificationDisabledForTesting); pigeonReturn.setUserAccessGroup(userAccessGroup); pigeonReturn.setPhoneNumber(phoneNumber); @@ -1648,8 +2246,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(5); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(5); toListResult.add(appVerificationDisabledForTesting); toListResult.add(userAccessGroup); toListResult.add(phoneNumber); @@ -1658,25 +2256,26 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonFirebaseAuthSettings fromList(@NonNull ArrayList __pigeon_list) { - PigeonFirebaseAuthSettings pigeonResult = new PigeonFirebaseAuthSettings(); - Object appVerificationDisabledForTesting = __pigeon_list.get(0); + static @NonNull InternalFirebaseAuthSettings fromList( + @NonNull ArrayList pigeonVar_list) { + InternalFirebaseAuthSettings pigeonResult = new InternalFirebaseAuthSettings(); + Object appVerificationDisabledForTesting = pigeonVar_list.get(0); pigeonResult.setAppVerificationDisabledForTesting( (Boolean) appVerificationDisabledForTesting); - Object userAccessGroup = __pigeon_list.get(1); + Object userAccessGroup = pigeonVar_list.get(1); pigeonResult.setUserAccessGroup((String) userAccessGroup); - Object phoneNumber = __pigeon_list.get(2); + Object phoneNumber = pigeonVar_list.get(2); pigeonResult.setPhoneNumber((String) phoneNumber); - Object smsCode = __pigeon_list.get(3); + Object smsCode = pigeonVar_list.get(3); pigeonResult.setSmsCode((String) smsCode); - Object forceRecaptchaFlow = __pigeon_list.get(4); + Object forceRecaptchaFlow = pigeonVar_list.get(4); pigeonResult.setForceRecaptchaFlow((Boolean) forceRecaptchaFlow); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonSignInProvider { + public static final class InternalSignInProvider { private @NonNull String providerId; public @NonNull String getProviderId() { @@ -1711,7 +2310,27 @@ public void setCustomParameters(@Nullable Map setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonSignInProvider() {} + InternalSignInProvider() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalSignInProvider that = (InternalSignInProvider) o; + return pigeonDeepEquals(providerId, that.providerId) + && pigeonDeepEquals(scopes, that.scopes) + && pigeonDeepEquals(customParameters, that.customParameters); + } + + @Override + public int hashCode() { + Object[] fields = new Object[] {getClass(), providerId, scopes, customParameters}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -1739,8 +2358,8 @@ public static final class Builder { return this; } - public @NonNull PigeonSignInProvider build() { - PigeonSignInProvider pigeonReturn = new PigeonSignInProvider(); + public @NonNull InternalSignInProvider build() { + InternalSignInProvider pigeonReturn = new InternalSignInProvider(); pigeonReturn.setProviderId(providerId); pigeonReturn.setScopes(scopes); pigeonReturn.setCustomParameters(customParameters); @@ -1749,28 +2368,28 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(3); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(3); toListResult.add(providerId); toListResult.add(scopes); toListResult.add(customParameters); return toListResult; } - static @NonNull PigeonSignInProvider fromList(@NonNull ArrayList __pigeon_list) { - PigeonSignInProvider pigeonResult = new PigeonSignInProvider(); - Object providerId = __pigeon_list.get(0); + static @NonNull InternalSignInProvider fromList(@NonNull ArrayList pigeonVar_list) { + InternalSignInProvider pigeonResult = new InternalSignInProvider(); + Object providerId = pigeonVar_list.get(0); pigeonResult.setProviderId((String) providerId); - Object scopes = __pigeon_list.get(1); + Object scopes = pigeonVar_list.get(1); pigeonResult.setScopes((List) scopes); - Object customParameters = __pigeon_list.get(2); + Object customParameters = pigeonVar_list.get(2); pigeonResult.setCustomParameters((Map) customParameters); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonVerifyPhoneNumberRequest { + public static final class InternalVerifyPhoneNumberRequest { private @Nullable String phoneNumber; public @Nullable String getPhoneNumber() { @@ -1835,7 +2454,39 @@ public void setMultiFactorSessionId(@Nullable String setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonVerifyPhoneNumberRequest() {} + InternalVerifyPhoneNumberRequest() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalVerifyPhoneNumberRequest that = (InternalVerifyPhoneNumberRequest) o; + return pigeonDeepEquals(phoneNumber, that.phoneNumber) + && pigeonDeepEquals(timeout, that.timeout) + && pigeonDeepEquals(forceResendingToken, that.forceResendingToken) + && pigeonDeepEquals(autoRetrievedSmsCodeForTesting, that.autoRetrievedSmsCodeForTesting) + && pigeonDeepEquals(multiFactorInfoId, that.multiFactorInfoId) + && pigeonDeepEquals(multiFactorSessionId, that.multiFactorSessionId); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + phoneNumber, + timeout, + forceResendingToken, + autoRetrievedSmsCodeForTesting, + multiFactorInfoId, + multiFactorSessionId + }; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -1887,8 +2538,8 @@ public static final class Builder { return this; } - public @NonNull PigeonVerifyPhoneNumberRequest build() { - PigeonVerifyPhoneNumberRequest pigeonReturn = new PigeonVerifyPhoneNumberRequest(); + public @NonNull InternalVerifyPhoneNumberRequest build() { + InternalVerifyPhoneNumberRequest pigeonReturn = new InternalVerifyPhoneNumberRequest(); pigeonReturn.setPhoneNumber(phoneNumber); pigeonReturn.setTimeout(timeout); pigeonReturn.setForceResendingToken(forceResendingToken); @@ -1900,8 +2551,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(6); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(6); toListResult.add(phoneNumber); toListResult.add(timeout); toListResult.add(forceResendingToken); @@ -1911,35 +2562,27 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonVerifyPhoneNumberRequest fromList( - @NonNull ArrayList __pigeon_list) { - PigeonVerifyPhoneNumberRequest pigeonResult = new PigeonVerifyPhoneNumberRequest(); - Object phoneNumber = __pigeon_list.get(0); + static @NonNull InternalVerifyPhoneNumberRequest fromList( + @NonNull ArrayList pigeonVar_list) { + InternalVerifyPhoneNumberRequest pigeonResult = new InternalVerifyPhoneNumberRequest(); + Object phoneNumber = pigeonVar_list.get(0); pigeonResult.setPhoneNumber((String) phoneNumber); - Object timeout = __pigeon_list.get(1); - pigeonResult.setTimeout( - (timeout == null) - ? null - : ((timeout instanceof Integer) ? (Integer) timeout : (Long) timeout)); - Object forceResendingToken = __pigeon_list.get(2); - pigeonResult.setForceResendingToken( - (forceResendingToken == null) - ? null - : ((forceResendingToken instanceof Integer) - ? (Integer) forceResendingToken - : (Long) forceResendingToken)); - Object autoRetrievedSmsCodeForTesting = __pigeon_list.get(3); + Object timeout = pigeonVar_list.get(1); + pigeonResult.setTimeout((Long) timeout); + Object forceResendingToken = pigeonVar_list.get(2); + pigeonResult.setForceResendingToken((Long) forceResendingToken); + Object autoRetrievedSmsCodeForTesting = pigeonVar_list.get(3); pigeonResult.setAutoRetrievedSmsCodeForTesting((String) autoRetrievedSmsCodeForTesting); - Object multiFactorInfoId = __pigeon_list.get(4); + Object multiFactorInfoId = pigeonVar_list.get(4); pigeonResult.setMultiFactorInfoId((String) multiFactorInfoId); - Object multiFactorSessionId = __pigeon_list.get(5); + Object multiFactorSessionId = pigeonVar_list.get(5); pigeonResult.setMultiFactorSessionId((String) multiFactorSessionId); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonIdTokenResult { + public static final class InternalIdTokenResult { private @Nullable String token; public @Nullable String getToken() { @@ -2010,6 +2653,40 @@ public void setSignInSecondFactor(@Nullable String setterArg) { this.signInSecondFactor = setterArg; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalIdTokenResult that = (InternalIdTokenResult) o; + return pigeonDeepEquals(token, that.token) + && pigeonDeepEquals(expirationTimestamp, that.expirationTimestamp) + && pigeonDeepEquals(authTimestamp, that.authTimestamp) + && pigeonDeepEquals(issuedAtTimestamp, that.issuedAtTimestamp) + && pigeonDeepEquals(signInProvider, that.signInProvider) + && pigeonDeepEquals(claims, that.claims) + && pigeonDeepEquals(signInSecondFactor, that.signInSecondFactor); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + token, + expirationTimestamp, + authTimestamp, + issuedAtTimestamp, + signInProvider, + claims, + signInSecondFactor + }; + return pigeonDeepHashCode(fields); + } + public static final class Builder { private @Nullable String token; @@ -2068,8 +2745,8 @@ public static final class Builder { return this; } - public @NonNull PigeonIdTokenResult build() { - PigeonIdTokenResult pigeonReturn = new PigeonIdTokenResult(); + public @NonNull InternalIdTokenResult build() { + InternalIdTokenResult pigeonReturn = new InternalIdTokenResult(); pigeonReturn.setToken(token); pigeonReturn.setExpirationTimestamp(expirationTimestamp); pigeonReturn.setAuthTimestamp(authTimestamp); @@ -2082,8 +2759,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(7); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(7); toListResult.add(token); toListResult.add(expirationTimestamp); toListResult.add(authTimestamp); @@ -2094,43 +2771,28 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonIdTokenResult fromList(@NonNull ArrayList __pigeon_list) { - PigeonIdTokenResult pigeonResult = new PigeonIdTokenResult(); - Object token = __pigeon_list.get(0); + static @NonNull InternalIdTokenResult fromList(@NonNull ArrayList pigeonVar_list) { + InternalIdTokenResult pigeonResult = new InternalIdTokenResult(); + Object token = pigeonVar_list.get(0); pigeonResult.setToken((String) token); - Object expirationTimestamp = __pigeon_list.get(1); - pigeonResult.setExpirationTimestamp( - (expirationTimestamp == null) - ? null - : ((expirationTimestamp instanceof Integer) - ? (Integer) expirationTimestamp - : (Long) expirationTimestamp)); - Object authTimestamp = __pigeon_list.get(2); - pigeonResult.setAuthTimestamp( - (authTimestamp == null) - ? null - : ((authTimestamp instanceof Integer) - ? (Integer) authTimestamp - : (Long) authTimestamp)); - Object issuedAtTimestamp = __pigeon_list.get(3); - pigeonResult.setIssuedAtTimestamp( - (issuedAtTimestamp == null) - ? null - : ((issuedAtTimestamp instanceof Integer) - ? (Integer) issuedAtTimestamp - : (Long) issuedAtTimestamp)); - Object signInProvider = __pigeon_list.get(4); + Object expirationTimestamp = pigeonVar_list.get(1); + pigeonResult.setExpirationTimestamp((Long) expirationTimestamp); + Object authTimestamp = pigeonVar_list.get(2); + pigeonResult.setAuthTimestamp((Long) authTimestamp); + Object issuedAtTimestamp = pigeonVar_list.get(3); + pigeonResult.setIssuedAtTimestamp((Long) issuedAtTimestamp); + Object signInProvider = pigeonVar_list.get(4); pigeonResult.setSignInProvider((String) signInProvider); - Object claims = __pigeon_list.get(5); + Object claims = pigeonVar_list.get(5); pigeonResult.setClaims((Map) claims); - Object signInSecondFactor = __pigeon_list.get(6); + Object signInSecondFactor = pigeonVar_list.get(6); pigeonResult.setSignInSecondFactor((String) signInSecondFactor); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonUserProfile { + public static final class InternalUserProfile { private @Nullable String displayName; public @Nullable String getDisplayName() { @@ -2178,7 +2840,29 @@ public void setPhotoUrlChanged(@NonNull Boolean setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonUserProfile() {} + InternalUserProfile() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalUserProfile that = (InternalUserProfile) o; + return pigeonDeepEquals(displayName, that.displayName) + && pigeonDeepEquals(photoUrl, that.photoUrl) + && pigeonDeepEquals(displayNameChanged, that.displayNameChanged) + && pigeonDeepEquals(photoUrlChanged, that.photoUrlChanged); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] {getClass(), displayName, photoUrl, displayNameChanged, photoUrlChanged}; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -2214,8 +2898,8 @@ public static final class Builder { return this; } - public @NonNull PigeonUserProfile build() { - PigeonUserProfile pigeonReturn = new PigeonUserProfile(); + public @NonNull InternalUserProfile build() { + InternalUserProfile pigeonReturn = new InternalUserProfile(); pigeonReturn.setDisplayName(displayName); pigeonReturn.setPhotoUrl(photoUrl); pigeonReturn.setDisplayNameChanged(displayNameChanged); @@ -2225,8 +2909,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(4); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(4); toListResult.add(displayName); toListResult.add(photoUrl); toListResult.add(displayNameChanged); @@ -2234,22 +2918,22 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonUserProfile fromList(@NonNull ArrayList __pigeon_list) { - PigeonUserProfile pigeonResult = new PigeonUserProfile(); - Object displayName = __pigeon_list.get(0); + static @NonNull InternalUserProfile fromList(@NonNull ArrayList pigeonVar_list) { + InternalUserProfile pigeonResult = new InternalUserProfile(); + Object displayName = pigeonVar_list.get(0); pigeonResult.setDisplayName((String) displayName); - Object photoUrl = __pigeon_list.get(1); + Object photoUrl = pigeonVar_list.get(1); pigeonResult.setPhotoUrl((String) photoUrl); - Object displayNameChanged = __pigeon_list.get(2); + Object displayNameChanged = pigeonVar_list.get(2); pigeonResult.setDisplayNameChanged((Boolean) displayNameChanged); - Object photoUrlChanged = __pigeon_list.get(3); + Object photoUrlChanged = pigeonVar_list.get(3); pigeonResult.setPhotoUrlChanged((Boolean) photoUrlChanged); return pigeonResult; } } /** Generated class from Pigeon that represents data sent in messages. */ - public static final class PigeonTotpSecret { + public static final class InternalTotpSecret { private @Nullable Long codeIntervalSeconds; public @Nullable Long getCodeIntervalSeconds() { @@ -2304,7 +2988,37 @@ public void setSecretKey(@NonNull String setterArg) { } /** Constructor is non-public to enforce null safety; use Builder. */ - PigeonTotpSecret() {} + InternalTotpSecret() {} + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InternalTotpSecret that = (InternalTotpSecret) o; + return pigeonDeepEquals(codeIntervalSeconds, that.codeIntervalSeconds) + && pigeonDeepEquals(codeLength, that.codeLength) + && pigeonDeepEquals(enrollmentCompletionDeadline, that.enrollmentCompletionDeadline) + && pigeonDeepEquals(hashingAlgorithm, that.hashingAlgorithm) + && pigeonDeepEquals(secretKey, that.secretKey); + } + + @Override + public int hashCode() { + Object[] fields = + new Object[] { + getClass(), + codeIntervalSeconds, + codeLength, + enrollmentCompletionDeadline, + hashingAlgorithm, + secretKey + }; + return pigeonDeepHashCode(fields); + } public static final class Builder { @@ -2348,8 +3062,8 @@ public static final class Builder { return this; } - public @NonNull PigeonTotpSecret build() { - PigeonTotpSecret pigeonReturn = new PigeonTotpSecret(); + public @NonNull InternalTotpSecret build() { + InternalTotpSecret pigeonReturn = new InternalTotpSecret(); pigeonReturn.setCodeIntervalSeconds(codeIntervalSeconds); pigeonReturn.setCodeLength(codeLength); pigeonReturn.setEnrollmentCompletionDeadline(enrollmentCompletionDeadline); @@ -2360,8 +3074,8 @@ public static final class Builder { } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList(5); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(5); toListResult.add(codeIntervalSeconds); toListResult.add(codeLength); toListResult.add(enrollmentCompletionDeadline); @@ -2370,104 +3084,75 @@ ArrayList toList() { return toListResult; } - static @NonNull PigeonTotpSecret fromList(@NonNull ArrayList __pigeon_list) { - PigeonTotpSecret pigeonResult = new PigeonTotpSecret(); - Object codeIntervalSeconds = __pigeon_list.get(0); - pigeonResult.setCodeIntervalSeconds( - (codeIntervalSeconds == null) - ? null - : ((codeIntervalSeconds instanceof Integer) - ? (Integer) codeIntervalSeconds - : (Long) codeIntervalSeconds)); - Object codeLength = __pigeon_list.get(1); - pigeonResult.setCodeLength( - (codeLength == null) - ? null - : ((codeLength instanceof Integer) ? (Integer) codeLength : (Long) codeLength)); - Object enrollmentCompletionDeadline = __pigeon_list.get(2); - pigeonResult.setEnrollmentCompletionDeadline( - (enrollmentCompletionDeadline == null) - ? null - : ((enrollmentCompletionDeadline instanceof Integer) - ? (Integer) enrollmentCompletionDeadline - : (Long) enrollmentCompletionDeadline)); - Object hashingAlgorithm = __pigeon_list.get(3); + static @NonNull InternalTotpSecret fromList(@NonNull ArrayList pigeonVar_list) { + InternalTotpSecret pigeonResult = new InternalTotpSecret(); + Object codeIntervalSeconds = pigeonVar_list.get(0); + pigeonResult.setCodeIntervalSeconds((Long) codeIntervalSeconds); + Object codeLength = pigeonVar_list.get(1); + pigeonResult.setCodeLength((Long) codeLength); + Object enrollmentCompletionDeadline = pigeonVar_list.get(2); + pigeonResult.setEnrollmentCompletionDeadline((Long) enrollmentCompletionDeadline); + Object hashingAlgorithm = pigeonVar_list.get(3); pigeonResult.setHashingAlgorithm((String) hashingAlgorithm); - Object secretKey = __pigeon_list.get(4); + Object secretKey = pigeonVar_list.get(4); pigeonResult.setSecretKey((String) secretKey); return pigeonResult; } } - /** Asynchronous error handling return type for non-nullable API method returns. */ - public interface Result { - /** Success case callback method for handling returns. */ - void success(@NonNull T result); - - /** Failure case callback method for handling errors. */ - void error(@NonNull Throwable error); - } - /** Asynchronous error handling return type for nullable API method returns. */ - public interface NullableResult { - /** Success case callback method for handling returns. */ - void success(@Nullable T result); - - /** Failure case callback method for handling errors. */ - void error(@NonNull Throwable error); - } - /** Asynchronous error handling return type for void API method returns. */ - public interface VoidResult { - /** Success case callback method for handling returns. */ - void success(); - - /** Failure case callback method for handling errors. */ - void error(@NonNull Throwable error); - } - - private static class FirebaseAuthHostApiCodec extends StandardMessageCodec { - public static final FirebaseAuthHostApiCodec INSTANCE = new FirebaseAuthHostApiCodec(); + private static class PigeonCodec extends StandardMessageCodec { + public static final PigeonCodec INSTANCE = new PigeonCodec(); - private FirebaseAuthHostApiCodec() {} + private PigeonCodec() {} @Override protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { switch (type) { - case (byte) 128: - return AuthPigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); case (byte) 129: - return PigeonActionCodeInfo.fromList((ArrayList) readValue(buffer)); + { + Object value = readValue(buffer); + return value == null + ? null + : ActionCodeInfoOperation.values()[((Long) value).intValue()]; + } case (byte) 130: - return PigeonActionCodeInfoData.fromList((ArrayList) readValue(buffer)); + return InternalMultiFactorSession.fromList((ArrayList) readValue(buffer)); case (byte) 131: - return PigeonActionCodeSettings.fromList((ArrayList) readValue(buffer)); + return InternalPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); case (byte) 132: - return PigeonAdditionalUserInfo.fromList((ArrayList) readValue(buffer)); + return InternalMultiFactorInfo.fromList((ArrayList) readValue(buffer)); case (byte) 133: - return PigeonAuthCredential.fromList((ArrayList) readValue(buffer)); + return AuthPigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); case (byte) 134: - return PigeonFirebaseAuthSettings.fromList((ArrayList) readValue(buffer)); + return InternalActionCodeInfoData.fromList((ArrayList) readValue(buffer)); case (byte) 135: - return PigeonIdTokenResult.fromList((ArrayList) readValue(buffer)); + return InternalActionCodeInfo.fromList((ArrayList) readValue(buffer)); case (byte) 136: - return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); + return InternalAdditionalUserInfo.fromList((ArrayList) readValue(buffer)); case (byte) 137: - return PigeonMultiFactorSession.fromList((ArrayList) readValue(buffer)); + return InternalAuthCredential.fromList((ArrayList) readValue(buffer)); case (byte) 138: - return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); + return InternalUserInfo.fromList((ArrayList) readValue(buffer)); case (byte) 139: - return PigeonSignInProvider.fromList((ArrayList) readValue(buffer)); + return InternalUserDetails.fromList((ArrayList) readValue(buffer)); case (byte) 140: - return PigeonTotpSecret.fromList((ArrayList) readValue(buffer)); + return InternalUserCredential.fromList((ArrayList) readValue(buffer)); case (byte) 141: - return PigeonUserCredential.fromList((ArrayList) readValue(buffer)); + return InternalAuthCredentialInput.fromList((ArrayList) readValue(buffer)); case (byte) 142: - return PigeonUserDetails.fromList((ArrayList) readValue(buffer)); + return InternalActionCodeSettings.fromList((ArrayList) readValue(buffer)); case (byte) 143: - return PigeonUserInfo.fromList((ArrayList) readValue(buffer)); + return InternalFirebaseAuthSettings.fromList((ArrayList) readValue(buffer)); case (byte) 144: - return PigeonUserProfile.fromList((ArrayList) readValue(buffer)); + return InternalSignInProvider.fromList((ArrayList) readValue(buffer)); case (byte) 145: - return PigeonVerifyPhoneNumberRequest.fromList((ArrayList) readValue(buffer)); + return InternalVerifyPhoneNumberRequest.fromList((ArrayList) readValue(buffer)); + case (byte) 146: + return InternalIdTokenResult.fromList((ArrayList) readValue(buffer)); + case (byte) 147: + return InternalUserProfile.fromList((ArrayList) readValue(buffer)); + case (byte) 148: + return InternalTotpSecret.fromList((ArrayList) readValue(buffer)); default: return super.readValueOfType(type, buffer); } @@ -2475,66 +3160,96 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { @Override protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof AuthPigeonFirebaseApp) { - stream.write(128); - writeValue(stream, ((AuthPigeonFirebaseApp) value).toList()); - } else if (value instanceof PigeonActionCodeInfo) { + if (value instanceof ActionCodeInfoOperation) { stream.write(129); - writeValue(stream, ((PigeonActionCodeInfo) value).toList()); - } else if (value instanceof PigeonActionCodeInfoData) { + writeValue(stream, value == null ? null : ((ActionCodeInfoOperation) value).index); + } else if (value instanceof InternalMultiFactorSession) { stream.write(130); - writeValue(stream, ((PigeonActionCodeInfoData) value).toList()); - } else if (value instanceof PigeonActionCodeSettings) { + writeValue(stream, ((InternalMultiFactorSession) value).toList()); + } else if (value instanceof InternalPhoneMultiFactorAssertion) { stream.write(131); - writeValue(stream, ((PigeonActionCodeSettings) value).toList()); - } else if (value instanceof PigeonAdditionalUserInfo) { + writeValue(stream, ((InternalPhoneMultiFactorAssertion) value).toList()); + } else if (value instanceof InternalMultiFactorInfo) { stream.write(132); - writeValue(stream, ((PigeonAdditionalUserInfo) value).toList()); - } else if (value instanceof PigeonAuthCredential) { + writeValue(stream, ((InternalMultiFactorInfo) value).toList()); + } else if (value instanceof AuthPigeonFirebaseApp) { stream.write(133); - writeValue(stream, ((PigeonAuthCredential) value).toList()); - } else if (value instanceof PigeonFirebaseAuthSettings) { + writeValue(stream, ((AuthPigeonFirebaseApp) value).toList()); + } else if (value instanceof InternalActionCodeInfoData) { stream.write(134); - writeValue(stream, ((PigeonFirebaseAuthSettings) value).toList()); - } else if (value instanceof PigeonIdTokenResult) { + writeValue(stream, ((InternalActionCodeInfoData) value).toList()); + } else if (value instanceof InternalActionCodeInfo) { stream.write(135); - writeValue(stream, ((PigeonIdTokenResult) value).toList()); - } else if (value instanceof PigeonMultiFactorInfo) { + writeValue(stream, ((InternalActionCodeInfo) value).toList()); + } else if (value instanceof InternalAdditionalUserInfo) { stream.write(136); - writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); - } else if (value instanceof PigeonMultiFactorSession) { + writeValue(stream, ((InternalAdditionalUserInfo) value).toList()); + } else if (value instanceof InternalAuthCredential) { stream.write(137); - writeValue(stream, ((PigeonMultiFactorSession) value).toList()); - } else if (value instanceof PigeonPhoneMultiFactorAssertion) { + writeValue(stream, ((InternalAuthCredential) value).toList()); + } else if (value instanceof InternalUserInfo) { stream.write(138); - writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); - } else if (value instanceof PigeonSignInProvider) { + writeValue(stream, ((InternalUserInfo) value).toList()); + } else if (value instanceof InternalUserDetails) { stream.write(139); - writeValue(stream, ((PigeonSignInProvider) value).toList()); - } else if (value instanceof PigeonTotpSecret) { + writeValue(stream, ((InternalUserDetails) value).toList()); + } else if (value instanceof InternalUserCredential) { stream.write(140); - writeValue(stream, ((PigeonTotpSecret) value).toList()); - } else if (value instanceof PigeonUserCredential) { + writeValue(stream, ((InternalUserCredential) value).toList()); + } else if (value instanceof InternalAuthCredentialInput) { stream.write(141); - writeValue(stream, ((PigeonUserCredential) value).toList()); - } else if (value instanceof PigeonUserDetails) { + writeValue(stream, ((InternalAuthCredentialInput) value).toList()); + } else if (value instanceof InternalActionCodeSettings) { stream.write(142); - writeValue(stream, ((PigeonUserDetails) value).toList()); - } else if (value instanceof PigeonUserInfo) { + writeValue(stream, ((InternalActionCodeSettings) value).toList()); + } else if (value instanceof InternalFirebaseAuthSettings) { stream.write(143); - writeValue(stream, ((PigeonUserInfo) value).toList()); - } else if (value instanceof PigeonUserProfile) { + writeValue(stream, ((InternalFirebaseAuthSettings) value).toList()); + } else if (value instanceof InternalSignInProvider) { stream.write(144); - writeValue(stream, ((PigeonUserProfile) value).toList()); - } else if (value instanceof PigeonVerifyPhoneNumberRequest) { + writeValue(stream, ((InternalSignInProvider) value).toList()); + } else if (value instanceof InternalVerifyPhoneNumberRequest) { stream.write(145); - writeValue(stream, ((PigeonVerifyPhoneNumberRequest) value).toList()); + writeValue(stream, ((InternalVerifyPhoneNumberRequest) value).toList()); + } else if (value instanceof InternalIdTokenResult) { + stream.write(146); + writeValue(stream, ((InternalIdTokenResult) value).toList()); + } else if (value instanceof InternalUserProfile) { + stream.write(147); + writeValue(stream, ((InternalUserProfile) value).toList()); + } else if (value instanceof InternalTotpSecret) { + stream.write(148); + writeValue(stream, ((InternalTotpSecret) value).toList()); } else { super.writeValue(stream, value); } } } + /** Asynchronous error handling return type for non-nullable API method returns. */ + public interface Result { + /** Success case callback method for handling returns. */ + void success(@NonNull T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for nullable API method returns. */ + public interface NullableResult { + /** Success case callback method for handling returns. */ + void success(@Nullable T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for void API method returns. */ + public interface VoidResult { + /** Success case callback method for handling returns. */ + void success(); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseAuthHostApi { @@ -2556,7 +3271,7 @@ void applyActionCode( void checkActionCode( @NonNull AuthPigeonFirebaseApp app, @NonNull String code, - @NonNull Result result); + @NonNull Result result); void confirmPasswordReset( @NonNull AuthPigeonFirebaseApp app, @@ -2568,37 +3283,37 @@ void createUserWithEmailAndPassword( @NonNull AuthPigeonFirebaseApp app, @NonNull String email, @NonNull String password, - @NonNull Result result); + @NonNull Result result); void signInAnonymously( - @NonNull AuthPigeonFirebaseApp app, @NonNull Result result); + @NonNull AuthPigeonFirebaseApp app, @NonNull Result result); void signInWithCredential( @NonNull AuthPigeonFirebaseApp app, @NonNull Map input, - @NonNull Result result); + @NonNull Result result); void signInWithCustomToken( @NonNull AuthPigeonFirebaseApp app, @NonNull String token, - @NonNull Result result); + @NonNull Result result); void signInWithEmailAndPassword( @NonNull AuthPigeonFirebaseApp app, @NonNull String email, @NonNull String password, - @NonNull Result result); + @NonNull Result result); void signInWithEmailLink( @NonNull AuthPigeonFirebaseApp app, @NonNull String email, @NonNull String emailLink, - @NonNull Result result); + @NonNull Result result); void signInWithProvider( @NonNull AuthPigeonFirebaseApp app, - @NonNull PigeonSignInProvider signInProvider, - @NonNull Result result); + @NonNull InternalSignInProvider signInProvider, + @NonNull Result result); void signOut(@NonNull AuthPigeonFirebaseApp app, @NonNull VoidResult result); @@ -2610,13 +3325,13 @@ void fetchSignInMethodsForEmail( void sendPasswordResetEmail( @NonNull AuthPigeonFirebaseApp app, @NonNull String email, - @Nullable PigeonActionCodeSettings actionCodeSettings, + @Nullable InternalActionCodeSettings actionCodeSettings, @NonNull VoidResult result); void sendSignInLinkToEmail( @NonNull AuthPigeonFirebaseApp app, @NonNull String email, - @NonNull PigeonActionCodeSettings actionCodeSettings, + @NonNull InternalActionCodeSettings actionCodeSettings, @NonNull VoidResult result); void setLanguageCode( @@ -2626,7 +3341,7 @@ void setLanguageCode( void setSettings( @NonNull AuthPigeonFirebaseApp app, - @NonNull PigeonFirebaseAuthSettings settings, + @NonNull InternalFirebaseAuthSettings settings, @NonNull VoidResult result); void verifyPasswordResetCode( @@ -2634,7 +3349,7 @@ void verifyPasswordResetCode( void verifyPhoneNumber( @NonNull AuthPigeonFirebaseApp app, - @NonNull PigeonVerifyPhoneNumberRequest request, + @NonNull InternalVerifyPhoneNumberRequest request, @NonNull Result result); void revokeTokenWithAuthorizationCode( @@ -2651,7 +3366,7 @@ void revokeAccessToken( /** The codec used by FirebaseAuthHostApi. */ static @NonNull MessageCodec getCodec() { - return FirebaseAuthHostApiCodec.INSTANCE; + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `FirebaseAuthHostApi` to handle messages through the @@ -2676,7 +3391,7 @@ static void setUp( if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); Result resultCallback = @@ -2708,7 +3423,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); Result resultCallback = @@ -2740,11 +3455,11 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String hostArg = (String) args.get(1); - Number portArg = (Number) args.get(2); + Long portArg = (Long) args.get(2); VoidResult resultCallback = new VoidResult() { public void success() { @@ -2758,11 +3473,7 @@ public void error(Throwable error) { } }; - api.useEmulator( - appArg, - hostArg, - (portArg == null) ? null : portArg.longValue(), - resultCallback); + api.useEmulator(appArg, hostArg, portArg, resultCallback); }); } else { channel.setMessageHandler(null); @@ -2778,7 +3489,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String codeArg = (String) args.get(1); @@ -2811,13 +3522,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String codeArg = (String) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonActionCodeInfo result) { + Result resultCallback = + new Result() { + public void success(InternalActionCodeInfo result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2844,7 +3555,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String codeArg = (String) args.get(1); @@ -2878,14 +3589,14 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String emailArg = (String) args.get(1); String passwordArg = (String) args.get(2); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2912,12 +3623,12 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2944,13 +3655,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); Map inputArg = (Map) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -2977,13 +3688,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String tokenArg = (String) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3010,14 +3721,14 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String emailArg = (String) args.get(1); String passwordArg = (String) args.get(2); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3044,14 +3755,14 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String emailArg = (String) args.get(1); String emailLinkArg = (String) args.get(2); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3078,13 +3789,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonSignInProvider signInProviderArg = (PigeonSignInProvider) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + InternalSignInProvider signInProviderArg = (InternalSignInProvider) args.get(1); + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3111,7 +3822,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); VoidResult resultCallback = @@ -3143,7 +3854,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String emailArg = (String) args.get(1); @@ -3176,12 +3887,12 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String emailArg = (String) args.get(1); - PigeonActionCodeSettings actionCodeSettingsArg = - (PigeonActionCodeSettings) args.get(2); + InternalActionCodeSettings actionCodeSettingsArg = + (InternalActionCodeSettings) args.get(2); VoidResult resultCallback = new VoidResult() { public void success() { @@ -3211,12 +3922,12 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String emailArg = (String) args.get(1); - PigeonActionCodeSettings actionCodeSettingsArg = - (PigeonActionCodeSettings) args.get(2); + InternalActionCodeSettings actionCodeSettingsArg = + (InternalActionCodeSettings) args.get(2); VoidResult resultCallback = new VoidResult() { public void success() { @@ -3246,7 +3957,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String languageCodeArg = (String) args.get(1); @@ -3279,10 +3990,11 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonFirebaseAuthSettings settingsArg = (PigeonFirebaseAuthSettings) args.get(1); + InternalFirebaseAuthSettings settingsArg = + (InternalFirebaseAuthSettings) args.get(1); VoidResult resultCallback = new VoidResult() { public void success() { @@ -3312,7 +4024,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String codeArg = (String) args.get(1); @@ -3345,11 +4057,11 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonVerifyPhoneNumberRequest requestArg = - (PigeonVerifyPhoneNumberRequest) args.get(1); + InternalVerifyPhoneNumberRequest requestArg = + (InternalVerifyPhoneNumberRequest) args.get(1); Result resultCallback = new Result() { public void success(String result) { @@ -3379,7 +4091,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String authorizationCodeArg = (String) args.get(1); @@ -3412,7 +4124,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String accessTokenArg = (String) args.get(1); @@ -3445,7 +4157,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); VoidResult resultCallback = @@ -3469,118 +4181,6 @@ public void error(Throwable error) { } } } - - private static class FirebaseAuthUserHostApiCodec extends StandardMessageCodec { - public static final FirebaseAuthUserHostApiCodec INSTANCE = new FirebaseAuthUserHostApiCodec(); - - private FirebaseAuthUserHostApiCodec() {} - - @Override - protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return AuthPigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); - case (byte) 129: - return PigeonActionCodeInfo.fromList((ArrayList) readValue(buffer)); - case (byte) 130: - return PigeonActionCodeInfoData.fromList((ArrayList) readValue(buffer)); - case (byte) 131: - return PigeonActionCodeSettings.fromList((ArrayList) readValue(buffer)); - case (byte) 132: - return PigeonAdditionalUserInfo.fromList((ArrayList) readValue(buffer)); - case (byte) 133: - return PigeonAuthCredential.fromList((ArrayList) readValue(buffer)); - case (byte) 134: - return PigeonFirebaseAuthSettings.fromList((ArrayList) readValue(buffer)); - case (byte) 135: - return PigeonIdTokenResult.fromList((ArrayList) readValue(buffer)); - case (byte) 136: - return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); - case (byte) 137: - return PigeonMultiFactorSession.fromList((ArrayList) readValue(buffer)); - case (byte) 138: - return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); - case (byte) 139: - return PigeonSignInProvider.fromList((ArrayList) readValue(buffer)); - case (byte) 140: - return PigeonTotpSecret.fromList((ArrayList) readValue(buffer)); - case (byte) 141: - return PigeonUserCredential.fromList((ArrayList) readValue(buffer)); - case (byte) 142: - return PigeonUserDetails.fromList((ArrayList) readValue(buffer)); - case (byte) 143: - return PigeonUserInfo.fromList((ArrayList) readValue(buffer)); - case (byte) 144: - return PigeonUserProfile.fromList((ArrayList) readValue(buffer)); - case (byte) 145: - return PigeonVerifyPhoneNumberRequest.fromList((ArrayList) readValue(buffer)); - default: - return super.readValueOfType(type, buffer); - } - } - - @Override - protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof AuthPigeonFirebaseApp) { - stream.write(128); - writeValue(stream, ((AuthPigeonFirebaseApp) value).toList()); - } else if (value instanceof PigeonActionCodeInfo) { - stream.write(129); - writeValue(stream, ((PigeonActionCodeInfo) value).toList()); - } else if (value instanceof PigeonActionCodeInfoData) { - stream.write(130); - writeValue(stream, ((PigeonActionCodeInfoData) value).toList()); - } else if (value instanceof PigeonActionCodeSettings) { - stream.write(131); - writeValue(stream, ((PigeonActionCodeSettings) value).toList()); - } else if (value instanceof PigeonAdditionalUserInfo) { - stream.write(132); - writeValue(stream, ((PigeonAdditionalUserInfo) value).toList()); - } else if (value instanceof PigeonAuthCredential) { - stream.write(133); - writeValue(stream, ((PigeonAuthCredential) value).toList()); - } else if (value instanceof PigeonFirebaseAuthSettings) { - stream.write(134); - writeValue(stream, ((PigeonFirebaseAuthSettings) value).toList()); - } else if (value instanceof PigeonIdTokenResult) { - stream.write(135); - writeValue(stream, ((PigeonIdTokenResult) value).toList()); - } else if (value instanceof PigeonMultiFactorInfo) { - stream.write(136); - writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); - } else if (value instanceof PigeonMultiFactorSession) { - stream.write(137); - writeValue(stream, ((PigeonMultiFactorSession) value).toList()); - } else if (value instanceof PigeonPhoneMultiFactorAssertion) { - stream.write(138); - writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); - } else if (value instanceof PigeonSignInProvider) { - stream.write(139); - writeValue(stream, ((PigeonSignInProvider) value).toList()); - } else if (value instanceof PigeonTotpSecret) { - stream.write(140); - writeValue(stream, ((PigeonTotpSecret) value).toList()); - } else if (value instanceof PigeonUserCredential) { - stream.write(141); - writeValue(stream, ((PigeonUserCredential) value).toList()); - } else if (value instanceof PigeonUserDetails) { - stream.write(142); - writeValue(stream, ((PigeonUserDetails) value).toList()); - } else if (value instanceof PigeonUserInfo) { - stream.write(143); - writeValue(stream, ((PigeonUserInfo) value).toList()); - } else if (value instanceof PigeonUserProfile) { - stream.write(144); - writeValue(stream, ((PigeonUserProfile) value).toList()); - } else if (value instanceof PigeonVerifyPhoneNumberRequest) { - stream.write(145); - writeValue(stream, ((PigeonVerifyPhoneNumberRequest) value).toList()); - } else { - super.writeValue(stream, value); - } - } - } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseAuthUserHostApi { @@ -3589,69 +4189,69 @@ public interface FirebaseAuthUserHostApi { void getIdToken( @NonNull AuthPigeonFirebaseApp app, @NonNull Boolean forceRefresh, - @NonNull Result result); + @NonNull Result result); void linkWithCredential( @NonNull AuthPigeonFirebaseApp app, @NonNull Map input, - @NonNull Result result); + @NonNull Result result); void linkWithProvider( @NonNull AuthPigeonFirebaseApp app, - @NonNull PigeonSignInProvider signInProvider, - @NonNull Result result); + @NonNull InternalSignInProvider signInProvider, + @NonNull Result result); void reauthenticateWithCredential( @NonNull AuthPigeonFirebaseApp app, @NonNull Map input, - @NonNull Result result); + @NonNull Result result); void reauthenticateWithProvider( @NonNull AuthPigeonFirebaseApp app, - @NonNull PigeonSignInProvider signInProvider, - @NonNull Result result); + @NonNull InternalSignInProvider signInProvider, + @NonNull Result result); - void reload(@NonNull AuthPigeonFirebaseApp app, @NonNull Result result); + void reload(@NonNull AuthPigeonFirebaseApp app, @NonNull Result result); void sendEmailVerification( @NonNull AuthPigeonFirebaseApp app, - @Nullable PigeonActionCodeSettings actionCodeSettings, + @Nullable InternalActionCodeSettings actionCodeSettings, @NonNull VoidResult result); void unlink( @NonNull AuthPigeonFirebaseApp app, @NonNull String providerId, - @NonNull Result result); + @NonNull Result result); void updateEmail( @NonNull AuthPigeonFirebaseApp app, @NonNull String newEmail, - @NonNull Result result); + @NonNull Result result); void updatePassword( @NonNull AuthPigeonFirebaseApp app, @NonNull String newPassword, - @NonNull Result result); + @NonNull Result result); void updatePhoneNumber( @NonNull AuthPigeonFirebaseApp app, @NonNull Map input, - @NonNull Result result); + @NonNull Result result); void updateProfile( @NonNull AuthPigeonFirebaseApp app, - @NonNull PigeonUserProfile profile, - @NonNull Result result); + @NonNull InternalUserProfile profile, + @NonNull Result result); void verifyBeforeUpdateEmail( @NonNull AuthPigeonFirebaseApp app, @NonNull String newEmail, - @Nullable PigeonActionCodeSettings actionCodeSettings, + @Nullable InternalActionCodeSettings actionCodeSettings, @NonNull VoidResult result); /** The codec used by FirebaseAuthUserHostApi. */ static @NonNull MessageCodec getCodec() { - return FirebaseAuthUserHostApiCodec.INSTANCE; + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `FirebaseAuthUserHostApi` to handle messages through the @@ -3677,7 +4277,7 @@ static void setUp( if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); VoidResult resultCallback = @@ -3709,13 +4309,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); Boolean forceRefreshArg = (Boolean) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonIdTokenResult result) { + Result resultCallback = + new Result() { + public void success(InternalIdTokenResult result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3742,13 +4342,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); Map inputArg = (Map) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3775,13 +4375,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonSignInProvider signInProviderArg = (PigeonSignInProvider) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + InternalSignInProvider signInProviderArg = (InternalSignInProvider) args.get(1); + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3808,13 +4408,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); Map inputArg = (Map) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3841,13 +4441,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonSignInProvider signInProviderArg = (PigeonSignInProvider) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + InternalSignInProvider signInProviderArg = (InternalSignInProvider) args.get(1); + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3874,12 +4474,12 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(PigeonUserDetails result) { + Result resultCallback = + new Result() { + public void success(InternalUserDetails result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3906,11 +4506,11 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonActionCodeSettings actionCodeSettingsArg = - (PigeonActionCodeSettings) args.get(1); + InternalActionCodeSettings actionCodeSettingsArg = + (InternalActionCodeSettings) args.get(1); VoidResult resultCallback = new VoidResult() { public void success() { @@ -3940,13 +4540,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String providerIdArg = (String) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -3973,13 +4573,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String newEmailArg = (String) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserDetails result) { + Result resultCallback = + new Result() { + public void success(InternalUserDetails result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4006,13 +4606,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String newPasswordArg = (String) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserDetails result) { + Result resultCallback = + new Result() { + public void success(InternalUserDetails result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4039,13 +4639,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); Map inputArg = (Map) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserDetails result) { + Result resultCallback = + new Result() { + public void success(InternalUserDetails result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4072,13 +4672,13 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonUserProfile profileArg = (PigeonUserProfile) args.get(1); - Result resultCallback = - new Result() { - public void success(PigeonUserDetails result) { + InternalUserProfile profileArg = (InternalUserProfile) args.get(1); + Result resultCallback = + new Result() { + public void success(InternalUserDetails result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4105,12 +4705,12 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String newEmailArg = (String) args.get(1); - PigeonActionCodeSettings actionCodeSettingsArg = - (PigeonActionCodeSettings) args.get(2); + InternalActionCodeSettings actionCodeSettingsArg = + (InternalActionCodeSettings) args.get(2); VoidResult resultCallback = new VoidResult() { public void success() { @@ -4133,54 +4733,12 @@ public void error(Throwable error) { } } } - - private static class MultiFactorUserHostApiCodec extends StandardMessageCodec { - public static final MultiFactorUserHostApiCodec INSTANCE = new MultiFactorUserHostApiCodec(); - - private MultiFactorUserHostApiCodec() {} - - @Override - protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return AuthPigeonFirebaseApp.fromList((ArrayList) readValue(buffer)); - case (byte) 129: - return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); - case (byte) 130: - return PigeonMultiFactorSession.fromList((ArrayList) readValue(buffer)); - case (byte) 131: - return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); - default: - return super.readValueOfType(type, buffer); - } - } - - @Override - protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof AuthPigeonFirebaseApp) { - stream.write(128); - writeValue(stream, ((AuthPigeonFirebaseApp) value).toList()); - } else if (value instanceof PigeonMultiFactorInfo) { - stream.write(129); - writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); - } else if (value instanceof PigeonMultiFactorSession) { - stream.write(130); - writeValue(stream, ((PigeonMultiFactorSession) value).toList()); - } else if (value instanceof PigeonPhoneMultiFactorAssertion) { - stream.write(131); - writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); - } else { - super.writeValue(stream, value); - } - } - } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface MultiFactorUserHostApi { void enrollPhone( @NonNull AuthPigeonFirebaseApp app, - @NonNull PigeonPhoneMultiFactorAssertion assertion, + @NonNull InternalPhoneMultiFactorAssertion assertion, @Nullable String displayName, @NonNull VoidResult result); @@ -4191,17 +4749,17 @@ void enrollTotp( @NonNull VoidResult result); void getSession( - @NonNull AuthPigeonFirebaseApp app, @NonNull Result result); + @NonNull AuthPigeonFirebaseApp app, @NonNull Result result); void unenroll( @NonNull AuthPigeonFirebaseApp app, @NonNull String factorUid, @NonNull VoidResult result); void getEnrolledFactors( - @NonNull AuthPigeonFirebaseApp app, @NonNull Result> result); + @NonNull AuthPigeonFirebaseApp app, @NonNull Result> result); /** The codec used by MultiFactorUserHostApi. */ static @NonNull MessageCodec getCodec() { - return MultiFactorUserHostApiCodec.INSTANCE; + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `MultiFactorUserHostApi` to handle messages through the @@ -4227,11 +4785,11 @@ static void setUp( if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - PigeonPhoneMultiFactorAssertion assertionArg = - (PigeonPhoneMultiFactorAssertion) args.get(1); + InternalPhoneMultiFactorAssertion assertionArg = + (InternalPhoneMultiFactorAssertion) args.get(1); String displayNameArg = (String) args.get(2); VoidResult resultCallback = new VoidResult() { @@ -4262,7 +4820,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String assertionIdArg = (String) args.get(1); @@ -4296,12 +4854,12 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - Result resultCallback = - new Result() { - public void success(PigeonMultiFactorSession result) { + Result resultCallback = + new Result() { + public void success(InternalMultiFactorSession result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4328,7 +4886,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); String factorUidArg = (String) args.get(1); @@ -4361,12 +4919,12 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; AuthPigeonFirebaseApp appArg = (AuthPigeonFirebaseApp) args.get(0); - Result> resultCallback = - new Result>() { - public void success(List result) { + Result> resultCallback = + new Result>() { + public void success(List result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4385,71 +4943,18 @@ public void error(Throwable error) { } } } - - private static class MultiFactoResolverHostApiCodec extends StandardMessageCodec { - public static final MultiFactoResolverHostApiCodec INSTANCE = - new MultiFactoResolverHostApiCodec(); - - private MultiFactoResolverHostApiCodec() {} - - @Override - protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return PigeonAdditionalUserInfo.fromList((ArrayList) readValue(buffer)); - case (byte) 129: - return PigeonAuthCredential.fromList((ArrayList) readValue(buffer)); - case (byte) 130: - return PigeonPhoneMultiFactorAssertion.fromList((ArrayList) readValue(buffer)); - case (byte) 131: - return PigeonUserCredential.fromList((ArrayList) readValue(buffer)); - case (byte) 132: - return PigeonUserDetails.fromList((ArrayList) readValue(buffer)); - case (byte) 133: - return PigeonUserInfo.fromList((ArrayList) readValue(buffer)); - default: - return super.readValueOfType(type, buffer); - } - } - - @Override - protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof PigeonAdditionalUserInfo) { - stream.write(128); - writeValue(stream, ((PigeonAdditionalUserInfo) value).toList()); - } else if (value instanceof PigeonAuthCredential) { - stream.write(129); - writeValue(stream, ((PigeonAuthCredential) value).toList()); - } else if (value instanceof PigeonPhoneMultiFactorAssertion) { - stream.write(130); - writeValue(stream, ((PigeonPhoneMultiFactorAssertion) value).toList()); - } else if (value instanceof PigeonUserCredential) { - stream.write(131); - writeValue(stream, ((PigeonUserCredential) value).toList()); - } else if (value instanceof PigeonUserDetails) { - stream.write(132); - writeValue(stream, ((PigeonUserDetails) value).toList()); - } else if (value instanceof PigeonUserInfo) { - stream.write(133); - writeValue(stream, ((PigeonUserInfo) value).toList()); - } else { - super.writeValue(stream, value); - } - } - } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface MultiFactoResolverHostApi { void resolveSignIn( @NonNull String resolverId, - @Nullable PigeonPhoneMultiFactorAssertion assertion, + @Nullable InternalPhoneMultiFactorAssertion assertion, @Nullable String totpAssertionId, - @NonNull Result result); + @NonNull Result result); /** The codec used by MultiFactoResolverHostApi. */ static @NonNull MessageCodec getCodec() { - return MultiFactoResolverHostApiCodec.INSTANCE; + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `MultiFactoResolverHostApi` to handle messages through the @@ -4475,15 +4980,15 @@ static void setUp( if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; String resolverIdArg = (String) args.get(0); - PigeonPhoneMultiFactorAssertion assertionArg = - (PigeonPhoneMultiFactorAssertion) args.get(1); + InternalPhoneMultiFactorAssertion assertionArg = + (InternalPhoneMultiFactorAssertion) args.get(1); String totpAssertionIdArg = (String) args.get(2); - Result resultCallback = - new Result() { - public void success(PigeonUserCredential result) { + Result resultCallback = + new Result() { + public void success(InternalUserCredential result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4502,37 +5007,10 @@ public void error(Throwable error) { } } } - - private static class MultiFactorTotpHostApiCodec extends StandardMessageCodec { - public static final MultiFactorTotpHostApiCodec INSTANCE = new MultiFactorTotpHostApiCodec(); - - private MultiFactorTotpHostApiCodec() {} - - @Override - protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return PigeonTotpSecret.fromList((ArrayList) readValue(buffer)); - default: - return super.readValueOfType(type, buffer); - } - } - - @Override - protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof PigeonTotpSecret) { - stream.write(128); - writeValue(stream, ((PigeonTotpSecret) value).toList()); - } else { - super.writeValue(stream, value); - } - } - } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface MultiFactorTotpHostApi { - void generateSecret(@NonNull String sessionId, @NonNull Result result); + void generateSecret(@NonNull String sessionId, @NonNull Result result); void getAssertionForEnrollment( @NonNull String secretKey, @NonNull String oneTimePassword, @NonNull Result result); @@ -4544,7 +5022,7 @@ void getAssertionForSignIn( /** The codec used by MultiFactorTotpHostApi. */ static @NonNull MessageCodec getCodec() { - return MultiFactorTotpHostApiCodec.INSTANCE; + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `MultiFactorTotpHostApi` to handle messages through the @@ -4570,12 +5048,12 @@ static void setUp( if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; String sessionIdArg = (String) args.get(0); - Result resultCallback = - new Result() { - public void success(PigeonTotpSecret result) { + Result resultCallback = + new Result() { + public void success(InternalTotpSecret result) { wrapped.add(0, result); reply.reply(wrapped); } @@ -4602,7 +5080,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; String secretKeyArg = (String) args.get(0); String oneTimePasswordArg = (String) args.get(1); @@ -4635,7 +5113,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; String enrollmentIdArg = (String) args.get(0); String oneTimePasswordArg = (String) args.get(1); @@ -4674,7 +5152,7 @@ void openInOtpApp( /** The codec used by MultiFactorTotpSecretHostApi. */ static @NonNull MessageCodec getCodec() { - return new StandardMessageCodec(); + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `MultiFactorTotpSecretHostApi` to handle messages through the @@ -4700,7 +5178,7 @@ static void setUp( if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; String secretKeyArg = (String) args.get(0); String accountNameArg = (String) args.get(1); @@ -4734,7 +5212,7 @@ public void error(Throwable error) { if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; String secretKeyArg = (String) args.get(0); String qrCodeUrlArg = (String) args.get(1); @@ -4759,33 +5237,6 @@ public void error(Throwable error) { } } } - - private static class GenerateInterfacesCodec extends StandardMessageCodec { - public static final GenerateInterfacesCodec INSTANCE = new GenerateInterfacesCodec(); - - private GenerateInterfacesCodec() {} - - @Override - protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { - switch (type) { - case (byte) 128: - return PigeonMultiFactorInfo.fromList((ArrayList) readValue(buffer)); - default: - return super.readValueOfType(type, buffer); - } - } - - @Override - protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { - if (value instanceof PigeonMultiFactorInfo) { - stream.write(128); - writeValue(stream, ((PigeonMultiFactorInfo) value).toList()); - } else { - super.writeValue(stream, value); - } - } - } - /** * Only used to generate the object interface that are use outside of the Pigeon interface * @@ -4793,11 +5244,11 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { */ public interface GenerateInterfaces { - void pigeonInterface(@NonNull PigeonMultiFactorInfo info); + void pigeonInterface(@NonNull InternalMultiFactorInfo info); /** The codec used by GenerateInterfaces. */ static @NonNull MessageCodec getCodec() { - return GenerateInterfacesCodec.INSTANCE; + return PigeonCodec.INSTANCE; } /** * Sets up an instance of `GenerateInterfaces` to handle messages through the `binaryMessenger`. @@ -4821,15 +5272,14 @@ static void setUp( if (api != null) { channel.setMessageHandler( (message, reply) -> { - ArrayList wrapped = new ArrayList(); + ArrayList wrapped = new ArrayList<>(); ArrayList args = (ArrayList) message; - PigeonMultiFactorInfo infoArg = (PigeonMultiFactorInfo) args.get(0); + InternalMultiFactorInfo infoArg = (InternalMultiFactorInfo) args.get(0); try { api.pigeonInterface(infoArg); wrapped.add(0, null); } catch (Throwable exception) { - ArrayList wrappedError = wrapError(exception); - wrapped = wrappedError; + wrapped = wrapError(exception); } reply.reply(wrapped); }); diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java index f92e6f5b741d..a227be99a49d 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PhoneNumberVerificationStreamHandler.java @@ -50,7 +50,7 @@ interface OnCredentialsListener { public PhoneNumberVerificationStreamHandler( Activity activity, @NonNull GeneratedAndroidFirebaseAuth.AuthPigeonFirebaseApp app, - @NonNull GeneratedAndroidFirebaseAuth.PigeonVerifyPhoneNumberRequest request, + @NonNull GeneratedAndroidFirebaseAuth.InternalVerifyPhoneNumberRequest request, @Nullable MultiFactorSession multiFactorSession, @Nullable PhoneMultiFactorInfo multiFactorInfo, OnCredentialsListener onCredentialsListener) { diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java index a94ae4d796a1..8c510f912e9d 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java @@ -39,17 +39,17 @@ public class PigeonParser { static List manuallyToList( - GeneratedAndroidFirebaseAuth.PigeonUserDetails pigeonUserDetails) { + GeneratedAndroidFirebaseAuth.InternalUserDetails pigeonUserDetails) { List output = new ArrayList<>(); output.add(pigeonUserDetails.getUserInfo().toList()); output.add(pigeonUserDetails.getProviderData()); return output; } - static GeneratedAndroidFirebaseAuth.PigeonUserCredential parseAuthResult( + static GeneratedAndroidFirebaseAuth.InternalUserCredential parseAuthResult( @NonNull AuthResult authResult) { - GeneratedAndroidFirebaseAuth.PigeonUserCredential.Builder builder = - new GeneratedAndroidFirebaseAuth.PigeonUserCredential.Builder(); + GeneratedAndroidFirebaseAuth.InternalUserCredential.Builder builder = + new GeneratedAndroidFirebaseAuth.InternalUserCredential.Builder(); builder.setAdditionalUserInfo(parseAdditionalUserInfo(authResult.getAdditionalUserInfo())); builder.setCredential(parseAuthCredential(authResult.getCredential())); @@ -58,14 +58,14 @@ static GeneratedAndroidFirebaseAuth.PigeonUserCredential parseAuthResult( return builder.build(); } - private static GeneratedAndroidFirebaseAuth.PigeonAdditionalUserInfo parseAdditionalUserInfo( + private static GeneratedAndroidFirebaseAuth.InternalAdditionalUserInfo parseAdditionalUserInfo( AdditionalUserInfo additionalUserInfo) { if (additionalUserInfo == null) { return null; } - GeneratedAndroidFirebaseAuth.PigeonAdditionalUserInfo.Builder builder = - new GeneratedAndroidFirebaseAuth.PigeonAdditionalUserInfo.Builder(); + GeneratedAndroidFirebaseAuth.InternalAdditionalUserInfo.Builder builder = + new GeneratedAndroidFirebaseAuth.InternalAdditionalUserInfo.Builder(); builder.setIsNewUser(additionalUserInfo.isNewUser()); builder.setProfile(additionalUserInfo.getProfile()); @@ -75,7 +75,7 @@ private static GeneratedAndroidFirebaseAuth.PigeonAdditionalUserInfo parseAdditi return builder.build(); } - static GeneratedAndroidFirebaseAuth.PigeonAuthCredential parseAuthCredential( + static GeneratedAndroidFirebaseAuth.InternalAuthCredential parseAuthCredential( AuthCredential authCredential) { if (authCredential == null) { return null; @@ -84,8 +84,8 @@ static GeneratedAndroidFirebaseAuth.PigeonAuthCredential parseAuthCredential( int authCredentialHashCode = authCredential.hashCode(); FlutterFirebaseAuthPlugin.authCredentials.put(authCredentialHashCode, authCredential); - GeneratedAndroidFirebaseAuth.PigeonAuthCredential.Builder builder = - new GeneratedAndroidFirebaseAuth.PigeonAuthCredential.Builder(); + GeneratedAndroidFirebaseAuth.InternalAuthCredential.Builder builder = + new GeneratedAndroidFirebaseAuth.InternalAuthCredential.Builder(); builder.setProviderId(authCredential.getProvider()); builder.setSignInMethod(authCredential.getSignInMethod()); @@ -97,17 +97,17 @@ static GeneratedAndroidFirebaseAuth.PigeonAuthCredential parseAuthCredential( return builder.build(); } - static GeneratedAndroidFirebaseAuth.PigeonUserDetails parseFirebaseUser( + static GeneratedAndroidFirebaseAuth.InternalUserDetails parseFirebaseUser( FirebaseUser firebaseUser) { if (firebaseUser == null) { return null; } - GeneratedAndroidFirebaseAuth.PigeonUserDetails.Builder builder = - new GeneratedAndroidFirebaseAuth.PigeonUserDetails.Builder(); + GeneratedAndroidFirebaseAuth.InternalUserDetails.Builder builder = + new GeneratedAndroidFirebaseAuth.InternalUserDetails.Builder(); - GeneratedAndroidFirebaseAuth.PigeonUserInfo.Builder builderInfo = - new GeneratedAndroidFirebaseAuth.PigeonUserInfo.Builder(); + GeneratedAndroidFirebaseAuth.InternalUserInfo.Builder builderInfo = + new GeneratedAndroidFirebaseAuth.InternalUserInfo.Builder(); builderInfo.setDisplayName(firebaseUser.getDisplayName()); builderInfo.setEmail(firebaseUser.getEmail()); @@ -249,7 +249,7 @@ static AuthCredential getCredential(Map credentialMap) { } static ActionCodeSettings getActionCodeSettings( - @NonNull GeneratedAndroidFirebaseAuth.PigeonActionCodeSettings pigeonActionCodeSettings) { + @NonNull GeneratedAndroidFirebaseAuth.InternalActionCodeSettings pigeonActionCodeSettings) { ActionCodeSettings.Builder builder = ActionCodeSettings.newBuilder(); builder.setUrl(pigeonActionCodeSettings.getUrl()); @@ -278,13 +278,13 @@ static ActionCodeSettings getActionCodeSettings( return builder.build(); } - static List multiFactorInfoToPigeon( + static List multiFactorInfoToPigeon( List hints) { - List pigeonHints = new ArrayList<>(); + List pigeonHints = new ArrayList<>(); for (MultiFactorInfo info : hints) { if (info instanceof PhoneMultiFactorInfo) { pigeonHints.add( - new GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo.Builder() + new GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo.Builder() .setPhoneNumber(((PhoneMultiFactorInfo) info).getPhoneNumber()) .setDisplayName(info.getDisplayName()) .setEnrollmentTimestamp((double) info.getEnrollmentTimestamp()) @@ -294,7 +294,7 @@ static List multiFactorInfoT } else { pigeonHints.add( - new GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo.Builder() + new GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo.Builder() .setDisplayName(info.getDisplayName()) .setEnrollmentTimestamp((double) info.getEnrollmentTimestamp()) .setUid(info.getUid()) @@ -307,18 +307,19 @@ static List multiFactorInfoT static List> multiFactorInfoToMap(List hints) { List> pigeonHints = new ArrayList<>(); - for (GeneratedAndroidFirebaseAuth.PigeonMultiFactorInfo info : multiFactorInfoToPigeon(hints)) { + for (GeneratedAndroidFirebaseAuth.InternalMultiFactorInfo info : + multiFactorInfoToPigeon(hints)) { pigeonHints.add(info.toList()); } return pigeonHints; } - static GeneratedAndroidFirebaseAuth.PigeonActionCodeInfo parseActionCodeResult( + static GeneratedAndroidFirebaseAuth.InternalActionCodeInfo parseActionCodeResult( @NonNull ActionCodeResult actionCodeResult) { - GeneratedAndroidFirebaseAuth.PigeonActionCodeInfo.Builder builder = - new GeneratedAndroidFirebaseAuth.PigeonActionCodeInfo.Builder(); - GeneratedAndroidFirebaseAuth.PigeonActionCodeInfoData.Builder builderData = - new GeneratedAndroidFirebaseAuth.PigeonActionCodeInfoData.Builder(); + GeneratedAndroidFirebaseAuth.InternalActionCodeInfo.Builder builder = + new GeneratedAndroidFirebaseAuth.InternalActionCodeInfo.Builder(); + GeneratedAndroidFirebaseAuth.InternalActionCodeInfoData.Builder builderData = + new GeneratedAndroidFirebaseAuth.InternalActionCodeInfoData.Builder(); int operation = actionCodeResult.getOperation(); @@ -363,10 +364,10 @@ static GeneratedAndroidFirebaseAuth.PigeonActionCodeInfo parseActionCodeResult( return builder.build(); } - static GeneratedAndroidFirebaseAuth.PigeonIdTokenResult parseTokenResult( + static GeneratedAndroidFirebaseAuth.InternalIdTokenResult parseTokenResult( @NonNull GetTokenResult tokenResult) { - final GeneratedAndroidFirebaseAuth.PigeonIdTokenResult.Builder builder = - new GeneratedAndroidFirebaseAuth.PigeonIdTokenResult.Builder(); + final GeneratedAndroidFirebaseAuth.InternalIdTokenResult.Builder builder = + new GeneratedAndroidFirebaseAuth.InternalIdTokenResult.Builder(); builder.setToken(tokenResult.getToken()); builder.setSignInProvider(tokenResult.getSignInProvider()); diff --git a/packages/firebase_auth/firebase_auth/example/android/app/build.gradle b/packages/firebase_auth/firebase_auth/example/android/app/build.gradle index 75b0c370e4d4..db427be91ec5 100644 --- a/packages/firebase_auth/firebase_auth/example/android/app/build.gradle +++ b/packages/firebase_auth/firebase_auth/example/android/app/build.gradle @@ -42,7 +42,7 @@ android { applicationId = "io.flutter.plugins.firebase.auth.example" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdk = 23 + minSdkVersion = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutterVersionCode.toInteger() versionName = flutterVersionName diff --git a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj index 719671ab76f6..4848b09b04b9 100644 --- a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; B6036D992F5B77F0D48D7883 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1026236A547BC5196614E954 /* Pods_Runner.framework */; }; C0151CEAF69E3751D6A8FA78 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2F30ED8EF0A1349EA81AEE1A /* GoogleService-Info.plist */; }; /* End PBXBuildFile section */ @@ -75,6 +76,7 @@ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 3D7BD4B06D0869EA1407E048 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -84,6 +86,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, B6036D992F5B77F0D48D7883 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -146,6 +149,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -198,6 +202,9 @@ 33CC11202044C79F0003C045 /* PBXTargetDependency */, ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 33CC10ED2044A3C60003C045 /* example.app */; productType = "com.apple.product-type.application"; @@ -237,6 +244,9 @@ Base, ); mainGroup = 33CC10E42044A3C60003C045; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -307,12 +317,10 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/firebase_messaging/firebase_messaging_Privacy.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/google_sign_in_ios/google_sign_in_ios_privacy.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/firebase_messaging_Privacy.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/google_sign_in_ios_privacy.bundle", ); runOnlyForDeploymentPostprocessing = 0; @@ -350,50 +358,20 @@ inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", "${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseAuth/FirebaseAuth.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseAuthInterop/FirebaseAuthInterop.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreExtension/FirebaseCoreExtension.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", "${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework", "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", - "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", "${BUILT_PRODUCTS_DIR}/GoogleSignIn/GoogleSignIn.framework", - "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", - "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", "${BUILT_PRODUCTS_DIR}/facebook_auth_desktop/facebook_auth_desktop.framework", "${BUILT_PRODUCTS_DIR}/flutter_secure_storage_macos/flutter_secure_storage_macos.framework", - "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", - "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", - "${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework", - "${BUILT_PRODUCTS_DIR}/url_launcher_macos/url_launcher_macos.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuth.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuthInterop.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleSignIn.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/facebook_auth_desktop.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage_macos.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_macos.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -721,6 +699,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index bfbc9cb8ef3c..126b4eb8ea7d 100644 --- a/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_auth/firebase_auth/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m index 8247abf829da..606dda68176d 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTFirebaseAuthPlugin.m @@ -95,7 +95,7 @@ @interface FLTFirebaseAuthPlugin () @property BOOL isReauthenticatingWithApple; @property(strong, nonatomic) NSString *currentNonce; @property(strong, nonatomic) void (^appleCompletion) - (PigeonUserCredential *_Nullable, FlutterError *_Nullable); + (InternalUserCredential *_Nullable, FlutterError *_Nullable); @property(strong, nonatomic) AuthPigeonFirebaseApp *appleArguments; /// YES while an `ASAuthorizationController` Sign in with Apple flow is active. @property(nonatomic, assign) BOOL appleSignInRequestInFlight; @@ -380,7 +380,7 @@ - (NSString *)stringBySha256HashingString:(NSString *)input { static void handleSignInWithApple(FLTFirebaseAuthPlugin *object, FIRAuthDataResult *authResult, NSString *authorizationCode, NSError *error) { - void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + void (^completion)(InternalUserCredential *_Nullable, FlutterError *_Nullable) = object.appleCompletion; if (completion == nil) { object.appleSignInRequestInFlight = NO; @@ -417,7 +417,7 @@ - (void)authorizationController:(ASAuthorizationController *)controller if (appleIDCredential.identityToken == nil) { NSLog(@"Unable to fetch identity token."); - void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + void (^completion)(InternalUserCredential *_Nullable, FlutterError *_Nullable) = self.appleCompletion; self.appleCompletion = nil; self.appleSignInRequestInFlight = NO; @@ -448,7 +448,7 @@ - (void)authorizationController:(ASAuthorizationController *)controller if (self.isReauthenticatingWithApple == YES) { self.isReauthenticatingWithApple = NO; - void (^capturedCompletion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + void (^capturedCompletion)(InternalUserCredential *_Nullable, FlutterError *_Nullable) = self.appleCompletion; [[FIRAuth.auth currentUser] reauthenticateWithCredential:credential @@ -459,7 +459,7 @@ - (void)authorizationController:(ASAuthorizationController *)controller } else if (self.linkWithAppleUser != nil) { FIRUser *userToLink = self.linkWithAppleUser; - void (^capturedCompletion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + void (^capturedCompletion)(InternalUserCredential *_Nullable, FlutterError *_Nullable) = self.appleCompletion; [userToLink linkWithCredential:credential completion:^(FIRAuthDataResult *authResult, NSError *error) { @@ -470,7 +470,7 @@ - (void)authorizationController:(ASAuthorizationController *)controller } else { FIRAuth *signInAuth = self.signInWithAppleAuth != nil ? self.signInWithAppleAuth : FIRAuth.auth; - void (^capturedCompletion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + void (^capturedCompletion)(InternalUserCredential *_Nullable, FlutterError *_Nullable) = self.appleCompletion; [signInAuth signInWithCredential:credential completion:^(FIRAuthDataResult *_Nullable authResult, @@ -480,7 +480,7 @@ - (void)authorizationController:(ASAuthorizationController *)controller }]; } } else { - void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + void (^completion)(InternalUserCredential *_Nullable, FlutterError *_Nullable) = self.appleCompletion; self.appleCompletion = nil; self.appleSignInRequestInFlight = NO; @@ -494,7 +494,7 @@ - (void)authorizationController:(ASAuthorizationController *)controller - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(macos(10.15), ios(13.0)) { - void (^completion)(PigeonUserCredential *_Nullable, FlutterError *_Nullable) = + void (^completion)(InternalUserCredential *_Nullable, FlutterError *_Nullable) = self.appleCompletion; self.appleCompletion = nil; self.appleSignInRequestInFlight = NO; @@ -537,7 +537,7 @@ - (void)authorizationController:(ASAuthorizationController *)controller } } -- (void)handleInternalError:(nonnull void (^)(PigeonUserCredential *_Nullable, +- (void)handleInternalError:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion withError:(NSError *)error { const NSError *underlyingError = error.userInfo[@"NSUnderlyingError"]; @@ -555,7 +555,7 @@ - (void)handleInternalError:(nonnull void (^)(PigeonUserCredential *_Nullable, } - (void)handleMultiFactorError:(AuthPigeonFirebaseApp *)app - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion withError:(NSError *_Nullable)error { FIRMultiFactorResolver *resolver = @@ -579,7 +579,7 @@ - (void)handleMultiFactorError:(AuthPigeonFirebaseApp *)app phoneNumber = phoneFactorInfo.phoneNumber; } - PigeonMultiFactorInfo *object = [PigeonMultiFactorInfo + InternalMultiFactorInfo *object = [InternalMultiFactorInfo makeWithDisplayName:multiFactorInfo.displayName enrollmentTimestamp:multiFactorInfo.enrollmentDate.timeIntervalSince1970 factorId:multiFactorInfo.factorID @@ -601,8 +601,8 @@ - (void)handleMultiFactorError:(AuthPigeonFirebaseApp *)app } static void launchAppleSignInRequest(FLTFirebaseAuthPlugin *object, AuthPigeonFirebaseApp *app, - PigeonSignInProvider *signInProvider, - void (^_Nonnull completion)(PigeonUserCredential *_Nullable, + InternalSignInProvider *signInProvider, + void (^_Nonnull completion)(InternalUserCredential *_Nullable, FlutterError *_Nullable)) { if (@available(iOS 13.0, macOS 10.15, *)) { if (object.appleSignInRequestInFlight) { @@ -645,7 +645,7 @@ static void launchAppleSignInRequest(FLTFirebaseAuthPlugin *object, AuthPigeonFi static void handleAppleAuthResult(FLTFirebaseAuthPlugin *object, AuthPigeonFirebaseApp *app, FIRAuth *auth, FIRAuthCredential *credentials, NSError *error, - void (^_Nonnull completion)(PigeonUserCredential *_Nullable, + void (^_Nonnull completion)(InternalUserCredential *_Nullable, FlutterError *_Nullable)) { if (error) { if (error.code == FIRAuthErrorCodeSecondFactorRequired) { @@ -928,7 +928,7 @@ - (nonnull ASPresentationAnchor)presentationAnchorForAuthorizationController: } - (void)enrollPhoneApp:(nonnull AuthPigeonFirebaseApp *)app - assertion:(nonnull PigeonPhoneMultiFactorAssertion *)assertion + assertion:(nonnull InternalPhoneMultiFactorAssertion *)assertion displayName:(nullable NSString *)displayName completion:(nonnull void (^)(FlutterError *_Nullable))completion { #if TARGET_OS_OSX @@ -962,13 +962,13 @@ - (void)enrollPhoneApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)getEnrolledFactorsApp:(nonnull AuthPigeonFirebaseApp *)app - completion:(nonnull void (^)(NSArray *_Nullable, + completion:(nonnull void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion { FIRMultiFactor *multiFactor = [self getAppMultiFactorFromPigeon:app]; NSArray *enrolledFactors = [multiFactor enrolledFactors]; - NSMutableArray *results = [NSMutableArray array]; + NSMutableArray *results = [NSMutableArray array]; for (FIRMultiFactorInfo *multiFactorInfo in enrolledFactors) { NSString *phoneNumber; @@ -977,7 +977,7 @@ - (void)getEnrolledFactorsApp:(nonnull AuthPigeonFirebaseApp *)app phoneNumber = phoneFactorInfo.phoneNumber; } - [results addObject:[PigeonMultiFactorInfo + [results addObject:[InternalMultiFactorInfo makeWithDisplayName:multiFactorInfo.displayName enrollmentTimestamp:multiFactorInfo.enrollmentDate.timeIntervalSince1970 factorId:multiFactorInfo.factorID @@ -989,7 +989,7 @@ - (void)getEnrolledFactorsApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)getSessionApp:(nonnull AuthPigeonFirebaseApp *)app - completion:(nonnull void (^)(PigeonMultiFactorSession *_Nullable, + completion:(nonnull void (^)(InternalMultiFactorSession *_Nullable, FlutterError *_Nullable))completion { FIRMultiFactor *multiFactor = [self getAppMultiFactorFromPigeon:app]; [multiFactor getSessionWithCompletion:^(FIRMultiFactorSession *_Nullable session, @@ -997,7 +997,7 @@ - (void)getSessionApp:(nonnull AuthPigeonFirebaseApp *)app NSString *UUID = [[NSUUID UUID] UUIDString]; self->_multiFactorSessionMap[UUID] = session; - PigeonMultiFactorSession *pigeonSession = [PigeonMultiFactorSession makeWithId:UUID]; + InternalMultiFactorSession *pigeonSession = [InternalMultiFactorSession makeWithId:UUID]; completion(pigeonSession, nil); }]; } @@ -1040,9 +1040,9 @@ - (void)enrollTotpApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)resolveSignInResolverId:(nonnull NSString *)resolverId - assertion:(nullable PigeonPhoneMultiFactorAssertion *)assertion + assertion:(nullable InternalPhoneMultiFactorAssertion *)assertion totpAssertionId:(nullable NSString *)totpAssertionId - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRMultiFactorResolver *resolver = _multiFactorResolverMap[resolverId]; @@ -1082,7 +1082,7 @@ - (void)resolveSignInResolverId:(nonnull NSString *)resolverId } - (void)generateSecretSessionId:(nonnull NSString *)sessionId - completion:(nonnull void (^)(PigeonTotpSecret *_Nullable, + completion:(nonnull void (^)(InternalTotpSecret *_Nullable, FlutterError *_Nullable))completion { FIRMultiFactorSession *multiFactorSession = _multiFactorSessionMap[sessionId]; @@ -1175,9 +1175,20 @@ - (void)revokeTokenWithAuthorizationCodeApp:(nonnull AuthPigeonFirebaseApp *)app }]; } +- (void)revokeAccessTokenApp:(nonnull AuthPigeonFirebaseApp *)app + accessToken:(nonnull NSString *)accessToken + completion:(nonnull void (^)(FlutterError *_Nullable))completion { + // `revokeAccessToken(_:)` is currently Android-only on the Firebase SDK. + // On Apple platforms use `revokeTokenWithAuthorizationCode:` instead. + completion([FlutterError errorWithCode:@"unsupported-platform-operation" + message:@"revokeAccessToken is not supported on iOS/macOS. " + @"Use revokeTokenWithAuthorizationCode instead." + details:nil]); +} + - (void)checkActionCodeApp:(nonnull AuthPigeonFirebaseApp *)app code:(nonnull NSString *)code - completion:(nonnull void (^)(PigeonActionCodeInfo *_Nullable, + completion:(nonnull void (^)(InternalActionCodeInfo *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; [auth checkActionCode:code @@ -1185,7 +1196,7 @@ - (void)checkActionCodeApp:(nonnull AuthPigeonFirebaseApp *)app if (error != nil) { completion(nil, [FLTFirebaseAuthPlugin convertToFlutterError:error]); } else { - PigeonActionCodeInfo *result = [self parseActionCode:info]; + InternalActionCodeInfo *result = [self parseActionCode:info]; if (result.operation == ActionCodeInfoOperationUnknown) { // Workaround: Firebase iOS SDK >=11.12.0 returns .unknown because // actionCodeOperation(forRequestType:) only matches camelCase but the @@ -1203,9 +1214,9 @@ - (void)checkActionCodeApp:(nonnull AuthPigeonFirebaseApp *)app }]; } -- (PigeonActionCodeInfo *_Nullable)parseActionCode:(nonnull FIRActionCodeInfo *)info { - PigeonActionCodeInfoData *data = [PigeonActionCodeInfoData makeWithEmail:info.email - previousEmail:info.previousEmail]; +- (InternalActionCodeInfo *_Nullable)parseActionCode:(nonnull FIRActionCodeInfo *)info { + InternalActionCodeInfoData *data = [InternalActionCodeInfoData makeWithEmail:info.email + previousEmail:info.previousEmail]; ActionCodeInfoOperation operation; @@ -1225,7 +1236,7 @@ - (PigeonActionCodeInfo *_Nullable)parseActionCode:(nonnull FIRActionCodeInfo *) operation = ActionCodeInfoOperationUnknown; } - return [PigeonActionCodeInfo makeWithOperation:operation data:data]; + return [InternalActionCodeInfo makeWithOperation:operation data:data]; } /// Maps a raw requestType string (either camelCase or SCREAMING_SNAKE_CASE) to @@ -1259,8 +1270,8 @@ + (ActionCodeInfoOperation)operationFromRequestType:(nullable NSString *)request /// result if the REST call fails for any reason. - (void)resolveActionCodeOperationForApp:(nonnull AuthPigeonFirebaseApp *)app code:(nonnull NSString *)code - fallbackInfo:(nonnull PigeonActionCodeInfo *)fallbackInfo - completion:(nonnull void (^)(PigeonActionCodeInfo *_Nullable, + fallbackInfo:(nonnull InternalActionCodeInfo *)fallbackInfo + completion:(nonnull void (^)(InternalActionCodeInfo *_Nullable, FlutterError *_Nullable))completion { FIRApp *firebaseApp = [FLTFirebasePlugin firebaseAppNamed:app.appName]; NSString *apiKey = firebaseApp.options.APIKey; @@ -1304,7 +1315,7 @@ - (void)resolveActionCodeOperationForApp:(nonnull AuthPigeonFirebaseApp *)app [FLTFirebaseAuthPlugin operationFromRequestType:json[@"requestType"]]; if (operation != ActionCodeInfoOperationUnknown) { - completion([PigeonActionCodeInfo makeWithOperation:operation data:fallbackInfo.data], + completion([InternalActionCodeInfo makeWithOperation:operation data:fallbackInfo.data], nil); } else { completion(fallbackInfo, nil); @@ -1332,7 +1343,7 @@ - (void)confirmPasswordResetApp:(nonnull AuthPigeonFirebaseApp *)app - (void)createUserWithEmailAndPasswordApp:(nonnull AuthPigeonFirebaseApp *)app email:(nonnull NSString *)email password:(nonnull NSString *)password - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; [auth createUserWithEmail:email @@ -1411,7 +1422,7 @@ - (void)registerIdTokenListenerApp:(nonnull AuthPigeonFirebaseApp *)app - (void)sendPasswordResetEmailApp:(nonnull AuthPigeonFirebaseApp *)app email:(nonnull NSString *)email - actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(nullable InternalActionCodeSettings *)actionCodeSettings completion:(nonnull void (^)(FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; if (actionCodeSettings != nil) { @@ -1439,7 +1450,7 @@ - (void)sendPasswordResetEmailApp:(nonnull AuthPigeonFirebaseApp *)app - (void)sendSignInLinkToEmailApp:(nonnull AuthPigeonFirebaseApp *)app email:(nonnull NSString *)email - actionCodeSettings:(nonnull PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(nonnull InternalActionCodeSettings *)actionCodeSettings completion:(nonnull void (^)(FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; [auth sendSignInLinkToEmail:email @@ -1448,7 +1459,7 @@ - (void)sendSignInLinkToEmailApp:(nonnull AuthPigeonFirebaseApp *)app if (error != nil) { if (error.code == FIRAuthErrorCodeInternalError) { [self - handleInternalError:^(PigeonUserCredential *_Nullable creds, + handleInternalError:^(InternalUserCredential *_Nullable creds, FlutterError *_Nullable internalError) { completion(internalError); } @@ -1478,7 +1489,7 @@ - (void)setLanguageCodeApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)setSettingsApp:(nonnull AuthPigeonFirebaseApp *)app - settings:(nonnull PigeonFirebaseAuthSettings *)settings + settings:(nonnull InternalFirebaseAuthSettings *)settings completion:(nonnull void (^)(FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; @@ -1506,7 +1517,7 @@ - (void)setSettingsApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)signInAnonymouslyApp:(nonnull AuthPigeonFirebaseApp *)app - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; [auth signInAnonymouslyWithCompletion:^(FIRAuthDataResult *authResult, NSError *error) { @@ -1522,7 +1533,7 @@ - (void)signInAnonymouslyApp:(nonnull AuthPigeonFirebaseApp *)app - (void)signInWithCredentialApp:(nonnull AuthPigeonFirebaseApp *)app input:(nonnull NSDictionary *)input - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; [self @@ -1603,7 +1614,7 @@ - (void)signInWithCredentialApp:(nonnull AuthPigeonFirebaseApp *)app - (void)signInWithCustomTokenApp:(nonnull AuthPigeonFirebaseApp *)app token:(nonnull NSString *)token - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; @@ -1628,7 +1639,7 @@ - (void)signInWithCustomTokenApp:(nonnull AuthPigeonFirebaseApp *)app - (void)signInWithEmailAndPasswordApp:(nonnull AuthPigeonFirebaseApp *)app email:(nonnull NSString *)email password:(nonnull NSString *)password - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; [auth signInWithEmail:email @@ -1653,7 +1664,7 @@ - (void)signInWithEmailAndPasswordApp:(nonnull AuthPigeonFirebaseApp *)app - (void)signInWithEmailLinkApp:(nonnull AuthPigeonFirebaseApp *)app email:(nonnull NSString *)email emailLink:(nonnull NSString *)emailLink - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; [auth signInWithEmail:email @@ -1676,8 +1687,8 @@ - (void)signInWithEmailLinkApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)signInWithProviderApp:(nonnull AuthPigeonFirebaseApp *)app - signInProvider:(nonnull PigeonSignInProvider *)signInProvider - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + signInProvider:(nonnull InternalSignInProvider *)signInProvider + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; @@ -1767,7 +1778,7 @@ - (void)verifyPasswordResetCodeApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)verifyPhoneNumberApp:(nonnull AuthPigeonFirebaseApp *)app - request:(nonnull PigeonVerifyPhoneNumberRequest *)request + request:(nonnull InternalVerifyPhoneNumberRequest *)request completion: (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { #if TARGET_OS_OSX @@ -1846,7 +1857,7 @@ - (void)deleteApp:(nonnull AuthPigeonFirebaseApp *)app - (void)getIdTokenApp:(nonnull AuthPigeonFirebaseApp *)app forceRefresh:(BOOL)forceRefresh - completion:(nonnull void (^)(PigeonIdTokenResult *_Nullable, + completion:(nonnull void (^)(InternalIdTokenResult *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -1871,7 +1882,7 @@ - (void)getIdTokenApp:(nonnull AuthPigeonFirebaseApp *)app - (void)linkWithCredentialApp:(nonnull AuthPigeonFirebaseApp *)app input:(nonnull NSDictionary *)input - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -1926,8 +1937,8 @@ - (void)linkWithCredentialApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)linkWithProviderApp:(nonnull AuthPigeonFirebaseApp *)app - signInProvider:(nonnull PigeonSignInProvider *)signInProvider - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + signInProvider:(nonnull InternalSignInProvider *)signInProvider + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -1979,7 +1990,7 @@ - (void)linkWithProviderApp:(nonnull AuthPigeonFirebaseApp *)app - (void)reauthenticateWithCredentialApp:(nonnull AuthPigeonFirebaseApp *)app input:(nonnull NSDictionary *)input - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -2037,8 +2048,8 @@ - (void)reauthenticateWithCredentialApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)reauthenticateWithProviderApp:(nonnull AuthPigeonFirebaseApp *)app - signInProvider:(nonnull PigeonSignInProvider *)signInProvider - completion:(nonnull void (^)(PigeonUserCredential *_Nullable, + signInProvider:(nonnull InternalSignInProvider *)signInProvider + completion:(nonnull void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -2080,7 +2091,7 @@ - (void)reauthenticateWithProviderApp:(nonnull AuthPigeonFirebaseApp *)app - (void)reloadApp:(nonnull AuthPigeonFirebaseApp *)app completion: - (nonnull void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion { + (nonnull void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; if (currentUser == nil) { @@ -2100,7 +2111,7 @@ - (void)reloadApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)sendEmailVerificationApp:(nonnull AuthPigeonFirebaseApp *)app - actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(nullable InternalActionCodeSettings *)actionCodeSettings completion:(nonnull void (^)(FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -2127,8 +2138,8 @@ - (void)sendEmailVerificationApp:(nonnull AuthPigeonFirebaseApp *)app - (void)unlinkApp:(nonnull AuthPigeonFirebaseApp *)app providerId:(nonnull NSString *)providerId - completion: - (nonnull void (^)(PigeonUserCredential *_Nullable, FlutterError *_Nullable))completion { + completion:(nonnull void (^)(InternalUserCredential *_Nullable, + FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; if (currentUser == nil) { @@ -2150,7 +2161,7 @@ - (void)unlinkApp:(nonnull AuthPigeonFirebaseApp *)app - (void)updateEmailApp:(nonnull AuthPigeonFirebaseApp *)app newEmail:(nonnull NSString *)newEmail - completion:(nonnull void (^)(PigeonUserDetails *_Nullable, + completion:(nonnull void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -2179,7 +2190,7 @@ - (void)updateEmailApp:(nonnull AuthPigeonFirebaseApp *)app - (void)updatePasswordApp:(nonnull AuthPigeonFirebaseApp *)app newPassword:(nonnull NSString *)newPassword - completion:(nonnull void (^)(PigeonUserDetails *_Nullable, + completion:(nonnull void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -2209,7 +2220,7 @@ - (void)updatePasswordApp:(nonnull AuthPigeonFirebaseApp *)app - (void)updatePhoneNumberApp:(nonnull AuthPigeonFirebaseApp *)app input:(nonnull NSDictionary *)input - completion:(nonnull void (^)(PigeonUserDetails *_Nullable, + completion:(nonnull void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion { #if TARGET_OS_IPHONE FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; @@ -2273,8 +2284,8 @@ - (void)updatePhoneNumberApp:(nonnull AuthPigeonFirebaseApp *)app } - (void)updateProfileApp:(nonnull AuthPigeonFirebaseApp *)app - profile:(nonnull PigeonUserProfile *)profile - completion:(nonnull void (^)(PigeonUserDetails *_Nullable, + profile:(nonnull InternalUserProfile *)profile + completion:(nonnull void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; @@ -2319,7 +2330,7 @@ - (void)updateProfileApp:(nonnull AuthPigeonFirebaseApp *)app - (void)verifyBeforeUpdateEmailApp:(nonnull AuthPigeonFirebaseApp *)app newEmail:(nonnull NSString *)newEmail - actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(nullable InternalActionCodeSettings *)actionCodeSettings completion:(nonnull void (^)(FlutterError *_Nullable))completion { FIRAuth *auth = [self getFIRAuthFromAppNameFromPigeon:app]; FIRUser *currentUser = auth.currentUser; diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTPhoneNumberVerificationStreamHandler.m b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTPhoneNumberVerificationStreamHandler.m index 69b9d7dea14d..511d2caa8841 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTPhoneNumberVerificationStreamHandler.m +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/FLTPhoneNumberVerificationStreamHandler.m @@ -18,7 +18,7 @@ @implementation FLTPhoneNumberVerificationStreamHandler { } #if TARGET_OS_OSX -- (instancetype)initWithAuth:(id)auth request:(PigeonVerifyPhoneNumberRequest *)request { +- (instancetype)initWithAuth:(id)auth request:(InternalVerifyPhoneNumberRequest *)request { self = [super init]; if (self) { _auth = auth; @@ -28,7 +28,7 @@ - (instancetype)initWithAuth:(id)auth request:(PigeonVerifyPhoneNumberRequest *) } #else - (instancetype)initWithAuth:(id)auth - request:(PigeonVerifyPhoneNumberRequest *)request + request:(InternalVerifyPhoneNumberRequest *)request session:(FIRMultiFactorSession *)session factorInfo:(FIRPhoneMultiFactorInfo *)factorInfo { self = [super init]; diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/PigeonParser.m b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/PigeonParser.m index f8ef1b77493c..8d7a7b1c2f0e 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/PigeonParser.m +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/PigeonParser.m @@ -10,30 +10,30 @@ @implementation PigeonParser -+ (PigeonUserCredential *) ++ (InternalUserCredential *) getPigeonUserCredentialFromAuthResult:(nonnull FIRAuthDataResult *)authResult authorizationCode:(nullable NSString *)authorizationCode { - return [PigeonUserCredential + return [InternalUserCredential makeWithUser:[self getPigeonDetails:authResult.user] additionalUserInfo:[self getPigeonAdditionalUserInfo:authResult.additionalUserInfo authorizationCode:authorizationCode] credential:[self getPigeonAuthCredential:authResult.credential token:nil]]; } -+ (PigeonUserCredential *)getPigeonUserCredentialFromFIRUser:(nonnull FIRUser *)user { - return [PigeonUserCredential makeWithUser:[self getPigeonDetails:user] - additionalUserInfo:nil - credential:nil]; ++ (InternalUserCredential *)getPigeonUserCredentialFromFIRUser:(nonnull FIRUser *)user { + return [InternalUserCredential makeWithUser:[self getPigeonDetails:user] + additionalUserInfo:nil + credential:nil]; } -+ (PigeonUserDetails *)getPigeonDetails:(nonnull FIRUser *)user { - return [PigeonUserDetails makeWithUserInfo:[self getPigeonUserInfo:user] - providerData:[self getProviderData:user.providerData]]; ++ (InternalUserDetails *)getPigeonDetails:(nonnull FIRUser *)user { + return [InternalUserDetails makeWithUserInfo:[self getPigeonUserInfo:user] + providerData:[self getProviderData:user.providerData]]; } -+ (PigeonUserInfo *)getPigeonUserInfo:(nonnull FIRUser *)user { ++ (InternalUserInfo *)getPigeonUserInfo:(nonnull FIRUser *)user { NSString *photoUrlString = user.photoURL.absoluteString; - return [PigeonUserInfo + return [InternalUserInfo makeWithUid:user.uid email:user.email displayName:user.displayName @@ -74,25 +74,26 @@ + (PigeonUserInfo *)getPigeonUserInfo:(nonnull FIRUser *)user { return [dataArray copy]; } -+ (PigeonAdditionalUserInfo *)getPigeonAdditionalUserInfo:(nonnull FIRAdditionalUserInfo *)userInfo - authorizationCode:(nullable NSString *)authorizationCode { - return [PigeonAdditionalUserInfo makeWithIsNewUser:userInfo.isNewUser - providerId:userInfo.providerID - username:userInfo.username - authorizationCode:authorizationCode - profile:userInfo.profile]; ++ (InternalAdditionalUserInfo *)getPigeonAdditionalUserInfo: + (nonnull FIRAdditionalUserInfo *)userInfo + authorizationCode:(nullable NSString *)authorizationCode { + return [InternalAdditionalUserInfo makeWithIsNewUser:userInfo.isNewUser + providerId:userInfo.providerID + username:userInfo.username + authorizationCode:authorizationCode + profile:userInfo.profile]; } -+ (PigeonTotpSecret *)getPigeonTotpSecret:(FIRTOTPSecret *)secret { - return [PigeonTotpSecret makeWithCodeIntervalSeconds:nil - codeLength:nil - enrollmentCompletionDeadline:nil - hashingAlgorithm:nil - secretKey:secret.sharedSecretKey]; ++ (InternalTotpSecret *)getPigeonTotpSecret:(FIRTOTPSecret *)secret { + return [InternalTotpSecret makeWithCodeIntervalSeconds:nil + codeLength:nil + enrollmentCompletionDeadline:nil + hashingAlgorithm:nil + secretKey:secret.sharedSecretKey]; } -+ (PigeonAuthCredential *)getPigeonAuthCredential:(FIRAuthCredential *)authCredential - token:(NSNumber *_Nullable)token { ++ (InternalAuthCredential *)getPigeonAuthCredential:(FIRAuthCredential *)authCredential + token:(NSNumber *_Nullable)token { if (authCredential == nil) { return nil; } @@ -110,14 +111,14 @@ + (PigeonAuthCredential *)getPigeonAuthCredential:(FIRAuthCredential *)authCrede NSUInteger nativeId = token != nil ? [token unsignedLongValue] : (NSUInteger)[authCredential hash]; - return [PigeonAuthCredential makeWithProviderId:authCredential.provider - signInMethod:authCredential.provider - nativeId:nativeId - accessToken:accessToken ?: nil]; + return [InternalAuthCredential makeWithProviderId:authCredential.provider + signInMethod:authCredential.provider + nativeId:nativeId + accessToken:accessToken ?: nil]; } + (FIRActionCodeSettings *_Nullable)parseActionCodeSettings: - (nullable PigeonActionCodeSettings *)settings { + (nullable InternalActionCodeSettings *)settings { if (settings == nil) { return nil; } @@ -141,21 +142,21 @@ + (FIRActionCodeSettings *_Nullable)parseActionCodeSettings: return codeSettings; } -+ (PigeonIdTokenResult *)parseIdTokenResult:(FIRAuthTokenResult *)tokenResult { ++ (InternalIdTokenResult *)parseIdTokenResult:(FIRAuthTokenResult *)tokenResult { long expirationTimestamp = (long)[tokenResult.expirationDate timeIntervalSince1970] * 1000; long authTimestamp = (long)[tokenResult.authDate timeIntervalSince1970] * 1000; long issuedAtTimestamp = (long)[tokenResult.issuedAtDate timeIntervalSince1970] * 1000; - return [PigeonIdTokenResult makeWithToken:tokenResult.token - expirationTimestamp:@(expirationTimestamp) - authTimestamp:@(authTimestamp) - issuedAtTimestamp:@(issuedAtTimestamp) - signInProvider:tokenResult.signInProvider - claims:tokenResult.claims - signInSecondFactor:tokenResult.signInSecondFactor]; + return [InternalIdTokenResult makeWithToken:tokenResult.token + expirationTimestamp:@(expirationTimestamp) + authTimestamp:@(authTimestamp) + issuedAtTimestamp:@(issuedAtTimestamp) + signInProvider:tokenResult.signInProvider + claims:tokenResult.claims + signInSecondFactor:tokenResult.signInSecondFactor]; } -+ (NSArray *_Nonnull)getManualList:(nonnull PigeonUserDetails *)userDetails { ++ (NSArray *_Nonnull)getManualList:(nonnull InternalUserDetails *)userDetails { NSMutableArray *output = [NSMutableArray array]; id userInfoList = [[userDetails userInfo] toList]; diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m index 365ff70d690c..d110643c17fc 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m @@ -1,22 +1,109 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v19.0.0), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import "include/Public/firebase_auth_messages.g.h" +#import "firebase_auth_messages.g.h" #if TARGET_OS_OSX -#import +@import FlutterMacOS; #else -#import +@import Flutter; #endif -#if !__has_feature(objc_arc) -#error File requires ARC to be enabled. -#endif +static BOOL __attribute__((unused)) FLTPigeonDeepEquals(id _Nullable a, id _Nullable b) { + if (a == b) { + return YES; + } + if (a == nil) { + return b == [NSNull null]; + } + if (b == nil) { + return a == [NSNull null]; + } + if ([a isKindOfClass:[NSNumber class]] && [b isKindOfClass:[NSNumber class]]) { + return + [a isEqual:b] || (isnan([(NSNumber *)a doubleValue]) && isnan([(NSNumber *)b doubleValue])); + } + if ([a isKindOfClass:[NSArray class]] && [b isKindOfClass:[NSArray class]]) { + NSArray *arrayA = (NSArray *)a; + NSArray *arrayB = (NSArray *)b; + if (arrayA.count != arrayB.count) { + return NO; + } + for (NSUInteger i = 0; i < arrayA.count; i++) { + if (!FLTPigeonDeepEquals(arrayA[i], arrayB[i])) { + return NO; + } + } + return YES; + } + if ([a isKindOfClass:[NSDictionary class]] && [b isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictA = (NSDictionary *)a; + NSDictionary *dictB = (NSDictionary *)b; + if (dictA.count != dictB.count) { + return NO; + } + for (id keyA in dictA) { + id valueA = dictA[keyA]; + BOOL found = NO; + for (id keyB in dictB) { + if (FLTPigeonDeepEquals(keyA, keyB)) { + id valueB = dictB[keyB]; + if (FLTPigeonDeepEquals(valueA, valueB)) { + found = YES; + break; + } else { + return NO; + } + } + } + if (!found) { + return NO; + } + } + return YES; + } + return [a isEqual:b]; +} + +static NSUInteger __attribute__((unused)) FLTPigeonDeepHash(id _Nullable value) { + if (value == nil || value == (id)[NSNull null]) { + return 0; + } + if ([value isKindOfClass:[NSNumber class]]) { + NSNumber *n = (NSNumber *)value; + double d = n.doubleValue; + if (isnan(d)) { + // Normalize NaN to a consistent hash. + return (NSUInteger)0x7FF8000000000000; + } + if (d == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + d = 0.0; + } + return @(d).hash; + } + if ([value isKindOfClass:[NSArray class]]) { + NSUInteger result = 1; + for (id item in (NSArray *)value) { + result = result * 31 + FLTPigeonDeepHash(item); + } + return result; + } + if ([value isKindOfClass:[NSDictionary class]]) { + NSUInteger result = 0; + NSDictionary *dict = (NSDictionary *)value; + for (id key in dict) { + result += ((FLTPigeonDeepHash(key) * 31) ^ FLTPigeonDeepHash(dict[key])); + } + return result; + } + return [value hash]; +} -static NSArray *wrapResult(id result, FlutterError *error) { +static NSArray *wrapResult(id result, FlutterError *error) { if (error) { return @[ error.code ?: [NSNull null], error.message ?: [NSNull null], error.details ?: [NSNull null] @@ -25,7 +112,7 @@ return @[ result ?: [NSNull null] ]; } -static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { +static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { id result = array[key]; return (result == [NSNull null]) ? nil : result; } @@ -42,167 +129,209 @@ - (instancetype)initWithValue:(ActionCodeInfoOperation)value { } @end -@interface PigeonMultiFactorSession () -+ (PigeonMultiFactorSession *)fromList:(NSArray *)list; -+ (nullable PigeonMultiFactorSession *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalMultiFactorSession () ++ (InternalMultiFactorSession *)fromList:(NSArray *)list; ++ (nullable InternalMultiFactorSession *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonPhoneMultiFactorAssertion () -+ (PigeonPhoneMultiFactorAssertion *)fromList:(NSArray *)list; -+ (nullable PigeonPhoneMultiFactorAssertion *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalPhoneMultiFactorAssertion () ++ (InternalPhoneMultiFactorAssertion *)fromList:(NSArray *)list; ++ (nullable InternalPhoneMultiFactorAssertion *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonMultiFactorInfo () -+ (PigeonMultiFactorInfo *)fromList:(NSArray *)list; -+ (nullable PigeonMultiFactorInfo *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalMultiFactorInfo () ++ (InternalMultiFactorInfo *)fromList:(NSArray *)list; ++ (nullable InternalMultiFactorInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end @interface AuthPigeonFirebaseApp () -+ (AuthPigeonFirebaseApp *)fromList:(NSArray *)list; -+ (nullable AuthPigeonFirebaseApp *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; ++ (AuthPigeonFirebaseApp *)fromList:(NSArray *)list; ++ (nullable AuthPigeonFirebaseApp *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; +@end + +@interface InternalActionCodeInfoData () ++ (InternalActionCodeInfoData *)fromList:(NSArray *)list; ++ (nullable InternalActionCodeInfoData *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonActionCodeInfoData () -+ (PigeonActionCodeInfoData *)fromList:(NSArray *)list; -+ (nullable PigeonActionCodeInfoData *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalActionCodeInfo () ++ (InternalActionCodeInfo *)fromList:(NSArray *)list; ++ (nullable InternalActionCodeInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonActionCodeInfo () -+ (PigeonActionCodeInfo *)fromList:(NSArray *)list; -+ (nullable PigeonActionCodeInfo *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalAdditionalUserInfo () ++ (InternalAdditionalUserInfo *)fromList:(NSArray *)list; ++ (nullable InternalAdditionalUserInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonAdditionalUserInfo () -+ (PigeonAdditionalUserInfo *)fromList:(NSArray *)list; -+ (nullable PigeonAdditionalUserInfo *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalAuthCredential () ++ (InternalAuthCredential *)fromList:(NSArray *)list; ++ (nullable InternalAuthCredential *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonAuthCredential () -+ (PigeonAuthCredential *)fromList:(NSArray *)list; -+ (nullable PigeonAuthCredential *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalUserInfo () ++ (InternalUserInfo *)fromList:(NSArray *)list; ++ (nullable InternalUserInfo *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonUserInfo () -+ (PigeonUserInfo *)fromList:(NSArray *)list; -+ (nullable PigeonUserInfo *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalUserDetails () ++ (InternalUserDetails *)fromList:(NSArray *)list; ++ (nullable InternalUserDetails *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonUserDetails () -+ (PigeonUserDetails *)fromList:(NSArray *)list; -+ (nullable PigeonUserDetails *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalUserCredential () ++ (InternalUserCredential *)fromList:(NSArray *)list; ++ (nullable InternalUserCredential *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonUserCredential () -+ (PigeonUserCredential *)fromList:(NSArray *)list; -+ (nullable PigeonUserCredential *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalAuthCredentialInput () ++ (InternalAuthCredentialInput *)fromList:(NSArray *)list; ++ (nullable InternalAuthCredentialInput *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonActionCodeSettings () -+ (PigeonActionCodeSettings *)fromList:(NSArray *)list; -+ (nullable PigeonActionCodeSettings *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalActionCodeSettings () ++ (InternalActionCodeSettings *)fromList:(NSArray *)list; ++ (nullable InternalActionCodeSettings *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonFirebaseAuthSettings () -+ (PigeonFirebaseAuthSettings *)fromList:(NSArray *)list; -+ (nullable PigeonFirebaseAuthSettings *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalFirebaseAuthSettings () ++ (InternalFirebaseAuthSettings *)fromList:(NSArray *)list; ++ (nullable InternalFirebaseAuthSettings *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonSignInProvider () -+ (PigeonSignInProvider *)fromList:(NSArray *)list; -+ (nullable PigeonSignInProvider *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalSignInProvider () ++ (InternalSignInProvider *)fromList:(NSArray *)list; ++ (nullable InternalSignInProvider *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonVerifyPhoneNumberRequest () -+ (PigeonVerifyPhoneNumberRequest *)fromList:(NSArray *)list; -+ (nullable PigeonVerifyPhoneNumberRequest *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalVerifyPhoneNumberRequest () ++ (InternalVerifyPhoneNumberRequest *)fromList:(NSArray *)list; ++ (nullable InternalVerifyPhoneNumberRequest *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonIdTokenResult () -+ (PigeonIdTokenResult *)fromList:(NSArray *)list; -+ (nullable PigeonIdTokenResult *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalIdTokenResult () ++ (InternalIdTokenResult *)fromList:(NSArray *)list; ++ (nullable InternalIdTokenResult *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonUserProfile () -+ (PigeonUserProfile *)fromList:(NSArray *)list; -+ (nullable PigeonUserProfile *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalUserProfile () ++ (InternalUserProfile *)fromList:(NSArray *)list; ++ (nullable InternalUserProfile *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@interface PigeonTotpSecret () -+ (PigeonTotpSecret *)fromList:(NSArray *)list; -+ (nullable PigeonTotpSecret *)nullableFromList:(NSArray *)list; -- (NSArray *)toList; +@interface InternalTotpSecret () ++ (InternalTotpSecret *)fromList:(NSArray *)list; ++ (nullable InternalTotpSecret *)nullableFromList:(NSArray *)list; +- (NSArray *)toList; @end -@implementation PigeonMultiFactorSession +@implementation InternalMultiFactorSession + (instancetype)makeWithId:(NSString *)id { - PigeonMultiFactorSession *pigeonResult = [[PigeonMultiFactorSession alloc] init]; + InternalMultiFactorSession *pigeonResult = [[InternalMultiFactorSession alloc] init]; pigeonResult.id = id; return pigeonResult; } -+ (PigeonMultiFactorSession *)fromList:(NSArray *)list { - PigeonMultiFactorSession *pigeonResult = [[PigeonMultiFactorSession alloc] init]; ++ (InternalMultiFactorSession *)fromList:(NSArray *)list { + InternalMultiFactorSession *pigeonResult = [[InternalMultiFactorSession alloc] init]; pigeonResult.id = GetNullableObjectAtIndex(list, 0); return pigeonResult; } -+ (nullable PigeonMultiFactorSession *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonMultiFactorSession fromList:list] : nil; ++ (nullable InternalMultiFactorSession *)nullableFromList:(NSArray *)list { + return (list) ? [InternalMultiFactorSession fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.id ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalMultiFactorSession *other = (InternalMultiFactorSession *)object; + return FLTPigeonDeepEquals(self.id, other.id); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.id); + return result; +} @end -@implementation PigeonPhoneMultiFactorAssertion +@implementation InternalPhoneMultiFactorAssertion + (instancetype)makeWithVerificationId:(NSString *)verificationId verificationCode:(NSString *)verificationCode { - PigeonPhoneMultiFactorAssertion *pigeonResult = [[PigeonPhoneMultiFactorAssertion alloc] init]; + InternalPhoneMultiFactorAssertion *pigeonResult = + [[InternalPhoneMultiFactorAssertion alloc] init]; pigeonResult.verificationId = verificationId; pigeonResult.verificationCode = verificationCode; return pigeonResult; } -+ (PigeonPhoneMultiFactorAssertion *)fromList:(NSArray *)list { - PigeonPhoneMultiFactorAssertion *pigeonResult = [[PigeonPhoneMultiFactorAssertion alloc] init]; ++ (InternalPhoneMultiFactorAssertion *)fromList:(NSArray *)list { + InternalPhoneMultiFactorAssertion *pigeonResult = + [[InternalPhoneMultiFactorAssertion alloc] init]; pigeonResult.verificationId = GetNullableObjectAtIndex(list, 0); pigeonResult.verificationCode = GetNullableObjectAtIndex(list, 1); return pigeonResult; } -+ (nullable PigeonPhoneMultiFactorAssertion *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonPhoneMultiFactorAssertion fromList:list] : nil; ++ (nullable InternalPhoneMultiFactorAssertion *)nullableFromList:(NSArray *)list { + return (list) ? [InternalPhoneMultiFactorAssertion fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.verificationId ?: [NSNull null], self.verificationCode ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalPhoneMultiFactorAssertion *other = (InternalPhoneMultiFactorAssertion *)object; + return FLTPigeonDeepEquals(self.verificationId, other.verificationId) && + FLTPigeonDeepEquals(self.verificationCode, other.verificationCode); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.verificationId); + result = result * 31 + FLTPigeonDeepHash(self.verificationCode); + return result; +} @end -@implementation PigeonMultiFactorInfo +@implementation InternalMultiFactorInfo + (instancetype)makeWithDisplayName:(nullable NSString *)displayName enrollmentTimestamp:(double)enrollmentTimestamp factorId:(nullable NSString *)factorId uid:(NSString *)uid phoneNumber:(nullable NSString *)phoneNumber { - PigeonMultiFactorInfo *pigeonResult = [[PigeonMultiFactorInfo alloc] init]; + InternalMultiFactorInfo *pigeonResult = [[InternalMultiFactorInfo alloc] init]; pigeonResult.displayName = displayName; pigeonResult.enrollmentTimestamp = enrollmentTimestamp; pigeonResult.factorId = factorId; @@ -210,8 +339,8 @@ + (instancetype)makeWithDisplayName:(nullable NSString *)displayName pigeonResult.phoneNumber = phoneNumber; return pigeonResult; } -+ (PigeonMultiFactorInfo *)fromList:(NSArray *)list { - PigeonMultiFactorInfo *pigeonResult = [[PigeonMultiFactorInfo alloc] init]; ++ (InternalMultiFactorInfo *)fromList:(NSArray *)list { + InternalMultiFactorInfo *pigeonResult = [[InternalMultiFactorInfo alloc] init]; pigeonResult.displayName = GetNullableObjectAtIndex(list, 0); pigeonResult.enrollmentTimestamp = [GetNullableObjectAtIndex(list, 1) doubleValue]; pigeonResult.factorId = GetNullableObjectAtIndex(list, 2); @@ -219,10 +348,10 @@ + (PigeonMultiFactorInfo *)fromList:(NSArray *)list { pigeonResult.phoneNumber = GetNullableObjectAtIndex(list, 4); return pigeonResult; } -+ (nullable PigeonMultiFactorInfo *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonMultiFactorInfo fromList:list] : nil; ++ (nullable InternalMultiFactorInfo *)nullableFromList:(NSArray *)list { + return (list) ? [InternalMultiFactorInfo fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.displayName ?: [NSNull null], @(self.enrollmentTimestamp), @@ -231,6 +360,32 @@ - (NSArray *)toList { self.phoneNumber ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalMultiFactorInfo *other = (InternalMultiFactorInfo *)object; + return FLTPigeonDeepEquals(self.displayName, other.displayName) && + (self.enrollmentTimestamp == other.enrollmentTimestamp || + (isnan(self.enrollmentTimestamp) && isnan(other.enrollmentTimestamp))) && + FLTPigeonDeepEquals(self.factorId, other.factorId) && + FLTPigeonDeepEquals(self.uid, other.uid) && + FLTPigeonDeepEquals(self.phoneNumber, other.phoneNumber); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.displayName); + result = result * 31 + (isnan(self.enrollmentTimestamp) ? (NSUInteger)0x7FF8000000000000 + : @(self.enrollmentTimestamp).hash); + result = result * 31 + FLTPigeonDeepHash(self.factorId); + result = result * 31 + FLTPigeonDeepHash(self.uid); + result = result * 31 + FLTPigeonDeepHash(self.phoneNumber); + return result; +} @end @implementation AuthPigeonFirebaseApp @@ -243,82 +398,138 @@ + (instancetype)makeWithAppName:(NSString *)appName pigeonResult.customAuthDomain = customAuthDomain; return pigeonResult; } -+ (AuthPigeonFirebaseApp *)fromList:(NSArray *)list { ++ (AuthPigeonFirebaseApp *)fromList:(NSArray *)list { AuthPigeonFirebaseApp *pigeonResult = [[AuthPigeonFirebaseApp alloc] init]; pigeonResult.appName = GetNullableObjectAtIndex(list, 0); pigeonResult.tenantId = GetNullableObjectAtIndex(list, 1); pigeonResult.customAuthDomain = GetNullableObjectAtIndex(list, 2); return pigeonResult; } -+ (nullable AuthPigeonFirebaseApp *)nullableFromList:(NSArray *)list { ++ (nullable AuthPigeonFirebaseApp *)nullableFromList:(NSArray *)list { return (list) ? [AuthPigeonFirebaseApp fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.appName ?: [NSNull null], self.tenantId ?: [NSNull null], self.customAuthDomain ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + AuthPigeonFirebaseApp *other = (AuthPigeonFirebaseApp *)object; + return FLTPigeonDeepEquals(self.appName, other.appName) && + FLTPigeonDeepEquals(self.tenantId, other.tenantId) && + FLTPigeonDeepEquals(self.customAuthDomain, other.customAuthDomain); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.appName); + result = result * 31 + FLTPigeonDeepHash(self.tenantId); + result = result * 31 + FLTPigeonDeepHash(self.customAuthDomain); + return result; +} @end -@implementation PigeonActionCodeInfoData +@implementation InternalActionCodeInfoData + (instancetype)makeWithEmail:(nullable NSString *)email previousEmail:(nullable NSString *)previousEmail { - PigeonActionCodeInfoData *pigeonResult = [[PigeonActionCodeInfoData alloc] init]; + InternalActionCodeInfoData *pigeonResult = [[InternalActionCodeInfoData alloc] init]; pigeonResult.email = email; pigeonResult.previousEmail = previousEmail; return pigeonResult; } -+ (PigeonActionCodeInfoData *)fromList:(NSArray *)list { - PigeonActionCodeInfoData *pigeonResult = [[PigeonActionCodeInfoData alloc] init]; ++ (InternalActionCodeInfoData *)fromList:(NSArray *)list { + InternalActionCodeInfoData *pigeonResult = [[InternalActionCodeInfoData alloc] init]; pigeonResult.email = GetNullableObjectAtIndex(list, 0); pigeonResult.previousEmail = GetNullableObjectAtIndex(list, 1); return pigeonResult; } -+ (nullable PigeonActionCodeInfoData *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonActionCodeInfoData fromList:list] : nil; ++ (nullable InternalActionCodeInfoData *)nullableFromList:(NSArray *)list { + return (list) ? [InternalActionCodeInfoData fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.email ?: [NSNull null], self.previousEmail ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalActionCodeInfoData *other = (InternalActionCodeInfoData *)object; + return FLTPigeonDeepEquals(self.email, other.email) && + FLTPigeonDeepEquals(self.previousEmail, other.previousEmail); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.email); + result = result * 31 + FLTPigeonDeepHash(self.previousEmail); + return result; +} @end -@implementation PigeonActionCodeInfo +@implementation InternalActionCodeInfo + (instancetype)makeWithOperation:(ActionCodeInfoOperation)operation - data:(PigeonActionCodeInfoData *)data { - PigeonActionCodeInfo *pigeonResult = [[PigeonActionCodeInfo alloc] init]; + data:(InternalActionCodeInfoData *)data { + InternalActionCodeInfo *pigeonResult = [[InternalActionCodeInfo alloc] init]; pigeonResult.operation = operation; pigeonResult.data = data; return pigeonResult; } -+ (PigeonActionCodeInfo *)fromList:(NSArray *)list { - PigeonActionCodeInfo *pigeonResult = [[PigeonActionCodeInfo alloc] init]; - pigeonResult.operation = [GetNullableObjectAtIndex(list, 0) integerValue]; ++ (InternalActionCodeInfo *)fromList:(NSArray *)list { + InternalActionCodeInfo *pigeonResult = [[InternalActionCodeInfo alloc] init]; + ActionCodeInfoOperationBox *boxedActionCodeInfoOperation = GetNullableObjectAtIndex(list, 0); + pigeonResult.operation = boxedActionCodeInfoOperation.value; pigeonResult.data = GetNullableObjectAtIndex(list, 1); return pigeonResult; } -+ (nullable PigeonActionCodeInfo *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonActionCodeInfo fromList:list] : nil; ++ (nullable InternalActionCodeInfo *)nullableFromList:(NSArray *)list { + return (list) ? [InternalActionCodeInfo fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ - @(self.operation), + [[ActionCodeInfoOperationBox alloc] initWithValue:self.operation], self.data ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalActionCodeInfo *other = (InternalActionCodeInfo *)object; + return self.operation == other.operation && FLTPigeonDeepEquals(self.data, other.data); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.operation).hash; + result = result * 31 + FLTPigeonDeepHash(self.data); + return result; +} @end -@implementation PigeonAdditionalUserInfo +@implementation InternalAdditionalUserInfo + (instancetype)makeWithIsNewUser:(BOOL)isNewUser providerId:(nullable NSString *)providerId username:(nullable NSString *)username authorizationCode:(nullable NSString *)authorizationCode profile:(nullable NSDictionary *)profile { - PigeonAdditionalUserInfo *pigeonResult = [[PigeonAdditionalUserInfo alloc] init]; + InternalAdditionalUserInfo *pigeonResult = [[InternalAdditionalUserInfo alloc] init]; pigeonResult.isNewUser = isNewUser; pigeonResult.providerId = providerId; pigeonResult.username = username; @@ -326,8 +537,8 @@ + (instancetype)makeWithIsNewUser:(BOOL)isNewUser pigeonResult.profile = profile; return pigeonResult; } -+ (PigeonAdditionalUserInfo *)fromList:(NSArray *)list { - PigeonAdditionalUserInfo *pigeonResult = [[PigeonAdditionalUserInfo alloc] init]; ++ (InternalAdditionalUserInfo *)fromList:(NSArray *)list { + InternalAdditionalUserInfo *pigeonResult = [[InternalAdditionalUserInfo alloc] init]; pigeonResult.isNewUser = [GetNullableObjectAtIndex(list, 0) boolValue]; pigeonResult.providerId = GetNullableObjectAtIndex(list, 1); pigeonResult.username = GetNullableObjectAtIndex(list, 2); @@ -335,10 +546,10 @@ + (PigeonAdditionalUserInfo *)fromList:(NSArray *)list { pigeonResult.profile = GetNullableObjectAtIndex(list, 4); return pigeonResult; } -+ (nullable PigeonAdditionalUserInfo *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonAdditionalUserInfo fromList:list] : nil; ++ (nullable InternalAdditionalUserInfo *)nullableFromList:(NSArray *)list { + return (list) ? [InternalAdditionalUserInfo fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ @(self.isNewUser), self.providerId ?: [NSNull null], @@ -347,32 +558,56 @@ - (NSArray *)toList { self.profile ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalAdditionalUserInfo *other = (InternalAdditionalUserInfo *)object; + return self.isNewUser == other.isNewUser && + FLTPigeonDeepEquals(self.providerId, other.providerId) && + FLTPigeonDeepEquals(self.username, other.username) && + FLTPigeonDeepEquals(self.authorizationCode, other.authorizationCode) && + FLTPigeonDeepEquals(self.profile, other.profile); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.isNewUser).hash; + result = result * 31 + FLTPigeonDeepHash(self.providerId); + result = result * 31 + FLTPigeonDeepHash(self.username); + result = result * 31 + FLTPigeonDeepHash(self.authorizationCode); + result = result * 31 + FLTPigeonDeepHash(self.profile); + return result; +} @end -@implementation PigeonAuthCredential +@implementation InternalAuthCredential + (instancetype)makeWithProviderId:(NSString *)providerId signInMethod:(NSString *)signInMethod nativeId:(NSInteger)nativeId accessToken:(nullable NSString *)accessToken { - PigeonAuthCredential *pigeonResult = [[PigeonAuthCredential alloc] init]; + InternalAuthCredential *pigeonResult = [[InternalAuthCredential alloc] init]; pigeonResult.providerId = providerId; pigeonResult.signInMethod = signInMethod; pigeonResult.nativeId = nativeId; pigeonResult.accessToken = accessToken; return pigeonResult; } -+ (PigeonAuthCredential *)fromList:(NSArray *)list { - PigeonAuthCredential *pigeonResult = [[PigeonAuthCredential alloc] init]; ++ (InternalAuthCredential *)fromList:(NSArray *)list { + InternalAuthCredential *pigeonResult = [[InternalAuthCredential alloc] init]; pigeonResult.providerId = GetNullableObjectAtIndex(list, 0); pigeonResult.signInMethod = GetNullableObjectAtIndex(list, 1); pigeonResult.nativeId = [GetNullableObjectAtIndex(list, 2) integerValue]; pigeonResult.accessToken = GetNullableObjectAtIndex(list, 3); return pigeonResult; } -+ (nullable PigeonAuthCredential *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonAuthCredential fromList:list] : nil; ++ (nullable InternalAuthCredential *)nullableFromList:(NSArray *)list { + return (list) ? [InternalAuthCredential fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.providerId ?: [NSNull null], self.signInMethod ?: [NSNull null], @@ -380,9 +615,31 @@ - (NSArray *)toList { self.accessToken ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalAuthCredential *other = (InternalAuthCredential *)object; + return FLTPigeonDeepEquals(self.providerId, other.providerId) && + FLTPigeonDeepEquals(self.signInMethod, other.signInMethod) && + self.nativeId == other.nativeId && + FLTPigeonDeepEquals(self.accessToken, other.accessToken); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.providerId); + result = result * 31 + FLTPigeonDeepHash(self.signInMethod); + result = result * 31 + @(self.nativeId).hash; + result = result * 31 + FLTPigeonDeepHash(self.accessToken); + return result; +} @end -@implementation PigeonUserInfo +@implementation InternalUserInfo + (instancetype)makeWithUid:(NSString *)uid email:(nullable NSString *)email displayName:(nullable NSString *)displayName @@ -395,7 +652,7 @@ + (instancetype)makeWithUid:(NSString *)uid refreshToken:(nullable NSString *)refreshToken creationTimestamp:(nullable NSNumber *)creationTimestamp lastSignInTimestamp:(nullable NSNumber *)lastSignInTimestamp { - PigeonUserInfo *pigeonResult = [[PigeonUserInfo alloc] init]; + InternalUserInfo *pigeonResult = [[InternalUserInfo alloc] init]; pigeonResult.uid = uid; pigeonResult.email = email; pigeonResult.displayName = displayName; @@ -410,8 +667,8 @@ + (instancetype)makeWithUid:(NSString *)uid pigeonResult.lastSignInTimestamp = lastSignInTimestamp; return pigeonResult; } -+ (PigeonUserInfo *)fromList:(NSArray *)list { - PigeonUserInfo *pigeonResult = [[PigeonUserInfo alloc] init]; ++ (InternalUserInfo *)fromList:(NSArray *)list { + InternalUserInfo *pigeonResult = [[InternalUserInfo alloc] init]; pigeonResult.uid = GetNullableObjectAtIndex(list, 0); pigeonResult.email = GetNullableObjectAtIndex(list, 1); pigeonResult.displayName = GetNullableObjectAtIndex(list, 2); @@ -426,10 +683,10 @@ + (PigeonUserInfo *)fromList:(NSArray *)list { pigeonResult.lastSignInTimestamp = GetNullableObjectAtIndex(list, 11); return pigeonResult; } -+ (nullable PigeonUserInfo *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonUserInfo fromList:list] : nil; ++ (nullable InternalUserInfo *)nullableFromList:(NSArray *)list { + return (list) ? [InternalUserInfo fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.uid ?: [NSNull null], self.email ?: [NSNull null], @@ -445,63 +702,192 @@ - (NSArray *)toList { self.lastSignInTimestamp ?: [NSNull null], ]; } -@end - -@implementation PigeonUserDetails -+ (instancetype)makeWithUserInfo:(PigeonUserInfo *)userInfo +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalUserInfo *other = (InternalUserInfo *)object; + return FLTPigeonDeepEquals(self.uid, other.uid) && FLTPigeonDeepEquals(self.email, other.email) && + FLTPigeonDeepEquals(self.displayName, other.displayName) && + FLTPigeonDeepEquals(self.photoUrl, other.photoUrl) && + FLTPigeonDeepEquals(self.phoneNumber, other.phoneNumber) && + self.isAnonymous == other.isAnonymous && self.isEmailVerified == other.isEmailVerified && + FLTPigeonDeepEquals(self.providerId, other.providerId) && + FLTPigeonDeepEquals(self.tenantId, other.tenantId) && + FLTPigeonDeepEquals(self.refreshToken, other.refreshToken) && + FLTPigeonDeepEquals(self.creationTimestamp, other.creationTimestamp) && + FLTPigeonDeepEquals(self.lastSignInTimestamp, other.lastSignInTimestamp); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.uid); + result = result * 31 + FLTPigeonDeepHash(self.email); + result = result * 31 + FLTPigeonDeepHash(self.displayName); + result = result * 31 + FLTPigeonDeepHash(self.photoUrl); + result = result * 31 + FLTPigeonDeepHash(self.phoneNumber); + result = result * 31 + @(self.isAnonymous).hash; + result = result * 31 + @(self.isEmailVerified).hash; + result = result * 31 + FLTPigeonDeepHash(self.providerId); + result = result * 31 + FLTPigeonDeepHash(self.tenantId); + result = result * 31 + FLTPigeonDeepHash(self.refreshToken); + result = result * 31 + FLTPigeonDeepHash(self.creationTimestamp); + result = result * 31 + FLTPigeonDeepHash(self.lastSignInTimestamp); + return result; +} +@end + +@implementation InternalUserDetails ++ (instancetype)makeWithUserInfo:(InternalUserInfo *)userInfo providerData:(NSArray *> *)providerData { - PigeonUserDetails *pigeonResult = [[PigeonUserDetails alloc] init]; + InternalUserDetails *pigeonResult = [[InternalUserDetails alloc] init]; pigeonResult.userInfo = userInfo; pigeonResult.providerData = providerData; return pigeonResult; } -+ (PigeonUserDetails *)fromList:(NSArray *)list { - PigeonUserDetails *pigeonResult = [[PigeonUserDetails alloc] init]; ++ (InternalUserDetails *)fromList:(NSArray *)list { + InternalUserDetails *pigeonResult = [[InternalUserDetails alloc] init]; pigeonResult.userInfo = GetNullableObjectAtIndex(list, 0); pigeonResult.providerData = GetNullableObjectAtIndex(list, 1); return pigeonResult; } -+ (nullable PigeonUserDetails *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonUserDetails fromList:list] : nil; ++ (nullable InternalUserDetails *)nullableFromList:(NSArray *)list { + return (list) ? [InternalUserDetails fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.userInfo ?: [NSNull null], self.providerData ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalUserDetails *other = (InternalUserDetails *)object; + return FLTPigeonDeepEquals(self.userInfo, other.userInfo) && + FLTPigeonDeepEquals(self.providerData, other.providerData); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.userInfo); + result = result * 31 + FLTPigeonDeepHash(self.providerData); + return result; +} @end -@implementation PigeonUserCredential -+ (instancetype)makeWithUser:(nullable PigeonUserDetails *)user - additionalUserInfo:(nullable PigeonAdditionalUserInfo *)additionalUserInfo - credential:(nullable PigeonAuthCredential *)credential { - PigeonUserCredential *pigeonResult = [[PigeonUserCredential alloc] init]; +@implementation InternalUserCredential ++ (instancetype)makeWithUser:(nullable InternalUserDetails *)user + additionalUserInfo:(nullable InternalAdditionalUserInfo *)additionalUserInfo + credential:(nullable InternalAuthCredential *)credential { + InternalUserCredential *pigeonResult = [[InternalUserCredential alloc] init]; pigeonResult.user = user; pigeonResult.additionalUserInfo = additionalUserInfo; pigeonResult.credential = credential; return pigeonResult; } -+ (PigeonUserCredential *)fromList:(NSArray *)list { - PigeonUserCredential *pigeonResult = [[PigeonUserCredential alloc] init]; ++ (InternalUserCredential *)fromList:(NSArray *)list { + InternalUserCredential *pigeonResult = [[InternalUserCredential alloc] init]; pigeonResult.user = GetNullableObjectAtIndex(list, 0); pigeonResult.additionalUserInfo = GetNullableObjectAtIndex(list, 1); pigeonResult.credential = GetNullableObjectAtIndex(list, 2); return pigeonResult; } -+ (nullable PigeonUserCredential *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonUserCredential fromList:list] : nil; ++ (nullable InternalUserCredential *)nullableFromList:(NSArray *)list { + return (list) ? [InternalUserCredential fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.user ?: [NSNull null], self.additionalUserInfo ?: [NSNull null], self.credential ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalUserCredential *other = (InternalUserCredential *)object; + return FLTPigeonDeepEquals(self.user, other.user) && + FLTPigeonDeepEquals(self.additionalUserInfo, other.additionalUserInfo) && + FLTPigeonDeepEquals(self.credential, other.credential); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.user); + result = result * 31 + FLTPigeonDeepHash(self.additionalUserInfo); + result = result * 31 + FLTPigeonDeepHash(self.credential); + return result; +} +@end + +@implementation InternalAuthCredentialInput ++ (instancetype)makeWithProviderId:(NSString *)providerId + signInMethod:(NSString *)signInMethod + token:(nullable NSString *)token + accessToken:(nullable NSString *)accessToken { + InternalAuthCredentialInput *pigeonResult = [[InternalAuthCredentialInput alloc] init]; + pigeonResult.providerId = providerId; + pigeonResult.signInMethod = signInMethod; + pigeonResult.token = token; + pigeonResult.accessToken = accessToken; + return pigeonResult; +} ++ (InternalAuthCredentialInput *)fromList:(NSArray *)list { + InternalAuthCredentialInput *pigeonResult = [[InternalAuthCredentialInput alloc] init]; + pigeonResult.providerId = GetNullableObjectAtIndex(list, 0); + pigeonResult.signInMethod = GetNullableObjectAtIndex(list, 1); + pigeonResult.token = GetNullableObjectAtIndex(list, 2); + pigeonResult.accessToken = GetNullableObjectAtIndex(list, 3); + return pigeonResult; +} ++ (nullable InternalAuthCredentialInput *)nullableFromList:(NSArray *)list { + return (list) ? [InternalAuthCredentialInput fromList:list] : nil; +} +- (NSArray *)toList { + return @[ + self.providerId ?: [NSNull null], + self.signInMethod ?: [NSNull null], + self.token ?: [NSNull null], + self.accessToken ?: [NSNull null], + ]; +} +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalAuthCredentialInput *other = (InternalAuthCredentialInput *)object; + return FLTPigeonDeepEquals(self.providerId, other.providerId) && + FLTPigeonDeepEquals(self.signInMethod, other.signInMethod) && + FLTPigeonDeepEquals(self.token, other.token) && + FLTPigeonDeepEquals(self.accessToken, other.accessToken); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.providerId); + result = result * 31 + FLTPigeonDeepHash(self.signInMethod); + result = result * 31 + FLTPigeonDeepHash(self.token); + result = result * 31 + FLTPigeonDeepHash(self.accessToken); + return result; +} @end -@implementation PigeonActionCodeSettings +@implementation InternalActionCodeSettings + (instancetype)makeWithUrl:(NSString *)url dynamicLinkDomain:(nullable NSString *)dynamicLinkDomain handleCodeInApp:(BOOL)handleCodeInApp @@ -510,7 +896,7 @@ + (instancetype)makeWithUrl:(NSString *)url androidInstallApp:(BOOL)androidInstallApp androidMinimumVersion:(nullable NSString *)androidMinimumVersion linkDomain:(nullable NSString *)linkDomain { - PigeonActionCodeSettings *pigeonResult = [[PigeonActionCodeSettings alloc] init]; + InternalActionCodeSettings *pigeonResult = [[InternalActionCodeSettings alloc] init]; pigeonResult.url = url; pigeonResult.dynamicLinkDomain = dynamicLinkDomain; pigeonResult.handleCodeInApp = handleCodeInApp; @@ -521,8 +907,8 @@ + (instancetype)makeWithUrl:(NSString *)url pigeonResult.linkDomain = linkDomain; return pigeonResult; } -+ (PigeonActionCodeSettings *)fromList:(NSArray *)list { - PigeonActionCodeSettings *pigeonResult = [[PigeonActionCodeSettings alloc] init]; ++ (InternalActionCodeSettings *)fromList:(NSArray *)list { + InternalActionCodeSettings *pigeonResult = [[InternalActionCodeSettings alloc] init]; pigeonResult.url = GetNullableObjectAtIndex(list, 0); pigeonResult.dynamicLinkDomain = GetNullableObjectAtIndex(list, 1); pigeonResult.handleCodeInApp = [GetNullableObjectAtIndex(list, 2) boolValue]; @@ -533,10 +919,10 @@ + (PigeonActionCodeSettings *)fromList:(NSArray *)list { pigeonResult.linkDomain = GetNullableObjectAtIndex(list, 7); return pigeonResult; } -+ (nullable PigeonActionCodeSettings *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonActionCodeSettings fromList:list] : nil; ++ (nullable InternalActionCodeSettings *)nullableFromList:(NSArray *)list { + return (list) ? [InternalActionCodeSettings fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.url ?: [NSNull null], self.dynamicLinkDomain ?: [NSNull null], @@ -548,15 +934,45 @@ - (NSArray *)toList { self.linkDomain ?: [NSNull null], ]; } -@end - -@implementation PigeonFirebaseAuthSettings +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalActionCodeSettings *other = (InternalActionCodeSettings *)object; + return FLTPigeonDeepEquals(self.url, other.url) && + FLTPigeonDeepEquals(self.dynamicLinkDomain, other.dynamicLinkDomain) && + self.handleCodeInApp == other.handleCodeInApp && + FLTPigeonDeepEquals(self.iOSBundleId, other.iOSBundleId) && + FLTPigeonDeepEquals(self.androidPackageName, other.androidPackageName) && + self.androidInstallApp == other.androidInstallApp && + FLTPigeonDeepEquals(self.androidMinimumVersion, other.androidMinimumVersion) && + FLTPigeonDeepEquals(self.linkDomain, other.linkDomain); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.url); + result = result * 31 + FLTPigeonDeepHash(self.dynamicLinkDomain); + result = result * 31 + @(self.handleCodeInApp).hash; + result = result * 31 + FLTPigeonDeepHash(self.iOSBundleId); + result = result * 31 + FLTPigeonDeepHash(self.androidPackageName); + result = result * 31 + @(self.androidInstallApp).hash; + result = result * 31 + FLTPigeonDeepHash(self.androidMinimumVersion); + result = result * 31 + FLTPigeonDeepHash(self.linkDomain); + return result; +} +@end + +@implementation InternalFirebaseAuthSettings + (instancetype)makeWithAppVerificationDisabledForTesting:(BOOL)appVerificationDisabledForTesting userAccessGroup:(nullable NSString *)userAccessGroup phoneNumber:(nullable NSString *)phoneNumber smsCode:(nullable NSString *)smsCode forceRecaptchaFlow:(nullable NSNumber *)forceRecaptchaFlow { - PigeonFirebaseAuthSettings *pigeonResult = [[PigeonFirebaseAuthSettings alloc] init]; + InternalFirebaseAuthSettings *pigeonResult = [[InternalFirebaseAuthSettings alloc] init]; pigeonResult.appVerificationDisabledForTesting = appVerificationDisabledForTesting; pigeonResult.userAccessGroup = userAccessGroup; pigeonResult.phoneNumber = phoneNumber; @@ -564,8 +980,8 @@ + (instancetype)makeWithAppVerificationDisabledForTesting:(BOOL)appVerificationD pigeonResult.forceRecaptchaFlow = forceRecaptchaFlow; return pigeonResult; } -+ (PigeonFirebaseAuthSettings *)fromList:(NSArray *)list { - PigeonFirebaseAuthSettings *pigeonResult = [[PigeonFirebaseAuthSettings alloc] init]; ++ (InternalFirebaseAuthSettings *)fromList:(NSArray *)list { + InternalFirebaseAuthSettings *pigeonResult = [[InternalFirebaseAuthSettings alloc] init]; pigeonResult.appVerificationDisabledForTesting = [GetNullableObjectAtIndex(list, 0) boolValue]; pigeonResult.userAccessGroup = GetNullableObjectAtIndex(list, 1); pigeonResult.phoneNumber = GetNullableObjectAtIndex(list, 2); @@ -573,10 +989,10 @@ + (PigeonFirebaseAuthSettings *)fromList:(NSArray *)list { pigeonResult.forceRecaptchaFlow = GetNullableObjectAtIndex(list, 4); return pigeonResult; } -+ (nullable PigeonFirebaseAuthSettings *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonFirebaseAuthSettings fromList:list] : nil; ++ (nullable InternalFirebaseAuthSettings *)nullableFromList:(NSArray *)list { + return (list) ? [InternalFirebaseAuthSettings fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ @(self.appVerificationDisabledForTesting), self.userAccessGroup ?: [NSNull null], @@ -585,46 +1001,90 @@ - (NSArray *)toList { self.forceRecaptchaFlow ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalFirebaseAuthSettings *other = (InternalFirebaseAuthSettings *)object; + return self.appVerificationDisabledForTesting == other.appVerificationDisabledForTesting && + FLTPigeonDeepEquals(self.userAccessGroup, other.userAccessGroup) && + FLTPigeonDeepEquals(self.phoneNumber, other.phoneNumber) && + FLTPigeonDeepEquals(self.smsCode, other.smsCode) && + FLTPigeonDeepEquals(self.forceRecaptchaFlow, other.forceRecaptchaFlow); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + @(self.appVerificationDisabledForTesting).hash; + result = result * 31 + FLTPigeonDeepHash(self.userAccessGroup); + result = result * 31 + FLTPigeonDeepHash(self.phoneNumber); + result = result * 31 + FLTPigeonDeepHash(self.smsCode); + result = result * 31 + FLTPigeonDeepHash(self.forceRecaptchaFlow); + return result; +} @end -@implementation PigeonSignInProvider +@implementation InternalSignInProvider + (instancetype)makeWithProviderId:(NSString *)providerId scopes:(nullable NSArray *)scopes customParameters: (nullable NSDictionary *)customParameters { - PigeonSignInProvider *pigeonResult = [[PigeonSignInProvider alloc] init]; + InternalSignInProvider *pigeonResult = [[InternalSignInProvider alloc] init]; pigeonResult.providerId = providerId; pigeonResult.scopes = scopes; pigeonResult.customParameters = customParameters; return pigeonResult; } -+ (PigeonSignInProvider *)fromList:(NSArray *)list { - PigeonSignInProvider *pigeonResult = [[PigeonSignInProvider alloc] init]; ++ (InternalSignInProvider *)fromList:(NSArray *)list { + InternalSignInProvider *pigeonResult = [[InternalSignInProvider alloc] init]; pigeonResult.providerId = GetNullableObjectAtIndex(list, 0); pigeonResult.scopes = GetNullableObjectAtIndex(list, 1); pigeonResult.customParameters = GetNullableObjectAtIndex(list, 2); return pigeonResult; } -+ (nullable PigeonSignInProvider *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonSignInProvider fromList:list] : nil; ++ (nullable InternalSignInProvider *)nullableFromList:(NSArray *)list { + return (list) ? [InternalSignInProvider fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.providerId ?: [NSNull null], self.scopes ?: [NSNull null], self.customParameters ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalSignInProvider *other = (InternalSignInProvider *)object; + return FLTPigeonDeepEquals(self.providerId, other.providerId) && + FLTPigeonDeepEquals(self.scopes, other.scopes) && + FLTPigeonDeepEquals(self.customParameters, other.customParameters); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.providerId); + result = result * 31 + FLTPigeonDeepHash(self.scopes); + result = result * 31 + FLTPigeonDeepHash(self.customParameters); + return result; +} @end -@implementation PigeonVerifyPhoneNumberRequest +@implementation InternalVerifyPhoneNumberRequest + (instancetype)makeWithPhoneNumber:(nullable NSString *)phoneNumber timeout:(NSInteger)timeout forceResendingToken:(nullable NSNumber *)forceResendingToken autoRetrievedSmsCodeForTesting:(nullable NSString *)autoRetrievedSmsCodeForTesting multiFactorInfoId:(nullable NSString *)multiFactorInfoId multiFactorSessionId:(nullable NSString *)multiFactorSessionId { - PigeonVerifyPhoneNumberRequest *pigeonResult = [[PigeonVerifyPhoneNumberRequest alloc] init]; + InternalVerifyPhoneNumberRequest *pigeonResult = [[InternalVerifyPhoneNumberRequest alloc] init]; pigeonResult.phoneNumber = phoneNumber; pigeonResult.timeout = timeout; pigeonResult.forceResendingToken = forceResendingToken; @@ -633,8 +1093,8 @@ + (instancetype)makeWithPhoneNumber:(nullable NSString *)phoneNumber pigeonResult.multiFactorSessionId = multiFactorSessionId; return pigeonResult; } -+ (PigeonVerifyPhoneNumberRequest *)fromList:(NSArray *)list { - PigeonVerifyPhoneNumberRequest *pigeonResult = [[PigeonVerifyPhoneNumberRequest alloc] init]; ++ (InternalVerifyPhoneNumberRequest *)fromList:(NSArray *)list { + InternalVerifyPhoneNumberRequest *pigeonResult = [[InternalVerifyPhoneNumberRequest alloc] init]; pigeonResult.phoneNumber = GetNullableObjectAtIndex(list, 0); pigeonResult.timeout = [GetNullableObjectAtIndex(list, 1) integerValue]; pigeonResult.forceResendingToken = GetNullableObjectAtIndex(list, 2); @@ -643,10 +1103,10 @@ + (PigeonVerifyPhoneNumberRequest *)fromList:(NSArray *)list { pigeonResult.multiFactorSessionId = GetNullableObjectAtIndex(list, 5); return pigeonResult; } -+ (nullable PigeonVerifyPhoneNumberRequest *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonVerifyPhoneNumberRequest fromList:list] : nil; ++ (nullable InternalVerifyPhoneNumberRequest *)nullableFromList:(NSArray *)list { + return (list) ? [InternalVerifyPhoneNumberRequest fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.phoneNumber ?: [NSNull null], @(self.timeout), @@ -656,9 +1116,36 @@ - (NSArray *)toList { self.multiFactorSessionId ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalVerifyPhoneNumberRequest *other = (InternalVerifyPhoneNumberRequest *)object; + return FLTPigeonDeepEquals(self.phoneNumber, other.phoneNumber) && + self.timeout == other.timeout && + FLTPigeonDeepEquals(self.forceResendingToken, other.forceResendingToken) && + FLTPigeonDeepEquals(self.autoRetrievedSmsCodeForTesting, + other.autoRetrievedSmsCodeForTesting) && + FLTPigeonDeepEquals(self.multiFactorInfoId, other.multiFactorInfoId) && + FLTPigeonDeepEquals(self.multiFactorSessionId, other.multiFactorSessionId); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.phoneNumber); + result = result * 31 + @(self.timeout).hash; + result = result * 31 + FLTPigeonDeepHash(self.forceResendingToken); + result = result * 31 + FLTPigeonDeepHash(self.autoRetrievedSmsCodeForTesting); + result = result * 31 + FLTPigeonDeepHash(self.multiFactorInfoId); + result = result * 31 + FLTPigeonDeepHash(self.multiFactorSessionId); + return result; +} @end -@implementation PigeonIdTokenResult +@implementation InternalIdTokenResult + (instancetype)makeWithToken:(nullable NSString *)token expirationTimestamp:(nullable NSNumber *)expirationTimestamp authTimestamp:(nullable NSNumber *)authTimestamp @@ -666,7 +1153,7 @@ + (instancetype)makeWithToken:(nullable NSString *)token signInProvider:(nullable NSString *)signInProvider claims:(nullable NSDictionary *)claims signInSecondFactor:(nullable NSString *)signInSecondFactor { - PigeonIdTokenResult *pigeonResult = [[PigeonIdTokenResult alloc] init]; + InternalIdTokenResult *pigeonResult = [[InternalIdTokenResult alloc] init]; pigeonResult.token = token; pigeonResult.expirationTimestamp = expirationTimestamp; pigeonResult.authTimestamp = authTimestamp; @@ -676,8 +1163,8 @@ + (instancetype)makeWithToken:(nullable NSString *)token pigeonResult.signInSecondFactor = signInSecondFactor; return pigeonResult; } -+ (PigeonIdTokenResult *)fromList:(NSArray *)list { - PigeonIdTokenResult *pigeonResult = [[PigeonIdTokenResult alloc] init]; ++ (InternalIdTokenResult *)fromList:(NSArray *)list { + InternalIdTokenResult *pigeonResult = [[InternalIdTokenResult alloc] init]; pigeonResult.token = GetNullableObjectAtIndex(list, 0); pigeonResult.expirationTimestamp = GetNullableObjectAtIndex(list, 1); pigeonResult.authTimestamp = GetNullableObjectAtIndex(list, 2); @@ -687,10 +1174,10 @@ + (PigeonIdTokenResult *)fromList:(NSArray *)list { pigeonResult.signInSecondFactor = GetNullableObjectAtIndex(list, 6); return pigeonResult; } -+ (nullable PigeonIdTokenResult *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonIdTokenResult fromList:list] : nil; ++ (nullable InternalIdTokenResult *)nullableFromList:(NSArray *)list { + return (list) ? [InternalIdTokenResult fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.token ?: [NSNull null], self.expirationTimestamp ?: [NSNull null], @@ -701,32 +1188,60 @@ - (NSArray *)toList { self.signInSecondFactor ?: [NSNull null], ]; } -@end - -@implementation PigeonUserProfile +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalIdTokenResult *other = (InternalIdTokenResult *)object; + return FLTPigeonDeepEquals(self.token, other.token) && + FLTPigeonDeepEquals(self.expirationTimestamp, other.expirationTimestamp) && + FLTPigeonDeepEquals(self.authTimestamp, other.authTimestamp) && + FLTPigeonDeepEquals(self.issuedAtTimestamp, other.issuedAtTimestamp) && + FLTPigeonDeepEquals(self.signInProvider, other.signInProvider) && + FLTPigeonDeepEquals(self.claims, other.claims) && + FLTPigeonDeepEquals(self.signInSecondFactor, other.signInSecondFactor); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.token); + result = result * 31 + FLTPigeonDeepHash(self.expirationTimestamp); + result = result * 31 + FLTPigeonDeepHash(self.authTimestamp); + result = result * 31 + FLTPigeonDeepHash(self.issuedAtTimestamp); + result = result * 31 + FLTPigeonDeepHash(self.signInProvider); + result = result * 31 + FLTPigeonDeepHash(self.claims); + result = result * 31 + FLTPigeonDeepHash(self.signInSecondFactor); + return result; +} +@end + +@implementation InternalUserProfile + (instancetype)makeWithDisplayName:(nullable NSString *)displayName photoUrl:(nullable NSString *)photoUrl displayNameChanged:(BOOL)displayNameChanged photoUrlChanged:(BOOL)photoUrlChanged { - PigeonUserProfile *pigeonResult = [[PigeonUserProfile alloc] init]; + InternalUserProfile *pigeonResult = [[InternalUserProfile alloc] init]; pigeonResult.displayName = displayName; pigeonResult.photoUrl = photoUrl; pigeonResult.displayNameChanged = displayNameChanged; pigeonResult.photoUrlChanged = photoUrlChanged; return pigeonResult; } -+ (PigeonUserProfile *)fromList:(NSArray *)list { - PigeonUserProfile *pigeonResult = [[PigeonUserProfile alloc] init]; ++ (InternalUserProfile *)fromList:(NSArray *)list { + InternalUserProfile *pigeonResult = [[InternalUserProfile alloc] init]; pigeonResult.displayName = GetNullableObjectAtIndex(list, 0); pigeonResult.photoUrl = GetNullableObjectAtIndex(list, 1); pigeonResult.displayNameChanged = [GetNullableObjectAtIndex(list, 2) boolValue]; pigeonResult.photoUrlChanged = [GetNullableObjectAtIndex(list, 3) boolValue]; return pigeonResult; } -+ (nullable PigeonUserProfile *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonUserProfile fromList:list] : nil; ++ (nullable InternalUserProfile *)nullableFromList:(NSArray *)list { + return (list) ? [InternalUserProfile fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.displayName ?: [NSNull null], self.photoUrl ?: [NSNull null], @@ -734,15 +1249,37 @@ - (NSArray *)toList { @(self.photoUrlChanged), ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalUserProfile *other = (InternalUserProfile *)object; + return FLTPigeonDeepEquals(self.displayName, other.displayName) && + FLTPigeonDeepEquals(self.photoUrl, other.photoUrl) && + self.displayNameChanged == other.displayNameChanged && + self.photoUrlChanged == other.photoUrlChanged; +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.displayName); + result = result * 31 + FLTPigeonDeepHash(self.photoUrl); + result = result * 31 + @(self.displayNameChanged).hash; + result = result * 31 + @(self.photoUrlChanged).hash; + return result; +} @end -@implementation PigeonTotpSecret +@implementation InternalTotpSecret + (instancetype)makeWithCodeIntervalSeconds:(nullable NSNumber *)codeIntervalSeconds codeLength:(nullable NSNumber *)codeLength enrollmentCompletionDeadline:(nullable NSNumber *)enrollmentCompletionDeadline hashingAlgorithm:(nullable NSString *)hashingAlgorithm secretKey:(NSString *)secretKey { - PigeonTotpSecret *pigeonResult = [[PigeonTotpSecret alloc] init]; + InternalTotpSecret *pigeonResult = [[InternalTotpSecret alloc] init]; pigeonResult.codeIntervalSeconds = codeIntervalSeconds; pigeonResult.codeLength = codeLength; pigeonResult.enrollmentCompletionDeadline = enrollmentCompletionDeadline; @@ -750,8 +1287,8 @@ + (instancetype)makeWithCodeIntervalSeconds:(nullable NSNumber *)codeIntervalSec pigeonResult.secretKey = secretKey; return pigeonResult; } -+ (PigeonTotpSecret *)fromList:(NSArray *)list { - PigeonTotpSecret *pigeonResult = [[PigeonTotpSecret alloc] init]; ++ (InternalTotpSecret *)fromList:(NSArray *)list { + InternalTotpSecret *pigeonResult = [[InternalTotpSecret alloc] init]; pigeonResult.codeIntervalSeconds = GetNullableObjectAtIndex(list, 0); pigeonResult.codeLength = GetNullableObjectAtIndex(list, 1); pigeonResult.enrollmentCompletionDeadline = GetNullableObjectAtIndex(list, 2); @@ -759,10 +1296,10 @@ + (PigeonTotpSecret *)fromList:(NSArray *)list { pigeonResult.secretKey = GetNullableObjectAtIndex(list, 4); return pigeonResult; } -+ (nullable PigeonTotpSecret *)nullableFromList:(NSArray *)list { - return (list) ? [PigeonTotpSecret fromList:list] : nil; ++ (nullable InternalTotpSecret *)nullableFromList:(NSArray *)list { + return (list) ? [InternalTotpSecret fromList:list] : nil; } -- (NSArray *)toList { +- (NSArray *)toList { return @[ self.codeIntervalSeconds ?: [NSNull null], self.codeLength ?: [NSNull null], @@ -771,141 +1308,180 @@ - (NSArray *)toList { self.secretKey ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + InternalTotpSecret *other = (InternalTotpSecret *)object; + return FLTPigeonDeepEquals(self.codeIntervalSeconds, other.codeIntervalSeconds) && + FLTPigeonDeepEquals(self.codeLength, other.codeLength) && + FLTPigeonDeepEquals(self.enrollmentCompletionDeadline, + other.enrollmentCompletionDeadline) && + FLTPigeonDeepEquals(self.hashingAlgorithm, other.hashingAlgorithm) && + FLTPigeonDeepEquals(self.secretKey, other.secretKey); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.codeIntervalSeconds); + result = result * 31 + FLTPigeonDeepHash(self.codeLength); + result = result * 31 + FLTPigeonDeepHash(self.enrollmentCompletionDeadline); + result = result * 31 + FLTPigeonDeepHash(self.hashingAlgorithm); + result = result * 31 + FLTPigeonDeepHash(self.secretKey); + return result; +} @end -@interface FirebaseAuthHostApiCodecReader : FlutterStandardReader +@interface nullFirebaseAuthMessagesPigeonCodecReader : FlutterStandardReader @end -@implementation FirebaseAuthHostApiCodecReader +@implementation nullFirebaseAuthMessagesPigeonCodecReader - (nullable id)readValueOfType:(UInt8)type { switch (type) { - case 128: - return [AuthPigeonFirebaseApp fromList:[self readValue]]; - case 129: - return [PigeonActionCodeInfo fromList:[self readValue]]; + case 129: { + NSNumber *enumAsNumber = [self readValue]; + return enumAsNumber == nil + ? nil + : [[ActionCodeInfoOperationBox alloc] initWithValue:[enumAsNumber integerValue]]; + } case 130: - return [PigeonActionCodeInfoData fromList:[self readValue]]; + return [InternalMultiFactorSession fromList:[self readValue]]; case 131: - return [PigeonActionCodeSettings fromList:[self readValue]]; + return [InternalPhoneMultiFactorAssertion fromList:[self readValue]]; case 132: - return [PigeonAdditionalUserInfo fromList:[self readValue]]; + return [InternalMultiFactorInfo fromList:[self readValue]]; case 133: - return [PigeonAuthCredential fromList:[self readValue]]; + return [AuthPigeonFirebaseApp fromList:[self readValue]]; case 134: - return [PigeonFirebaseAuthSettings fromList:[self readValue]]; + return [InternalActionCodeInfoData fromList:[self readValue]]; case 135: - return [PigeonIdTokenResult fromList:[self readValue]]; + return [InternalActionCodeInfo fromList:[self readValue]]; case 136: - return [PigeonMultiFactorInfo fromList:[self readValue]]; + return [InternalAdditionalUserInfo fromList:[self readValue]]; case 137: - return [PigeonMultiFactorSession fromList:[self readValue]]; + return [InternalAuthCredential fromList:[self readValue]]; case 138: - return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; + return [InternalUserInfo fromList:[self readValue]]; case 139: - return [PigeonSignInProvider fromList:[self readValue]]; + return [InternalUserDetails fromList:[self readValue]]; case 140: - return [PigeonTotpSecret fromList:[self readValue]]; + return [InternalUserCredential fromList:[self readValue]]; case 141: - return [PigeonUserCredential fromList:[self readValue]]; + return [InternalAuthCredentialInput fromList:[self readValue]]; case 142: - return [PigeonUserDetails fromList:[self readValue]]; + return [InternalActionCodeSettings fromList:[self readValue]]; case 143: - return [PigeonUserInfo fromList:[self readValue]]; + return [InternalFirebaseAuthSettings fromList:[self readValue]]; case 144: - return [PigeonUserProfile fromList:[self readValue]]; + return [InternalSignInProvider fromList:[self readValue]]; case 145: - return [PigeonVerifyPhoneNumberRequest fromList:[self readValue]]; + return [InternalVerifyPhoneNumberRequest fromList:[self readValue]]; + case 146: + return [InternalIdTokenResult fromList:[self readValue]]; + case 147: + return [InternalUserProfile fromList:[self readValue]]; + case 148: + return [InternalTotpSecret fromList:[self readValue]]; default: return [super readValueOfType:type]; } } @end -@interface FirebaseAuthHostApiCodecWriter : FlutterStandardWriter +@interface nullFirebaseAuthMessagesPigeonCodecWriter : FlutterStandardWriter @end -@implementation FirebaseAuthHostApiCodecWriter +@implementation nullFirebaseAuthMessagesPigeonCodecWriter - (void)writeValue:(id)value { - if ([value isKindOfClass:[AuthPigeonFirebaseApp class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonActionCodeInfo class]]) { + if ([value isKindOfClass:[ActionCodeInfoOperationBox class]]) { + ActionCodeInfoOperationBox *box = (ActionCodeInfoOperationBox *)value; [self writeByte:129]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonActionCodeInfoData class]]) { + [self writeValue:(value == nil ? [NSNull null] : [NSNumber numberWithInteger:box.value])]; + } else if ([value isKindOfClass:[InternalMultiFactorSession class]]) { [self writeByte:130]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonActionCodeSettings class]]) { + } else if ([value isKindOfClass:[InternalPhoneMultiFactorAssertion class]]) { [self writeByte:131]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonAdditionalUserInfo class]]) { + } else if ([value isKindOfClass:[InternalMultiFactorInfo class]]) { [self writeByte:132]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonAuthCredential class]]) { + } else if ([value isKindOfClass:[AuthPigeonFirebaseApp class]]) { [self writeByte:133]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonFirebaseAuthSettings class]]) { + } else if ([value isKindOfClass:[InternalActionCodeInfoData class]]) { [self writeByte:134]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonIdTokenResult class]]) { + } else if ([value isKindOfClass:[InternalActionCodeInfo class]]) { [self writeByte:135]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { + } else if ([value isKindOfClass:[InternalAdditionalUserInfo class]]) { [self writeByte:136]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { + } else if ([value isKindOfClass:[InternalAuthCredential class]]) { [self writeByte:137]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { + } else if ([value isKindOfClass:[InternalUserInfo class]]) { [self writeByte:138]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonSignInProvider class]]) { + } else if ([value isKindOfClass:[InternalUserDetails class]]) { [self writeByte:139]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonTotpSecret class]]) { + } else if ([value isKindOfClass:[InternalUserCredential class]]) { [self writeByte:140]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserCredential class]]) { + } else if ([value isKindOfClass:[InternalAuthCredentialInput class]]) { [self writeByte:141]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserDetails class]]) { + } else if ([value isKindOfClass:[InternalActionCodeSettings class]]) { [self writeByte:142]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserInfo class]]) { + } else if ([value isKindOfClass:[InternalFirebaseAuthSettings class]]) { [self writeByte:143]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserProfile class]]) { + } else if ([value isKindOfClass:[InternalSignInProvider class]]) { [self writeByte:144]; [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonVerifyPhoneNumberRequest class]]) { + } else if ([value isKindOfClass:[InternalVerifyPhoneNumberRequest class]]) { [self writeByte:145]; [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalIdTokenResult class]]) { + [self writeByte:146]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalUserProfile class]]) { + [self writeByte:147]; + [self writeValue:[value toList]]; + } else if ([value isKindOfClass:[InternalTotpSecret class]]) { + [self writeByte:148]; + [self writeValue:[value toList]]; } else { [super writeValue:value]; } } @end -@interface FirebaseAuthHostApiCodecReaderWriter : FlutterStandardReaderWriter +@interface nullFirebaseAuthMessagesPigeonCodecReaderWriter : FlutterStandardReaderWriter @end -@implementation FirebaseAuthHostApiCodecReaderWriter +@implementation nullFirebaseAuthMessagesPigeonCodecReaderWriter - (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[FirebaseAuthHostApiCodecWriter alloc] initWithData:data]; + return [[nullFirebaseAuthMessagesPigeonCodecWriter alloc] initWithData:data]; } - (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[FirebaseAuthHostApiCodecReader alloc] initWithData:data]; + return [[nullFirebaseAuthMessagesPigeonCodecReader alloc] initWithData:data]; } @end -NSObject *FirebaseAuthHostApiGetCodec(void) { +NSObject *nullGetFirebaseAuthMessagesCodec(void) { static FlutterStandardMessageCodec *sSharedObject = nil; static dispatch_once_t sPred = 0; dispatch_once(&sPred, ^{ - FirebaseAuthHostApiCodecReaderWriter *readerWriter = - [[FirebaseAuthHostApiCodecReaderWriter alloc] init]; + nullFirebaseAuthMessagesPigeonCodecReaderWriter *readerWriter = + [[nullFirebaseAuthMessagesPigeonCodecReaderWriter alloc] init]; sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; }); return sSharedObject; } - void SetUpFirebaseAuthHostApi(id binaryMessenger, NSObject *api) { SetUpFirebaseAuthHostApiWithSuffix(binaryMessenger, api, @""); @@ -925,14 +1501,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.registerIdTokenListener", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(registerIdTokenListenerApp:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(registerIdTokenListenerApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api registerIdTokenListenerApp:arg_app completion:^(NSString *_Nullable output, @@ -952,14 +1528,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.registerAuthStateListener", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(registerAuthStateListenerApp:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(registerAuthStateListenerApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api registerAuthStateListenerApp:arg_app completion:^(NSString *_Nullable output, @@ -978,14 +1554,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"interface.FirebaseAuthHostApi.useEmulator", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(useEmulatorApp:host:port:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(useEmulatorApp:host:port:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_host = GetNullableObjectAtIndex(args, 1); NSInteger arg_port = [GetNullableObjectAtIndex(args, 2) integerValue]; @@ -1007,14 +1583,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"interface.FirebaseAuthHostApi.applyActionCode", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(applyActionCodeApp:code:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(applyActionCodeApp:code:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_code = GetNullableObjectAtIndex(args, 1); [api applyActionCodeApp:arg_app @@ -1034,19 +1610,19 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"interface.FirebaseAuthHostApi.checkActionCode", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(checkActionCodeApp:code:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(checkActionCodeApp:code:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_code = GetNullableObjectAtIndex(args, 1); [api checkActionCodeApp:arg_app code:arg_code - completion:^(PigeonActionCodeInfo *_Nullable output, + completion:^(InternalActionCodeInfo *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1063,7 +1639,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.confirmPasswordReset", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(confirmPasswordResetApp:code:newPassword:completion:)], @@ -1071,7 +1647,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(confirmPasswordResetApp:code:newPassword:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_code = GetNullableObjectAtIndex(args, 1); NSString *arg_newPassword = GetNullableObjectAtIndex(args, 2); @@ -1094,7 +1670,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.createUserWithEmailAndPassword", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api @@ -1104,14 +1680,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(createUserWithEmailAndPasswordApp:email:password:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_email = GetNullableObjectAtIndex(args, 1); NSString *arg_password = GetNullableObjectAtIndex(args, 2); [api createUserWithEmailAndPasswordApp:arg_app email:arg_email password:arg_password - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1128,17 +1704,17 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.signInAnonymously", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(signInAnonymouslyApp:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(signInAnonymouslyApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api signInAnonymouslyApp:arg_app - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1155,19 +1731,19 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.signInWithCredential", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(signInWithCredentialApp:input:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(signInWithCredentialApp:input:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); [api signInWithCredentialApp:arg_app input:arg_input - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1184,19 +1760,19 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.signInWithCustomToken", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(signInWithCustomTokenApp:token:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(signInWithCustomTokenApp:token:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_token = GetNullableObjectAtIndex(args, 1); [api signInWithCustomTokenApp:arg_app token:arg_token - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1213,7 +1789,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.signInWithEmailAndPassword", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector( @@ -1222,14 +1798,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(signInWithEmailAndPasswordApp:email:password:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_email = GetNullableObjectAtIndex(args, 1); NSString *arg_password = GetNullableObjectAtIndex(args, 2); [api signInWithEmailAndPasswordApp:arg_app email:arg_email password:arg_password - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1246,7 +1822,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.signInWithEmailLink", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(signInWithEmailLinkApp:email:emailLink:completion:)], @@ -1254,14 +1830,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(signInWithEmailLinkApp:email:emailLink:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_email = GetNullableObjectAtIndex(args, 1); NSString *arg_emailLink = GetNullableObjectAtIndex(args, 2); [api signInWithEmailLinkApp:arg_app email:arg_email emailLink:arg_emailLink - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1278,7 +1854,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.signInWithProvider", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(signInWithProviderApp:signInProvider:completion:)], @@ -1286,12 +1862,12 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(signInWithProviderApp:signInProvider:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); + InternalSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); [api signInWithProviderApp:arg_app signInProvider:arg_signInProvider - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1307,14 +1883,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"interface.FirebaseAuthHostApi.signOut", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(signOutApp:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to @selector(signOutApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api signOutApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -1333,14 +1909,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.fetchSignInMethodsForEmail", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(fetchSignInMethodsForEmailApp:email:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(fetchSignInMethodsForEmailApp:email:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_email = GetNullableObjectAtIndex(args, 1); [api fetchSignInMethodsForEmailApp:arg_app @@ -1362,7 +1938,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.sendPasswordResetEmail", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector: @selector(sendPasswordResetEmailApp:email:actionCodeSettings:completion:)], @@ -1370,10 +1946,10 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(sendPasswordResetEmailApp:email:actionCodeSettings:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_email = GetNullableObjectAtIndex(args, 1); - PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); + InternalActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); [api sendPasswordResetEmailApp:arg_app email:arg_email actionCodeSettings:arg_actionCodeSettings @@ -1393,7 +1969,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.sendSignInLinkToEmail", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector: @selector(sendSignInLinkToEmailApp:email:actionCodeSettings:completion:)], @@ -1401,10 +1977,10 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(sendSignInLinkToEmailApp:email:actionCodeSettings:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_email = GetNullableObjectAtIndex(args, 1); - PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); + InternalActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); [api sendSignInLinkToEmailApp:arg_app email:arg_email actionCodeSettings:arg_actionCodeSettings @@ -1423,14 +1999,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"interface.FirebaseAuthHostApi.setLanguageCode", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(setLanguageCodeApp:languageCode:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(setLanguageCodeApp:languageCode:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_languageCode = GetNullableObjectAtIndex(args, 1); [api setLanguageCodeApp:arg_app @@ -1450,16 +2026,16 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"interface.FirebaseAuthHostApi.setSettings", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(setSettingsApp:settings:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(setSettingsApp:settings:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonFirebaseAuthSettings *arg_settings = GetNullableObjectAtIndex(args, 1); + InternalFirebaseAuthSettings *arg_settings = GetNullableObjectAtIndex(args, 1); [api setSettingsApp:arg_app settings:arg_settings completion:^(FlutterError *_Nullable error) { @@ -1478,14 +2054,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.verifyPasswordResetCode", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(verifyPasswordResetCodeApp:code:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(verifyPasswordResetCodeApp:code:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_code = GetNullableObjectAtIndex(args, 1); [api verifyPasswordResetCodeApp:arg_app @@ -1507,16 +2083,16 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.verifyPhoneNumber", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(verifyPhoneNumberApp:request:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(verifyPhoneNumberApp:request:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonVerifyPhoneNumberRequest *arg_request = GetNullableObjectAtIndex(args, 1); + InternalVerifyPhoneNumberRequest *arg_request = GetNullableObjectAtIndex(args, 1); [api verifyPhoneNumberApp:arg_app request:arg_request completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { @@ -1535,7 +2111,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.revokeTokenWithAuthorizationCode", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(revokeTokenWithAuthorizationCodeApp: authorizationCode:completion:)], @@ -1543,7 +2119,7 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"@selector(revokeTokenWithAuthorizationCodeApp:authorizationCode:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_authorizationCode = GetNullableObjectAtIndex(args, 1); [api revokeTokenWithAuthorizationCodeApp:arg_app @@ -1556,6 +2132,34 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng [channel setMessageHandler:nil]; } } + { + FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] + initWithName:[NSString + stringWithFormat:@"%@%@", + @"dev.flutter.pigeon.firebase_auth_platform_interface." + @"FirebaseAuthHostApi.revokeAccessToken", + messageChannelSuffix] + binaryMessenger:binaryMessenger + codec:nullGetFirebaseAuthMessagesCodec()]; + if (api) { + NSCAssert([api respondsToSelector:@selector(revokeAccessTokenApp:accessToken:completion:)], + @"FirebaseAuthHostApi api (%@) doesn't respond to " + @"@selector(revokeAccessTokenApp:accessToken:completion:)", + api); + [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { + NSArray *args = message; + AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); + NSString *arg_accessToken = GetNullableObjectAtIndex(args, 1); + [api revokeAccessTokenApp:arg_app + accessToken:arg_accessToken + completion:^(FlutterError *_Nullable error) { + callback(wrapResult(nil, error)); + }]; + }]; + } else { + [channel setMessageHandler:nil]; + } + } { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] initWithName:[NSString @@ -1564,14 +2168,14 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng @"FirebaseAuthHostApi.initializeRecaptchaConfig", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(initializeRecaptchaConfigApp:completion:)], @"FirebaseAuthHostApi api (%@) doesn't respond to " @"@selector(initializeRecaptchaConfigApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api initializeRecaptchaConfigApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -1583,139 +2187,6 @@ void SetUpFirebaseAuthHostApiWithSuffix(id binaryMesseng } } } -@interface FirebaseAuthUserHostApiCodecReader : FlutterStandardReader -@end -@implementation FirebaseAuthUserHostApiCodecReader -- (nullable id)readValueOfType:(UInt8)type { - switch (type) { - case 128: - return [AuthPigeonFirebaseApp fromList:[self readValue]]; - case 129: - return [PigeonActionCodeInfo fromList:[self readValue]]; - case 130: - return [PigeonActionCodeInfoData fromList:[self readValue]]; - case 131: - return [PigeonActionCodeSettings fromList:[self readValue]]; - case 132: - return [PigeonAdditionalUserInfo fromList:[self readValue]]; - case 133: - return [PigeonAuthCredential fromList:[self readValue]]; - case 134: - return [PigeonFirebaseAuthSettings fromList:[self readValue]]; - case 135: - return [PigeonIdTokenResult fromList:[self readValue]]; - case 136: - return [PigeonMultiFactorInfo fromList:[self readValue]]; - case 137: - return [PigeonMultiFactorSession fromList:[self readValue]]; - case 138: - return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; - case 139: - return [PigeonSignInProvider fromList:[self readValue]]; - case 140: - return [PigeonTotpSecret fromList:[self readValue]]; - case 141: - return [PigeonUserCredential fromList:[self readValue]]; - case 142: - return [PigeonUserDetails fromList:[self readValue]]; - case 143: - return [PigeonUserInfo fromList:[self readValue]]; - case 144: - return [PigeonUserProfile fromList:[self readValue]]; - case 145: - return [PigeonVerifyPhoneNumberRequest fromList:[self readValue]]; - default: - return [super readValueOfType:type]; - } -} -@end - -@interface FirebaseAuthUserHostApiCodecWriter : FlutterStandardWriter -@end -@implementation FirebaseAuthUserHostApiCodecWriter -- (void)writeValue:(id)value { - if ([value isKindOfClass:[AuthPigeonFirebaseApp class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonActionCodeInfo class]]) { - [self writeByte:129]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonActionCodeInfoData class]]) { - [self writeByte:130]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonActionCodeSettings class]]) { - [self writeByte:131]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonAdditionalUserInfo class]]) { - [self writeByte:132]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonAuthCredential class]]) { - [self writeByte:133]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonFirebaseAuthSettings class]]) { - [self writeByte:134]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonIdTokenResult class]]) { - [self writeByte:135]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { - [self writeByte:136]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { - [self writeByte:137]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { - [self writeByte:138]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonSignInProvider class]]) { - [self writeByte:139]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonTotpSecret class]]) { - [self writeByte:140]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserCredential class]]) { - [self writeByte:141]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserDetails class]]) { - [self writeByte:142]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserInfo class]]) { - [self writeByte:143]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserProfile class]]) { - [self writeByte:144]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonVerifyPhoneNumberRequest class]]) { - [self writeByte:145]; - [self writeValue:[value toList]]; - } else { - [super writeValue:value]; - } -} -@end - -@interface FirebaseAuthUserHostApiCodecReaderWriter : FlutterStandardReaderWriter -@end -@implementation FirebaseAuthUserHostApiCodecReaderWriter -- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[FirebaseAuthUserHostApiCodecWriter alloc] initWithData:data]; -} -- (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[FirebaseAuthUserHostApiCodecReader alloc] initWithData:data]; -} -@end - -NSObject *FirebaseAuthUserHostApiGetCodec(void) { - static FlutterStandardMessageCodec *sSharedObject = nil; - static dispatch_once_t sPred = 0; - dispatch_once(&sPred, ^{ - FirebaseAuthUserHostApiCodecReaderWriter *readerWriter = - [[FirebaseAuthUserHostApiCodecReaderWriter alloc] init]; - sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; - }); - return sSharedObject; -} - void SetUpFirebaseAuthUserHostApi(id binaryMessenger, NSObject *api) { SetUpFirebaseAuthUserHostApiWithSuffix(binaryMessenger, api, @""); @@ -1734,14 +2205,14 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"interface.FirebaseAuthUserHostApi.delete", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(deleteApp:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to @selector(deleteApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api deleteApp:arg_app completion:^(FlutterError *_Nullable error) { @@ -1759,19 +2230,20 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"interface.FirebaseAuthUserHostApi.getIdToken", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(getIdTokenApp:forceRefresh:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(getIdTokenApp:forceRefresh:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); BOOL arg_forceRefresh = [GetNullableObjectAtIndex(args, 1) boolValue]; [api getIdTokenApp:arg_app forceRefresh:arg_forceRefresh - completion:^(PigeonIdTokenResult *_Nullable output, FlutterError *_Nullable error) { + completion:^(InternalIdTokenResult *_Nullable output, + FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; }]; @@ -1787,19 +2259,19 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.linkWithCredential", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(linkWithCredentialApp:input:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(linkWithCredentialApp:input:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); [api linkWithCredentialApp:arg_app input:arg_input - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1816,19 +2288,19 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.linkWithProvider", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(linkWithProviderApp:signInProvider:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(linkWithProviderApp:signInProvider:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); + InternalSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); [api linkWithProviderApp:arg_app signInProvider:arg_signInProvider - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1845,7 +2317,7 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.reauthenticateWithCredential", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(reauthenticateWithCredentialApp:input:completion:)], @@ -1853,12 +2325,12 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"@selector(reauthenticateWithCredentialApp:input:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); [api reauthenticateWithCredentialApp:arg_app input:arg_input - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1875,7 +2347,7 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.reauthenticateWithProvider", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector( @@ -1884,12 +2356,12 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"@selector(reauthenticateWithProviderApp:signInProvider:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); + InternalSignInProvider *arg_signInProvider = GetNullableObjectAtIndex(args, 1); [api reauthenticateWithProviderApp:arg_app signInProvider:arg_signInProvider - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -1905,17 +2377,17 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"interface.FirebaseAuthUserHostApi.reload", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(reloadApp:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to @selector(reloadApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api reloadApp:arg_app - completion:^(PigeonUserDetails *_Nullable output, FlutterError *_Nullable error) { + completion:^(InternalUserDetails *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; }]; @@ -1931,7 +2403,7 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.sendEmailVerification", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector( @@ -1940,9 +2412,9 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"@selector(sendEmailVerificationApp:actionCodeSettings:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 1); + InternalActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 1); [api sendEmailVerificationApp:arg_app actionCodeSettings:arg_actionCodeSettings completion:^(FlutterError *_Nullable error) { @@ -1960,19 +2432,19 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"interface.FirebaseAuthUserHostApi.unlink", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(unlinkApp:providerId:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(unlinkApp:providerId:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_providerId = GetNullableObjectAtIndex(args, 1); [api unlinkApp:arg_app providerId:arg_providerId - completion:^(PigeonUserCredential *_Nullable output, FlutterError *_Nullable error) { + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; }]; @@ -1987,21 +2459,22 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"interface.FirebaseAuthUserHostApi.updateEmail", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(updateEmailApp:newEmail:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(updateEmailApp:newEmail:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_newEmail = GetNullableObjectAtIndex(args, 1); - [api updateEmailApp:arg_app - newEmail:arg_newEmail - completion:^(PigeonUserDetails *_Nullable output, FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; + [api + updateEmailApp:arg_app + newEmail:arg_newEmail + completion:^(InternalUserDetails *_Nullable output, FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; }]; } else { [channel setMessageHandler:nil]; @@ -2015,19 +2488,19 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.updatePassword", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(updatePasswordApp:newPassword:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(updatePasswordApp:newPassword:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_newPassword = GetNullableObjectAtIndex(args, 1); [api updatePasswordApp:arg_app newPassword:arg_newPassword - completion:^(PigeonUserDetails *_Nullable output, + completion:^(InternalUserDetails *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -2044,19 +2517,19 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.updatePhoneNumber", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(updatePhoneNumberApp:input:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(updatePhoneNumberApp:input:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSDictionary *arg_input = GetNullableObjectAtIndex(args, 1); [api updatePhoneNumberApp:arg_app input:arg_input - completion:^(PigeonUserDetails *_Nullable output, + completion:^(InternalUserDetails *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -2073,22 +2546,22 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.updateProfile", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(updateProfileApp:profile:completion:)], @"FirebaseAuthUserHostApi api (%@) doesn't respond to " @"@selector(updateProfileApp:profile:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonUserProfile *arg_profile = GetNullableObjectAtIndex(args, 1); - [api - updateProfileApp:arg_app - profile:arg_profile - completion:^(PigeonUserDetails *_Nullable output, FlutterError *_Nullable error) { - callback(wrapResult(output, error)); - }]; + InternalUserProfile *arg_profile = GetNullableObjectAtIndex(args, 1); + [api updateProfileApp:arg_app + profile:arg_profile + completion:^(InternalUserDetails *_Nullable output, + FlutterError *_Nullable error) { + callback(wrapResult(output, error)); + }]; }]; } else { [channel setMessageHandler:nil]; @@ -2102,7 +2575,7 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"FirebaseAuthUserHostApi.verifyBeforeUpdateEmail", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:FirebaseAuthUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(verifyBeforeUpdateEmailApp:newEmail: actionCodeSettings:completion:)], @@ -2110,10 +2583,10 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes @"@selector(verifyBeforeUpdateEmailApp:newEmail:actionCodeSettings:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_newEmail = GetNullableObjectAtIndex(args, 1); - PigeonActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); + InternalActionCodeSettings *arg_actionCodeSettings = GetNullableObjectAtIndex(args, 2); [api verifyBeforeUpdateEmailApp:arg_app newEmail:arg_newEmail actionCodeSettings:arg_actionCodeSettings @@ -2126,69 +2599,6 @@ void SetUpFirebaseAuthUserHostApiWithSuffix(id binaryMes } } } -@interface MultiFactorUserHostApiCodecReader : FlutterStandardReader -@end -@implementation MultiFactorUserHostApiCodecReader -- (nullable id)readValueOfType:(UInt8)type { - switch (type) { - case 128: - return [AuthPigeonFirebaseApp fromList:[self readValue]]; - case 129: - return [PigeonMultiFactorInfo fromList:[self readValue]]; - case 130: - return [PigeonMultiFactorSession fromList:[self readValue]]; - case 131: - return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; - default: - return [super readValueOfType:type]; - } -} -@end - -@interface MultiFactorUserHostApiCodecWriter : FlutterStandardWriter -@end -@implementation MultiFactorUserHostApiCodecWriter -- (void)writeValue:(id)value { - if ([value isKindOfClass:[AuthPigeonFirebaseApp class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { - [self writeByte:129]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonMultiFactorSession class]]) { - [self writeByte:130]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { - [self writeByte:131]; - [self writeValue:[value toList]]; - } else { - [super writeValue:value]; - } -} -@end - -@interface MultiFactorUserHostApiCodecReaderWriter : FlutterStandardReaderWriter -@end -@implementation MultiFactorUserHostApiCodecReaderWriter -- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[MultiFactorUserHostApiCodecWriter alloc] initWithData:data]; -} -- (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[MultiFactorUserHostApiCodecReader alloc] initWithData:data]; -} -@end - -NSObject *MultiFactorUserHostApiGetCodec(void) { - static FlutterStandardMessageCodec *sSharedObject = nil; - static dispatch_once_t sPred = 0; - dispatch_once(&sPred, ^{ - MultiFactorUserHostApiCodecReaderWriter *readerWriter = - [[MultiFactorUserHostApiCodecReaderWriter alloc] init]; - sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; - }); - return sSharedObject; -} - void SetUpMultiFactorUserHostApi(id binaryMessenger, NSObject *api) { SetUpMultiFactorUserHostApiWithSuffix(binaryMessenger, api, @""); @@ -2207,7 +2617,7 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess @"interface.MultiFactorUserHostApi.enrollPhone", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(enrollPhoneApp:assertion:displayName:completion:)], @@ -2215,9 +2625,9 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess @"@selector(enrollPhoneApp:assertion:displayName:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); - PigeonPhoneMultiFactorAssertion *arg_assertion = GetNullableObjectAtIndex(args, 1); + InternalPhoneMultiFactorAssertion *arg_assertion = GetNullableObjectAtIndex(args, 1); NSString *arg_displayName = GetNullableObjectAtIndex(args, 2); [api enrollPhoneApp:arg_app assertion:arg_assertion @@ -2237,7 +2647,7 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess @"interface.MultiFactorUserHostApi.enrollTotp", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(enrollTotpApp:assertionId:displayName:completion:)], @@ -2245,7 +2655,7 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess @"@selector(enrollTotpApp:assertionId:displayName:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_assertionId = GetNullableObjectAtIndex(args, 1); NSString *arg_displayName = GetNullableObjectAtIndex(args, 2); @@ -2267,17 +2677,17 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess @"interface.MultiFactorUserHostApi.getSession", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(getSessionApp:completion:)], @"MultiFactorUserHostApi api (%@) doesn't respond to " @"@selector(getSessionApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api getSessionApp:arg_app - completion:^(PigeonMultiFactorSession *_Nullable output, + completion:^(InternalMultiFactorSession *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -2293,14 +2703,14 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess @"interface.MultiFactorUserHostApi.unenroll", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(unenrollApp:factorUid:completion:)], @"MultiFactorUserHostApi api (%@) doesn't respond to " @"@selector(unenrollApp:factorUid:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); NSString *arg_factorUid = GetNullableObjectAtIndex(args, 1); [api unenrollApp:arg_app @@ -2321,17 +2731,17 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess @"MultiFactorUserHostApi.getEnrolledFactors", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorUserHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(getEnrolledFactorsApp:completion:)], @"MultiFactorUserHostApi api (%@) doesn't respond to " @"@selector(getEnrolledFactorsApp:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; AuthPigeonFirebaseApp *arg_app = GetNullableObjectAtIndex(args, 0); [api getEnrolledFactorsApp:arg_app - completion:^(NSArray *_Nullable output, + completion:^(NSArray *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -2341,79 +2751,6 @@ void SetUpMultiFactorUserHostApiWithSuffix(id binaryMess } } } -@interface MultiFactoResolverHostApiCodecReader : FlutterStandardReader -@end -@implementation MultiFactoResolverHostApiCodecReader -- (nullable id)readValueOfType:(UInt8)type { - switch (type) { - case 128: - return [PigeonAdditionalUserInfo fromList:[self readValue]]; - case 129: - return [PigeonAuthCredential fromList:[self readValue]]; - case 130: - return [PigeonPhoneMultiFactorAssertion fromList:[self readValue]]; - case 131: - return [PigeonUserCredential fromList:[self readValue]]; - case 132: - return [PigeonUserDetails fromList:[self readValue]]; - case 133: - return [PigeonUserInfo fromList:[self readValue]]; - default: - return [super readValueOfType:type]; - } -} -@end - -@interface MultiFactoResolverHostApiCodecWriter : FlutterStandardWriter -@end -@implementation MultiFactoResolverHostApiCodecWriter -- (void)writeValue:(id)value { - if ([value isKindOfClass:[PigeonAdditionalUserInfo class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonAuthCredential class]]) { - [self writeByte:129]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonPhoneMultiFactorAssertion class]]) { - [self writeByte:130]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserCredential class]]) { - [self writeByte:131]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserDetails class]]) { - [self writeByte:132]; - [self writeValue:[value toList]]; - } else if ([value isKindOfClass:[PigeonUserInfo class]]) { - [self writeByte:133]; - [self writeValue:[value toList]]; - } else { - [super writeValue:value]; - } -} -@end - -@interface MultiFactoResolverHostApiCodecReaderWriter : FlutterStandardReaderWriter -@end -@implementation MultiFactoResolverHostApiCodecReaderWriter -- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[MultiFactoResolverHostApiCodecWriter alloc] initWithData:data]; -} -- (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[MultiFactoResolverHostApiCodecReader alloc] initWithData:data]; -} -@end - -NSObject *MultiFactoResolverHostApiGetCodec(void) { - static FlutterStandardMessageCodec *sSharedObject = nil; - static dispatch_once_t sPred = 0; - dispatch_once(&sPred, ^{ - MultiFactoResolverHostApiCodecReaderWriter *readerWriter = - [[MultiFactoResolverHostApiCodecReaderWriter alloc] init]; - sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; - }); - return sSharedObject; -} - void SetUpMultiFactoResolverHostApi(id binaryMessenger, NSObject *api) { SetUpMultiFactoResolverHostApiWithSuffix(binaryMessenger, api, @""); @@ -2433,7 +2770,7 @@ void SetUpMultiFactoResolverHostApiWithSuffix(id binaryM @"MultiFactoResolverHostApi.resolveSignIn", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactoResolverHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector: @selector(resolveSignInResolverId:assertion:totpAssertionId:completion:)], @@ -2441,14 +2778,14 @@ void SetUpMultiFactoResolverHostApiWithSuffix(id binaryM @"@selector(resolveSignInResolverId:assertion:totpAssertionId:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; NSString *arg_resolverId = GetNullableObjectAtIndex(args, 0); - PigeonPhoneMultiFactorAssertion *arg_assertion = GetNullableObjectAtIndex(args, 1); + InternalPhoneMultiFactorAssertion *arg_assertion = GetNullableObjectAtIndex(args, 1); NSString *arg_totpAssertionId = GetNullableObjectAtIndex(args, 2); [api resolveSignInResolverId:arg_resolverId assertion:arg_assertion totpAssertionId:arg_totpAssertionId - completion:^(PigeonUserCredential *_Nullable output, + completion:^(InternalUserCredential *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -2458,54 +2795,6 @@ void SetUpMultiFactoResolverHostApiWithSuffix(id binaryM } } } -@interface MultiFactorTotpHostApiCodecReader : FlutterStandardReader -@end -@implementation MultiFactorTotpHostApiCodecReader -- (nullable id)readValueOfType:(UInt8)type { - switch (type) { - case 128: - return [PigeonTotpSecret fromList:[self readValue]]; - default: - return [super readValueOfType:type]; - } -} -@end - -@interface MultiFactorTotpHostApiCodecWriter : FlutterStandardWriter -@end -@implementation MultiFactorTotpHostApiCodecWriter -- (void)writeValue:(id)value { - if ([value isKindOfClass:[PigeonTotpSecret class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else { - [super writeValue:value]; - } -} -@end - -@interface MultiFactorTotpHostApiCodecReaderWriter : FlutterStandardReaderWriter -@end -@implementation MultiFactorTotpHostApiCodecReaderWriter -- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[MultiFactorTotpHostApiCodecWriter alloc] initWithData:data]; -} -- (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[MultiFactorTotpHostApiCodecReader alloc] initWithData:data]; -} -@end - -NSObject *MultiFactorTotpHostApiGetCodec(void) { - static FlutterStandardMessageCodec *sSharedObject = nil; - static dispatch_once_t sPred = 0; - dispatch_once(&sPred, ^{ - MultiFactorTotpHostApiCodecReaderWriter *readerWriter = - [[MultiFactorTotpHostApiCodecReaderWriter alloc] init]; - sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; - }); - return sSharedObject; -} - void SetUpMultiFactorTotpHostApi(id binaryMessenger, NSObject *api) { SetUpMultiFactorTotpHostApiWithSuffix(binaryMessenger, api, @""); @@ -2525,17 +2814,17 @@ void SetUpMultiFactorTotpHostApiWithSuffix(id binaryMess @"MultiFactorTotpHostApi.generateSecret", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorTotpHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(generateSecretSessionId:completion:)], @"MultiFactorTotpHostApi api (%@) doesn't respond to " @"@selector(generateSecretSessionId:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; NSString *arg_sessionId = GetNullableObjectAtIndex(args, 0); [api generateSecretSessionId:arg_sessionId - completion:^(PigeonTotpSecret *_Nullable output, + completion:^(InternalTotpSecret *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; @@ -2552,7 +2841,7 @@ void SetUpMultiFactorTotpHostApiWithSuffix(id binaryMess @"MultiFactorTotpHostApi.getAssertionForEnrollment", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorTotpHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector: @selector(getAssertionForEnrollmentSecretKey:oneTimePassword:completion:)], @@ -2560,7 +2849,7 @@ void SetUpMultiFactorTotpHostApiWithSuffix(id binaryMess @"@selector(getAssertionForEnrollmentSecretKey:oneTimePassword:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; NSString *arg_secretKey = GetNullableObjectAtIndex(args, 0); NSString *arg_oneTimePassword = GetNullableObjectAtIndex(args, 1); [api getAssertionForEnrollmentSecretKey:arg_secretKey @@ -2582,7 +2871,7 @@ void SetUpMultiFactorTotpHostApiWithSuffix(id binaryMess @"MultiFactorTotpHostApi.getAssertionForSignIn", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorTotpHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector: @selector(getAssertionForSignInEnrollmentId:oneTimePassword:completion:)], @@ -2590,7 +2879,7 @@ void SetUpMultiFactorTotpHostApiWithSuffix(id binaryMess @"@selector(getAssertionForSignInEnrollmentId:oneTimePassword:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; NSString *arg_enrollmentId = GetNullableObjectAtIndex(args, 0); NSString *arg_oneTimePassword = GetNullableObjectAtIndex(args, 1); [api getAssertionForSignInEnrollmentId:arg_enrollmentId @@ -2605,12 +2894,6 @@ void SetUpMultiFactorTotpHostApiWithSuffix(id binaryMess } } } -NSObject *MultiFactorTotpSecretHostApiGetCodec(void) { - static FlutterStandardMessageCodec *sSharedObject = nil; - sSharedObject = [FlutterStandardMessageCodec sharedInstance]; - return sSharedObject; -} - void SetUpMultiFactorTotpSecretHostApi(id binaryMessenger, NSObject *api) { SetUpMultiFactorTotpSecretHostApiWithSuffix(binaryMessenger, api, @""); @@ -2630,7 +2913,7 @@ void SetUpMultiFactorTotpSecretHostApiWithSuffix(id bina @"MultiFactorTotpSecretHostApi.generateQrCodeUrl", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorTotpSecretHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector( @@ -2639,7 +2922,7 @@ void SetUpMultiFactorTotpSecretHostApiWithSuffix(id bina @"@selector(generateQrCodeUrlSecretKey:accountName:issuer:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; NSString *arg_secretKey = GetNullableObjectAtIndex(args, 0); NSString *arg_accountName = GetNullableObjectAtIndex(args, 1); NSString *arg_issuer = GetNullableObjectAtIndex(args, 2); @@ -2663,14 +2946,14 @@ void SetUpMultiFactorTotpSecretHostApiWithSuffix(id bina @"MultiFactorTotpSecretHostApi.openInOtpApp", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:MultiFactorTotpSecretHostApiGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector(openInOtpAppSecretKey:qrCodeUrl:completion:)], @"MultiFactorTotpSecretHostApi api (%@) doesn't respond to " @"@selector(openInOtpAppSecretKey:qrCodeUrl:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; + NSArray *args = message; NSString *arg_secretKey = GetNullableObjectAtIndex(args, 0); NSString *arg_qrCodeUrl = GetNullableObjectAtIndex(args, 1); [api openInOtpAppSecretKey:arg_secretKey @@ -2684,54 +2967,6 @@ void SetUpMultiFactorTotpSecretHostApiWithSuffix(id bina } } } -@interface GenerateInterfacesCodecReader : FlutterStandardReader -@end -@implementation GenerateInterfacesCodecReader -- (nullable id)readValueOfType:(UInt8)type { - switch (type) { - case 128: - return [PigeonMultiFactorInfo fromList:[self readValue]]; - default: - return [super readValueOfType:type]; - } -} -@end - -@interface GenerateInterfacesCodecWriter : FlutterStandardWriter -@end -@implementation GenerateInterfacesCodecWriter -- (void)writeValue:(id)value { - if ([value isKindOfClass:[PigeonMultiFactorInfo class]]) { - [self writeByte:128]; - [self writeValue:[value toList]]; - } else { - [super writeValue:value]; - } -} -@end - -@interface GenerateInterfacesCodecReaderWriter : FlutterStandardReaderWriter -@end -@implementation GenerateInterfacesCodecReaderWriter -- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data { - return [[GenerateInterfacesCodecWriter alloc] initWithData:data]; -} -- (FlutterStandardReader *)readerWithData:(NSData *)data { - return [[GenerateInterfacesCodecReader alloc] initWithData:data]; -} -@end - -NSObject *GenerateInterfacesGetCodec(void) { - static FlutterStandardMessageCodec *sSharedObject = nil; - static dispatch_once_t sPred = 0; - dispatch_once(&sPred, ^{ - GenerateInterfacesCodecReaderWriter *readerWriter = - [[GenerateInterfacesCodecReaderWriter alloc] init]; - sSharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter]; - }); - return sSharedObject; -} - void SetUpGenerateInterfaces(id binaryMessenger, NSObject *api) { SetUpGenerateInterfacesWithSuffix(binaryMessenger, api, @""); @@ -2750,15 +2985,15 @@ void SetUpGenerateInterfacesWithSuffix(id binaryMessenge @"interface.GenerateInterfaces.pigeonInterface", messageChannelSuffix] binaryMessenger:binaryMessenger - codec:GenerateInterfacesGetCodec()]; + codec:nullGetFirebaseAuthMessagesCodec()]; if (api) { NSCAssert( [api respondsToSelector:@selector(pigeonInterfaceInfo:error:)], @"GenerateInterfaces api (%@) doesn't respond to @selector(pigeonInterfaceInfo:error:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { - NSArray *args = message; - PigeonMultiFactorInfo *arg_info = GetNullableObjectAtIndex(args, 0); + NSArray *args = message; + InternalMultiFactorInfo *arg_info = GetNullableObjectAtIndex(args, 0); FlutterError *error; [api pigeonInterfaceInfo:arg_info error:&error]; callback(wrapResult(nil, error)); diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/FLTPhoneNumberVerificationStreamHandler.h b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/FLTPhoneNumberVerificationStreamHandler.h index a576f233e99a..53e5f28cea90 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/FLTPhoneNumberVerificationStreamHandler.h +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/FLTPhoneNumberVerificationStreamHandler.h @@ -26,7 +26,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithAuth:(FIRAuth *)auth arguments:(NSDictionary *)arguments; #else - (instancetype)initWithAuth:(FIRAuth *)auth - request:(PigeonVerifyPhoneNumberRequest *)request + request:(InternalVerifyPhoneNumberRequest *)request session:(FIRMultiFactorSession *)session factorInfo:(FIRPhoneMultiFactorInfo *)factorInfo; #endif diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/PigeonParser.h b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/PigeonParser.h index 515a61a895b5..b500fd2c878e 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/PigeonParser.h +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Private/PigeonParser.h @@ -16,18 +16,18 @@ @interface PigeonParser : NSObject -+ (NSArray *_Nonnull)getManualList:(nonnull PigeonUserDetails *)userDetails; -+ (PigeonUserCredential *_Nullable) ++ (NSArray *_Nonnull)getManualList:(nonnull InternalUserDetails *)userDetails; ++ (InternalUserCredential *_Nullable) getPigeonUserCredentialFromAuthResult:(nonnull FIRAuthDataResult *)authResult authorizationCode:(nullable NSString *)authorizationCode; -+ (PigeonUserDetails *_Nullable)getPigeonDetails:(nonnull FIRUser *)user; -+ (PigeonUserInfo *_Nullable)getPigeonUserInfo:(nonnull FIRUser *)user; ++ (InternalUserDetails *_Nullable)getPigeonDetails:(nonnull FIRUser *)user; ++ (InternalUserInfo *_Nullable)getPigeonUserInfo:(nonnull FIRUser *)user; + (FIRActionCodeSettings *_Nullable)parseActionCodeSettings: - (nullable PigeonActionCodeSettings *)settings; -+ (PigeonUserCredential *_Nullable)getPigeonUserCredentialFromFIRUser:(nonnull FIRUser *)user; -+ (PigeonIdTokenResult *_Nonnull)parseIdTokenResult:(nonnull FIRAuthTokenResult *)tokenResult; -+ (PigeonTotpSecret *_Nonnull)getPigeonTotpSecret:(nonnull FIRTOTPSecret *)secret; -+ (PigeonAuthCredential *_Nullable)getPigeonAuthCredential: - (FIRAuthCredential *_Nullable)authCredentialToken - token:(NSNumber *_Nullable)token; + (nullable InternalActionCodeSettings *)settings; ++ (InternalUserCredential *_Nullable)getPigeonUserCredentialFromFIRUser:(nonnull FIRUser *)user; ++ (InternalIdTokenResult *_Nonnull)parseIdTokenResult:(nonnull FIRAuthTokenResult *)tokenResult; ++ (InternalTotpSecret *_Nonnull)getPigeonTotpSecret:(nonnull FIRTOTPSecret *)secret; ++ (InternalAuthCredential *_Nullable)getPigeonAuthCredential: + (FIRAuthCredential *_Nullable)authCredentialToken + token:(NSNumber *_Nullable)token; @end diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/CustomPigeonHeader.h b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/CustomPigeonHeader.h index 17111415acb6..d32a6b451629 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/CustomPigeonHeader.h +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/CustomPigeonHeader.h @@ -3,14 +3,14 @@ // found in the LICENSE file. #import "firebase_auth_messages.g.h" -@interface PigeonMultiFactorInfo (Map) +@interface InternalMultiFactorInfo (Map) - (NSDictionary *)toList; @end -@interface PigeonUserDetails (Map) +@interface InternalUserDetails (Map) - (NSDictionary *)toList; @end -@interface PigeonUserInfo (Map) +@interface InternalUserInfo (Map) - (NSDictionary *)toList; @end diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/firebase_auth_messages.g.h b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/firebase_auth_messages.g.h index fe48f267f2af..f83da7e34a3b 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/firebase_auth_messages.g.h +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/firebase_auth_messages.g.h @@ -1,10 +1,10 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v19.0.0), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import +@import Foundation; @protocol FlutterBinaryMessenger; @protocol FlutterMessageCodec; @@ -38,33 +38,34 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { - (instancetype)initWithValue:(ActionCodeInfoOperation)value; @end -@class PigeonMultiFactorSession; -@class PigeonPhoneMultiFactorAssertion; -@class PigeonMultiFactorInfo; +@class InternalMultiFactorSession; +@class InternalPhoneMultiFactorAssertion; +@class InternalMultiFactorInfo; @class AuthPigeonFirebaseApp; -@class PigeonActionCodeInfoData; -@class PigeonActionCodeInfo; -@class PigeonAdditionalUserInfo; -@class PigeonAuthCredential; -@class PigeonUserInfo; -@class PigeonUserDetails; -@class PigeonUserCredential; -@class PigeonActionCodeSettings; -@class PigeonFirebaseAuthSettings; -@class PigeonSignInProvider; -@class PigeonVerifyPhoneNumberRequest; -@class PigeonIdTokenResult; -@class PigeonUserProfile; -@class PigeonTotpSecret; - -@interface PigeonMultiFactorSession : NSObject +@class InternalActionCodeInfoData; +@class InternalActionCodeInfo; +@class InternalAdditionalUserInfo; +@class InternalAuthCredential; +@class InternalUserInfo; +@class InternalUserDetails; +@class InternalUserCredential; +@class InternalAuthCredentialInput; +@class InternalActionCodeSettings; +@class InternalFirebaseAuthSettings; +@class InternalSignInProvider; +@class InternalVerifyPhoneNumberRequest; +@class InternalIdTokenResult; +@class InternalUserProfile; +@class InternalTotpSecret; + +@interface InternalMultiFactorSession : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithId:(NSString *)id; @property(nonatomic, copy) NSString *id; @end -@interface PigeonPhoneMultiFactorAssertion : NSObject +@interface InternalPhoneMultiFactorAssertion : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithVerificationId:(NSString *)verificationId @@ -73,7 +74,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy) NSString *verificationCode; @end -@interface PigeonMultiFactorInfo : NSObject +@interface InternalMultiFactorInfo : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithDisplayName:(nullable NSString *)displayName @@ -99,23 +100,23 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy, nullable) NSString *customAuthDomain; @end -@interface PigeonActionCodeInfoData : NSObject +@interface InternalActionCodeInfoData : NSObject + (instancetype)makeWithEmail:(nullable NSString *)email previousEmail:(nullable NSString *)previousEmail; @property(nonatomic, copy, nullable) NSString *email; @property(nonatomic, copy, nullable) NSString *previousEmail; @end -@interface PigeonActionCodeInfo : NSObject +@interface InternalActionCodeInfo : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithOperation:(ActionCodeInfoOperation)operation - data:(PigeonActionCodeInfoData *)data; + data:(InternalActionCodeInfoData *)data; @property(nonatomic, assign) ActionCodeInfoOperation operation; -@property(nonatomic, strong) PigeonActionCodeInfoData *data; +@property(nonatomic, strong) InternalActionCodeInfoData *data; @end -@interface PigeonAdditionalUserInfo : NSObject +@interface InternalAdditionalUserInfo : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithIsNewUser:(BOOL)isNewUser @@ -130,7 +131,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy, nullable) NSDictionary *profile; @end -@interface PigeonAuthCredential : NSObject +@interface InternalAuthCredential : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithProviderId:(NSString *)providerId @@ -143,7 +144,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy, nullable) NSString *accessToken; @end -@interface PigeonUserInfo : NSObject +@interface InternalUserInfo : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithUid:(NSString *)uid @@ -172,25 +173,38 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, strong, nullable) NSNumber *lastSignInTimestamp; @end -@interface PigeonUserDetails : NSObject +@interface InternalUserDetails : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; -+ (instancetype)makeWithUserInfo:(PigeonUserInfo *)userInfo ++ (instancetype)makeWithUserInfo:(InternalUserInfo *)userInfo providerData:(NSArray *> *)providerData; -@property(nonatomic, strong) PigeonUserInfo *userInfo; +@property(nonatomic, strong) InternalUserInfo *userInfo; @property(nonatomic, copy) NSArray *> *providerData; @end -@interface PigeonUserCredential : NSObject -+ (instancetype)makeWithUser:(nullable PigeonUserDetails *)user - additionalUserInfo:(nullable PigeonAdditionalUserInfo *)additionalUserInfo - credential:(nullable PigeonAuthCredential *)credential; -@property(nonatomic, strong, nullable) PigeonUserDetails *user; -@property(nonatomic, strong, nullable) PigeonAdditionalUserInfo *additionalUserInfo; -@property(nonatomic, strong, nullable) PigeonAuthCredential *credential; +@interface InternalUserCredential : NSObject ++ (instancetype)makeWithUser:(nullable InternalUserDetails *)user + additionalUserInfo:(nullable InternalAdditionalUserInfo *)additionalUserInfo + credential:(nullable InternalAuthCredential *)credential; +@property(nonatomic, strong, nullable) InternalUserDetails *user; +@property(nonatomic, strong, nullable) InternalAdditionalUserInfo *additionalUserInfo; +@property(nonatomic, strong, nullable) InternalAuthCredential *credential; @end -@interface PigeonActionCodeSettings : NSObject +@interface InternalAuthCredentialInput : NSObject +/// `init` unavailable to enforce nonnull fields, see the `make` class method. +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)makeWithProviderId:(NSString *)providerId + signInMethod:(NSString *)signInMethod + token:(nullable NSString *)token + accessToken:(nullable NSString *)accessToken; +@property(nonatomic, copy) NSString *providerId; +@property(nonatomic, copy) NSString *signInMethod; +@property(nonatomic, copy, nullable) NSString *token; +@property(nonatomic, copy, nullable) NSString *accessToken; +@end + +@interface InternalActionCodeSettings : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithUrl:(NSString *)url @@ -211,7 +225,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy, nullable) NSString *linkDomain; @end -@interface PigeonFirebaseAuthSettings : NSObject +@interface InternalFirebaseAuthSettings : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithAppVerificationDisabledForTesting:(BOOL)appVerificationDisabledForTesting @@ -226,7 +240,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, strong, nullable) NSNumber *forceRecaptchaFlow; @end -@interface PigeonSignInProvider : NSObject +@interface InternalSignInProvider : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithProviderId:(NSString *)providerId @@ -238,7 +252,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy, nullable) NSDictionary *customParameters; @end -@interface PigeonVerifyPhoneNumberRequest : NSObject +@interface InternalVerifyPhoneNumberRequest : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithPhoneNumber:(nullable NSString *)phoneNumber @@ -255,7 +269,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy, nullable) NSString *multiFactorSessionId; @end -@interface PigeonIdTokenResult : NSObject +@interface InternalIdTokenResult : NSObject + (instancetype)makeWithToken:(nullable NSString *)token expirationTimestamp:(nullable NSNumber *)expirationTimestamp authTimestamp:(nullable NSNumber *)authTimestamp @@ -272,7 +286,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy, nullable) NSString *signInSecondFactor; @end -@interface PigeonUserProfile : NSObject +@interface InternalUserProfile : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithDisplayName:(nullable NSString *)displayName @@ -285,7 +299,7 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, assign) BOOL photoUrlChanged; @end -@interface PigeonTotpSecret : NSObject +@interface InternalTotpSecret : NSObject /// `init` unavailable to enforce nonnull fields, see the `make` class method. - (instancetype)init NS_UNAVAILABLE; + (instancetype)makeWithCodeIntervalSeconds:(nullable NSNumber *)codeIntervalSeconds @@ -300,8 +314,8 @@ typedef NS_ENUM(NSUInteger, ActionCodeInfoOperation) { @property(nonatomic, copy) NSString *secretKey; @end -/// The codec used by FirebaseAuthHostApi. -NSObject *FirebaseAuthHostApiGetCodec(void); +/// The codec used by all APIs. +NSObject *nullGetFirebaseAuthMessagesCodec(void); @protocol FirebaseAuthHostApi - (void)registerIdTokenListenerApp:(AuthPigeonFirebaseApp *)app @@ -319,8 +333,8 @@ NSObject *FirebaseAuthHostApiGetCodec(void); completion:(void (^)(FlutterError *_Nullable))completion; - (void)checkActionCodeApp:(AuthPigeonFirebaseApp *)app code:(NSString *)code - completion: - (void (^)(PigeonActionCodeInfo *_Nullable, FlutterError *_Nullable))completion; + completion:(void (^)(InternalActionCodeInfo *_Nullable, + FlutterError *_Nullable))completion; - (void)confirmPasswordResetApp:(AuthPigeonFirebaseApp *)app code:(NSString *)code newPassword:(NSString *)newPassword @@ -328,32 +342,32 @@ NSObject *FirebaseAuthHostApiGetCodec(void); - (void)createUserWithEmailAndPasswordApp:(AuthPigeonFirebaseApp *)app email:(NSString *)email password:(NSString *)password - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)signInAnonymouslyApp:(AuthPigeonFirebaseApp *)app - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)signInWithCredentialApp:(AuthPigeonFirebaseApp *)app input:(NSDictionary *)input - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)signInWithCustomTokenApp:(AuthPigeonFirebaseApp *)app token:(NSString *)token - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)signInWithEmailAndPasswordApp:(AuthPigeonFirebaseApp *)app email:(NSString *)email password:(NSString *)password - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)signInWithEmailLinkApp:(AuthPigeonFirebaseApp *)app email:(NSString *)email emailLink:(NSString *)emailLink - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)signInWithProviderApp:(AuthPigeonFirebaseApp *)app - signInProvider:(PigeonSignInProvider *)signInProvider - completion:(void (^)(PigeonUserCredential *_Nullable, + signInProvider:(InternalSignInProvider *)signInProvider + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)signOutApp:(AuthPigeonFirebaseApp *)app completion:(void (^)(FlutterError *_Nullable))completion; @@ -363,28 +377,31 @@ NSObject *FirebaseAuthHostApiGetCodec(void); FlutterError *_Nullable))completion; - (void)sendPasswordResetEmailApp:(AuthPigeonFirebaseApp *)app email:(NSString *)email - actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(nullable InternalActionCodeSettings *)actionCodeSettings completion:(void (^)(FlutterError *_Nullable))completion; - (void)sendSignInLinkToEmailApp:(AuthPigeonFirebaseApp *)app email:(NSString *)email - actionCodeSettings:(PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(InternalActionCodeSettings *)actionCodeSettings completion:(void (^)(FlutterError *_Nullable))completion; - (void)setLanguageCodeApp:(AuthPigeonFirebaseApp *)app languageCode:(nullable NSString *)languageCode completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)setSettingsApp:(AuthPigeonFirebaseApp *)app - settings:(PigeonFirebaseAuthSettings *)settings + settings:(InternalFirebaseAuthSettings *)settings completion:(void (^)(FlutterError *_Nullable))completion; - (void)verifyPasswordResetCodeApp:(AuthPigeonFirebaseApp *)app code:(NSString *)code completion: (void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)verifyPhoneNumberApp:(AuthPigeonFirebaseApp *)app - request:(PigeonVerifyPhoneNumberRequest *)request + request:(InternalVerifyPhoneNumberRequest *)request completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)revokeTokenWithAuthorizationCodeApp:(AuthPigeonFirebaseApp *)app authorizationCode:(NSString *)authorizationCode completion:(void (^)(FlutterError *_Nullable))completion; +- (void)revokeAccessTokenApp:(AuthPigeonFirebaseApp *)app + accessToken:(NSString *)accessToken + completion:(void (^)(FlutterError *_Nullable))completion; - (void)initializeRecaptchaConfigApp:(AuthPigeonFirebaseApp *)app completion:(void (^)(FlutterError *_Nullable))completion; @end @@ -396,57 +413,56 @@ extern void SetUpFirebaseAuthHostApiWithSuffix(id binary NSObject *_Nullable api, NSString *messageChannelSuffix); -/// The codec used by FirebaseAuthUserHostApi. -NSObject *FirebaseAuthUserHostApiGetCodec(void); - @protocol FirebaseAuthUserHostApi - (void)deleteApp:(AuthPigeonFirebaseApp *)app completion:(void (^)(FlutterError *_Nullable))completion; - (void)getIdTokenApp:(AuthPigeonFirebaseApp *)app forceRefresh:(BOOL)forceRefresh - completion:(void (^)(PigeonIdTokenResult *_Nullable, FlutterError *_Nullable))completion; + completion: + (void (^)(InternalIdTokenResult *_Nullable, FlutterError *_Nullable))completion; - (void)linkWithCredentialApp:(AuthPigeonFirebaseApp *)app input:(NSDictionary *)input - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)linkWithProviderApp:(AuthPigeonFirebaseApp *)app - signInProvider:(PigeonSignInProvider *)signInProvider - completion: - (void (^)(PigeonUserCredential *_Nullable, FlutterError *_Nullable))completion; + signInProvider:(InternalSignInProvider *)signInProvider + completion:(void (^)(InternalUserCredential *_Nullable, + FlutterError *_Nullable))completion; - (void)reauthenticateWithCredentialApp:(AuthPigeonFirebaseApp *)app input:(NSDictionary *)input - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)reauthenticateWithProviderApp:(AuthPigeonFirebaseApp *)app - signInProvider:(PigeonSignInProvider *)signInProvider - completion:(void (^)(PigeonUserCredential *_Nullable, + signInProvider:(InternalSignInProvider *)signInProvider + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)reloadApp:(AuthPigeonFirebaseApp *)app - completion:(void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; + completion:(void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion; - (void)sendEmailVerificationApp:(AuthPigeonFirebaseApp *)app - actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(nullable InternalActionCodeSettings *)actionCodeSettings completion:(void (^)(FlutterError *_Nullable))completion; - (void)unlinkApp:(AuthPigeonFirebaseApp *)app providerId:(NSString *)providerId - completion:(void (^)(PigeonUserCredential *_Nullable, FlutterError *_Nullable))completion; + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; - (void)updateEmailApp:(AuthPigeonFirebaseApp *)app newEmail:(NSString *)newEmail - completion:(void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; + completion: + (void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion; - (void)updatePasswordApp:(AuthPigeonFirebaseApp *)app newPassword:(NSString *)newPassword completion: - (void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; + (void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion; - (void)updatePhoneNumberApp:(AuthPigeonFirebaseApp *)app input:(NSDictionary *)input completion: - (void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; + (void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion; - (void)updateProfileApp:(AuthPigeonFirebaseApp *)app - profile:(PigeonUserProfile *)profile + profile:(InternalUserProfile *)profile completion: - (void (^)(PigeonUserDetails *_Nullable, FlutterError *_Nullable))completion; + (void (^)(InternalUserDetails *_Nullable, FlutterError *_Nullable))completion; - (void)verifyBeforeUpdateEmailApp:(AuthPigeonFirebaseApp *)app newEmail:(NSString *)newEmail - actionCodeSettings:(nullable PigeonActionCodeSettings *)actionCodeSettings + actionCodeSettings:(nullable InternalActionCodeSettings *)actionCodeSettings completion:(void (^)(FlutterError *_Nullable))completion; @end @@ -457,12 +473,9 @@ extern void SetUpFirebaseAuthUserHostApiWithSuffix(id bi NSObject *_Nullable api, NSString *messageChannelSuffix); -/// The codec used by MultiFactorUserHostApi. -NSObject *MultiFactorUserHostApiGetCodec(void); - @protocol MultiFactorUserHostApi - (void)enrollPhoneApp:(AuthPigeonFirebaseApp *)app - assertion:(PigeonPhoneMultiFactorAssertion *)assertion + assertion:(InternalPhoneMultiFactorAssertion *)assertion displayName:(nullable NSString *)displayName completion:(void (^)(FlutterError *_Nullable))completion; - (void)enrollTotpApp:(AuthPigeonFirebaseApp *)app @@ -471,12 +484,12 @@ NSObject *MultiFactorUserHostApiGetCodec(void); completion:(void (^)(FlutterError *_Nullable))completion; - (void)getSessionApp:(AuthPigeonFirebaseApp *)app completion: - (void (^)(PigeonMultiFactorSession *_Nullable, FlutterError *_Nullable))completion; + (void (^)(InternalMultiFactorSession *_Nullable, FlutterError *_Nullable))completion; - (void)unenrollApp:(AuthPigeonFirebaseApp *)app factorUid:(NSString *)factorUid completion:(void (^)(FlutterError *_Nullable))completion; - (void)getEnrolledFactorsApp:(AuthPigeonFirebaseApp *)app - completion:(void (^)(NSArray *_Nullable, + completion:(void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion; @end @@ -487,14 +500,11 @@ extern void SetUpMultiFactorUserHostApiWithSuffix(id bin NSObject *_Nullable api, NSString *messageChannelSuffix); -/// The codec used by MultiFactoResolverHostApi. -NSObject *MultiFactoResolverHostApiGetCodec(void); - @protocol MultiFactoResolverHostApi - (void)resolveSignInResolverId:(NSString *)resolverId - assertion:(nullable PigeonPhoneMultiFactorAssertion *)assertion + assertion:(nullable InternalPhoneMultiFactorAssertion *)assertion totpAssertionId:(nullable NSString *)totpAssertionId - completion:(void (^)(PigeonUserCredential *_Nullable, + completion:(void (^)(InternalUserCredential *_Nullable, FlutterError *_Nullable))completion; @end @@ -505,13 +515,10 @@ extern void SetUpMultiFactoResolverHostApiWithSuffix( id binaryMessenger, NSObject *_Nullable api, NSString *messageChannelSuffix); -/// The codec used by MultiFactorTotpHostApi. -NSObject *MultiFactorTotpHostApiGetCodec(void); - @protocol MultiFactorTotpHostApi - (void)generateSecretSessionId:(NSString *)sessionId - completion: - (void (^)(PigeonTotpSecret *_Nullable, FlutterError *_Nullable))completion; + completion:(void (^)(InternalTotpSecret *_Nullable, + FlutterError *_Nullable))completion; - (void)getAssertionForEnrollmentSecretKey:(NSString *)secretKey oneTimePassword:(NSString *)oneTimePassword completion:(void (^)(NSString *_Nullable, @@ -529,9 +536,6 @@ extern void SetUpMultiFactorTotpHostApiWithSuffix(id bin NSObject *_Nullable api, NSString *messageChannelSuffix); -/// The codec used by MultiFactorTotpSecretHostApi. -NSObject *MultiFactorTotpSecretHostApiGetCodec(void); - @protocol MultiFactorTotpSecretHostApi - (void)generateQrCodeUrlSecretKey:(NSString *)secretKey accountName:(nullable NSString *)accountName @@ -551,12 +555,9 @@ extern void SetUpMultiFactorTotpSecretHostApiWithSuffix( id binaryMessenger, NSObject *_Nullable api, NSString *messageChannelSuffix); -/// The codec used by GenerateInterfaces. -NSObject *GenerateInterfacesGetCodec(void); - /// Only used to generate the object interface that are use outside of the Pigeon interface @protocol GenerateInterfaces -- (void)pigeonInterfaceInfo:(PigeonMultiFactorInfo *)info +- (void)pigeonInterfaceInfo:(InternalMultiFactorInfo *)info error:(FlutterError *_Nullable *_Nonnull)error; @end diff --git a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart index f53d18e5dccf..cbaaafcdacce 100644 --- a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart @@ -68,8 +68,8 @@ void main() { final int kMockLastSignInTimestamp = DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - final kMockUser = PigeonUserDetails( - userInfo: PigeonUserInfo( + final kMockUser = InternalUserDetails( + userInfo: InternalUserInfo( uid: '12345', displayName: 'displayName', creationTimestamp: kMockCreationTimestamp, @@ -98,7 +98,7 @@ void main() { MockFirebaseAuth mockAuthPlatform = MockFirebaseAuth(); group('$FirebaseAuth', () { - PigeonUserDetails user; + InternalUserDetails user; // used to generate a unique application name for each test var testCount = 0; @@ -995,7 +995,7 @@ class MockFirebaseAuth extends Mock @override FirebaseAuthPlatform setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { return super.noSuchMethod( @@ -1192,7 +1192,7 @@ class FakeFirebaseAuthPlatform extends Fake @override FirebaseAuthPlatform setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { return this; @@ -1203,7 +1203,7 @@ class MockUserPlatform extends Mock with MockPlatformInterfaceMixin implements TestUserPlatform { MockUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - PigeonUserDetails _user) { + InternalUserDetails _user) { TestUserPlatform(auth, multiFactor, _user); } } @@ -1254,7 +1254,7 @@ class TestFirebaseAuthPlatform extends FirebaseAuthPlatform { @override FirebaseAuthPlatform setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { return this; @@ -1323,7 +1323,7 @@ class TestAuthProvider extends AuthProvider { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - PigeonUserDetails data) + InternalUserDetails data) : super(auth, multiFactor, data); } diff --git a/packages/firebase_auth/firebase_auth/test/user_test.dart b/packages/firebase_auth/firebase_auth/test/user_test.dart index 0b2abfb19ce9..967be866fee2 100644 --- a/packages/firebase_auth/firebase_auth/test/user_test.dart +++ b/packages/firebase_auth/firebase_auth/test/user_test.dart @@ -31,7 +31,7 @@ void main() { late FirebaseAuth auth; - final kMockIdTokenResult = PigeonIdTokenResult( + final kMockIdTokenResult = InternalIdTokenResult( token: '12345', expirationTimestamp: 123456, authTimestamp: 1234567, @@ -47,8 +47,8 @@ void main() { final int kMockLastSignInTimestamp = DateTime.now().subtract(const Duration(days: 1)).millisecondsSinceEpoch; - final kMockUser = PigeonUserDetails( - userInfo: PigeonUserInfo( + final kMockUser = InternalUserDetails( + userInfo: InternalUserInfo( uid: '12345', displayName: 'displayName', creationTimestamp: kMockCreationTimestamp, @@ -85,7 +85,7 @@ void main() { var mockAuthPlatform = MockFirebaseAuth(); group('$User', () { - late PigeonUserDetails user; + late InternalUserDetails user; // used to generate a unique application name for each test var testCount = 0; @@ -376,7 +376,7 @@ class MockFirebaseAuth extends Mock @override FirebaseAuthPlatform setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { return super.noSuchMethod( @@ -393,7 +393,7 @@ class MockFirebaseAuth extends Mock class MockUserPlatform extends Mock with MockPlatformInterfaceMixin implements TestUserPlatform { - MockUserPlatform(FirebaseAuthPlatform auth, PigeonUserDetails _user) { + MockUserPlatform(FirebaseAuthPlatform auth, InternalUserDetails _user) { TestUserPlatform(auth, TestMultiFactorPlatform(auth), _user); } @@ -544,7 +544,7 @@ class TestFirebaseAuthPlatform extends FirebaseAuthPlatform { @override FirebaseAuthPlatform setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { return this; @@ -553,7 +553,7 @@ class TestFirebaseAuthPlatform extends FirebaseAuthPlatform { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - PigeonUserDetails data) + InternalUserDetails data) : super(auth, multiFactor, data); } diff --git a/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.cpp b/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.cpp index 5a4f1bf27faf..a931dac2b36b 100644 --- a/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.cpp +++ b/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.cpp @@ -79,9 +79,9 @@ Auth* GetAuthFromPigeon(const AuthPigeonFirebaseApp& pigeonApp) { return auth; } -PigeonUserCredential ParseAuthResult( +InternalUserCredential ParseAuthResult( const firebase::auth::AuthResult* authResult) { - PigeonUserCredential result = PigeonUserCredential(); + InternalUserCredential result = InternalUserCredential(); result.set_user(FirebaseAuthPlugin::ParseUserDetails(authResult->user)); result.set_additional_user_info(FirebaseAuthPlugin::ParseAdditionalUserInfo( authResult->additional_user_info)); @@ -133,29 +133,29 @@ firebase_auth_windows::FirebaseAuthPlugin::ConvertToEncodableValue( } } -PigeonAdditionalUserInfo FirebaseAuthPlugin::ParseAdditionalUserInfo( +InternalAdditionalUserInfo FirebaseAuthPlugin::ParseAdditionalUserInfo( const firebase::auth::AdditionalUserInfo additionalUserInfo) { // Cannot know if the user is new or not with current API - PigeonAdditionalUserInfo result = PigeonAdditionalUserInfo(false); + InternalAdditionalUserInfo result = InternalAdditionalUserInfo(false); result.set_profile(ConvertToEncodableMap(additionalUserInfo.profile)); result.set_provider_id(additionalUserInfo.provider_id); result.set_username(additionalUserInfo.user_name); return result; } -PigeonUserDetails FirebaseAuthPlugin::ParseUserDetails( +InternalUserDetails FirebaseAuthPlugin::ParseUserDetails( const firebase::auth::User user) { - PigeonUserDetails result = - PigeonUserDetails(FirebaseAuthPlugin::ParseUserInfo(&user), - FirebaseAuthPlugin::ParseProviderData(&user)); + InternalUserDetails result = + InternalUserDetails(FirebaseAuthPlugin::ParseUserInfo(&user), + FirebaseAuthPlugin::ParseProviderData(&user)); return result; } -PigeonUserInfo FirebaseAuthPlugin::ParseUserInfo( +InternalUserInfo FirebaseAuthPlugin::ParseUserInfo( const firebase::auth::User* user) { - PigeonUserInfo result = PigeonUserInfo(user->uid(), user->is_anonymous(), - user->is_email_verified()); + InternalUserInfo result = InternalUserInfo(user->uid(), user->is_anonymous(), + user->is_email_verified()); result.set_display_name(user->display_name()); result.set_email(user->email()); result.set_phone_number(user->phone_number()); @@ -322,7 +322,8 @@ class FlutterIdTokenListener : public firebase::auth::IdTokenListener { void OnIdTokenChanged(Auth* auth) override { // Generate your ID Token firebase::auth::User user = auth->current_user(); - PigeonUserDetails userDetails = FirebaseAuthPlugin::ParseUserDetails(user); + InternalUserDetails userDetails = + FirebaseAuthPlugin::ParseUserDetails(user); using flutter::EncodableList; using flutter::EncodableMap; @@ -406,7 +407,8 @@ class FlutterAuthStateListener : public firebase::auth::AuthStateListener { void OnAuthStateChanged(Auth* auth) override { // Generate your ID Token firebase::auth::User user = auth->current_user(); - PigeonUserDetails userDetails = FirebaseAuthPlugin::ParseUserDetails(user); + InternalUserDetails userDetails = + FirebaseAuthPlugin::ParseUserDetails(user); using flutter::EncodableList; using flutter::EncodableMap; @@ -503,7 +505,7 @@ void FirebaseAuthPlugin::ApplyActionCode( void FirebaseAuthPlugin::CheckActionCode( const AuthPigeonFirebaseApp& app, const std::string& code, - std::function reply)> result) { + std::function reply)> result) { result(FlutterError("unimplemented", "CheckActionCode is not available on this platform yet.", nullptr)); @@ -521,7 +523,7 @@ void FirebaseAuthPlugin::ConfirmPasswordReset( void FirebaseAuthPlugin::CreateUserWithEmailAndPassword( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& password, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::Future createUserFuture = @@ -533,7 +535,7 @@ void FirebaseAuthPlugin::CreateUserWithEmailAndPassword( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -544,7 +546,7 @@ void FirebaseAuthPlugin::CreateUserWithEmailAndPassword( void FirebaseAuthPlugin::SignInAnonymously( const AuthPigeonFirebaseApp& app, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::Future signInFuture = @@ -555,7 +557,7 @@ void FirebaseAuthPlugin::SignInAnonymously( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -689,7 +691,7 @@ firebase::auth::Credential getCredentialFromArguments( void FirebaseAuthPlugin::SignInWithCredential( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::Future signInFuture = @@ -700,10 +702,11 @@ void FirebaseAuthPlugin::SignInWithCredential( [result](const firebase::Future& completed_future) { if (completed_future.error() == 0) { // TODO: not the right return type from C++ SDK - PigeonUserInfo credential = ParseUserInfo(completed_future.result()); - PigeonUserCredential userCredential = PigeonUserCredential(); - PigeonUserDetails user = - PigeonUserDetails(credential, flutter::EncodableList()); + InternalUserInfo credential = + ParseUserInfo(completed_future.result()); + InternalUserCredential userCredential = InternalUserCredential(); + InternalUserDetails user = + InternalUserDetails(credential, flutter::EncodableList()); userCredential.set_user(user); result(userCredential); } else { @@ -714,7 +717,7 @@ void FirebaseAuthPlugin::SignInWithCredential( void FirebaseAuthPlugin::SignInWithCustomToken( const AuthPigeonFirebaseApp& app, const std::string& token, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::Future signInFuture = @@ -725,7 +728,7 @@ void FirebaseAuthPlugin::SignInWithCustomToken( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -737,7 +740,7 @@ void FirebaseAuthPlugin::SignInWithCustomToken( void FirebaseAuthPlugin::SignInWithEmailAndPassword( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& password, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::Future signInFuture = @@ -748,7 +751,7 @@ void FirebaseAuthPlugin::SignInWithEmailAndPassword( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -760,7 +763,7 @@ void FirebaseAuthPlugin::SignInWithEmailAndPassword( void FirebaseAuthPlugin::SignInWithEmailLink( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& email_link, - std::function reply)> result) { + std::function reply)> result) { result(FlutterError( "unimplemented", "SignInWithEmailLink is not available on this platform yet.", nullptr)); @@ -795,7 +798,7 @@ std::map TransformEncodableMap( } firebase::auth::FederatedOAuthProvider getProviderFromArguments( - const PigeonSignInProvider& sign_in_provider) { + const InternalSignInProvider& sign_in_provider) { firebase::auth::FederatedOAuthProviderData federatedOAuthProviderData = firebase::auth::FederatedOAuthProviderData( sign_in_provider.provider_id().c_str(), @@ -809,8 +812,8 @@ firebase::auth::FederatedOAuthProvider getProviderFromArguments( void FirebaseAuthPlugin::SignInWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) { + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::Future signInFuture = @@ -822,7 +825,7 @@ void FirebaseAuthPlugin::SignInWithProvider( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -875,7 +878,7 @@ void FirebaseAuthPlugin::FetchSignInMethodsForEmail( void FirebaseAuthPlugin::SendPasswordResetEmail( const AuthPigeonFirebaseApp& app, const std::string& email, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); @@ -895,7 +898,7 @@ void FirebaseAuthPlugin::SendPasswordResetEmail( void FirebaseAuthPlugin::SendSignInLinkToEmail( const AuthPigeonFirebaseApp& app, const std::string& email, - const PigeonActionCodeSettings& action_code_settings, + const InternalActionCodeSettings& action_code_settings, std::function reply)> result) { result(FlutterError( "unimplemented", @@ -920,7 +923,7 @@ void FirebaseAuthPlugin::SetLanguageCode( void FirebaseAuthPlugin::SetSettings( const AuthPigeonFirebaseApp& app, - const PigeonFirebaseAuthSettings& settings, + const InternalFirebaseAuthSettings& settings, std::function reply)> result) { result(FlutterError("unimplemented", "SetSettings is not available on this platform yet.", @@ -938,7 +941,7 @@ void FirebaseAuthPlugin::VerifyPasswordResetCode( void FirebaseAuthPlugin::VerifyPhoneNumber( const AuthPigeonFirebaseApp& app, - const PigeonVerifyPhoneNumberRequest& request, + const InternalVerifyPhoneNumberRequest& request, std::function reply)> result) { result(FlutterError( "unimplemented", @@ -965,7 +968,7 @@ void FirebaseAuthPlugin::Delete( void FirebaseAuthPlugin::GetIdToken( const AuthPigeonFirebaseApp& app, bool force_refresh, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -975,7 +978,7 @@ void FirebaseAuthPlugin::GetIdToken( [result](const firebase::Future& completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonIdTokenResult token_result; + InternalIdTokenResult token_result; std::string_view sv(*completed_future.result()); token_result.set_token(sv); result(token_result); @@ -987,7 +990,7 @@ void FirebaseAuthPlugin::GetIdToken( void FirebaseAuthPlugin::LinkWithCredential( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -999,7 +1002,7 @@ void FirebaseAuthPlugin::LinkWithCredential( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -1010,8 +1013,8 @@ void FirebaseAuthPlugin::LinkWithCredential( void FirebaseAuthPlugin::LinkWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) { + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1023,7 +1026,7 @@ void FirebaseAuthPlugin::LinkWithProvider( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -1034,7 +1037,7 @@ void FirebaseAuthPlugin::LinkWithProvider( void FirebaseAuthPlugin::ReauthenticateWithCredential( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1053,8 +1056,8 @@ void FirebaseAuthPlugin::ReauthenticateWithCredential( void FirebaseAuthPlugin::ReauthenticateWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) { + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1067,7 +1070,7 @@ void FirebaseAuthPlugin::ReauthenticateWithProvider( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -1078,7 +1081,7 @@ void FirebaseAuthPlugin::ReauthenticateWithProvider( void FirebaseAuthPlugin::Reload( const AuthPigeonFirebaseApp& app, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1088,7 +1091,7 @@ void FirebaseAuthPlugin::Reload( const firebase::Future& completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserDetails user = ParseUserDetails(firebaseAuth->current_user()); + InternalUserDetails user = ParseUserDetails(firebaseAuth->current_user()); result(user); } else { result(FirebaseAuthPlugin::ParseError(completed_future)); @@ -1098,7 +1101,7 @@ void FirebaseAuthPlugin::Reload( void FirebaseAuthPlugin::SendEmailVerification( const AuthPigeonFirebaseApp& app, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1117,7 +1120,7 @@ void FirebaseAuthPlugin::SendEmailVerification( void FirebaseAuthPlugin::Unlink( const AuthPigeonFirebaseApp& app, const std::string& provider_id, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1129,7 +1132,7 @@ void FirebaseAuthPlugin::Unlink( completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserCredential credential = + InternalUserCredential credential = ParseAuthResult(completed_future.result()); result(credential); } else { @@ -1140,7 +1143,7 @@ void FirebaseAuthPlugin::Unlink( void FirebaseAuthPlugin::UpdateEmail( const AuthPigeonFirebaseApp& app, const std::string& new_email, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1151,7 +1154,7 @@ void FirebaseAuthPlugin::UpdateEmail( const firebase::Future& completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserDetails user = ParseUserDetails(firebaseAuth->current_user()); + InternalUserDetails user = ParseUserDetails(firebaseAuth->current_user()); result(user); } else { result(FirebaseAuthPlugin::ParseError(completed_future)); @@ -1161,7 +1164,7 @@ void FirebaseAuthPlugin::UpdateEmail( void FirebaseAuthPlugin::UpdatePassword( const AuthPigeonFirebaseApp& app, const std::string& new_password, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1171,7 +1174,7 @@ void FirebaseAuthPlugin::UpdatePassword( const firebase::Future& completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserDetails user = ParseUserDetails(firebaseAuth->current_user()); + InternalUserDetails user = ParseUserDetails(firebaseAuth->current_user()); result(user); } else { result(FirebaseAuthPlugin::ParseError(completed_future)); @@ -1202,7 +1205,7 @@ firebase::auth::PhoneAuthCredential getPhoneCredentialFromArguments( void FirebaseAuthPlugin::UpdatePhoneNumber( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) { + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1214,7 +1217,8 @@ void FirebaseAuthPlugin::UpdatePhoneNumber( [result](const firebase::Future& completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserDetails user = ParseUserDetails(*completed_future.result()); + InternalUserDetails user = + ParseUserDetails(*completed_future.result()); result(user); } else { result(FirebaseAuthPlugin::ParseError(completed_future)); @@ -1223,8 +1227,8 @@ void FirebaseAuthPlugin::UpdatePhoneNumber( } void FirebaseAuthPlugin::UpdateProfile( - const AuthPigeonFirebaseApp& app, const PigeonUserProfile& profile, - std::function reply)> result) { + const AuthPigeonFirebaseApp& app, const InternalUserProfile& profile, + std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1243,7 +1247,7 @@ void FirebaseAuthPlugin::UpdateProfile( const firebase::Future& completed_future) { // We are probably in a different thread right now. if (completed_future.error() == 0) { - PigeonUserDetails user = ParseUserDetails(firebaseAuth->current_user()); + InternalUserDetails user = ParseUserDetails(firebaseAuth->current_user()); result(user); } else { result(FirebaseAuthPlugin::ParseError(completed_future)); @@ -1253,7 +1257,7 @@ void FirebaseAuthPlugin::UpdateProfile( void FirebaseAuthPlugin::VerifyBeforeUpdateEmail( const AuthPigeonFirebaseApp& app, const std::string& new_email, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) { firebase::auth::Auth* firebaseAuth = GetAuthFromPigeon(app); firebase::auth::User user = firebaseAuth->current_user(); @@ -1286,6 +1290,23 @@ void FirebaseAuthPlugin::RevokeTokenWithAuthorizationCode( nullptr)); } +void FirebaseAuthPlugin::RevokeAccessToken( + const AuthPigeonFirebaseApp& app, const std::string& access_token, + std::function reply)> result) { + result(FlutterError("unimplemented", + "RevokeAccessToken is not available on this platform.", + nullptr)); +} + +void FirebaseAuthPlugin::InitializeRecaptchaConfig( + const AuthPigeonFirebaseApp& app, + std::function reply)> result) { + result(FlutterError( + "unimplemented", + "InitializeRecaptchaConfig is not available on this platform yet.", + nullptr)); +} + flutter::EncodableMap FirebaseAuthPlugin::GetPluginConstantsForFirebaseApp( const firebase::App& app) { flutter::EncodableMap constants; @@ -1294,7 +1315,7 @@ flutter::EncodableMap FirebaseAuthPlugin::GetPluginConstantsForFirebaseApp( firebase::auth::User user = auth->current_user(); if (user.is_valid()) { - PigeonUserDetails userDetails = ParseUserDetails(user); + InternalUserDetails userDetails = ParseUserDetails(user); flutter::EncodableList userDetailsList; userDetailsList.push_back( flutter::EncodableValue(userDetails.user_info().ToEncodableList())); diff --git a/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.h b/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.h index a75ff33e6cf5..575e201ff355 100644 --- a/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.h +++ b/packages/firebase_auth/firebase_auth/windows/firebase_auth_plugin.h @@ -42,14 +42,14 @@ class FirebaseAuthPlugin : public flutter::Plugin, static std::string GetAuthErrorCode(AuthError authError); static FlutterError ParseError(const firebase::FutureBase& future); - static PigeonUserDetails ParseUserDetails(const firebase::auth::User user); - static PigeonAdditionalUserInfo ParseAdditionalUserInfo( + static InternalUserDetails ParseUserDetails(const firebase::auth::User user); + static InternalAdditionalUserInfo ParseAdditionalUserInfo( const firebase::auth::AdditionalUserInfo user); static flutter::EncodableMap ConvertToEncodableMap( const std::map& originalMap); static flutter::EncodableValue ConvertToEncodableValue( const firebase::Variant& variant); - static PigeonUserInfo ParseUserInfo(const firebase::auth::User* user); + static InternalUserInfo ParseUserInfo(const firebase::auth::User* user); static flutter::EncodableList ParseProviderData( const firebase::auth::User* user); static flutter::EncodableValue ParseUserInfoToMap( @@ -70,7 +70,8 @@ class FirebaseAuthPlugin : public flutter::Plugin, std::function reply)> result) override; virtual void CheckActionCode( const AuthPigeonFirebaseApp& app, const std::string& code, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void ConfirmPasswordReset( const AuthPigeonFirebaseApp& app, const std::string& code, const std::string& new_password, @@ -78,28 +79,35 @@ class FirebaseAuthPlugin : public flutter::Plugin, virtual void CreateUserWithEmailAndPassword( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& password, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void SignInAnonymously( const AuthPigeonFirebaseApp& app, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void SignInWithCredential( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void SignInWithCustomToken( const AuthPigeonFirebaseApp& app, const std::string& token, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void SignInWithEmailAndPassword( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& password, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void SignInWithEmailLink( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& email_link, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void SignInWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) override; + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) + override; virtual void SignOut( const AuthPigeonFirebaseApp& app, std::function reply)> result) override; @@ -109,25 +117,25 @@ class FirebaseAuthPlugin : public flutter::Plugin, override; virtual void SendPasswordResetEmail( const AuthPigeonFirebaseApp& app, const std::string& email, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) override; virtual void SendSignInLinkToEmail( const AuthPigeonFirebaseApp& app, const std::string& email, - const PigeonActionCodeSettings& action_code_settings, + const InternalActionCodeSettings& action_code_settings, std::function reply)> result) override; virtual void SetLanguageCode( const AuthPigeonFirebaseApp& app, const std::string* language_code, std::function reply)> result) override; virtual void SetSettings( const AuthPigeonFirebaseApp& app, - const PigeonFirebaseAuthSettings& settings, + const InternalFirebaseAuthSettings& settings, std::function reply)> result) override; virtual void VerifyPasswordResetCode( const AuthPigeonFirebaseApp& app, const std::string& code, std::function reply)> result) override; virtual void VerifyPhoneNumber( const AuthPigeonFirebaseApp& app, - const PigeonVerifyPhoneNumberRequest& request, + const InternalVerifyPhoneNumberRequest& request, std::function reply)> result) override; // FirebaseAuthUserHostApi methods. @@ -136,52 +144,66 @@ class FirebaseAuthPlugin : public flutter::Plugin, std::function reply)> result) override; virtual void GetIdToken( const AuthPigeonFirebaseApp& app, bool force_refresh, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void LinkWithCredential( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void LinkWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) override; + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) + override; virtual void ReauthenticateWithCredential( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) override; + std::function reply)> result) + override; virtual void ReauthenticateWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) override; + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) + override; virtual void Reload( const AuthPigeonFirebaseApp& app, - std::function reply)> result) override; + std::function reply)> result) override; virtual void SendEmailVerification( const AuthPigeonFirebaseApp& app, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) override; - virtual void Unlink( - const AuthPigeonFirebaseApp& app, const std::string& provider_id, - std::function reply)> result) override; + virtual void Unlink(const AuthPigeonFirebaseApp& app, + const std::string& provider_id, + std::function reply)> + result) override; virtual void UpdateEmail( const AuthPigeonFirebaseApp& app, const std::string& new_email, - std::function reply)> result) override; + std::function reply)> result) override; virtual void UpdatePassword( const AuthPigeonFirebaseApp& app, const std::string& new_password, - std::function reply)> result) override; + std::function reply)> result) override; virtual void UpdatePhoneNumber( const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) override; + std::function reply)> result) override; virtual void UpdateProfile( - const AuthPigeonFirebaseApp& app, const PigeonUserProfile& profile, - std::function reply)> result) override; + const AuthPigeonFirebaseApp& app, const InternalUserProfile& profile, + std::function reply)> result) override; virtual void VerifyBeforeUpdateEmail( const AuthPigeonFirebaseApp& app, const std::string& new_email, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) override; virtual void RevokeTokenWithAuthorizationCode( const AuthPigeonFirebaseApp& app, const std::string& authorization_code, std::function reply)> result) override; + virtual void RevokeAccessToken( + const AuthPigeonFirebaseApp& app, const std::string& access_token, + std::function reply)> result) override; + + virtual void InitializeRecaptchaConfig( + const AuthPigeonFirebaseApp& app, + std::function reply)> result) override; + // FlutterFirebasePlugin methods. flutter::EncodableMap GetPluginConstantsForFirebaseApp( const firebase::App& app) override; diff --git a/packages/firebase_auth/firebase_auth/windows/messages.g.cpp b/packages/firebase_auth/firebase_auth/windows/messages.g.cpp index 59043185cf1b..ea2200e617b2 100644 --- a/packages/firebase_auth/firebase_auth/windows/messages.g.cpp +++ b/packages/firebase_auth/firebase_auth/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v19.0.0), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_auth_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,56 +33,283 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } -// PigeonMultiFactorSession +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); -PigeonMultiFactorSession::PigeonMultiFactorSession(const std::string& id) +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace +// InternalMultiFactorSession + +InternalMultiFactorSession::InternalMultiFactorSession(const std::string& id) : id_(id) {} -const std::string& PigeonMultiFactorSession::id() const { return id_; } +const std::string& InternalMultiFactorSession::id() const { return id_; } -void PigeonMultiFactorSession::set_id(std::string_view value_arg) { +void InternalMultiFactorSession::set_id(std::string_view value_arg) { id_ = value_arg; } -EncodableList PigeonMultiFactorSession::ToEncodableList() const { +EncodableList InternalMultiFactorSession::ToEncodableList() const { EncodableList list; list.reserve(1); list.push_back(EncodableValue(id_)); return list; } -PigeonMultiFactorSession PigeonMultiFactorSession::FromEncodableList( +InternalMultiFactorSession InternalMultiFactorSession::FromEncodableList( const EncodableList& list) { - PigeonMultiFactorSession decoded(std::get(list[0])); + InternalMultiFactorSession decoded(std::get(list[0])); return decoded; } -// PigeonPhoneMultiFactorAssertion +bool InternalMultiFactorSession::operator==( + const InternalMultiFactorSession& other) const { + return PigeonInternalDeepEquals(id_, other.id_); +} + +bool InternalMultiFactorSession::operator!=( + const InternalMultiFactorSession& other) const { + return !(*this == other); +} + +size_t InternalMultiFactorSession::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(id_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalMultiFactorSession& v) { + return v.Hash(); +} + +// InternalPhoneMultiFactorAssertion -PigeonPhoneMultiFactorAssertion::PigeonPhoneMultiFactorAssertion( +InternalPhoneMultiFactorAssertion::InternalPhoneMultiFactorAssertion( const std::string& verification_id, const std::string& verification_code) : verification_id_(verification_id), verification_code_(verification_code) {} -const std::string& PigeonPhoneMultiFactorAssertion::verification_id() const { +const std::string& InternalPhoneMultiFactorAssertion::verification_id() const { return verification_id_; } -void PigeonPhoneMultiFactorAssertion::set_verification_id( +void InternalPhoneMultiFactorAssertion::set_verification_id( std::string_view value_arg) { verification_id_ = value_arg; } -const std::string& PigeonPhoneMultiFactorAssertion::verification_code() const { +const std::string& InternalPhoneMultiFactorAssertion::verification_code() + const { return verification_code_; } -void PigeonPhoneMultiFactorAssertion::set_verification_code( +void InternalPhoneMultiFactorAssertion::set_verification_code( std::string_view value_arg) { verification_code_ = value_arg; } -EncodableList PigeonPhoneMultiFactorAssertion::ToEncodableList() const { +EncodableList InternalPhoneMultiFactorAssertion::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(EncodableValue(verification_id_)); @@ -88,24 +317,46 @@ EncodableList PigeonPhoneMultiFactorAssertion::ToEncodableList() const { return list; } -PigeonPhoneMultiFactorAssertion -PigeonPhoneMultiFactorAssertion::FromEncodableList(const EncodableList& list) { - PigeonPhoneMultiFactorAssertion decoded(std::get(list[0]), - std::get(list[1])); +InternalPhoneMultiFactorAssertion +InternalPhoneMultiFactorAssertion::FromEncodableList( + const EncodableList& list) { + InternalPhoneMultiFactorAssertion decoded(std::get(list[0]), + std::get(list[1])); return decoded; } -// PigeonMultiFactorInfo +bool InternalPhoneMultiFactorAssertion::operator==( + const InternalPhoneMultiFactorAssertion& other) const { + return PigeonInternalDeepEquals(verification_id_, other.verification_id_) && + PigeonInternalDeepEquals(verification_code_, other.verification_code_); +} + +bool InternalPhoneMultiFactorAssertion::operator!=( + const InternalPhoneMultiFactorAssertion& other) const { + return !(*this == other); +} + +size_t InternalPhoneMultiFactorAssertion::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(verification_id_); + result = result * 31 + PigeonInternalDeepHash(verification_code_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalPhoneMultiFactorAssertion& v) { + return v.Hash(); +} + +// InternalMultiFactorInfo -PigeonMultiFactorInfo::PigeonMultiFactorInfo(double enrollment_timestamp, - const std::string& uid) +InternalMultiFactorInfo::InternalMultiFactorInfo(double enrollment_timestamp, + const std::string& uid) : enrollment_timestamp_(enrollment_timestamp), uid_(uid) {} -PigeonMultiFactorInfo::PigeonMultiFactorInfo(const std::string* display_name, - double enrollment_timestamp, - const std::string* factor_id, - const std::string& uid, - const std::string* phone_number) +InternalMultiFactorInfo::InternalMultiFactorInfo( + const std::string* display_name, double enrollment_timestamp, + const std::string* factor_id, const std::string& uid, + const std::string* phone_number) : display_name_(display_name ? std::optional(*display_name) : std::nullopt), enrollment_timestamp_(enrollment_timestamp), @@ -115,62 +366,62 @@ PigeonMultiFactorInfo::PigeonMultiFactorInfo(const std::string* display_name, phone_number_(phone_number ? std::optional(*phone_number) : std::nullopt) {} -const std::string* PigeonMultiFactorInfo::display_name() const { +const std::string* InternalMultiFactorInfo::display_name() const { return display_name_ ? &(*display_name_) : nullptr; } -void PigeonMultiFactorInfo::set_display_name( +void InternalMultiFactorInfo::set_display_name( const std::string_view* value_arg) { display_name_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonMultiFactorInfo::set_display_name(std::string_view value_arg) { +void InternalMultiFactorInfo::set_display_name(std::string_view value_arg) { display_name_ = value_arg; } -double PigeonMultiFactorInfo::enrollment_timestamp() const { +double InternalMultiFactorInfo::enrollment_timestamp() const { return enrollment_timestamp_; } -void PigeonMultiFactorInfo::set_enrollment_timestamp(double value_arg) { +void InternalMultiFactorInfo::set_enrollment_timestamp(double value_arg) { enrollment_timestamp_ = value_arg; } -const std::string* PigeonMultiFactorInfo::factor_id() const { +const std::string* InternalMultiFactorInfo::factor_id() const { return factor_id_ ? &(*factor_id_) : nullptr; } -void PigeonMultiFactorInfo::set_factor_id(const std::string_view* value_arg) { +void InternalMultiFactorInfo::set_factor_id(const std::string_view* value_arg) { factor_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonMultiFactorInfo::set_factor_id(std::string_view value_arg) { +void InternalMultiFactorInfo::set_factor_id(std::string_view value_arg) { factor_id_ = value_arg; } -const std::string& PigeonMultiFactorInfo::uid() const { return uid_; } +const std::string& InternalMultiFactorInfo::uid() const { return uid_; } -void PigeonMultiFactorInfo::set_uid(std::string_view value_arg) { +void InternalMultiFactorInfo::set_uid(std::string_view value_arg) { uid_ = value_arg; } -const std::string* PigeonMultiFactorInfo::phone_number() const { +const std::string* InternalMultiFactorInfo::phone_number() const { return phone_number_ ? &(*phone_number_) : nullptr; } -void PigeonMultiFactorInfo::set_phone_number( +void InternalMultiFactorInfo::set_phone_number( const std::string_view* value_arg) { phone_number_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonMultiFactorInfo::set_phone_number(std::string_view value_arg) { +void InternalMultiFactorInfo::set_phone_number(std::string_view value_arg) { phone_number_ = value_arg; } -EncodableList PigeonMultiFactorInfo::ToEncodableList() const { +EncodableList InternalMultiFactorInfo::ToEncodableList() const { EncodableList list; list.reserve(5); list.push_back(display_name_ ? EncodableValue(*display_name_) @@ -183,10 +434,10 @@ EncodableList PigeonMultiFactorInfo::ToEncodableList() const { return list; } -PigeonMultiFactorInfo PigeonMultiFactorInfo::FromEncodableList( +InternalMultiFactorInfo InternalMultiFactorInfo::FromEncodableList( const EncodableList& list) { - PigeonMultiFactorInfo decoded(std::get(list[1]), - std::get(list[3])); + InternalMultiFactorInfo decoded(std::get(list[1]), + std::get(list[3])); auto& encodable_display_name = list[0]; if (!encodable_display_name.IsNull()) { decoded.set_display_name(std::get(encodable_display_name)); @@ -202,6 +453,35 @@ PigeonMultiFactorInfo PigeonMultiFactorInfo::FromEncodableList( return decoded; } +bool InternalMultiFactorInfo::operator==( + const InternalMultiFactorInfo& other) const { + return PigeonInternalDeepEquals(display_name_, other.display_name_) && + PigeonInternalDeepEquals(enrollment_timestamp_, + other.enrollment_timestamp_) && + PigeonInternalDeepEquals(factor_id_, other.factor_id_) && + PigeonInternalDeepEquals(uid_, other.uid_) && + PigeonInternalDeepEquals(phone_number_, other.phone_number_); +} + +bool InternalMultiFactorInfo::operator!=( + const InternalMultiFactorInfo& other) const { + return !(*this == other); +} + +size_t InternalMultiFactorInfo::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(display_name_); + result = result * 31 + PigeonInternalDeepHash(enrollment_timestamp_); + result = result * 31 + PigeonInternalDeepHash(factor_id_); + result = result * 31 + PigeonInternalDeepHash(uid_); + result = result * 31 + PigeonInternalDeepHash(phone_number_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalMultiFactorInfo& v) { + return v.Hash(); +} + // AuthPigeonFirebaseApp AuthPigeonFirebaseApp::AuthPigeonFirebaseApp(const std::string& app_name) @@ -275,44 +555,70 @@ AuthPigeonFirebaseApp AuthPigeonFirebaseApp::FromEncodableList( return decoded; } -// PigeonActionCodeInfoData +bool AuthPigeonFirebaseApp::operator==( + const AuthPigeonFirebaseApp& other) const { + return PigeonInternalDeepEquals(app_name_, other.app_name_) && + PigeonInternalDeepEquals(tenant_id_, other.tenant_id_) && + PigeonInternalDeepEquals(custom_auth_domain_, + other.custom_auth_domain_); +} + +bool AuthPigeonFirebaseApp::operator!=( + const AuthPigeonFirebaseApp& other) const { + return !(*this == other); +} + +size_t AuthPigeonFirebaseApp::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(app_name_); + result = result * 31 + PigeonInternalDeepHash(tenant_id_); + result = result * 31 + PigeonInternalDeepHash(custom_auth_domain_); + return result; +} + +size_t PigeonInternalDeepHash(const AuthPigeonFirebaseApp& v) { + return v.Hash(); +} + +// InternalActionCodeInfoData -PigeonActionCodeInfoData::PigeonActionCodeInfoData() {} +InternalActionCodeInfoData::InternalActionCodeInfoData() {} -PigeonActionCodeInfoData::PigeonActionCodeInfoData( +InternalActionCodeInfoData::InternalActionCodeInfoData( const std::string* email, const std::string* previous_email) : email_(email ? std::optional(*email) : std::nullopt), previous_email_(previous_email ? std::optional(*previous_email) : std::nullopt) {} -const std::string* PigeonActionCodeInfoData::email() const { +const std::string* InternalActionCodeInfoData::email() const { return email_ ? &(*email_) : nullptr; } -void PigeonActionCodeInfoData::set_email(const std::string_view* value_arg) { +void InternalActionCodeInfoData::set_email(const std::string_view* value_arg) { email_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonActionCodeInfoData::set_email(std::string_view value_arg) { +void InternalActionCodeInfoData::set_email(std::string_view value_arg) { email_ = value_arg; } -const std::string* PigeonActionCodeInfoData::previous_email() const { +const std::string* InternalActionCodeInfoData::previous_email() const { return previous_email_ ? &(*previous_email_) : nullptr; } -void PigeonActionCodeInfoData::set_previous_email( +void InternalActionCodeInfoData::set_previous_email( const std::string_view* value_arg) { previous_email_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonActionCodeInfoData::set_previous_email(std::string_view value_arg) { +void InternalActionCodeInfoData::set_previous_email( + std::string_view value_arg) { previous_email_ = value_arg; } -EncodableList PigeonActionCodeInfoData::ToEncodableList() const { +EncodableList InternalActionCodeInfoData::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(email_ ? EncodableValue(*email_) : EncodableValue()); @@ -321,9 +627,9 @@ EncodableList PigeonActionCodeInfoData::ToEncodableList() const { return list; } -PigeonActionCodeInfoData PigeonActionCodeInfoData::FromEncodableList( +InternalActionCodeInfoData InternalActionCodeInfoData::FromEncodableList( const EncodableList& list) { - PigeonActionCodeInfoData decoded; + InternalActionCodeInfoData decoded; auto& encodable_email = list[0]; if (!encodable_email.IsNull()) { decoded.set_email(std::get(encodable_email)); @@ -335,65 +641,112 @@ PigeonActionCodeInfoData PigeonActionCodeInfoData::FromEncodableList( return decoded; } -// PigeonActionCodeInfo +bool InternalActionCodeInfoData::operator==( + const InternalActionCodeInfoData& other) const { + return PigeonInternalDeepEquals(email_, other.email_) && + PigeonInternalDeepEquals(previous_email_, other.previous_email_); +} + +bool InternalActionCodeInfoData::operator!=( + const InternalActionCodeInfoData& other) const { + return !(*this == other); +} + +size_t InternalActionCodeInfoData::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(email_); + result = result * 31 + PigeonInternalDeepHash(previous_email_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalActionCodeInfoData& v) { + return v.Hash(); +} + +// InternalActionCodeInfo -PigeonActionCodeInfo::PigeonActionCodeInfo( +InternalActionCodeInfo::InternalActionCodeInfo( const ActionCodeInfoOperation& operation, - const PigeonActionCodeInfoData& data) + const InternalActionCodeInfoData& data) : operation_(operation), - data_(std::make_unique(data)) {} + data_(std::make_unique(data)) {} -PigeonActionCodeInfo::PigeonActionCodeInfo(const PigeonActionCodeInfo& other) +InternalActionCodeInfo::InternalActionCodeInfo( + const InternalActionCodeInfo& other) : operation_(other.operation_), - data_(std::make_unique(*other.data_)) {} + data_(std::make_unique(*other.data_)) {} -PigeonActionCodeInfo& PigeonActionCodeInfo::operator=( - const PigeonActionCodeInfo& other) { +InternalActionCodeInfo& InternalActionCodeInfo::operator=( + const InternalActionCodeInfo& other) { operation_ = other.operation_; - data_ = std::make_unique(*other.data_); + data_ = std::make_unique(*other.data_); return *this; } -const ActionCodeInfoOperation& PigeonActionCodeInfo::operation() const { +const ActionCodeInfoOperation& InternalActionCodeInfo::operation() const { return operation_; } -void PigeonActionCodeInfo::set_operation( +void InternalActionCodeInfo::set_operation( const ActionCodeInfoOperation& value_arg) { operation_ = value_arg; } -const PigeonActionCodeInfoData& PigeonActionCodeInfo::data() const { +const InternalActionCodeInfoData& InternalActionCodeInfo::data() const { return *data_; } -void PigeonActionCodeInfo::set_data(const PigeonActionCodeInfoData& value_arg) { - data_ = std::make_unique(value_arg); +void InternalActionCodeInfo::set_data( + const InternalActionCodeInfoData& value_arg) { + data_ = std::make_unique(value_arg); } -EncodableList PigeonActionCodeInfo::ToEncodableList() const { +EncodableList InternalActionCodeInfo::ToEncodableList() const { EncodableList list; list.reserve(2); - list.push_back(EncodableValue((int)operation_)); + list.push_back(CustomEncodableValue(operation_)); list.push_back(CustomEncodableValue(*data_)); return list; } -PigeonActionCodeInfo PigeonActionCodeInfo::FromEncodableList( +InternalActionCodeInfo InternalActionCodeInfo::FromEncodableList( const EncodableList& list) { - PigeonActionCodeInfo decoded( - (ActionCodeInfoOperation)(std::get(list[0])), - std::any_cast( + InternalActionCodeInfo decoded( + std::any_cast( + std::get(list[0])), + std::any_cast( std::get(list[1]))); return decoded; } -// PigeonAdditionalUserInfo +bool InternalActionCodeInfo::operator==( + const InternalActionCodeInfo& other) const { + return PigeonInternalDeepEquals(operation_, other.operation_) && + PigeonInternalDeepEquals(data_, other.data_); +} + +bool InternalActionCodeInfo::operator!=( + const InternalActionCodeInfo& other) const { + return !(*this == other); +} + +size_t InternalActionCodeInfo::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(operation_); + result = result * 31 + PigeonInternalDeepHash(data_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalActionCodeInfo& v) { + return v.Hash(); +} + +// InternalAdditionalUserInfo -PigeonAdditionalUserInfo::PigeonAdditionalUserInfo(bool is_new_user) +InternalAdditionalUserInfo::InternalAdditionalUserInfo(bool is_new_user) : is_new_user_(is_new_user) {} -PigeonAdditionalUserInfo::PigeonAdditionalUserInfo( +InternalAdditionalUserInfo::InternalAdditionalUserInfo( bool is_new_user, const std::string* provider_id, const std::string* username, const std::string* authorization_code, const EncodableMap* profile) @@ -408,66 +761,67 @@ PigeonAdditionalUserInfo::PigeonAdditionalUserInfo( profile_(profile ? std::optional(*profile) : std::nullopt) { } -bool PigeonAdditionalUserInfo::is_new_user() const { return is_new_user_; } +bool InternalAdditionalUserInfo::is_new_user() const { return is_new_user_; } -void PigeonAdditionalUserInfo::set_is_new_user(bool value_arg) { +void InternalAdditionalUserInfo::set_is_new_user(bool value_arg) { is_new_user_ = value_arg; } -const std::string* PigeonAdditionalUserInfo::provider_id() const { +const std::string* InternalAdditionalUserInfo::provider_id() const { return provider_id_ ? &(*provider_id_) : nullptr; } -void PigeonAdditionalUserInfo::set_provider_id( +void InternalAdditionalUserInfo::set_provider_id( const std::string_view* value_arg) { provider_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonAdditionalUserInfo::set_provider_id(std::string_view value_arg) { +void InternalAdditionalUserInfo::set_provider_id(std::string_view value_arg) { provider_id_ = value_arg; } -const std::string* PigeonAdditionalUserInfo::username() const { +const std::string* InternalAdditionalUserInfo::username() const { return username_ ? &(*username_) : nullptr; } -void PigeonAdditionalUserInfo::set_username(const std::string_view* value_arg) { +void InternalAdditionalUserInfo::set_username( + const std::string_view* value_arg) { username_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonAdditionalUserInfo::set_username(std::string_view value_arg) { +void InternalAdditionalUserInfo::set_username(std::string_view value_arg) { username_ = value_arg; } -const std::string* PigeonAdditionalUserInfo::authorization_code() const { +const std::string* InternalAdditionalUserInfo::authorization_code() const { return authorization_code_ ? &(*authorization_code_) : nullptr; } -void PigeonAdditionalUserInfo::set_authorization_code( +void InternalAdditionalUserInfo::set_authorization_code( const std::string_view* value_arg) { authorization_code_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonAdditionalUserInfo::set_authorization_code( +void InternalAdditionalUserInfo::set_authorization_code( std::string_view value_arg) { authorization_code_ = value_arg; } -const EncodableMap* PigeonAdditionalUserInfo::profile() const { +const EncodableMap* InternalAdditionalUserInfo::profile() const { return profile_ ? &(*profile_) : nullptr; } -void PigeonAdditionalUserInfo::set_profile(const EncodableMap* value_arg) { +void InternalAdditionalUserInfo::set_profile(const EncodableMap* value_arg) { profile_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonAdditionalUserInfo::set_profile(const EncodableMap& value_arg) { +void InternalAdditionalUserInfo::set_profile(const EncodableMap& value_arg) { profile_ = value_arg; } -EncodableList PigeonAdditionalUserInfo::ToEncodableList() const { +EncodableList InternalAdditionalUserInfo::ToEncodableList() const { EncodableList list; list.reserve(5); list.push_back(EncodableValue(is_new_user_)); @@ -480,9 +834,9 @@ EncodableList PigeonAdditionalUserInfo::ToEncodableList() const { return list; } -PigeonAdditionalUserInfo PigeonAdditionalUserInfo::FromEncodableList( +InternalAdditionalUserInfo InternalAdditionalUserInfo::FromEncodableList( const EncodableList& list) { - PigeonAdditionalUserInfo decoded(std::get(list[0])); + InternalAdditionalUserInfo decoded(std::get(list[0])); auto& encodable_provider_id = list[1]; if (!encodable_provider_id.IsNull()) { decoded.set_provider_id(std::get(encodable_provider_id)); @@ -503,61 +857,90 @@ PigeonAdditionalUserInfo PigeonAdditionalUserInfo::FromEncodableList( return decoded; } -// PigeonAuthCredential +bool InternalAdditionalUserInfo::operator==( + const InternalAdditionalUserInfo& other) const { + return PigeonInternalDeepEquals(is_new_user_, other.is_new_user_) && + PigeonInternalDeepEquals(provider_id_, other.provider_id_) && + PigeonInternalDeepEquals(username_, other.username_) && + PigeonInternalDeepEquals(authorization_code_, + other.authorization_code_) && + PigeonInternalDeepEquals(profile_, other.profile_); +} + +bool InternalAdditionalUserInfo::operator!=( + const InternalAdditionalUserInfo& other) const { + return !(*this == other); +} + +size_t InternalAdditionalUserInfo::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(is_new_user_); + result = result * 31 + PigeonInternalDeepHash(provider_id_); + result = result * 31 + PigeonInternalDeepHash(username_); + result = result * 31 + PigeonInternalDeepHash(authorization_code_); + result = result * 31 + PigeonInternalDeepHash(profile_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalAdditionalUserInfo& v) { + return v.Hash(); +} + +// InternalAuthCredential -PigeonAuthCredential::PigeonAuthCredential(const std::string& provider_id, - const std::string& sign_in_method, - int64_t native_id) +InternalAuthCredential::InternalAuthCredential( + const std::string& provider_id, const std::string& sign_in_method, + int64_t native_id) : provider_id_(provider_id), sign_in_method_(sign_in_method), native_id_(native_id) {} -PigeonAuthCredential::PigeonAuthCredential(const std::string& provider_id, - const std::string& sign_in_method, - int64_t native_id, - const std::string* access_token) +InternalAuthCredential::InternalAuthCredential( + const std::string& provider_id, const std::string& sign_in_method, + int64_t native_id, const std::string* access_token) : provider_id_(provider_id), sign_in_method_(sign_in_method), native_id_(native_id), access_token_(access_token ? std::optional(*access_token) : std::nullopt) {} -const std::string& PigeonAuthCredential::provider_id() const { +const std::string& InternalAuthCredential::provider_id() const { return provider_id_; } -void PigeonAuthCredential::set_provider_id(std::string_view value_arg) { +void InternalAuthCredential::set_provider_id(std::string_view value_arg) { provider_id_ = value_arg; } -const std::string& PigeonAuthCredential::sign_in_method() const { +const std::string& InternalAuthCredential::sign_in_method() const { return sign_in_method_; } -void PigeonAuthCredential::set_sign_in_method(std::string_view value_arg) { +void InternalAuthCredential::set_sign_in_method(std::string_view value_arg) { sign_in_method_ = value_arg; } -int64_t PigeonAuthCredential::native_id() const { return native_id_; } +int64_t InternalAuthCredential::native_id() const { return native_id_; } -void PigeonAuthCredential::set_native_id(int64_t value_arg) { +void InternalAuthCredential::set_native_id(int64_t value_arg) { native_id_ = value_arg; } -const std::string* PigeonAuthCredential::access_token() const { +const std::string* InternalAuthCredential::access_token() const { return access_token_ ? &(*access_token_) : nullptr; } -void PigeonAuthCredential::set_access_token(const std::string_view* value_arg) { +void InternalAuthCredential::set_access_token( + const std::string_view* value_arg) { access_token_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonAuthCredential::set_access_token(std::string_view value_arg) { +void InternalAuthCredential::set_access_token(std::string_view value_arg) { access_token_ = value_arg; } -EncodableList PigeonAuthCredential::ToEncodableList() const { +EncodableList InternalAuthCredential::ToEncodableList() const { EncodableList list; list.reserve(4); list.push_back(EncodableValue(provider_id_)); @@ -568,11 +951,11 @@ EncodableList PigeonAuthCredential::ToEncodableList() const { return list; } -PigeonAuthCredential PigeonAuthCredential::FromEncodableList( +InternalAuthCredential InternalAuthCredential::FromEncodableList( const EncodableList& list) { - PigeonAuthCredential decoded(std::get(list[0]), - std::get(list[1]), - list[2].LongValue()); + InternalAuthCredential decoded(std::get(list[0]), + std::get(list[1]), + std::get(list[2])); auto& encodable_access_token = list[3]; if (!encodable_access_token.IsNull()) { decoded.set_access_token(std::get(encodable_access_token)); @@ -580,15 +963,41 @@ PigeonAuthCredential PigeonAuthCredential::FromEncodableList( return decoded; } -// PigeonUserInfo +bool InternalAuthCredential::operator==( + const InternalAuthCredential& other) const { + return PigeonInternalDeepEquals(provider_id_, other.provider_id_) && + PigeonInternalDeepEquals(sign_in_method_, other.sign_in_method_) && + PigeonInternalDeepEquals(native_id_, other.native_id_) && + PigeonInternalDeepEquals(access_token_, other.access_token_); +} + +bool InternalAuthCredential::operator!=( + const InternalAuthCredential& other) const { + return !(*this == other); +} + +size_t InternalAuthCredential::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(provider_id_); + result = result * 31 + PigeonInternalDeepHash(sign_in_method_); + result = result * 31 + PigeonInternalDeepHash(native_id_); + result = result * 31 + PigeonInternalDeepHash(access_token_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalAuthCredential& v) { + return v.Hash(); +} + +// InternalUserInfo -PigeonUserInfo::PigeonUserInfo(const std::string& uid, bool is_anonymous, - bool is_email_verified) +InternalUserInfo::InternalUserInfo(const std::string& uid, bool is_anonymous, + bool is_email_verified) : uid_(uid), is_anonymous_(is_anonymous), is_email_verified_(is_email_verified) {} -PigeonUserInfo::PigeonUserInfo( +InternalUserInfo::InternalUserInfo( const std::string& uid, const std::string* email, const std::string* display_name, const std::string* photo_url, const std::string* phone_number, bool is_anonymous, bool is_email_verified, @@ -619,139 +1028,139 @@ PigeonUserInfo::PigeonUserInfo( ? std::optional(*last_sign_in_timestamp) : std::nullopt) {} -const std::string& PigeonUserInfo::uid() const { return uid_; } +const std::string& InternalUserInfo::uid() const { return uid_; } -void PigeonUserInfo::set_uid(std::string_view value_arg) { uid_ = value_arg; } +void InternalUserInfo::set_uid(std::string_view value_arg) { uid_ = value_arg; } -const std::string* PigeonUserInfo::email() const { +const std::string* InternalUserInfo::email() const { return email_ ? &(*email_) : nullptr; } -void PigeonUserInfo::set_email(const std::string_view* value_arg) { +void InternalUserInfo::set_email(const std::string_view* value_arg) { email_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_email(std::string_view value_arg) { +void InternalUserInfo::set_email(std::string_view value_arg) { email_ = value_arg; } -const std::string* PigeonUserInfo::display_name() const { +const std::string* InternalUserInfo::display_name() const { return display_name_ ? &(*display_name_) : nullptr; } -void PigeonUserInfo::set_display_name(const std::string_view* value_arg) { +void InternalUserInfo::set_display_name(const std::string_view* value_arg) { display_name_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_display_name(std::string_view value_arg) { +void InternalUserInfo::set_display_name(std::string_view value_arg) { display_name_ = value_arg; } -const std::string* PigeonUserInfo::photo_url() const { +const std::string* InternalUserInfo::photo_url() const { return photo_url_ ? &(*photo_url_) : nullptr; } -void PigeonUserInfo::set_photo_url(const std::string_view* value_arg) { +void InternalUserInfo::set_photo_url(const std::string_view* value_arg) { photo_url_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_photo_url(std::string_view value_arg) { +void InternalUserInfo::set_photo_url(std::string_view value_arg) { photo_url_ = value_arg; } -const std::string* PigeonUserInfo::phone_number() const { +const std::string* InternalUserInfo::phone_number() const { return phone_number_ ? &(*phone_number_) : nullptr; } -void PigeonUserInfo::set_phone_number(const std::string_view* value_arg) { +void InternalUserInfo::set_phone_number(const std::string_view* value_arg) { phone_number_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_phone_number(std::string_view value_arg) { +void InternalUserInfo::set_phone_number(std::string_view value_arg) { phone_number_ = value_arg; } -bool PigeonUserInfo::is_anonymous() const { return is_anonymous_; } +bool InternalUserInfo::is_anonymous() const { return is_anonymous_; } -void PigeonUserInfo::set_is_anonymous(bool value_arg) { +void InternalUserInfo::set_is_anonymous(bool value_arg) { is_anonymous_ = value_arg; } -bool PigeonUserInfo::is_email_verified() const { return is_email_verified_; } +bool InternalUserInfo::is_email_verified() const { return is_email_verified_; } -void PigeonUserInfo::set_is_email_verified(bool value_arg) { +void InternalUserInfo::set_is_email_verified(bool value_arg) { is_email_verified_ = value_arg; } -const std::string* PigeonUserInfo::provider_id() const { +const std::string* InternalUserInfo::provider_id() const { return provider_id_ ? &(*provider_id_) : nullptr; } -void PigeonUserInfo::set_provider_id(const std::string_view* value_arg) { +void InternalUserInfo::set_provider_id(const std::string_view* value_arg) { provider_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_provider_id(std::string_view value_arg) { +void InternalUserInfo::set_provider_id(std::string_view value_arg) { provider_id_ = value_arg; } -const std::string* PigeonUserInfo::tenant_id() const { +const std::string* InternalUserInfo::tenant_id() const { return tenant_id_ ? &(*tenant_id_) : nullptr; } -void PigeonUserInfo::set_tenant_id(const std::string_view* value_arg) { +void InternalUserInfo::set_tenant_id(const std::string_view* value_arg) { tenant_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_tenant_id(std::string_view value_arg) { +void InternalUserInfo::set_tenant_id(std::string_view value_arg) { tenant_id_ = value_arg; } -const std::string* PigeonUserInfo::refresh_token() const { +const std::string* InternalUserInfo::refresh_token() const { return refresh_token_ ? &(*refresh_token_) : nullptr; } -void PigeonUserInfo::set_refresh_token(const std::string_view* value_arg) { +void InternalUserInfo::set_refresh_token(const std::string_view* value_arg) { refresh_token_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_refresh_token(std::string_view value_arg) { +void InternalUserInfo::set_refresh_token(std::string_view value_arg) { refresh_token_ = value_arg; } -const int64_t* PigeonUserInfo::creation_timestamp() const { +const int64_t* InternalUserInfo::creation_timestamp() const { return creation_timestamp_ ? &(*creation_timestamp_) : nullptr; } -void PigeonUserInfo::set_creation_timestamp(const int64_t* value_arg) { +void InternalUserInfo::set_creation_timestamp(const int64_t* value_arg) { creation_timestamp_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_creation_timestamp(int64_t value_arg) { +void InternalUserInfo::set_creation_timestamp(int64_t value_arg) { creation_timestamp_ = value_arg; } -const int64_t* PigeonUserInfo::last_sign_in_timestamp() const { +const int64_t* InternalUserInfo::last_sign_in_timestamp() const { return last_sign_in_timestamp_ ? &(*last_sign_in_timestamp_) : nullptr; } -void PigeonUserInfo::set_last_sign_in_timestamp(const int64_t* value_arg) { +void InternalUserInfo::set_last_sign_in_timestamp(const int64_t* value_arg) { last_sign_in_timestamp_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserInfo::set_last_sign_in_timestamp(int64_t value_arg) { +void InternalUserInfo::set_last_sign_in_timestamp(int64_t value_arg) { last_sign_in_timestamp_ = value_arg; } -EncodableList PigeonUserInfo::ToEncodableList() const { +EncodableList InternalUserInfo::ToEncodableList() const { EncodableList list; list.reserve(12); list.push_back(EncodableValue(uid_)); @@ -776,9 +1185,10 @@ EncodableList PigeonUserInfo::ToEncodableList() const { return list; } -PigeonUserInfo PigeonUserInfo::FromEncodableList(const EncodableList& list) { - PigeonUserInfo decoded(std::get(list[0]), - std::get(list[5]), std::get(list[6])); +InternalUserInfo InternalUserInfo::FromEncodableList( + const EncodableList& list) { + InternalUserInfo decoded(std::get(list[0]), + std::get(list[5]), std::get(list[6])); auto& encodable_email = list[1]; if (!encodable_email.IsNull()) { decoded.set_email(std::get(encodable_email)); @@ -809,51 +1219,93 @@ PigeonUserInfo PigeonUserInfo::FromEncodableList(const EncodableList& list) { } auto& encodable_creation_timestamp = list[10]; if (!encodable_creation_timestamp.IsNull()) { - decoded.set_creation_timestamp(encodable_creation_timestamp.LongValue()); + decoded.set_creation_timestamp( + std::get(encodable_creation_timestamp)); } auto& encodable_last_sign_in_timestamp = list[11]; if (!encodable_last_sign_in_timestamp.IsNull()) { decoded.set_last_sign_in_timestamp( - encodable_last_sign_in_timestamp.LongValue()); + std::get(encodable_last_sign_in_timestamp)); } return decoded; } -// PigeonUserDetails - -PigeonUserDetails::PigeonUserDetails(const PigeonUserInfo& user_info, - const EncodableList& provider_data) - : user_info_(std::make_unique(user_info)), +bool InternalUserInfo::operator==(const InternalUserInfo& other) const { + return PigeonInternalDeepEquals(uid_, other.uid_) && + PigeonInternalDeepEquals(email_, other.email_) && + PigeonInternalDeepEquals(display_name_, other.display_name_) && + PigeonInternalDeepEquals(photo_url_, other.photo_url_) && + PigeonInternalDeepEquals(phone_number_, other.phone_number_) && + PigeonInternalDeepEquals(is_anonymous_, other.is_anonymous_) && + PigeonInternalDeepEquals(is_email_verified_, + other.is_email_verified_) && + PigeonInternalDeepEquals(provider_id_, other.provider_id_) && + PigeonInternalDeepEquals(tenant_id_, other.tenant_id_) && + PigeonInternalDeepEquals(refresh_token_, other.refresh_token_) && + PigeonInternalDeepEquals(creation_timestamp_, + other.creation_timestamp_) && + PigeonInternalDeepEquals(last_sign_in_timestamp_, + other.last_sign_in_timestamp_); +} + +bool InternalUserInfo::operator!=(const InternalUserInfo& other) const { + return !(*this == other); +} + +size_t InternalUserInfo::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(uid_); + result = result * 31 + PigeonInternalDeepHash(email_); + result = result * 31 + PigeonInternalDeepHash(display_name_); + result = result * 31 + PigeonInternalDeepHash(photo_url_); + result = result * 31 + PigeonInternalDeepHash(phone_number_); + result = result * 31 + PigeonInternalDeepHash(is_anonymous_); + result = result * 31 + PigeonInternalDeepHash(is_email_verified_); + result = result * 31 + PigeonInternalDeepHash(provider_id_); + result = result * 31 + PigeonInternalDeepHash(tenant_id_); + result = result * 31 + PigeonInternalDeepHash(refresh_token_); + result = result * 31 + PigeonInternalDeepHash(creation_timestamp_); + result = result * 31 + PigeonInternalDeepHash(last_sign_in_timestamp_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalUserInfo& v) { return v.Hash(); } + +// InternalUserDetails + +InternalUserDetails::InternalUserDetails(const InternalUserInfo& user_info, + const EncodableList& provider_data) + : user_info_(std::make_unique(user_info)), provider_data_(provider_data) {} -PigeonUserDetails::PigeonUserDetails(const PigeonUserDetails& other) - : user_info_(std::make_unique(*other.user_info_)), +InternalUserDetails::InternalUserDetails(const InternalUserDetails& other) + : user_info_(std::make_unique(*other.user_info_)), provider_data_(other.provider_data_) {} -PigeonUserDetails& PigeonUserDetails::operator=( - const PigeonUserDetails& other) { - user_info_ = std::make_unique(*other.user_info_); +InternalUserDetails& InternalUserDetails::operator=( + const InternalUserDetails& other) { + user_info_ = std::make_unique(*other.user_info_); provider_data_ = other.provider_data_; return *this; } -const PigeonUserInfo& PigeonUserDetails::user_info() const { +const InternalUserInfo& InternalUserDetails::user_info() const { return *user_info_; } -void PigeonUserDetails::set_user_info(const PigeonUserInfo& value_arg) { - user_info_ = std::make_unique(value_arg); +void InternalUserDetails::set_user_info(const InternalUserInfo& value_arg) { + user_info_ = std::make_unique(value_arg); } -const EncodableList& PigeonUserDetails::provider_data() const { +const EncodableList& InternalUserDetails::provider_data() const { return provider_data_; } -void PigeonUserDetails::set_provider_data(const EncodableList& value_arg) { +void InternalUserDetails::set_provider_data(const EncodableList& value_arg) { provider_data_ = value_arg; } -EncodableList PigeonUserDetails::ToEncodableList() const { +EncodableList InternalUserDetails::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(CustomEncodableValue(*user_info_)); @@ -861,101 +1313,123 @@ EncodableList PigeonUserDetails::ToEncodableList() const { return list; } -PigeonUserDetails PigeonUserDetails::FromEncodableList( +InternalUserDetails InternalUserDetails::FromEncodableList( const EncodableList& list) { - PigeonUserDetails decoded(std::any_cast( - std::get(list[0])), - std::get(list[1])); + InternalUserDetails decoded(std::any_cast( + std::get(list[0])), + std::get(list[1])); return decoded; } -// PigeonUserCredential +bool InternalUserDetails::operator==(const InternalUserDetails& other) const { + return PigeonInternalDeepEquals(user_info_, other.user_info_) && + PigeonInternalDeepEquals(provider_data_, other.provider_data_); +} + +bool InternalUserDetails::operator!=(const InternalUserDetails& other) const { + return !(*this == other); +} + +size_t InternalUserDetails::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(user_info_); + result = result * 31 + PigeonInternalDeepHash(provider_data_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalUserDetails& v) { return v.Hash(); } + +// InternalUserCredential -PigeonUserCredential::PigeonUserCredential() {} +InternalUserCredential::InternalUserCredential() {} -PigeonUserCredential::PigeonUserCredential( - const PigeonUserDetails* user, - const PigeonAdditionalUserInfo* additional_user_info, - const PigeonAuthCredential* credential) - : user_(user ? std::make_unique(*user) : nullptr), +InternalUserCredential::InternalUserCredential( + const InternalUserDetails* user, + const InternalAdditionalUserInfo* additional_user_info, + const InternalAuthCredential* credential) + : user_(user ? std::make_unique(*user) : nullptr), additional_user_info_(additional_user_info - ? std::make_unique( + ? std::make_unique( *additional_user_info) : nullptr), credential_(credential - ? std::make_unique(*credential) + ? std::make_unique(*credential) : nullptr) {} -PigeonUserCredential::PigeonUserCredential(const PigeonUserCredential& other) - : user_(other.user_ ? std::make_unique(*other.user_) +InternalUserCredential::InternalUserCredential( + const InternalUserCredential& other) + : user_(other.user_ ? std::make_unique(*other.user_) : nullptr), additional_user_info_(other.additional_user_info_ - ? std::make_unique( + ? std::make_unique( *other.additional_user_info_) : nullptr), - credential_(other.credential_ ? std::make_unique( + credential_(other.credential_ ? std::make_unique( *other.credential_) : nullptr) {} -PigeonUserCredential& PigeonUserCredential::operator=( - const PigeonUserCredential& other) { - user_ = - other.user_ ? std::make_unique(*other.user_) : nullptr; +InternalUserCredential& InternalUserCredential::operator=( + const InternalUserCredential& other) { + user_ = other.user_ ? std::make_unique(*other.user_) + : nullptr; additional_user_info_ = other.additional_user_info_ - ? std::make_unique( + ? std::make_unique( *other.additional_user_info_) : nullptr; - credential_ = other.credential_ - ? std::make_unique(*other.credential_) - : nullptr; + credential_ = + other.credential_ + ? std::make_unique(*other.credential_) + : nullptr; return *this; } -const PigeonUserDetails* PigeonUserCredential::user() const { +const InternalUserDetails* InternalUserCredential::user() const { return user_.get(); } -void PigeonUserCredential::set_user(const PigeonUserDetails* value_arg) { - user_ = value_arg ? std::make_unique(*value_arg) : nullptr; +void InternalUserCredential::set_user(const InternalUserDetails* value_arg) { + user_ = + value_arg ? std::make_unique(*value_arg) : nullptr; } -void PigeonUserCredential::set_user(const PigeonUserDetails& value_arg) { - user_ = std::make_unique(value_arg); +void InternalUserCredential::set_user(const InternalUserDetails& value_arg) { + user_ = std::make_unique(value_arg); } -const PigeonAdditionalUserInfo* PigeonUserCredential::additional_user_info() +const InternalAdditionalUserInfo* InternalUserCredential::additional_user_info() const { return additional_user_info_.get(); } -void PigeonUserCredential::set_additional_user_info( - const PigeonAdditionalUserInfo* value_arg) { +void InternalUserCredential::set_additional_user_info( + const InternalAdditionalUserInfo* value_arg) { additional_user_info_ = - value_arg ? std::make_unique(*value_arg) + value_arg ? std::make_unique(*value_arg) : nullptr; } -void PigeonUserCredential::set_additional_user_info( - const PigeonAdditionalUserInfo& value_arg) { - additional_user_info_ = std::make_unique(value_arg); +void InternalUserCredential::set_additional_user_info( + const InternalAdditionalUserInfo& value_arg) { + additional_user_info_ = + std::make_unique(value_arg); } -const PigeonAuthCredential* PigeonUserCredential::credential() const { +const InternalAuthCredential* InternalUserCredential::credential() const { return credential_.get(); } -void PigeonUserCredential::set_credential( - const PigeonAuthCredential* value_arg) { - credential_ = - value_arg ? std::make_unique(*value_arg) : nullptr; +void InternalUserCredential::set_credential( + const InternalAuthCredential* value_arg) { + credential_ = value_arg ? std::make_unique(*value_arg) + : nullptr; } -void PigeonUserCredential::set_credential( - const PigeonAuthCredential& value_arg) { - credential_ = std::make_unique(value_arg); +void InternalUserCredential::set_credential( + const InternalAuthCredential& value_arg) { + credential_ = std::make_unique(value_arg); } -EncodableList PigeonUserCredential::ToEncodableList() const { +EncodableList InternalUserCredential::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(user_ ? CustomEncodableValue(*user_) : EncodableValue()); @@ -967,38 +1441,173 @@ EncodableList PigeonUserCredential::ToEncodableList() const { return list; } -PigeonUserCredential PigeonUserCredential::FromEncodableList( +InternalUserCredential InternalUserCredential::FromEncodableList( const EncodableList& list) { - PigeonUserCredential decoded; + InternalUserCredential decoded; auto& encodable_user = list[0]; if (!encodable_user.IsNull()) { - decoded.set_user(std::any_cast( + decoded.set_user(std::any_cast( std::get(encodable_user))); } auto& encodable_additional_user_info = list[1]; if (!encodable_additional_user_info.IsNull()) { decoded.set_additional_user_info( - std::any_cast( + std::any_cast( std::get(encodable_additional_user_info))); } auto& encodable_credential = list[2]; if (!encodable_credential.IsNull()) { - decoded.set_credential(std::any_cast( + decoded.set_credential(std::any_cast( std::get(encodable_credential))); } return decoded; } -// PigeonActionCodeSettings +bool InternalUserCredential::operator==( + const InternalUserCredential& other) const { + return PigeonInternalDeepEquals(user_, other.user_) && + PigeonInternalDeepEquals(additional_user_info_, + other.additional_user_info_) && + PigeonInternalDeepEquals(credential_, other.credential_); +} + +bool InternalUserCredential::operator!=( + const InternalUserCredential& other) const { + return !(*this == other); +} + +size_t InternalUserCredential::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(user_); + result = result * 31 + PigeonInternalDeepHash(additional_user_info_); + result = result * 31 + PigeonInternalDeepHash(credential_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalUserCredential& v) { + return v.Hash(); +} + +// InternalAuthCredentialInput + +InternalAuthCredentialInput::InternalAuthCredentialInput( + const std::string& provider_id, const std::string& sign_in_method) + : provider_id_(provider_id), sign_in_method_(sign_in_method) {} + +InternalAuthCredentialInput::InternalAuthCredentialInput( + const std::string& provider_id, const std::string& sign_in_method, + const std::string* token, const std::string* access_token) + : provider_id_(provider_id), + sign_in_method_(sign_in_method), + token_(token ? std::optional(*token) : std::nullopt), + access_token_(access_token ? std::optional(*access_token) + : std::nullopt) {} + +const std::string& InternalAuthCredentialInput::provider_id() const { + return provider_id_; +} + +void InternalAuthCredentialInput::set_provider_id(std::string_view value_arg) { + provider_id_ = value_arg; +} + +const std::string& InternalAuthCredentialInput::sign_in_method() const { + return sign_in_method_; +} + +void InternalAuthCredentialInput::set_sign_in_method( + std::string_view value_arg) { + sign_in_method_ = value_arg; +} + +const std::string* InternalAuthCredentialInput::token() const { + return token_ ? &(*token_) : nullptr; +} + +void InternalAuthCredentialInput::set_token(const std::string_view* value_arg) { + token_ = value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void InternalAuthCredentialInput::set_token(std::string_view value_arg) { + token_ = value_arg; +} + +const std::string* InternalAuthCredentialInput::access_token() const { + return access_token_ ? &(*access_token_) : nullptr; +} + +void InternalAuthCredentialInput::set_access_token( + const std::string_view* value_arg) { + access_token_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void InternalAuthCredentialInput::set_access_token(std::string_view value_arg) { + access_token_ = value_arg; +} + +EncodableList InternalAuthCredentialInput::ToEncodableList() const { + EncodableList list; + list.reserve(4); + list.push_back(EncodableValue(provider_id_)); + list.push_back(EncodableValue(sign_in_method_)); + list.push_back(token_ ? EncodableValue(*token_) : EncodableValue()); + list.push_back(access_token_ ? EncodableValue(*access_token_) + : EncodableValue()); + return list; +} + +InternalAuthCredentialInput InternalAuthCredentialInput::FromEncodableList( + const EncodableList& list) { + InternalAuthCredentialInput decoded(std::get(list[0]), + std::get(list[1])); + auto& encodable_token = list[2]; + if (!encodable_token.IsNull()) { + decoded.set_token(std::get(encodable_token)); + } + auto& encodable_access_token = list[3]; + if (!encodable_access_token.IsNull()) { + decoded.set_access_token(std::get(encodable_access_token)); + } + return decoded; +} + +bool InternalAuthCredentialInput::operator==( + const InternalAuthCredentialInput& other) const { + return PigeonInternalDeepEquals(provider_id_, other.provider_id_) && + PigeonInternalDeepEquals(sign_in_method_, other.sign_in_method_) && + PigeonInternalDeepEquals(token_, other.token_) && + PigeonInternalDeepEquals(access_token_, other.access_token_); +} + +bool InternalAuthCredentialInput::operator!=( + const InternalAuthCredentialInput& other) const { + return !(*this == other); +} + +size_t InternalAuthCredentialInput::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(provider_id_); + result = result * 31 + PigeonInternalDeepHash(sign_in_method_); + result = result * 31 + PigeonInternalDeepHash(token_); + result = result * 31 + PigeonInternalDeepHash(access_token_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalAuthCredentialInput& v) { + return v.Hash(); +} + +// InternalActionCodeSettings -PigeonActionCodeSettings::PigeonActionCodeSettings(const std::string& url, - bool handle_code_in_app, - bool android_install_app) +InternalActionCodeSettings::InternalActionCodeSettings(const std::string& url, + bool handle_code_in_app, + bool android_install_app) : url_(url), handle_code_in_app_(handle_code_in_app), android_install_app_(android_install_app) {} -PigeonActionCodeSettings::PigeonActionCodeSettings( +InternalActionCodeSettings::InternalActionCodeSettings( const std::string& url, const std::string* dynamic_link_domain, bool handle_code_in_app, const std::string* i_o_s_bundle_id, const std::string* android_package_name, bool android_install_app, @@ -1022,102 +1631,103 @@ PigeonActionCodeSettings::PigeonActionCodeSettings( link_domain_(link_domain ? std::optional(*link_domain) : std::nullopt) {} -const std::string& PigeonActionCodeSettings::url() const { return url_; } +const std::string& InternalActionCodeSettings::url() const { return url_; } -void PigeonActionCodeSettings::set_url(std::string_view value_arg) { +void InternalActionCodeSettings::set_url(std::string_view value_arg) { url_ = value_arg; } -const std::string* PigeonActionCodeSettings::dynamic_link_domain() const { +const std::string* InternalActionCodeSettings::dynamic_link_domain() const { return dynamic_link_domain_ ? &(*dynamic_link_domain_) : nullptr; } -void PigeonActionCodeSettings::set_dynamic_link_domain( +void InternalActionCodeSettings::set_dynamic_link_domain( const std::string_view* value_arg) { dynamic_link_domain_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonActionCodeSettings::set_dynamic_link_domain( +void InternalActionCodeSettings::set_dynamic_link_domain( std::string_view value_arg) { dynamic_link_domain_ = value_arg; } -bool PigeonActionCodeSettings::handle_code_in_app() const { +bool InternalActionCodeSettings::handle_code_in_app() const { return handle_code_in_app_; } -void PigeonActionCodeSettings::set_handle_code_in_app(bool value_arg) { +void InternalActionCodeSettings::set_handle_code_in_app(bool value_arg) { handle_code_in_app_ = value_arg; } -const std::string* PigeonActionCodeSettings::i_o_s_bundle_id() const { +const std::string* InternalActionCodeSettings::i_o_s_bundle_id() const { return i_o_s_bundle_id_ ? &(*i_o_s_bundle_id_) : nullptr; } -void PigeonActionCodeSettings::set_i_o_s_bundle_id( +void InternalActionCodeSettings::set_i_o_s_bundle_id( const std::string_view* value_arg) { i_o_s_bundle_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonActionCodeSettings::set_i_o_s_bundle_id(std::string_view value_arg) { +void InternalActionCodeSettings::set_i_o_s_bundle_id( + std::string_view value_arg) { i_o_s_bundle_id_ = value_arg; } -const std::string* PigeonActionCodeSettings::android_package_name() const { +const std::string* InternalActionCodeSettings::android_package_name() const { return android_package_name_ ? &(*android_package_name_) : nullptr; } -void PigeonActionCodeSettings::set_android_package_name( +void InternalActionCodeSettings::set_android_package_name( const std::string_view* value_arg) { android_package_name_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonActionCodeSettings::set_android_package_name( +void InternalActionCodeSettings::set_android_package_name( std::string_view value_arg) { android_package_name_ = value_arg; } -bool PigeonActionCodeSettings::android_install_app() const { +bool InternalActionCodeSettings::android_install_app() const { return android_install_app_; } -void PigeonActionCodeSettings::set_android_install_app(bool value_arg) { +void InternalActionCodeSettings::set_android_install_app(bool value_arg) { android_install_app_ = value_arg; } -const std::string* PigeonActionCodeSettings::android_minimum_version() const { +const std::string* InternalActionCodeSettings::android_minimum_version() const { return android_minimum_version_ ? &(*android_minimum_version_) : nullptr; } -void PigeonActionCodeSettings::set_android_minimum_version( +void InternalActionCodeSettings::set_android_minimum_version( const std::string_view* value_arg) { android_minimum_version_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonActionCodeSettings::set_android_minimum_version( +void InternalActionCodeSettings::set_android_minimum_version( std::string_view value_arg) { android_minimum_version_ = value_arg; } -const std::string* PigeonActionCodeSettings::link_domain() const { +const std::string* InternalActionCodeSettings::link_domain() const { return link_domain_ ? &(*link_domain_) : nullptr; } -void PigeonActionCodeSettings::set_link_domain( +void InternalActionCodeSettings::set_link_domain( const std::string_view* value_arg) { link_domain_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonActionCodeSettings::set_link_domain(std::string_view value_arg) { +void InternalActionCodeSettings::set_link_domain(std::string_view value_arg) { link_domain_ = value_arg; } -EncodableList PigeonActionCodeSettings::ToEncodableList() const { +EncodableList InternalActionCodeSettings::ToEncodableList() const { EncodableList list; list.reserve(8); list.push_back(EncodableValue(url_)); @@ -1137,11 +1747,11 @@ EncodableList PigeonActionCodeSettings::ToEncodableList() const { return list; } -PigeonActionCodeSettings PigeonActionCodeSettings::FromEncodableList( +InternalActionCodeSettings InternalActionCodeSettings::FromEncodableList( const EncodableList& list) { - PigeonActionCodeSettings decoded(std::get(list[0]), - std::get(list[2]), - std::get(list[5])); + InternalActionCodeSettings decoded(std::get(list[0]), + std::get(list[2]), + std::get(list[5])); auto& encodable_dynamic_link_domain = list[1]; if (!encodable_dynamic_link_domain.IsNull()) { decoded.set_dynamic_link_domain( @@ -1169,14 +1779,53 @@ PigeonActionCodeSettings PigeonActionCodeSettings::FromEncodableList( return decoded; } -// PigeonFirebaseAuthSettings +bool InternalActionCodeSettings::operator==( + const InternalActionCodeSettings& other) const { + return PigeonInternalDeepEquals(url_, other.url_) && + PigeonInternalDeepEquals(dynamic_link_domain_, + other.dynamic_link_domain_) && + PigeonInternalDeepEquals(handle_code_in_app_, + other.handle_code_in_app_) && + PigeonInternalDeepEquals(i_o_s_bundle_id_, other.i_o_s_bundle_id_) && + PigeonInternalDeepEquals(android_package_name_, + other.android_package_name_) && + PigeonInternalDeepEquals(android_install_app_, + other.android_install_app_) && + PigeonInternalDeepEquals(android_minimum_version_, + other.android_minimum_version_) && + PigeonInternalDeepEquals(link_domain_, other.link_domain_); +} + +bool InternalActionCodeSettings::operator!=( + const InternalActionCodeSettings& other) const { + return !(*this == other); +} + +size_t InternalActionCodeSettings::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(url_); + result = result * 31 + PigeonInternalDeepHash(dynamic_link_domain_); + result = result * 31 + PigeonInternalDeepHash(handle_code_in_app_); + result = result * 31 + PigeonInternalDeepHash(i_o_s_bundle_id_); + result = result * 31 + PigeonInternalDeepHash(android_package_name_); + result = result * 31 + PigeonInternalDeepHash(android_install_app_); + result = result * 31 + PigeonInternalDeepHash(android_minimum_version_); + result = result * 31 + PigeonInternalDeepHash(link_domain_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalActionCodeSettings& v) { + return v.Hash(); +} + +// InternalFirebaseAuthSettings -PigeonFirebaseAuthSettings::PigeonFirebaseAuthSettings( +InternalFirebaseAuthSettings::InternalFirebaseAuthSettings( bool app_verification_disabled_for_testing) : app_verification_disabled_for_testing_( app_verification_disabled_for_testing) {} -PigeonFirebaseAuthSettings::PigeonFirebaseAuthSettings( +InternalFirebaseAuthSettings::InternalFirebaseAuthSettings( bool app_verification_disabled_for_testing, const std::string* user_access_group, const std::string* phone_number, const std::string* sms_code, const bool* force_recaptcha_flow) @@ -1193,72 +1842,74 @@ PigeonFirebaseAuthSettings::PigeonFirebaseAuthSettings( ? std::optional(*force_recaptcha_flow) : std::nullopt) {} -bool PigeonFirebaseAuthSettings::app_verification_disabled_for_testing() const { +bool InternalFirebaseAuthSettings::app_verification_disabled_for_testing() + const { return app_verification_disabled_for_testing_; } -void PigeonFirebaseAuthSettings::set_app_verification_disabled_for_testing( +void InternalFirebaseAuthSettings::set_app_verification_disabled_for_testing( bool value_arg) { app_verification_disabled_for_testing_ = value_arg; } -const std::string* PigeonFirebaseAuthSettings::user_access_group() const { +const std::string* InternalFirebaseAuthSettings::user_access_group() const { return user_access_group_ ? &(*user_access_group_) : nullptr; } -void PigeonFirebaseAuthSettings::set_user_access_group( +void InternalFirebaseAuthSettings::set_user_access_group( const std::string_view* value_arg) { user_access_group_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseAuthSettings::set_user_access_group( +void InternalFirebaseAuthSettings::set_user_access_group( std::string_view value_arg) { user_access_group_ = value_arg; } -const std::string* PigeonFirebaseAuthSettings::phone_number() const { +const std::string* InternalFirebaseAuthSettings::phone_number() const { return phone_number_ ? &(*phone_number_) : nullptr; } -void PigeonFirebaseAuthSettings::set_phone_number( +void InternalFirebaseAuthSettings::set_phone_number( const std::string_view* value_arg) { phone_number_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseAuthSettings::set_phone_number(std::string_view value_arg) { +void InternalFirebaseAuthSettings::set_phone_number( + std::string_view value_arg) { phone_number_ = value_arg; } -const std::string* PigeonFirebaseAuthSettings::sms_code() const { +const std::string* InternalFirebaseAuthSettings::sms_code() const { return sms_code_ ? &(*sms_code_) : nullptr; } -void PigeonFirebaseAuthSettings::set_sms_code( +void InternalFirebaseAuthSettings::set_sms_code( const std::string_view* value_arg) { sms_code_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseAuthSettings::set_sms_code(std::string_view value_arg) { +void InternalFirebaseAuthSettings::set_sms_code(std::string_view value_arg) { sms_code_ = value_arg; } -const bool* PigeonFirebaseAuthSettings::force_recaptcha_flow() const { +const bool* InternalFirebaseAuthSettings::force_recaptcha_flow() const { return force_recaptcha_flow_ ? &(*force_recaptcha_flow_) : nullptr; } -void PigeonFirebaseAuthSettings::set_force_recaptcha_flow( +void InternalFirebaseAuthSettings::set_force_recaptcha_flow( const bool* value_arg) { force_recaptcha_flow_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFirebaseAuthSettings::set_force_recaptcha_flow(bool value_arg) { +void InternalFirebaseAuthSettings::set_force_recaptcha_flow(bool value_arg) { force_recaptcha_flow_ = value_arg; } -EncodableList PigeonFirebaseAuthSettings::ToEncodableList() const { +EncodableList InternalFirebaseAuthSettings::ToEncodableList() const { EncodableList list; list.reserve(5); list.push_back(EncodableValue(app_verification_disabled_for_testing_)); @@ -1272,9 +1923,9 @@ EncodableList PigeonFirebaseAuthSettings::ToEncodableList() const { return list; } -PigeonFirebaseAuthSettings PigeonFirebaseAuthSettings::FromEncodableList( +InternalFirebaseAuthSettings InternalFirebaseAuthSettings::FromEncodableList( const EncodableList& list) { - PigeonFirebaseAuthSettings decoded(std::get(list[0])); + InternalFirebaseAuthSettings decoded(std::get(list[0])); auto& encodable_user_access_group = list[1]; if (!encodable_user_access_group.IsNull()) { decoded.set_user_access_group( @@ -1296,12 +1947,45 @@ PigeonFirebaseAuthSettings PigeonFirebaseAuthSettings::FromEncodableList( return decoded; } -// PigeonSignInProvider +bool InternalFirebaseAuthSettings::operator==( + const InternalFirebaseAuthSettings& other) const { + return PigeonInternalDeepEquals( + app_verification_disabled_for_testing_, + other.app_verification_disabled_for_testing_) && + PigeonInternalDeepEquals(user_access_group_, + other.user_access_group_) && + PigeonInternalDeepEquals(phone_number_, other.phone_number_) && + PigeonInternalDeepEquals(sms_code_, other.sms_code_) && + PigeonInternalDeepEquals(force_recaptcha_flow_, + other.force_recaptcha_flow_); +} + +bool InternalFirebaseAuthSettings::operator!=( + const InternalFirebaseAuthSettings& other) const { + return !(*this == other); +} + +size_t InternalFirebaseAuthSettings::Hash() const { + size_t result = 1; + result = result * 31 + + PigeonInternalDeepHash(app_verification_disabled_for_testing_); + result = result * 31 + PigeonInternalDeepHash(user_access_group_); + result = result * 31 + PigeonInternalDeepHash(phone_number_); + result = result * 31 + PigeonInternalDeepHash(sms_code_); + result = result * 31 + PigeonInternalDeepHash(force_recaptcha_flow_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalFirebaseAuthSettings& v) { + return v.Hash(); +} + +// InternalSignInProvider -PigeonSignInProvider::PigeonSignInProvider(const std::string& provider_id) +InternalSignInProvider::InternalSignInProvider(const std::string& provider_id) : provider_id_(provider_id) {} -PigeonSignInProvider::PigeonSignInProvider( +InternalSignInProvider::InternalSignInProvider( const std::string& provider_id, const EncodableList* scopes, const EncodableMap* custom_parameters) : provider_id_(provider_id), @@ -1310,42 +1994,42 @@ PigeonSignInProvider::PigeonSignInProvider( ? std::optional(*custom_parameters) : std::nullopt) {} -const std::string& PigeonSignInProvider::provider_id() const { +const std::string& InternalSignInProvider::provider_id() const { return provider_id_; } -void PigeonSignInProvider::set_provider_id(std::string_view value_arg) { +void InternalSignInProvider::set_provider_id(std::string_view value_arg) { provider_id_ = value_arg; } -const EncodableList* PigeonSignInProvider::scopes() const { +const EncodableList* InternalSignInProvider::scopes() const { return scopes_ ? &(*scopes_) : nullptr; } -void PigeonSignInProvider::set_scopes(const EncodableList* value_arg) { +void InternalSignInProvider::set_scopes(const EncodableList* value_arg) { scopes_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSignInProvider::set_scopes(const EncodableList& value_arg) { +void InternalSignInProvider::set_scopes(const EncodableList& value_arg) { scopes_ = value_arg; } -const EncodableMap* PigeonSignInProvider::custom_parameters() const { +const EncodableMap* InternalSignInProvider::custom_parameters() const { return custom_parameters_ ? &(*custom_parameters_) : nullptr; } -void PigeonSignInProvider::set_custom_parameters( +void InternalSignInProvider::set_custom_parameters( const EncodableMap* value_arg) { custom_parameters_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSignInProvider::set_custom_parameters( +void InternalSignInProvider::set_custom_parameters( const EncodableMap& value_arg) { custom_parameters_ = value_arg; } -EncodableList PigeonSignInProvider::ToEncodableList() const { +EncodableList InternalSignInProvider::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(EncodableValue(provider_id_)); @@ -1355,9 +2039,9 @@ EncodableList PigeonSignInProvider::ToEncodableList() const { return list; } -PigeonSignInProvider PigeonSignInProvider::FromEncodableList( +InternalSignInProvider InternalSignInProvider::FromEncodableList( const EncodableList& list) { - PigeonSignInProvider decoded(std::get(list[0])); + InternalSignInProvider decoded(std::get(list[0])); auto& encodable_scopes = list[1]; if (!encodable_scopes.IsNull()) { decoded.set_scopes(std::get(encodable_scopes)); @@ -1370,12 +2054,37 @@ PigeonSignInProvider PigeonSignInProvider::FromEncodableList( return decoded; } -// PigeonVerifyPhoneNumberRequest +bool InternalSignInProvider::operator==( + const InternalSignInProvider& other) const { + return PigeonInternalDeepEquals(provider_id_, other.provider_id_) && + PigeonInternalDeepEquals(scopes_, other.scopes_) && + PigeonInternalDeepEquals(custom_parameters_, other.custom_parameters_); +} + +bool InternalSignInProvider::operator!=( + const InternalSignInProvider& other) const { + return !(*this == other); +} + +size_t InternalSignInProvider::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(provider_id_); + result = result * 31 + PigeonInternalDeepHash(scopes_); + result = result * 31 + PigeonInternalDeepHash(custom_parameters_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalSignInProvider& v) { + return v.Hash(); +} + +// InternalVerifyPhoneNumberRequest -PigeonVerifyPhoneNumberRequest::PigeonVerifyPhoneNumberRequest(int64_t timeout) +InternalVerifyPhoneNumberRequest::InternalVerifyPhoneNumberRequest( + int64_t timeout) : timeout_(timeout) {} -PigeonVerifyPhoneNumberRequest::PigeonVerifyPhoneNumberRequest( +InternalVerifyPhoneNumberRequest::InternalVerifyPhoneNumberRequest( const std::string* phone_number, int64_t timeout, const int64_t* force_resending_token, const std::string* auto_retrieved_sms_code_for_testing, @@ -1399,93 +2108,93 @@ PigeonVerifyPhoneNumberRequest::PigeonVerifyPhoneNumberRequest( ? std::optional(*multi_factor_session_id) : std::nullopt) {} -const std::string* PigeonVerifyPhoneNumberRequest::phone_number() const { +const std::string* InternalVerifyPhoneNumberRequest::phone_number() const { return phone_number_ ? &(*phone_number_) : nullptr; } -void PigeonVerifyPhoneNumberRequest::set_phone_number( +void InternalVerifyPhoneNumberRequest::set_phone_number( const std::string_view* value_arg) { phone_number_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonVerifyPhoneNumberRequest::set_phone_number( +void InternalVerifyPhoneNumberRequest::set_phone_number( std::string_view value_arg) { phone_number_ = value_arg; } -int64_t PigeonVerifyPhoneNumberRequest::timeout() const { return timeout_; } +int64_t InternalVerifyPhoneNumberRequest::timeout() const { return timeout_; } -void PigeonVerifyPhoneNumberRequest::set_timeout(int64_t value_arg) { +void InternalVerifyPhoneNumberRequest::set_timeout(int64_t value_arg) { timeout_ = value_arg; } -const int64_t* PigeonVerifyPhoneNumberRequest::force_resending_token() const { +const int64_t* InternalVerifyPhoneNumberRequest::force_resending_token() const { return force_resending_token_ ? &(*force_resending_token_) : nullptr; } -void PigeonVerifyPhoneNumberRequest::set_force_resending_token( +void InternalVerifyPhoneNumberRequest::set_force_resending_token( const int64_t* value_arg) { force_resending_token_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonVerifyPhoneNumberRequest::set_force_resending_token( +void InternalVerifyPhoneNumberRequest::set_force_resending_token( int64_t value_arg) { force_resending_token_ = value_arg; } const std::string* -PigeonVerifyPhoneNumberRequest::auto_retrieved_sms_code_for_testing() const { +InternalVerifyPhoneNumberRequest::auto_retrieved_sms_code_for_testing() const { return auto_retrieved_sms_code_for_testing_ ? &(*auto_retrieved_sms_code_for_testing_) : nullptr; } -void PigeonVerifyPhoneNumberRequest::set_auto_retrieved_sms_code_for_testing( +void InternalVerifyPhoneNumberRequest::set_auto_retrieved_sms_code_for_testing( const std::string_view* value_arg) { auto_retrieved_sms_code_for_testing_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonVerifyPhoneNumberRequest::set_auto_retrieved_sms_code_for_testing( +void InternalVerifyPhoneNumberRequest::set_auto_retrieved_sms_code_for_testing( std::string_view value_arg) { auto_retrieved_sms_code_for_testing_ = value_arg; } -const std::string* PigeonVerifyPhoneNumberRequest::multi_factor_info_id() +const std::string* InternalVerifyPhoneNumberRequest::multi_factor_info_id() const { return multi_factor_info_id_ ? &(*multi_factor_info_id_) : nullptr; } -void PigeonVerifyPhoneNumberRequest::set_multi_factor_info_id( +void InternalVerifyPhoneNumberRequest::set_multi_factor_info_id( const std::string_view* value_arg) { multi_factor_info_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonVerifyPhoneNumberRequest::set_multi_factor_info_id( +void InternalVerifyPhoneNumberRequest::set_multi_factor_info_id( std::string_view value_arg) { multi_factor_info_id_ = value_arg; } -const std::string* PigeonVerifyPhoneNumberRequest::multi_factor_session_id() +const std::string* InternalVerifyPhoneNumberRequest::multi_factor_session_id() const { return multi_factor_session_id_ ? &(*multi_factor_session_id_) : nullptr; } -void PigeonVerifyPhoneNumberRequest::set_multi_factor_session_id( +void InternalVerifyPhoneNumberRequest::set_multi_factor_session_id( const std::string_view* value_arg) { multi_factor_session_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonVerifyPhoneNumberRequest::set_multi_factor_session_id( +void InternalVerifyPhoneNumberRequest::set_multi_factor_session_id( std::string_view value_arg) { multi_factor_session_id_ = value_arg; } -EncodableList PigeonVerifyPhoneNumberRequest::ToEncodableList() const { +EncodableList InternalVerifyPhoneNumberRequest::ToEncodableList() const { EncodableList list; list.reserve(6); list.push_back(phone_number_ ? EncodableValue(*phone_number_) @@ -1505,9 +2214,9 @@ EncodableList PigeonVerifyPhoneNumberRequest::ToEncodableList() const { return list; } -PigeonVerifyPhoneNumberRequest -PigeonVerifyPhoneNumberRequest::FromEncodableList(const EncodableList& list) { - PigeonVerifyPhoneNumberRequest decoded(list[1].LongValue()); +InternalVerifyPhoneNumberRequest +InternalVerifyPhoneNumberRequest::FromEncodableList(const EncodableList& list) { + InternalVerifyPhoneNumberRequest decoded(std::get(list[1])); auto& encodable_phone_number = list[0]; if (!encodable_phone_number.IsNull()) { decoded.set_phone_number(std::get(encodable_phone_number)); @@ -1515,7 +2224,7 @@ PigeonVerifyPhoneNumberRequest::FromEncodableList(const EncodableList& list) { auto& encodable_force_resending_token = list[2]; if (!encodable_force_resending_token.IsNull()) { decoded.set_force_resending_token( - encodable_force_resending_token.LongValue()); + std::get(encodable_force_resending_token)); } auto& encodable_auto_retrieved_sms_code_for_testing = list[3]; if (!encodable_auto_retrieved_sms_code_for_testing.IsNull()) { @@ -1535,11 +2244,46 @@ PigeonVerifyPhoneNumberRequest::FromEncodableList(const EncodableList& list) { return decoded; } -// PigeonIdTokenResult +bool InternalVerifyPhoneNumberRequest::operator==( + const InternalVerifyPhoneNumberRequest& other) const { + return PigeonInternalDeepEquals(phone_number_, other.phone_number_) && + PigeonInternalDeepEquals(timeout_, other.timeout_) && + PigeonInternalDeepEquals(force_resending_token_, + other.force_resending_token_) && + PigeonInternalDeepEquals(auto_retrieved_sms_code_for_testing_, + other.auto_retrieved_sms_code_for_testing_) && + PigeonInternalDeepEquals(multi_factor_info_id_, + other.multi_factor_info_id_) && + PigeonInternalDeepEquals(multi_factor_session_id_, + other.multi_factor_session_id_); +} + +bool InternalVerifyPhoneNumberRequest::operator!=( + const InternalVerifyPhoneNumberRequest& other) const { + return !(*this == other); +} + +size_t InternalVerifyPhoneNumberRequest::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(phone_number_); + result = result * 31 + PigeonInternalDeepHash(timeout_); + result = result * 31 + PigeonInternalDeepHash(force_resending_token_); + result = result * 31 + + PigeonInternalDeepHash(auto_retrieved_sms_code_for_testing_); + result = result * 31 + PigeonInternalDeepHash(multi_factor_info_id_); + result = result * 31 + PigeonInternalDeepHash(multi_factor_session_id_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalVerifyPhoneNumberRequest& v) { + return v.Hash(); +} + +// InternalIdTokenResult -PigeonIdTokenResult::PigeonIdTokenResult() {} +InternalIdTokenResult::InternalIdTokenResult() {} -PigeonIdTokenResult::PigeonIdTokenResult( +InternalIdTokenResult::InternalIdTokenResult( const std::string* token, const int64_t* expiration_timestamp, const int64_t* auth_timestamp, const int64_t* issued_at_timestamp, const std::string* sign_in_provider, const EncodableMap* claims, @@ -1561,99 +2305,99 @@ PigeonIdTokenResult::PigeonIdTokenResult( *sign_in_second_factor) : std::nullopt) {} -const std::string* PigeonIdTokenResult::token() const { +const std::string* InternalIdTokenResult::token() const { return token_ ? &(*token_) : nullptr; } -void PigeonIdTokenResult::set_token(const std::string_view* value_arg) { +void InternalIdTokenResult::set_token(const std::string_view* value_arg) { token_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonIdTokenResult::set_token(std::string_view value_arg) { +void InternalIdTokenResult::set_token(std::string_view value_arg) { token_ = value_arg; } -const int64_t* PigeonIdTokenResult::expiration_timestamp() const { +const int64_t* InternalIdTokenResult::expiration_timestamp() const { return expiration_timestamp_ ? &(*expiration_timestamp_) : nullptr; } -void PigeonIdTokenResult::set_expiration_timestamp(const int64_t* value_arg) { +void InternalIdTokenResult::set_expiration_timestamp(const int64_t* value_arg) { expiration_timestamp_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonIdTokenResult::set_expiration_timestamp(int64_t value_arg) { +void InternalIdTokenResult::set_expiration_timestamp(int64_t value_arg) { expiration_timestamp_ = value_arg; } -const int64_t* PigeonIdTokenResult::auth_timestamp() const { +const int64_t* InternalIdTokenResult::auth_timestamp() const { return auth_timestamp_ ? &(*auth_timestamp_) : nullptr; } -void PigeonIdTokenResult::set_auth_timestamp(const int64_t* value_arg) { +void InternalIdTokenResult::set_auth_timestamp(const int64_t* value_arg) { auth_timestamp_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonIdTokenResult::set_auth_timestamp(int64_t value_arg) { +void InternalIdTokenResult::set_auth_timestamp(int64_t value_arg) { auth_timestamp_ = value_arg; } -const int64_t* PigeonIdTokenResult::issued_at_timestamp() const { +const int64_t* InternalIdTokenResult::issued_at_timestamp() const { return issued_at_timestamp_ ? &(*issued_at_timestamp_) : nullptr; } -void PigeonIdTokenResult::set_issued_at_timestamp(const int64_t* value_arg) { +void InternalIdTokenResult::set_issued_at_timestamp(const int64_t* value_arg) { issued_at_timestamp_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonIdTokenResult::set_issued_at_timestamp(int64_t value_arg) { +void InternalIdTokenResult::set_issued_at_timestamp(int64_t value_arg) { issued_at_timestamp_ = value_arg; } -const std::string* PigeonIdTokenResult::sign_in_provider() const { +const std::string* InternalIdTokenResult::sign_in_provider() const { return sign_in_provider_ ? &(*sign_in_provider_) : nullptr; } -void PigeonIdTokenResult::set_sign_in_provider( +void InternalIdTokenResult::set_sign_in_provider( const std::string_view* value_arg) { sign_in_provider_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonIdTokenResult::set_sign_in_provider(std::string_view value_arg) { +void InternalIdTokenResult::set_sign_in_provider(std::string_view value_arg) { sign_in_provider_ = value_arg; } -const EncodableMap* PigeonIdTokenResult::claims() const { +const EncodableMap* InternalIdTokenResult::claims() const { return claims_ ? &(*claims_) : nullptr; } -void PigeonIdTokenResult::set_claims(const EncodableMap* value_arg) { +void InternalIdTokenResult::set_claims(const EncodableMap* value_arg) { claims_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonIdTokenResult::set_claims(const EncodableMap& value_arg) { +void InternalIdTokenResult::set_claims(const EncodableMap& value_arg) { claims_ = value_arg; } -const std::string* PigeonIdTokenResult::sign_in_second_factor() const { +const std::string* InternalIdTokenResult::sign_in_second_factor() const { return sign_in_second_factor_ ? &(*sign_in_second_factor_) : nullptr; } -void PigeonIdTokenResult::set_sign_in_second_factor( +void InternalIdTokenResult::set_sign_in_second_factor( const std::string_view* value_arg) { sign_in_second_factor_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonIdTokenResult::set_sign_in_second_factor( +void InternalIdTokenResult::set_sign_in_second_factor( std::string_view value_arg) { sign_in_second_factor_ = value_arg; } -EncodableList PigeonIdTokenResult::ToEncodableList() const { +EncodableList InternalIdTokenResult::ToEncodableList() const { EncodableList list; list.reserve(7); list.push_back(token_ ? EncodableValue(*token_) : EncodableValue()); @@ -1672,9 +2416,9 @@ EncodableList PigeonIdTokenResult::ToEncodableList() const { return list; } -PigeonIdTokenResult PigeonIdTokenResult::FromEncodableList( +InternalIdTokenResult InternalIdTokenResult::FromEncodableList( const EncodableList& list) { - PigeonIdTokenResult decoded; + InternalIdTokenResult decoded; auto& encodable_token = list[0]; if (!encodable_token.IsNull()) { decoded.set_token(std::get(encodable_token)); @@ -1682,15 +2426,16 @@ PigeonIdTokenResult PigeonIdTokenResult::FromEncodableList( auto& encodable_expiration_timestamp = list[1]; if (!encodable_expiration_timestamp.IsNull()) { decoded.set_expiration_timestamp( - encodable_expiration_timestamp.LongValue()); + std::get(encodable_expiration_timestamp)); } auto& encodable_auth_timestamp = list[2]; if (!encodable_auth_timestamp.IsNull()) { - decoded.set_auth_timestamp(encodable_auth_timestamp.LongValue()); + decoded.set_auth_timestamp(std::get(encodable_auth_timestamp)); } auto& encodable_issued_at_timestamp = list[3]; if (!encodable_issued_at_timestamp.IsNull()) { - decoded.set_issued_at_timestamp(encodable_issued_at_timestamp.LongValue()); + decoded.set_issued_at_timestamp( + std::get(encodable_issued_at_timestamp)); } auto& encodable_sign_in_provider = list[4]; if (!encodable_sign_in_provider.IsNull()) { @@ -1709,65 +2454,102 @@ PigeonIdTokenResult PigeonIdTokenResult::FromEncodableList( return decoded; } -// PigeonUserProfile +bool InternalIdTokenResult::operator==( + const InternalIdTokenResult& other) const { + return PigeonInternalDeepEquals(token_, other.token_) && + PigeonInternalDeepEquals(expiration_timestamp_, + other.expiration_timestamp_) && + PigeonInternalDeepEquals(auth_timestamp_, other.auth_timestamp_) && + PigeonInternalDeepEquals(issued_at_timestamp_, + other.issued_at_timestamp_) && + PigeonInternalDeepEquals(sign_in_provider_, other.sign_in_provider_) && + PigeonInternalDeepEquals(claims_, other.claims_) && + PigeonInternalDeepEquals(sign_in_second_factor_, + other.sign_in_second_factor_); +} -PigeonUserProfile::PigeonUserProfile(bool display_name_changed, - bool photo_url_changed) - : display_name_changed_(display_name_changed), - photo_url_changed_(photo_url_changed) {} +bool InternalIdTokenResult::operator!=( + const InternalIdTokenResult& other) const { + return !(*this == other); +} -PigeonUserProfile::PigeonUserProfile(const std::string* display_name, - const std::string* photo_url, - bool display_name_changed, - bool photo_url_changed) - : display_name_(display_name ? std::optional(*display_name) - : std::nullopt), - photo_url_(photo_url ? std::optional(*photo_url) +size_t InternalIdTokenResult::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(token_); + result = result * 31 + PigeonInternalDeepHash(expiration_timestamp_); + result = result * 31 + PigeonInternalDeepHash(auth_timestamp_); + result = result * 31 + PigeonInternalDeepHash(issued_at_timestamp_); + result = result * 31 + PigeonInternalDeepHash(sign_in_provider_); + result = result * 31 + PigeonInternalDeepHash(claims_); + result = result * 31 + PigeonInternalDeepHash(sign_in_second_factor_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalIdTokenResult& v) { + return v.Hash(); +} + +// InternalUserProfile + +InternalUserProfile::InternalUserProfile(bool display_name_changed, + bool photo_url_changed) + : display_name_changed_(display_name_changed), + photo_url_changed_(photo_url_changed) {} + +InternalUserProfile::InternalUserProfile(const std::string* display_name, + const std::string* photo_url, + bool display_name_changed, + bool photo_url_changed) + : display_name_(display_name ? std::optional(*display_name) + : std::nullopt), + photo_url_(photo_url ? std::optional(*photo_url) : std::nullopt), display_name_changed_(display_name_changed), photo_url_changed_(photo_url_changed) {} -const std::string* PigeonUserProfile::display_name() const { +const std::string* InternalUserProfile::display_name() const { return display_name_ ? &(*display_name_) : nullptr; } -void PigeonUserProfile::set_display_name(const std::string_view* value_arg) { +void InternalUserProfile::set_display_name(const std::string_view* value_arg) { display_name_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserProfile::set_display_name(std::string_view value_arg) { +void InternalUserProfile::set_display_name(std::string_view value_arg) { display_name_ = value_arg; } -const std::string* PigeonUserProfile::photo_url() const { +const std::string* InternalUserProfile::photo_url() const { return photo_url_ ? &(*photo_url_) : nullptr; } -void PigeonUserProfile::set_photo_url(const std::string_view* value_arg) { +void InternalUserProfile::set_photo_url(const std::string_view* value_arg) { photo_url_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonUserProfile::set_photo_url(std::string_view value_arg) { +void InternalUserProfile::set_photo_url(std::string_view value_arg) { photo_url_ = value_arg; } -bool PigeonUserProfile::display_name_changed() const { +bool InternalUserProfile::display_name_changed() const { return display_name_changed_; } -void PigeonUserProfile::set_display_name_changed(bool value_arg) { +void InternalUserProfile::set_display_name_changed(bool value_arg) { display_name_changed_ = value_arg; } -bool PigeonUserProfile::photo_url_changed() const { return photo_url_changed_; } +bool InternalUserProfile::photo_url_changed() const { + return photo_url_changed_; +} -void PigeonUserProfile::set_photo_url_changed(bool value_arg) { +void InternalUserProfile::set_photo_url_changed(bool value_arg) { photo_url_changed_ = value_arg; } -EncodableList PigeonUserProfile::ToEncodableList() const { +EncodableList InternalUserProfile::ToEncodableList() const { EncodableList list; list.reserve(4); list.push_back(display_name_ ? EncodableValue(*display_name_) @@ -1778,9 +2560,9 @@ EncodableList PigeonUserProfile::ToEncodableList() const { return list; } -PigeonUserProfile PigeonUserProfile::FromEncodableList( +InternalUserProfile InternalUserProfile::FromEncodableList( const EncodableList& list) { - PigeonUserProfile decoded(std::get(list[2]), std::get(list[3])); + InternalUserProfile decoded(std::get(list[2]), std::get(list[3])); auto& encodable_display_name = list[0]; if (!encodable_display_name.IsNull()) { decoded.set_display_name(std::get(encodable_display_name)); @@ -1792,12 +2574,35 @@ PigeonUserProfile PigeonUserProfile::FromEncodableList( return decoded; } -// PigeonTotpSecret +bool InternalUserProfile::operator==(const InternalUserProfile& other) const { + return PigeonInternalDeepEquals(display_name_, other.display_name_) && + PigeonInternalDeepEquals(photo_url_, other.photo_url_) && + PigeonInternalDeepEquals(display_name_changed_, + other.display_name_changed_) && + PigeonInternalDeepEquals(photo_url_changed_, other.photo_url_changed_); +} + +bool InternalUserProfile::operator!=(const InternalUserProfile& other) const { + return !(*this == other); +} + +size_t InternalUserProfile::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(display_name_); + result = result * 31 + PigeonInternalDeepHash(photo_url_); + result = result * 31 + PigeonInternalDeepHash(display_name_changed_); + result = result * 31 + PigeonInternalDeepHash(photo_url_changed_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalUserProfile& v) { return v.Hash(); } -PigeonTotpSecret::PigeonTotpSecret(const std::string& secret_key) +// InternalTotpSecret + +InternalTotpSecret::InternalTotpSecret(const std::string& secret_key) : secret_key_(secret_key) {} -PigeonTotpSecret::PigeonTotpSecret( +InternalTotpSecret::InternalTotpSecret( const int64_t* code_interval_seconds, const int64_t* code_length, const int64_t* enrollment_completion_deadline, const std::string* hashing_algorithm, const std::string& secret_key) @@ -1815,67 +2620,69 @@ PigeonTotpSecret::PigeonTotpSecret( : std::nullopt), secret_key_(secret_key) {} -const int64_t* PigeonTotpSecret::code_interval_seconds() const { +const int64_t* InternalTotpSecret::code_interval_seconds() const { return code_interval_seconds_ ? &(*code_interval_seconds_) : nullptr; } -void PigeonTotpSecret::set_code_interval_seconds(const int64_t* value_arg) { +void InternalTotpSecret::set_code_interval_seconds(const int64_t* value_arg) { code_interval_seconds_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonTotpSecret::set_code_interval_seconds(int64_t value_arg) { +void InternalTotpSecret::set_code_interval_seconds(int64_t value_arg) { code_interval_seconds_ = value_arg; } -const int64_t* PigeonTotpSecret::code_length() const { +const int64_t* InternalTotpSecret::code_length() const { return code_length_ ? &(*code_length_) : nullptr; } -void PigeonTotpSecret::set_code_length(const int64_t* value_arg) { +void InternalTotpSecret::set_code_length(const int64_t* value_arg) { code_length_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonTotpSecret::set_code_length(int64_t value_arg) { +void InternalTotpSecret::set_code_length(int64_t value_arg) { code_length_ = value_arg; } -const int64_t* PigeonTotpSecret::enrollment_completion_deadline() const { +const int64_t* InternalTotpSecret::enrollment_completion_deadline() const { return enrollment_completion_deadline_ ? &(*enrollment_completion_deadline_) : nullptr; } -void PigeonTotpSecret::set_enrollment_completion_deadline( +void InternalTotpSecret::set_enrollment_completion_deadline( const int64_t* value_arg) { enrollment_completion_deadline_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonTotpSecret::set_enrollment_completion_deadline(int64_t value_arg) { +void InternalTotpSecret::set_enrollment_completion_deadline(int64_t value_arg) { enrollment_completion_deadline_ = value_arg; } -const std::string* PigeonTotpSecret::hashing_algorithm() const { +const std::string* InternalTotpSecret::hashing_algorithm() const { return hashing_algorithm_ ? &(*hashing_algorithm_) : nullptr; } -void PigeonTotpSecret::set_hashing_algorithm( +void InternalTotpSecret::set_hashing_algorithm( const std::string_view* value_arg) { hashing_algorithm_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonTotpSecret::set_hashing_algorithm(std::string_view value_arg) { +void InternalTotpSecret::set_hashing_algorithm(std::string_view value_arg) { hashing_algorithm_ = value_arg; } -const std::string& PigeonTotpSecret::secret_key() const { return secret_key_; } +const std::string& InternalTotpSecret::secret_key() const { + return secret_key_; +} -void PigeonTotpSecret::set_secret_key(std::string_view value_arg) { +void InternalTotpSecret::set_secret_key(std::string_view value_arg) { secret_key_ = value_arg; } -EncodableList PigeonTotpSecret::ToEncodableList() const { +EncodableList InternalTotpSecret::ToEncodableList() const { EncodableList list; list.reserve(5); list.push_back(code_interval_seconds_ @@ -1892,22 +2699,22 @@ EncodableList PigeonTotpSecret::ToEncodableList() const { return list; } -PigeonTotpSecret PigeonTotpSecret::FromEncodableList( +InternalTotpSecret InternalTotpSecret::FromEncodableList( const EncodableList& list) { - PigeonTotpSecret decoded(std::get(list[4])); + InternalTotpSecret decoded(std::get(list[4])); auto& encodable_code_interval_seconds = list[0]; if (!encodable_code_interval_seconds.IsNull()) { decoded.set_code_interval_seconds( - encodable_code_interval_seconds.LongValue()); + std::get(encodable_code_interval_seconds)); } auto& encodable_code_length = list[1]; if (!encodable_code_length.IsNull()) { - decoded.set_code_length(encodable_code_length.LongValue()); + decoded.set_code_length(std::get(encodable_code_length)); } auto& encodable_enrollment_completion_deadline = list[2]; if (!encodable_enrollment_completion_deadline.IsNull()) { decoded.set_enrollment_completion_deadline( - encodable_enrollment_completion_deadline.LongValue()); + std::get(encodable_enrollment_completion_deadline)); } auto& encodable_hashing_algorithm = list[3]; if (!encodable_hashing_algorithm.IsNull()) { @@ -1917,236 +2724,314 @@ PigeonTotpSecret PigeonTotpSecret::FromEncodableList( return decoded; } -FirebaseAuthHostApiCodecSerializer::FirebaseAuthHostApiCodecSerializer() {} +bool InternalTotpSecret::operator==(const InternalTotpSecret& other) const { + return PigeonInternalDeepEquals(code_interval_seconds_, + other.code_interval_seconds_) && + PigeonInternalDeepEquals(code_length_, other.code_length_) && + PigeonInternalDeepEquals(enrollment_completion_deadline_, + other.enrollment_completion_deadline_) && + PigeonInternalDeepEquals(hashing_algorithm_, + other.hashing_algorithm_) && + PigeonInternalDeepEquals(secret_key_, other.secret_key_); +} + +bool InternalTotpSecret::operator!=(const InternalTotpSecret& other) const { + return !(*this == other); +} + +size_t InternalTotpSecret::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(code_interval_seconds_); + result = result * 31 + PigeonInternalDeepHash(code_length_); + result = + result * 31 + PigeonInternalDeepHash(enrollment_completion_deadline_); + result = result * 31 + PigeonInternalDeepHash(hashing_algorithm_); + result = result * 31 + PigeonInternalDeepHash(secret_key_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalTotpSecret& v) { return v.Hash(); } -EncodableValue FirebaseAuthHostApiCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { +PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} + +EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { - case 128: - return CustomEncodableValue(AuthPigeonFirebaseApp::FromEncodableList( + case 129: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 130: { + return CustomEncodableValue(InternalMultiFactorSession::FromEncodableList( std::get(ReadValue(stream)))); - case 129: - return CustomEncodableValue(PigeonActionCodeInfo::FromEncodableList( + } + case 131: { + return CustomEncodableValue( + InternalPhoneMultiFactorAssertion::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 132: { + return CustomEncodableValue(InternalMultiFactorInfo::FromEncodableList( std::get(ReadValue(stream)))); - case 130: - return CustomEncodableValue(PigeonActionCodeInfoData::FromEncodableList( + } + case 133: { + return CustomEncodableValue(AuthPigeonFirebaseApp::FromEncodableList( std::get(ReadValue(stream)))); - case 131: - return CustomEncodableValue(PigeonActionCodeSettings::FromEncodableList( + } + case 134: { + return CustomEncodableValue(InternalActionCodeInfoData::FromEncodableList( std::get(ReadValue(stream)))); - case 132: - return CustomEncodableValue(PigeonAdditionalUserInfo::FromEncodableList( + } + case 135: { + return CustomEncodableValue(InternalActionCodeInfo::FromEncodableList( std::get(ReadValue(stream)))); - case 133: - return CustomEncodableValue(PigeonAuthCredential::FromEncodableList( + } + case 136: { + return CustomEncodableValue(InternalAdditionalUserInfo::FromEncodableList( std::get(ReadValue(stream)))); - case 134: - return CustomEncodableValue(PigeonFirebaseAuthSettings::FromEncodableList( + } + case 137: { + return CustomEncodableValue(InternalAuthCredential::FromEncodableList( std::get(ReadValue(stream)))); - case 135: - return CustomEncodableValue(PigeonIdTokenResult::FromEncodableList( + } + case 138: { + return CustomEncodableValue(InternalUserInfo::FromEncodableList( std::get(ReadValue(stream)))); - case 136: - return CustomEncodableValue(PigeonMultiFactorInfo::FromEncodableList( + } + case 139: { + return CustomEncodableValue(InternalUserDetails::FromEncodableList( std::get(ReadValue(stream)))); - case 137: - return CustomEncodableValue(PigeonMultiFactorSession::FromEncodableList( + } + case 140: { + return CustomEncodableValue(InternalUserCredential::FromEncodableList( std::get(ReadValue(stream)))); - case 138: + } + case 141: { return CustomEncodableValue( - PigeonPhoneMultiFactorAssertion::FromEncodableList( + InternalAuthCredentialInput::FromEncodableList( std::get(ReadValue(stream)))); - case 139: - return CustomEncodableValue(PigeonSignInProvider::FromEncodableList( - std::get(ReadValue(stream)))); - case 140: - return CustomEncodableValue(PigeonTotpSecret::FromEncodableList( + } + case 142: { + return CustomEncodableValue(InternalActionCodeSettings::FromEncodableList( std::get(ReadValue(stream)))); - case 141: - return CustomEncodableValue(PigeonUserCredential::FromEncodableList( + } + case 143: { + return CustomEncodableValue( + InternalFirebaseAuthSettings::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 144: { + return CustomEncodableValue(InternalSignInProvider::FromEncodableList( std::get(ReadValue(stream)))); - case 142: - return CustomEncodableValue(PigeonUserDetails::FromEncodableList( + } + case 145: { + return CustomEncodableValue( + InternalVerifyPhoneNumberRequest::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 146: { + return CustomEncodableValue(InternalIdTokenResult::FromEncodableList( std::get(ReadValue(stream)))); - case 143: - return CustomEncodableValue(PigeonUserInfo::FromEncodableList( + } + case 147: { + return CustomEncodableValue(InternalUserProfile::FromEncodableList( std::get(ReadValue(stream)))); - case 144: - return CustomEncodableValue(PigeonUserProfile::FromEncodableList( + } + case 148: { + return CustomEncodableValue(InternalTotpSecret::FromEncodableList( std::get(ReadValue(stream)))); - case 145: - return CustomEncodableValue( - PigeonVerifyPhoneNumberRequest::FromEncodableList( - std::get(ReadValue(stream)))); + } default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } -void FirebaseAuthHostApiCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { +void PigeonInternalCodecSerializer::WriteValue( + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(AuthPigeonFirebaseApp)) { - stream->WriteByte(128); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonActionCodeInfo)) { + if (custom_value->type() == typeid(ActionCodeInfoOperation)) { stream->WriteByte(129); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), + stream); return; } - if (custom_value->type() == typeid(PigeonActionCodeInfoData)) { + if (custom_value->type() == typeid(InternalMultiFactorSession)) { stream->WriteByte(130); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); return; } - if (custom_value->type() == typeid(PigeonActionCodeSettings)) { + if (custom_value->type() == typeid(InternalPhoneMultiFactorAssertion)) { stream->WriteByte(131); WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), + EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonAdditionalUserInfo)) { + if (custom_value->type() == typeid(InternalMultiFactorInfo)) { stream->WriteByte(132); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonAuthCredential)) { + if (custom_value->type() == typeid(AuthPigeonFirebaseApp)) { stream->WriteByte(133); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonFirebaseAuthSettings)) { + if (custom_value->type() == typeid(InternalActionCodeInfoData)) { stream->WriteByte(134); WriteValue(EncodableValue( - std::any_cast(*custom_value) + std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonIdTokenResult)) { + if (custom_value->type() == typeid(InternalActionCodeInfo)) { stream->WriteByte(135); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonMultiFactorInfo)) { + if (custom_value->type() == typeid(InternalAdditionalUserInfo)) { stream->WriteByte(136); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); return; } - if (custom_value->type() == typeid(PigeonMultiFactorSession)) { + if (custom_value->type() == typeid(InternalAuthCredential)) { stream->WriteByte(137); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonPhoneMultiFactorAssertion)) { + if (custom_value->type() == typeid(InternalUserInfo)) { stream->WriteByte(138); - WriteValue(EncodableValue(std::any_cast( - *custom_value) - .ToEncodableList()), - stream); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); return; } - if (custom_value->type() == typeid(PigeonSignInProvider)) { + if (custom_value->type() == typeid(InternalUserDetails)) { stream->WriteByte(139); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonTotpSecret)) { + if (custom_value->type() == typeid(InternalUserCredential)) { stream->WriteByte(140); WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonUserCredential)) { + if (custom_value->type() == typeid(InternalAuthCredentialInput)) { stream->WriteByte(141); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); return; } - if (custom_value->type() == typeid(PigeonUserDetails)) { + if (custom_value->type() == typeid(InternalActionCodeSettings)) { stream->WriteByte(142); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonUserInfo)) { + if (custom_value->type() == typeid(InternalFirebaseAuthSettings)) { stream->WriteByte(143); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(InternalSignInProvider)) { + stream->WriteByte(144); WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonUserProfile)) { - stream->WriteByte(144); - WriteValue(EncodableValue(std::any_cast(*custom_value) + if (custom_value->type() == typeid(InternalVerifyPhoneNumberRequest)) { + stream->WriteByte(145); + WriteValue(EncodableValue(std::any_cast( + *custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonVerifyPhoneNumberRequest)) { - stream->WriteByte(145); - WriteValue(EncodableValue(std::any_cast( - *custom_value) + if (custom_value->type() == typeid(InternalIdTokenResult)) { + stream->WriteByte(146); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(InternalUserProfile)) { + stream->WriteByte(147); + WriteValue( + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(InternalTotpSecret)) { + stream->WriteByte(148); + WriteValue(EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } } - flutter::StandardCodecSerializer::WriteValue(value, stream); + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseAuthHostApi. -const flutter::StandardMessageCodec& FirebaseAuthHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &FirebaseAuthHostApiCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& FirebaseAuthHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseAuthHostApi` to handle messages through the // `binary_messenger`. -void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void FirebaseAuthHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAuthHostApi* api) { FirebaseAuthHostApi::SetUp(binary_messenger, api, ""); } -void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void FirebaseAuthHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAuthHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -2163,7 +3048,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2202,7 +3087,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2240,7 +3125,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2290,7 +3175,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2335,7 +3220,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2353,7 +3238,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& code_arg = std::get(encodable_code_arg); api->CheckActionCode( app_arg, code_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2381,7 +3266,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2433,7 +3318,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2459,7 +3344,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_password_arg); api->CreateUserWithEmailAndPassword( app_arg, email_arg, password_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2487,7 +3372,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2498,7 +3383,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& app_arg = std::any_cast( std::get(encodable_app_arg)); api->SignInAnonymously( - app_arg, [reply](ErrorOr&& output) { + app_arg, [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2526,7 +3411,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2545,7 +3430,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_input_arg); api->SignInWithCredential( app_arg, input_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2573,7 +3458,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2592,7 +3477,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_token_arg); api->SignInWithCustomToken( app_arg, token_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2620,7 +3505,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2646,7 +3531,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_password_arg); api->SignInWithEmailAndPassword( app_arg, email_arg, password_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2674,7 +3559,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2700,7 +3585,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_email_link_arg); api->SignInWithEmailLink( app_arg, email_arg, email_link_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2728,7 +3613,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2744,12 +3629,12 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& sign_in_provider_arg = - std::any_cast( + std::any_cast( std::get( encodable_sign_in_provider_arg)); api->SignInWithProvider( app_arg, sign_in_provider_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -2776,7 +3661,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2814,7 +3699,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2860,7 +3745,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2878,16 +3763,12 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& email_arg = std::get(encodable_email_arg); const auto& encodable_action_code_settings_arg = args.at(2); - // IF CODE REGENERATED, PLEASE REINSERT THIS. IF ARG IS NULL, APP - // CRASHES - const PigeonActionCodeSettings* action_code_settings_arg = - nullptr; - if (!encodable_action_code_settings_arg.IsNull()) { - action_code_settings_arg = - &(std::any_cast( - std::get( - encodable_action_code_settings_arg))); - } + const auto* action_code_settings_arg = + encodable_action_code_settings_arg.IsNull() + ? nullptr + : &(std::any_cast( + std::get( + encodable_action_code_settings_arg))); api->SendPasswordResetEmail( app_arg, email_arg, action_code_settings_arg, [reply](std::optional&& output) { @@ -2917,7 +3798,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -2940,7 +3821,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& action_code_settings_arg = - std::any_cast( + std::any_cast( std::get( encodable_action_code_settings_arg)); api->SendSignInLinkToEmail( @@ -2972,7 +3853,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3013,7 +3894,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3029,7 +3910,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& settings_arg = - std::any_cast( + std::any_cast( std::get(encodable_settings_arg)); api->SetSettings(app_arg, settings_arg, [reply](std::optional&& output) { @@ -3059,7 +3940,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3104,7 +3985,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3120,7 +4001,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& request_arg = - std::any_cast( + std::any_cast( std::get(encodable_request_arg)); api->VerifyPhoneNumber( app_arg, request_arg, [reply](ErrorOr&& output) { @@ -3151,7 +4032,7 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3187,6 +4068,90 @@ void FirebaseAuthHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, channel.SetMessageHandler(nullptr); } } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_auth_platform_interface." + "FirebaseAuthHostApi.revokeAccessToken" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = std::any_cast( + std::get(encodable_app_arg)); + const auto& encodable_access_token_arg = args.at(1); + if (encodable_access_token_arg.IsNull()) { + reply(WrapError("access_token_arg unexpectedly null.")); + return; + } + const auto& access_token_arg = + std::get(encodable_access_token_arg); + api->RevokeAccessToken( + app_arg, access_token_arg, + [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.firebase_auth_platform_interface." + "FirebaseAuthHostApi.initializeRecaptchaConfig" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const ::flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_app_arg = args.at(0); + if (encodable_app_arg.IsNull()) { + reply(WrapError("app_arg unexpectedly null.")); + return; + } + const auto& app_arg = std::any_cast( + std::get(encodable_app_arg)); + api->InitializeRecaptchaConfig( + app_arg, [reply](std::optional&& output) { + if (output.has_value()) { + reply(WrapError(output.value())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue()); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } } EncodableValue FirebaseAuthHostApi::WrapError(std::string_view error_message) { @@ -3201,239 +4166,23 @@ EncodableValue FirebaseAuthHostApi::WrapError(const FlutterError& error) { error.details()}); } -FirebaseAuthUserHostApiCodecSerializer:: - FirebaseAuthUserHostApiCodecSerializer() {} - -EncodableValue FirebaseAuthUserHostApiCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - switch (type) { - case 128: - return CustomEncodableValue(AuthPigeonFirebaseApp::FromEncodableList( - std::get(ReadValue(stream)))); - case 129: - return CustomEncodableValue(PigeonActionCodeInfo::FromEncodableList( - std::get(ReadValue(stream)))); - case 130: - return CustomEncodableValue(PigeonActionCodeInfoData::FromEncodableList( - std::get(ReadValue(stream)))); - case 131: - return CustomEncodableValue(PigeonActionCodeSettings::FromEncodableList( - std::get(ReadValue(stream)))); - case 132: - return CustomEncodableValue(PigeonAdditionalUserInfo::FromEncodableList( - std::get(ReadValue(stream)))); - case 133: - return CustomEncodableValue(PigeonAuthCredential::FromEncodableList( - std::get(ReadValue(stream)))); - case 134: - return CustomEncodableValue(PigeonFirebaseAuthSettings::FromEncodableList( - std::get(ReadValue(stream)))); - case 135: - return CustomEncodableValue(PigeonIdTokenResult::FromEncodableList( - std::get(ReadValue(stream)))); - case 136: - return CustomEncodableValue(PigeonMultiFactorInfo::FromEncodableList( - std::get(ReadValue(stream)))); - case 137: - return CustomEncodableValue(PigeonMultiFactorSession::FromEncodableList( - std::get(ReadValue(stream)))); - case 138: - return CustomEncodableValue( - PigeonPhoneMultiFactorAssertion::FromEncodableList( - std::get(ReadValue(stream)))); - case 139: - return CustomEncodableValue(PigeonSignInProvider::FromEncodableList( - std::get(ReadValue(stream)))); - case 140: - return CustomEncodableValue(PigeonTotpSecret::FromEncodableList( - std::get(ReadValue(stream)))); - case 141: - return CustomEncodableValue(PigeonUserCredential::FromEncodableList( - std::get(ReadValue(stream)))); - case 142: - return CustomEncodableValue(PigeonUserDetails::FromEncodableList( - std::get(ReadValue(stream)))); - case 143: - return CustomEncodableValue(PigeonUserInfo::FromEncodableList( - std::get(ReadValue(stream)))); - case 144: - return CustomEncodableValue(PigeonUserProfile::FromEncodableList( - std::get(ReadValue(stream)))); - case 145: - return CustomEncodableValue( - PigeonVerifyPhoneNumberRequest::FromEncodableList( - std::get(ReadValue(stream)))); - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void FirebaseAuthUserHostApiCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = - std::get_if(&value)) { - if (custom_value->type() == typeid(AuthPigeonFirebaseApp)) { - stream->WriteByte(128); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonActionCodeInfo)) { - stream->WriteByte(129); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonActionCodeInfoData)) { - stream->WriteByte(130); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonActionCodeSettings)) { - stream->WriteByte(131); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonAdditionalUserInfo)) { - stream->WriteByte(132); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonAuthCredential)) { - stream->WriteByte(133); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonFirebaseAuthSettings)) { - stream->WriteByte(134); - WriteValue(EncodableValue( - std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonIdTokenResult)) { - stream->WriteByte(135); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonMultiFactorInfo)) { - stream->WriteByte(136); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonMultiFactorSession)) { - stream->WriteByte(137); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonPhoneMultiFactorAssertion)) { - stream->WriteByte(138); - WriteValue(EncodableValue(std::any_cast( - *custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonSignInProvider)) { - stream->WriteByte(139); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonTotpSecret)) { - stream->WriteByte(140); - WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonUserCredential)) { - stream->WriteByte(141); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonUserDetails)) { - stream->WriteByte(142); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonUserInfo)) { - stream->WriteByte(143); - WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonUserProfile)) { - stream->WriteByte(144); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonVerifyPhoneNumberRequest)) { - stream->WriteByte(145); - WriteValue(EncodableValue(std::any_cast( - *custom_value) - .ToEncodableList()), - stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - /// The codec used by FirebaseAuthUserHostApi. -const flutter::StandardMessageCodec& FirebaseAuthUserHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &FirebaseAuthUserHostApiCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& FirebaseAuthUserHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseAuthUserHostApi` to handle messages through // the `binary_messenger`. -void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAuthUserHostApi* api) { +void FirebaseAuthUserHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAuthUserHostApi* api) { FirebaseAuthUserHostApi::SetUp(binary_messenger, api, ""); } -void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAuthUserHostApi* api, - const std::string& message_channel_suffix) { +void FirebaseAuthUserHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, FirebaseAuthUserHostApi* api, + const std::string& message_channel_suffix) { const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix @@ -3447,7 +4196,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3485,7 +4234,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3503,7 +4252,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& force_refresh_arg = std::get(encodable_force_refresh_arg); api->GetIdToken(app_arg, force_refresh_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3531,7 +4280,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3550,7 +4299,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_input_arg); api->LinkWithCredential( app_arg, input_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3578,7 +4327,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3594,12 +4343,12 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& sign_in_provider_arg = - std::any_cast( + std::any_cast( std::get( encodable_sign_in_provider_arg)); api->LinkWithProvider( app_arg, sign_in_provider_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3627,7 +4376,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3646,7 +4395,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_input_arg); api->ReauthenticateWithCredential( app_arg, input_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3674,7 +4423,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3690,12 +4439,12 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& sign_in_provider_arg = - std::any_cast( + std::any_cast( std::get( encodable_sign_in_provider_arg)); api->ReauthenticateWithProvider( app_arg, sign_in_provider_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3722,7 +4471,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3733,7 +4482,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& app_arg = std::any_cast( std::get(encodable_app_arg)); api->Reload( - app_arg, [reply](ErrorOr&& output) { + app_arg, [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3761,7 +4510,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3772,16 +4521,12 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& app_arg = std::any_cast( std::get(encodable_app_arg)); const auto& encodable_action_code_settings_arg = args.at(1); - // IF CODE REGENERATED, PLEASE REINSERT THIS. IF ARG IS NULL, APP - // CRASHES - const PigeonActionCodeSettings* action_code_settings_arg = - nullptr; - if (!encodable_action_code_settings_arg.IsNull()) { - action_code_settings_arg = - &(std::any_cast( - std::get( - encodable_action_code_settings_arg))); - } + const auto* action_code_settings_arg = + encodable_action_code_settings_arg.IsNull() + ? nullptr + : &(std::any_cast( + std::get( + encodable_action_code_settings_arg))); api->SendEmailVerification( app_arg, action_code_settings_arg, [reply](std::optional&& output) { @@ -3810,7 +4555,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3828,7 +4573,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& provider_id_arg = std::get(encodable_provider_id_arg); api->Unlink(app_arg, provider_id_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3856,7 +4601,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3874,7 +4619,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& new_email_arg = std::get(encodable_new_email_arg); api->UpdateEmail(app_arg, new_email_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3902,7 +4647,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3919,17 +4664,18 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } const auto& new_password_arg = std::get(encodable_new_password_arg); - api->UpdatePassword(app_arg, new_password_arg, - [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(CustomEncodableValue( - std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); + api->UpdatePassword( + app_arg, new_password_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); } catch (const std::exception& exception) { reply(WrapError(exception.what())); } @@ -3948,7 +4694,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -3967,7 +4713,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_input_arg); api->UpdatePhoneNumber( app_arg, input_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -3995,7 +4741,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -4010,19 +4756,21 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, reply(WrapError("profile_arg unexpectedly null.")); return; } - const auto& profile_arg = std::any_cast( - std::get(encodable_profile_arg)); - api->UpdateProfile(app_arg, profile_arg, - [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back(CustomEncodableValue( - std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); + const auto& profile_arg = + std::any_cast( + std::get(encodable_profile_arg)); + api->UpdateProfile( + app_arg, profile_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); } catch (const std::exception& exception) { reply(WrapError(exception.what())); } @@ -4041,7 +4789,7 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -4059,16 +4807,12 @@ void FirebaseAuthUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& new_email_arg = std::get(encodable_new_email_arg); const auto& encodable_action_code_settings_arg = args.at(2); - // IF CODE REGENERATED, PLEASE REINSERT THIS. IF ARG IS NULL, APP - // CRASHES - const PigeonActionCodeSettings* action_code_settings_arg = - nullptr; - if (!encodable_action_code_settings_arg.IsNull()) { - action_code_settings_arg = - &(std::any_cast( - std::get( - encodable_action_code_settings_arg))); - } + const auto* action_code_settings_arg = + encodable_action_code_settings_arg.IsNull() + ? nullptr + : &(std::any_cast( + std::get( + encodable_action_code_settings_arg))); api->VerifyBeforeUpdateEmail( app_arg, new_email_arg, action_code_settings_arg, [reply](std::optional&& output) { @@ -4103,84 +4847,20 @@ EncodableValue FirebaseAuthUserHostApi::WrapError(const FlutterError& error) { error.details()}); } -MultiFactorUserHostApiCodecSerializer::MultiFactorUserHostApiCodecSerializer() { -} - -EncodableValue MultiFactorUserHostApiCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - switch (type) { - case 128: - return CustomEncodableValue(AuthPigeonFirebaseApp::FromEncodableList( - std::get(ReadValue(stream)))); - case 129: - return CustomEncodableValue(PigeonMultiFactorInfo::FromEncodableList( - std::get(ReadValue(stream)))); - case 130: - return CustomEncodableValue(PigeonMultiFactorSession::FromEncodableList( - std::get(ReadValue(stream)))); - case 131: - return CustomEncodableValue( - PigeonPhoneMultiFactorAssertion::FromEncodableList( - std::get(ReadValue(stream)))); - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void MultiFactorUserHostApiCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = - std::get_if(&value)) { - if (custom_value->type() == typeid(AuthPigeonFirebaseApp)) { - stream->WriteByte(128); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonMultiFactorInfo)) { - stream->WriteByte(129); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonMultiFactorSession)) { - stream->WriteByte(130); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonPhoneMultiFactorAssertion)) { - stream->WriteByte(131); - WriteValue(EncodableValue(std::any_cast( - *custom_value) - .ToEncodableList()), - stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - /// The codec used by MultiFactorUserHostApi. -const flutter::StandardMessageCodec& MultiFactorUserHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &MultiFactorUserHostApiCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& MultiFactorUserHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `MultiFactorUserHostApi` to handle messages through // the `binary_messenger`. -void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void MultiFactorUserHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorUserHostApi* api) { MultiFactorUserHostApi::SetUp(binary_messenger, api, ""); } -void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void MultiFactorUserHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorUserHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -4197,7 +4877,7 @@ void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -4213,7 +4893,7 @@ void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& assertion_arg = - std::any_cast( + std::any_cast( std::get(encodable_assertion_arg)); const auto& encodable_display_name_arg = args.at(2); const auto* display_name_arg = @@ -4246,7 +4926,7 @@ void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -4294,7 +4974,7 @@ void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -4305,7 +4985,8 @@ void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& app_arg = std::any_cast( std::get(encodable_app_arg)); api->GetSession( - app_arg, [reply](ErrorOr&& output) { + app_arg, + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -4332,7 +5013,7 @@ void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -4377,7 +5058,7 @@ void MultiFactorUserHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -4421,108 +5102,23 @@ EncodableValue MultiFactorUserHostApi::WrapError(const FlutterError& error) { error.details()}); } -MultiFactoResolverHostApiCodecSerializer:: - MultiFactoResolverHostApiCodecSerializer() {} - -EncodableValue MultiFactoResolverHostApiCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - switch (type) { - case 128: - return CustomEncodableValue(PigeonAdditionalUserInfo::FromEncodableList( - std::get(ReadValue(stream)))); - case 129: - return CustomEncodableValue(PigeonAuthCredential::FromEncodableList( - std::get(ReadValue(stream)))); - case 130: - return CustomEncodableValue( - PigeonPhoneMultiFactorAssertion::FromEncodableList( - std::get(ReadValue(stream)))); - case 131: - return CustomEncodableValue(PigeonUserCredential::FromEncodableList( - std::get(ReadValue(stream)))); - case 132: - return CustomEncodableValue(PigeonUserDetails::FromEncodableList( - std::get(ReadValue(stream)))); - case 133: - return CustomEncodableValue(PigeonUserInfo::FromEncodableList( - std::get(ReadValue(stream)))); - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void MultiFactoResolverHostApiCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = - std::get_if(&value)) { - if (custom_value->type() == typeid(PigeonAdditionalUserInfo)) { - stream->WriteByte(128); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonAuthCredential)) { - stream->WriteByte(129); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonPhoneMultiFactorAssertion)) { - stream->WriteByte(130); - WriteValue(EncodableValue(std::any_cast( - *custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonUserCredential)) { - stream->WriteByte(131); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonUserDetails)) { - stream->WriteByte(132); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonUserInfo)) { - stream->WriteByte(133); - WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), - stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - /// The codec used by MultiFactoResolverHostApi. -const flutter::StandardMessageCodec& MultiFactoResolverHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &MultiFactoResolverHostApiCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& MultiFactoResolverHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `MultiFactoResolverHostApi` to handle messages through // the `binary_messenger`. void MultiFactoResolverHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, + ::flutter::BinaryMessenger* binary_messenger, MultiFactoResolverHostApi* api) { MultiFactoResolverHostApi::SetUp(binary_messenger, api, ""); } void MultiFactoResolverHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, MultiFactoResolverHostApi* api, - const std::string& message_channel_suffix) { + ::flutter::BinaryMessenger* binary_messenger, + MultiFactoResolverHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix @@ -4535,41 +5131,44 @@ void MultiFactoResolverHostApi::SetUp( prepended_suffix, &GetCodec()); if (api != nullptr) { - channel.SetMessageHandler( - [api](const EncodableValue& message, - const flutter::MessageReply& reply) { - try { - const auto& args = std::get(message); - const auto& encodable_resolver_id_arg = args.at(0); - if (encodable_resolver_id_arg.IsNull()) { - reply(WrapError("resolver_id_arg unexpectedly null.")); - return; - } - const auto& resolver_id_arg = - std::get(encodable_resolver_id_arg); - const auto& encodable_assertion_arg = args.at(1); - const auto* assertion_arg = - &(std::any_cast( - std::get(encodable_assertion_arg))); - const auto& encodable_totp_assertion_id_arg = args.at(2); - const auto* totp_assertion_id_arg = - std::get_if(&encodable_totp_assertion_id_arg); - api->ResolveSignIn( - resolver_id_arg, assertion_arg, totp_assertion_id_arg, - [reply](ErrorOr&& output) { - if (output.has_error()) { - reply(WrapError(output.error())); - return; - } - EncodableList wrapped; - wrapped.push_back( - CustomEncodableValue(std::move(output).TakeValue())); - reply(EncodableValue(std::move(wrapped))); - }); - } catch (const std::exception& exception) { - reply(WrapError(exception.what())); - } - }); + channel.SetMessageHandler([api](const EncodableValue& message, + const ::flutter::MessageReply< + EncodableValue>& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_resolver_id_arg = args.at(0); + if (encodable_resolver_id_arg.IsNull()) { + reply(WrapError("resolver_id_arg unexpectedly null.")); + return; + } + const auto& resolver_id_arg = + std::get(encodable_resolver_id_arg); + const auto& encodable_assertion_arg = args.at(1); + const auto* assertion_arg = + encodable_assertion_arg.IsNull() + ? nullptr + : &(std::any_cast( + std::get( + encodable_assertion_arg))); + const auto& encodable_totp_assertion_id_arg = args.at(2); + const auto* totp_assertion_id_arg = + std::get_if(&encodable_totp_assertion_id_arg); + api->ResolveSignIn( + resolver_id_arg, assertion_arg, totp_assertion_id_arg, + [reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); } else { channel.SetMessageHandler(nullptr); } @@ -4589,50 +5188,20 @@ EncodableValue MultiFactoResolverHostApi::WrapError(const FlutterError& error) { error.details()}); } -MultiFactorTotpHostApiCodecSerializer::MultiFactorTotpHostApiCodecSerializer() { -} - -EncodableValue MultiFactorTotpHostApiCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - switch (type) { - case 128: - return CustomEncodableValue(PigeonTotpSecret::FromEncodableList( - std::get(ReadValue(stream)))); - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void MultiFactorTotpHostApiCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = - std::get_if(&value)) { - if (custom_value->type() == typeid(PigeonTotpSecret)) { - stream->WriteByte(128); - WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), - stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - /// The codec used by MultiFactorTotpHostApi. -const flutter::StandardMessageCodec& MultiFactorTotpHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &MultiFactorTotpHostApiCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& MultiFactorTotpHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `MultiFactorTotpHostApi` to handle messages through // the `binary_messenger`. -void MultiFactorTotpHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void MultiFactorTotpHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpHostApi* api) { MultiFactorTotpHostApi::SetUp(binary_messenger, api, ""); } -void MultiFactorTotpHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void MultiFactorTotpHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -4649,7 +5218,7 @@ void MultiFactorTotpHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_session_id_arg = args.at(0); @@ -4660,7 +5229,8 @@ void MultiFactorTotpHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, const auto& session_id_arg = std::get(encodable_session_id_arg); api->GenerateSecret( - session_id_arg, [reply](ErrorOr&& output) { + session_id_arg, + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -4688,7 +5258,7 @@ void MultiFactorTotpHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_secret_key_arg = args.at(0); @@ -4735,7 +5305,7 @@ void MultiFactorTotpHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_enrollment_id_arg = args.at(0); @@ -4788,21 +5358,22 @@ EncodableValue MultiFactorTotpHostApi::WrapError(const FlutterError& error) { } /// The codec used by MultiFactorTotpSecretHostApi. -const flutter::StandardMessageCodec& MultiFactorTotpSecretHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &flutter::StandardCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& +MultiFactorTotpSecretHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `MultiFactorTotpSecretHostApi` to handle messages // through the `binary_messenger`. void MultiFactorTotpSecretHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, + ::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpSecretHostApi* api) { MultiFactorTotpSecretHostApi::SetUp(binary_messenger, api, ""); } void MultiFactorTotpSecretHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, + ::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpSecretHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -4819,7 +5390,7 @@ void MultiFactorTotpSecretHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_secret_key_arg = args.at(0); @@ -4865,7 +5436,7 @@ void MultiFactorTotpSecretHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_secret_key_arg = args.at(0); @@ -4916,49 +5487,20 @@ EncodableValue MultiFactorTotpSecretHostApi::WrapError( error.details()}); } -GenerateInterfacesCodecSerializer::GenerateInterfacesCodecSerializer() {} - -EncodableValue GenerateInterfacesCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - switch (type) { - case 128: - return CustomEncodableValue(PigeonMultiFactorInfo::FromEncodableList( - std::get(ReadValue(stream)))); - default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); - } -} - -void GenerateInterfacesCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - if (const CustomEncodableValue* custom_value = - std::get_if(&value)) { - if (custom_value->type() == typeid(PigeonMultiFactorInfo)) { - stream->WriteByte(128); - WriteValue( - EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - } - flutter::StandardCodecSerializer::WriteValue(value, stream); -} - /// The codec used by GenerateInterfaces. -const flutter::StandardMessageCodec& GenerateInterfaces::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &GenerateInterfacesCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& GenerateInterfaces::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `GenerateInterfaces` to handle messages through the // `binary_messenger`. -void GenerateInterfaces::SetUp(flutter::BinaryMessenger* binary_messenger, +void GenerateInterfaces::SetUp(::flutter::BinaryMessenger* binary_messenger, GenerateInterfaces* api) { GenerateInterfaces::SetUp(binary_messenger, api, ""); } -void GenerateInterfaces::SetUp(flutter::BinaryMessenger* binary_messenger, +void GenerateInterfaces::SetUp(::flutter::BinaryMessenger* binary_messenger, GenerateInterfaces* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -4975,7 +5517,7 @@ void GenerateInterfaces::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_info_arg = args.at(0); @@ -4984,7 +5526,7 @@ void GenerateInterfaces::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& info_arg = - std::any_cast( + std::any_cast( std::get(encodable_info_arg)); std::optional output = api->PigeonInterface(info_arg); diff --git a/packages/firebase_auth/firebase_auth/windows/messages.g.h b/packages/firebase_auth/firebase_auth/windows/messages.g.h index 91fe62cbaa74..e1e1af028fbc 100644 --- a/packages/firebase_auth/firebase_auth/windows/messages.g.h +++ b/packages/firebase_auth/firebase_auth/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v19.0.0), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -68,56 +68,60 @@ class ErrorOr { // [checkActionCode]. enum class ActionCodeInfoOperation { // Unknown operation. - unknown = 0, + kUnknown = 0, // Password reset code generated via [sendPasswordResetEmail]. - passwordReset = 1, + kPasswordReset = 1, // Email verification code generated via [User.sendEmailVerification]. - verifyEmail = 2, + kVerifyEmail = 2, // Email change revocation code generated via [User.updateEmail]. - recoverEmail = 3, + kRecoverEmail = 3, // Email sign in code generated via [sendSignInLinkToEmail]. - emailSignIn = 4, + kEmailSignIn = 4, // Verify and change email code generated via [User.verifyBeforeUpdateEmail]. - verifyAndChangeEmail = 5, + kVerifyAndChangeEmail = 5, // Action code for reverting second factor addition. - revertSecondFactorAddition = 6 + kRevertSecondFactorAddition = 6 }; // Generated class from Pigeon that represents data sent in messages. -class PigeonMultiFactorSession { +class InternalMultiFactorSession { public: // Constructs an object setting all fields. - explicit PigeonMultiFactorSession(const std::string& id); + explicit InternalMultiFactorSession(const std::string& id); const std::string& id() const; void set_id(std::string_view value_arg); + bool operator==(const InternalMultiFactorSession& other) const; + bool operator!=(const InternalMultiFactorSession& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalMultiFactorSession FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonMultiFactorSession FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string id_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonPhoneMultiFactorAssertion { +class InternalPhoneMultiFactorAssertion { public: // Constructs an object setting all fields. - explicit PigeonPhoneMultiFactorAssertion( + explicit InternalPhoneMultiFactorAssertion( const std::string& verification_id, const std::string& verification_code); const std::string& verification_id() const; @@ -126,41 +130,45 @@ class PigeonPhoneMultiFactorAssertion { const std::string& verification_code() const; void set_verification_code(std::string_view value_arg); + bool operator==(const InternalPhoneMultiFactorAssertion& other) const; + bool operator!=(const InternalPhoneMultiFactorAssertion& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalPhoneMultiFactorAssertion FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonPhoneMultiFactorAssertion FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string verification_id_; std::string verification_code_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonMultiFactorInfo { +class InternalMultiFactorInfo { public: // Constructs an object setting all non-nullable fields. - explicit PigeonMultiFactorInfo(double enrollment_timestamp, - const std::string& uid); + explicit InternalMultiFactorInfo(double enrollment_timestamp, + const std::string& uid); // Constructs an object setting all fields. - explicit PigeonMultiFactorInfo(const std::string* display_name, - double enrollment_timestamp, - const std::string* factor_id, - const std::string& uid, - const std::string* phone_number); + explicit InternalMultiFactorInfo(const std::string* display_name, + double enrollment_timestamp, + const std::string* factor_id, + const std::string& uid, + const std::string* phone_number); const std::string* display_name() const; void set_display_name(const std::string_view* value_arg); @@ -180,24 +188,28 @@ class PigeonMultiFactorInfo { void set_phone_number(const std::string_view* value_arg); void set_phone_number(std::string_view value_arg); + bool operator==(const InternalMultiFactorInfo& other) const; + bool operator!=(const InternalMultiFactorInfo& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalMultiFactorInfo FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonMultiFactorInfo FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::optional display_name_; double enrollment_timestamp_; std::optional factor_id_; @@ -227,38 +239,42 @@ class AuthPigeonFirebaseApp { void set_custom_auth_domain(const std::string_view* value_arg); void set_custom_auth_domain(std::string_view value_arg); + bool operator==(const AuthPigeonFirebaseApp& other) const; + bool operator!=(const AuthPigeonFirebaseApp& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static AuthPigeonFirebaseApp FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + + private: friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string app_name_; std::optional tenant_id_; std::optional custom_auth_domain_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonActionCodeInfoData { +class InternalActionCodeInfoData { public: // Constructs an object setting all non-nullable fields. - PigeonActionCodeInfoData(); + InternalActionCodeInfoData(); // Constructs an object setting all fields. - explicit PigeonActionCodeInfoData(const std::string* email, - const std::string* previous_email); + explicit InternalActionCodeInfoData(const std::string* email, + const std::string* previous_email); const std::string* email() const; void set_email(const std::string_view* value_arg); @@ -268,82 +284,90 @@ class PigeonActionCodeInfoData { void set_previous_email(const std::string_view* value_arg); void set_previous_email(std::string_view value_arg); + bool operator==(const InternalActionCodeInfoData& other) const; + bool operator!=(const InternalActionCodeInfoData& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: - static PigeonActionCodeInfoData FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class PigeonActionCodeInfo; + static InternalActionCodeInfoData FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + friend class InternalActionCodeInfo; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::optional email_; std::optional previous_email_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonActionCodeInfo { +class InternalActionCodeInfo { public: // Constructs an object setting all fields. - explicit PigeonActionCodeInfo(const ActionCodeInfoOperation& operation, - const PigeonActionCodeInfoData& data); - - ~PigeonActionCodeInfo() = default; - PigeonActionCodeInfo(const PigeonActionCodeInfo& other); - PigeonActionCodeInfo& operator=(const PigeonActionCodeInfo& other); - PigeonActionCodeInfo(PigeonActionCodeInfo&& other) = default; - PigeonActionCodeInfo& operator=(PigeonActionCodeInfo&& other) noexcept = + explicit InternalActionCodeInfo(const ActionCodeInfoOperation& operation, + const InternalActionCodeInfoData& data); + + ~InternalActionCodeInfo() = default; + InternalActionCodeInfo(const InternalActionCodeInfo& other); + InternalActionCodeInfo& operator=(const InternalActionCodeInfo& other); + InternalActionCodeInfo(InternalActionCodeInfo&& other) = default; + InternalActionCodeInfo& operator=(InternalActionCodeInfo&& other) noexcept = default; const ActionCodeInfoOperation& operation() const; void set_operation(const ActionCodeInfoOperation& value_arg); - const PigeonActionCodeInfoData& data() const; - void set_data(const PigeonActionCodeInfoData& value_arg); + const InternalActionCodeInfoData& data() const; + void set_data(const InternalActionCodeInfoData& value_arg); + + bool operator==(const InternalActionCodeInfo& other) const; + bool operator!=(const InternalActionCodeInfo& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalActionCodeInfo FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; private: - static PigeonActionCodeInfo FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; ActionCodeInfoOperation operation_; - std::unique_ptr data_; + std::unique_ptr data_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonAdditionalUserInfo { +class InternalAdditionalUserInfo { public: // Constructs an object setting all non-nullable fields. - explicit PigeonAdditionalUserInfo(bool is_new_user); + explicit InternalAdditionalUserInfo(bool is_new_user); // Constructs an object setting all fields. - explicit PigeonAdditionalUserInfo(bool is_new_user, - const std::string* provider_id, - const std::string* username, - const std::string* authorization_code, - const flutter::EncodableMap* profile); + explicit InternalAdditionalUserInfo(bool is_new_user, + const std::string* provider_id, + const std::string* username, + const std::string* authorization_code, + const ::flutter::EncodableMap* profile); bool is_new_user() const; void set_is_new_user(bool value_arg); @@ -360,49 +384,53 @@ class PigeonAdditionalUserInfo { void set_authorization_code(const std::string_view* value_arg); void set_authorization_code(std::string_view value_arg); - const flutter::EncodableMap* profile() const; - void set_profile(const flutter::EncodableMap* value_arg); - void set_profile(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* profile() const; + void set_profile(const ::flutter::EncodableMap* value_arg); + void set_profile(const ::flutter::EncodableMap& value_arg); + + bool operator==(const InternalAdditionalUserInfo& other) const; + bool operator!=(const InternalAdditionalUserInfo& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; private: - static PigeonAdditionalUserInfo FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class PigeonUserCredential; + static InternalAdditionalUserInfo FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + friend class InternalUserCredential; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; bool is_new_user_; std::optional provider_id_; std::optional username_; std::optional authorization_code_; - std::optional profile_; + std::optional<::flutter::EncodableMap> profile_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonAuthCredential { +class InternalAuthCredential { public: // Constructs an object setting all non-nullable fields. - explicit PigeonAuthCredential(const std::string& provider_id, - const std::string& sign_in_method, - int64_t native_id); + explicit InternalAuthCredential(const std::string& provider_id, + const std::string& sign_in_method, + int64_t native_id); // Constructs an object setting all fields. - explicit PigeonAuthCredential(const std::string& provider_id, - const std::string& sign_in_method, - int64_t native_id, - const std::string* access_token); + explicit InternalAuthCredential(const std::string& provider_id, + const std::string& sign_in_method, + int64_t native_id, + const std::string* access_token); const std::string& provider_id() const; void set_provider_id(std::string_view value_arg); @@ -417,25 +445,29 @@ class PigeonAuthCredential { void set_access_token(const std::string_view* value_arg); void set_access_token(std::string_view value_arg); + bool operator==(const InternalAuthCredential& other) const; + bool operator!=(const InternalAuthCredential& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalAuthCredential FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonAuthCredential FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; - friend class PigeonUserCredential; + friend class InternalUserCredential; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string provider_id_; std::string sign_in_method_; int64_t native_id_; @@ -443,14 +475,14 @@ class PigeonAuthCredential { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonUserInfo { +class InternalUserInfo { public: // Constructs an object setting all non-nullable fields. - explicit PigeonUserInfo(const std::string& uid, bool is_anonymous, - bool is_email_verified); + explicit InternalUserInfo(const std::string& uid, bool is_anonymous, + bool is_email_verified); // Constructs an object setting all fields. - explicit PigeonUserInfo( + explicit InternalUserInfo( const std::string& uid, const std::string* email, const std::string* display_name, const std::string* photo_url, const std::string* phone_number, bool is_anonymous, @@ -503,25 +535,29 @@ class PigeonUserInfo { void set_last_sign_in_timestamp(const int64_t* value_arg); void set_last_sign_in_timestamp(int64_t value_arg); - flutter::EncodableList ToEncodableList() const; + bool operator==(const InternalUserInfo& other) const; + bool operator!=(const InternalUserInfo& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; private: - static PigeonUserInfo FromEncodableList(const flutter::EncodableList& list); - friend class PigeonUserDetails; + static InternalUserInfo FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + friend class InternalUserDetails; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string uid_; std::optional email_; std::optional display_name_; @@ -537,117 +573,178 @@ class PigeonUserInfo { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonUserDetails { +class InternalUserDetails { public: // Constructs an object setting all fields. - explicit PigeonUserDetails(const PigeonUserInfo& user_info, - const flutter::EncodableList& provider_data); + explicit InternalUserDetails(const InternalUserInfo& user_info, + const ::flutter::EncodableList& provider_data); + + ~InternalUserDetails() = default; + InternalUserDetails(const InternalUserDetails& other); + InternalUserDetails& operator=(const InternalUserDetails& other); + InternalUserDetails(InternalUserDetails&& other) = default; + InternalUserDetails& operator=(InternalUserDetails&& other) noexcept = + default; + const InternalUserInfo& user_info() const; + void set_user_info(const InternalUserInfo& value_arg); + + const ::flutter::EncodableList& provider_data() const; + void set_provider_data(const ::flutter::EncodableList& value_arg); - ~PigeonUserDetails() = default; - PigeonUserDetails(const PigeonUserDetails& other); - PigeonUserDetails& operator=(const PigeonUserDetails& other); - PigeonUserDetails(PigeonUserDetails&& other) = default; - PigeonUserDetails& operator=(PigeonUserDetails&& other) noexcept = default; - const PigeonUserInfo& user_info() const; - void set_user_info(const PigeonUserInfo& value_arg); + bool operator==(const InternalUserDetails& other) const; + bool operator!=(const InternalUserDetails& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; - const flutter::EncodableList& provider_data() const; - void set_provider_data(const flutter::EncodableList& value_arg); + private: + static InternalUserDetails FromEncodableList( + const ::flutter::EncodableList& list); - static PigeonUserDetails FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + public: + ::flutter::EncodableList ToEncodableList() const; private: - friend class PigeonUserCredential; + friend class InternalUserCredential; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; - std::unique_ptr user_info_; - flutter::EncodableList provider_data_; + friend class PigeonInternalCodecSerializer; + std::unique_ptr user_info_; + ::flutter::EncodableList provider_data_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonUserCredential { +class InternalUserCredential { public: // Constructs an object setting all non-nullable fields. - PigeonUserCredential(); + InternalUserCredential(); // Constructs an object setting all fields. - explicit PigeonUserCredential( - const PigeonUserDetails* user, - const PigeonAdditionalUserInfo* additional_user_info, - const PigeonAuthCredential* credential); - - ~PigeonUserCredential() = default; - PigeonUserCredential(const PigeonUserCredential& other); - PigeonUserCredential& operator=(const PigeonUserCredential& other); - PigeonUserCredential(PigeonUserCredential&& other) = default; - PigeonUserCredential& operator=(PigeonUserCredential&& other) noexcept = + explicit InternalUserCredential( + const InternalUserDetails* user, + const InternalAdditionalUserInfo* additional_user_info, + const InternalAuthCredential* credential); + + ~InternalUserCredential() = default; + InternalUserCredential(const InternalUserCredential& other); + InternalUserCredential& operator=(const InternalUserCredential& other); + InternalUserCredential(InternalUserCredential&& other) = default; + InternalUserCredential& operator=(InternalUserCredential&& other) noexcept = default; - const PigeonUserDetails* user() const; - void set_user(const PigeonUserDetails* value_arg); - void set_user(const PigeonUserDetails& value_arg); + const InternalUserDetails* user() const; + void set_user(const InternalUserDetails* value_arg); + void set_user(const InternalUserDetails& value_arg); + + const InternalAdditionalUserInfo* additional_user_info() const; + void set_additional_user_info(const InternalAdditionalUserInfo* value_arg); + void set_additional_user_info(const InternalAdditionalUserInfo& value_arg); + + const InternalAuthCredential* credential() const; + void set_credential(const InternalAuthCredential* value_arg); + void set_credential(const InternalAuthCredential& value_arg); + + bool operator==(const InternalUserCredential& other) const; + bool operator!=(const InternalUserCredential& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalUserCredential FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + friend class FirebaseAuthHostApi; + friend class FirebaseAuthUserHostApi; + friend class MultiFactorUserHostApi; + friend class MultiFactoResolverHostApi; + friend class MultiFactorTotpHostApi; + friend class MultiFactorTotpSecretHostApi; + friend class GenerateInterfaces; + friend class PigeonInternalCodecSerializer; + std::unique_ptr user_; + std::unique_ptr additional_user_info_; + std::unique_ptr credential_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class InternalAuthCredentialInput { + public: + // Constructs an object setting all non-nullable fields. + explicit InternalAuthCredentialInput(const std::string& provider_id, + const std::string& sign_in_method); + + // Constructs an object setting all fields. + explicit InternalAuthCredentialInput(const std::string& provider_id, + const std::string& sign_in_method, + const std::string* token, + const std::string* access_token); + + const std::string& provider_id() const; + void set_provider_id(std::string_view value_arg); + + const std::string& sign_in_method() const; + void set_sign_in_method(std::string_view value_arg); + + const std::string* token() const; + void set_token(const std::string_view* value_arg); + void set_token(std::string_view value_arg); + + const std::string* access_token() const; + void set_access_token(const std::string_view* value_arg); + void set_access_token(std::string_view value_arg); - const PigeonAdditionalUserInfo* additional_user_info() const; - void set_additional_user_info(const PigeonAdditionalUserInfo* value_arg); - void set_additional_user_info(const PigeonAdditionalUserInfo& value_arg); + bool operator==(const InternalAuthCredentialInput& other) const; + bool operator!=(const InternalAuthCredentialInput& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; - const PigeonAuthCredential* credential() const; - void set_credential(const PigeonAuthCredential* value_arg); - void set_credential(const PigeonAuthCredential& value_arg); + private: + static InternalAuthCredentialInput FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; private: - static PigeonUserCredential FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; - std::unique_ptr user_; - std::unique_ptr additional_user_info_; - std::unique_ptr credential_; + friend class PigeonInternalCodecSerializer; + std::string provider_id_; + std::string sign_in_method_; + std::optional token_; + std::optional access_token_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonActionCodeSettings { +class InternalActionCodeSettings { public: // Constructs an object setting all non-nullable fields. - explicit PigeonActionCodeSettings(const std::string& url, - bool handle_code_in_app, - bool android_install_app); + explicit InternalActionCodeSettings(const std::string& url, + bool handle_code_in_app, + bool android_install_app); // Constructs an object setting all fields. - explicit PigeonActionCodeSettings(const std::string& url, - const std::string* dynamic_link_domain, - bool handle_code_in_app, - const std::string* i_o_s_bundle_id, - const std::string* android_package_name, - bool android_install_app, - const std::string* android_minimum_version, - const std::string* link_domain); + explicit InternalActionCodeSettings( + const std::string& url, const std::string* dynamic_link_domain, + bool handle_code_in_app, const std::string* i_o_s_bundle_id, + const std::string* android_package_name, bool android_install_app, + const std::string* android_minimum_version, + const std::string* link_domain); const std::string& url() const; void set_url(std::string_view value_arg); @@ -678,24 +775,28 @@ class PigeonActionCodeSettings { void set_link_domain(const std::string_view* value_arg); void set_link_domain(std::string_view value_arg); + bool operator==(const InternalActionCodeSettings& other) const; + bool operator!=(const InternalActionCodeSettings& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalActionCodeSettings FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonActionCodeSettings FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string url_; std::optional dynamic_link_domain_; bool handle_code_in_app_; @@ -707,14 +808,14 @@ class PigeonActionCodeSettings { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonFirebaseAuthSettings { +class InternalFirebaseAuthSettings { public: // Constructs an object setting all non-nullable fields. - explicit PigeonFirebaseAuthSettings( + explicit InternalFirebaseAuthSettings( bool app_verification_disabled_for_testing); // Constructs an object setting all fields. - explicit PigeonFirebaseAuthSettings( + explicit InternalFirebaseAuthSettings( bool app_verification_disabled_for_testing, const std::string* user_access_group, const std::string* phone_number, const std::string* sms_code, const bool* force_recaptcha_flow); @@ -738,24 +839,28 @@ class PigeonFirebaseAuthSettings { void set_force_recaptcha_flow(const bool* value_arg); void set_force_recaptcha_flow(bool value_arg); + bool operator==(const InternalFirebaseAuthSettings& other) const; + bool operator!=(const InternalFirebaseAuthSettings& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalFirebaseAuthSettings FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonFirebaseAuthSettings FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; bool app_verification_disabled_for_testing_; std::optional user_access_group_; std::optional phone_number_; @@ -764,58 +869,62 @@ class PigeonFirebaseAuthSettings { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonSignInProvider { +class InternalSignInProvider { public: // Constructs an object setting all non-nullable fields. - explicit PigeonSignInProvider(const std::string& provider_id); + explicit InternalSignInProvider(const std::string& provider_id); // Constructs an object setting all fields. - explicit PigeonSignInProvider(const std::string& provider_id, - const flutter::EncodableList* scopes, - const flutter::EncodableMap* custom_parameters); + explicit InternalSignInProvider( + const std::string& provider_id, const ::flutter::EncodableList* scopes, + const ::flutter::EncodableMap* custom_parameters); const std::string& provider_id() const; void set_provider_id(std::string_view value_arg); - const flutter::EncodableList* scopes() const; - void set_scopes(const flutter::EncodableList* value_arg); - void set_scopes(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList* scopes() const; + void set_scopes(const ::flutter::EncodableList* value_arg); + void set_scopes(const ::flutter::EncodableList& value_arg); - const flutter::EncodableMap* custom_parameters() const; - void set_custom_parameters(const flutter::EncodableMap* value_arg); - void set_custom_parameters(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* custom_parameters() const; + void set_custom_parameters(const ::flutter::EncodableMap* value_arg); + void set_custom_parameters(const ::flutter::EncodableMap& value_arg); + + bool operator==(const InternalSignInProvider& other) const; + bool operator!=(const InternalSignInProvider& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalSignInProvider FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; private: - static PigeonSignInProvider FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string provider_id_; - std::optional scopes_; - std::optional custom_parameters_; + std::optional<::flutter::EncodableList> scopes_; + std::optional<::flutter::EncodableMap> custom_parameters_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonVerifyPhoneNumberRequest { +class InternalVerifyPhoneNumberRequest { public: // Constructs an object setting all non-nullable fields. - explicit PigeonVerifyPhoneNumberRequest(int64_t timeout); + explicit InternalVerifyPhoneNumberRequest(int64_t timeout); // Constructs an object setting all fields. - explicit PigeonVerifyPhoneNumberRequest( + explicit InternalVerifyPhoneNumberRequest( const std::string* phone_number, int64_t timeout, const int64_t* force_resending_token, const std::string* auto_retrieved_sms_code_for_testing, @@ -846,24 +955,28 @@ class PigeonVerifyPhoneNumberRequest { void set_multi_factor_session_id(const std::string_view* value_arg); void set_multi_factor_session_id(std::string_view value_arg); + bool operator==(const InternalVerifyPhoneNumberRequest& other) const; + bool operator!=(const InternalVerifyPhoneNumberRequest& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalVerifyPhoneNumberRequest FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonVerifyPhoneNumberRequest FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::optional phone_number_; int64_t timeout_; std::optional force_resending_token_; @@ -873,19 +986,19 @@ class PigeonVerifyPhoneNumberRequest { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonIdTokenResult { +class InternalIdTokenResult { public: // Constructs an object setting all non-nullable fields. - PigeonIdTokenResult(); + InternalIdTokenResult(); // Constructs an object setting all fields. - explicit PigeonIdTokenResult(const std::string* token, - const int64_t* expiration_timestamp, - const int64_t* auth_timestamp, - const int64_t* issued_at_timestamp, - const std::string* sign_in_provider, - const flutter::EncodableMap* claims, - const std::string* sign_in_second_factor); + explicit InternalIdTokenResult(const std::string* token, + const int64_t* expiration_timestamp, + const int64_t* auth_timestamp, + const int64_t* issued_at_timestamp, + const std::string* sign_in_provider, + const ::flutter::EncodableMap* claims, + const std::string* sign_in_second_factor); const std::string* token() const; void set_token(const std::string_view* value_arg); @@ -907,51 +1020,57 @@ class PigeonIdTokenResult { void set_sign_in_provider(const std::string_view* value_arg); void set_sign_in_provider(std::string_view value_arg); - const flutter::EncodableMap* claims() const; - void set_claims(const flutter::EncodableMap* value_arg); - void set_claims(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* claims() const; + void set_claims(const ::flutter::EncodableMap* value_arg); + void set_claims(const ::flutter::EncodableMap& value_arg); const std::string* sign_in_second_factor() const; void set_sign_in_second_factor(const std::string_view* value_arg); void set_sign_in_second_factor(std::string_view value_arg); + bool operator==(const InternalIdTokenResult& other) const; + bool operator!=(const InternalIdTokenResult& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalIdTokenResult FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonIdTokenResult FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::optional token_; std::optional expiration_timestamp_; std::optional auth_timestamp_; std::optional issued_at_timestamp_; std::optional sign_in_provider_; - std::optional claims_; + std::optional<::flutter::EncodableMap> claims_; std::optional sign_in_second_factor_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonUserProfile { +class InternalUserProfile { public: // Constructs an object setting all non-nullable fields. - explicit PigeonUserProfile(bool display_name_changed, bool photo_url_changed); + explicit InternalUserProfile(bool display_name_changed, + bool photo_url_changed); // Constructs an object setting all fields. - explicit PigeonUserProfile(const std::string* display_name, - const std::string* photo_url, - bool display_name_changed, bool photo_url_changed); + explicit InternalUserProfile(const std::string* display_name, + const std::string* photo_url, + bool display_name_changed, + bool photo_url_changed); const std::string* display_name() const; void set_display_name(const std::string_view* value_arg); @@ -967,24 +1086,28 @@ class PigeonUserProfile { bool photo_url_changed() const; void set_photo_url_changed(bool value_arg); + bool operator==(const InternalUserProfile& other) const; + bool operator!=(const InternalUserProfile& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalUserProfile FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonUserProfile FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::optional display_name_; std::optional photo_url_; bool display_name_changed_; @@ -992,17 +1115,17 @@ class PigeonUserProfile { }; // Generated class from Pigeon that represents data sent in messages. -class PigeonTotpSecret { +class InternalTotpSecret { public: // Constructs an object setting all non-nullable fields. - explicit PigeonTotpSecret(const std::string& secret_key); + explicit InternalTotpSecret(const std::string& secret_key); // Constructs an object setting all fields. - explicit PigeonTotpSecret(const int64_t* code_interval_seconds, - const int64_t* code_length, - const int64_t* enrollment_completion_deadline, - const std::string* hashing_algorithm, - const std::string& secret_key); + explicit InternalTotpSecret(const int64_t* code_interval_seconds, + const int64_t* code_length, + const int64_t* enrollment_completion_deadline, + const std::string* hashing_algorithm, + const std::string& secret_key); const int64_t* code_interval_seconds() const; void set_code_interval_seconds(const int64_t* value_arg); @@ -1023,23 +1146,28 @@ class PigeonTotpSecret { const std::string& secret_key() const; void set_secret_key(std::string_view value_arg); + bool operator==(const InternalTotpSecret& other) const; + bool operator!=(const InternalTotpSecret& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalTotpSecret FromEncodableList( + const ::flutter::EncodableList& list); + + public: + ::flutter::EncodableList ToEncodableList() const; + private: - static PigeonTotpSecret FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseAuthHostApi; - friend class FirebaseAuthHostApiCodecSerializer; friend class FirebaseAuthUserHostApi; - friend class FirebaseAuthUserHostApiCodecSerializer; friend class MultiFactorUserHostApi; - friend class MultiFactorUserHostApiCodecSerializer; friend class MultiFactoResolverHostApi; - friend class MultiFactoResolverHostApiCodecSerializer; friend class MultiFactorTotpHostApi; - friend class MultiFactorTotpHostApiCodecSerializer; friend class MultiFactorTotpSecretHostApi; - friend class MultiFactorTotpSecretHostApiCodecSerializer; friend class GenerateInterfaces; - friend class GenerateInterfacesCodecSerializer; + friend class PigeonInternalCodecSerializer; std::optional code_interval_seconds_; std::optional code_length_; std::optional enrollment_completion_deadline_; @@ -1047,21 +1175,21 @@ class PigeonTotpSecret { std::string secret_key_; }; -class FirebaseAuthHostApiCodecSerializer - : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: - FirebaseAuthHostApiCodecSerializer(); - inline static FirebaseAuthHostApiCodecSerializer& GetInstance() { - static FirebaseAuthHostApiCodecSerializer sInstance; + PigeonInternalCodecSerializer(); + inline static PigeonInternalCodecSerializer& GetInstance() { + static PigeonInternalCodecSerializer sInstance; return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -1085,7 +1213,7 @@ class FirebaseAuthHostApi { std::function reply)> result) = 0; virtual void CheckActionCode( const AuthPigeonFirebaseApp& app, const std::string& code, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void ConfirmPasswordReset( const AuthPigeonFirebaseApp& app, const std::string& code, const std::string& new_password, @@ -1093,92 +1221,81 @@ class FirebaseAuthHostApi { virtual void CreateUserWithEmailAndPassword( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& password, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SignInAnonymously( const AuthPigeonFirebaseApp& app, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SignInWithCredential( - const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) = 0; + const AuthPigeonFirebaseApp& app, const ::flutter::EncodableMap& input, + std::function reply)> result) = 0; virtual void SignInWithCustomToken( const AuthPigeonFirebaseApp& app, const std::string& token, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SignInWithEmailAndPassword( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& password, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SignInWithEmailLink( const AuthPigeonFirebaseApp& app, const std::string& email, const std::string& email_link, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SignInWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) = 0; + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) = 0; virtual void SignOut( const AuthPigeonFirebaseApp& app, std::function reply)> result) = 0; virtual void FetchSignInMethodsForEmail( const AuthPigeonFirebaseApp& app, const std::string& email, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SendPasswordResetEmail( const AuthPigeonFirebaseApp& app, const std::string& email, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) = 0; virtual void SendSignInLinkToEmail( const AuthPigeonFirebaseApp& app, const std::string& email, - const PigeonActionCodeSettings& action_code_settings, + const InternalActionCodeSettings& action_code_settings, std::function reply)> result) = 0; virtual void SetLanguageCode( const AuthPigeonFirebaseApp& app, const std::string* language_code, std::function reply)> result) = 0; virtual void SetSettings( const AuthPigeonFirebaseApp& app, - const PigeonFirebaseAuthSettings& settings, + const InternalFirebaseAuthSettings& settings, std::function reply)> result) = 0; virtual void VerifyPasswordResetCode( const AuthPigeonFirebaseApp& app, const std::string& code, std::function reply)> result) = 0; virtual void VerifyPhoneNumber( const AuthPigeonFirebaseApp& app, - const PigeonVerifyPhoneNumberRequest& request, + const InternalVerifyPhoneNumberRequest& request, std::function reply)> result) = 0; virtual void RevokeTokenWithAuthorizationCode( const AuthPigeonFirebaseApp& app, const std::string& authorization_code, std::function reply)> result) = 0; + virtual void RevokeAccessToken( + const AuthPigeonFirebaseApp& app, const std::string& access_token, + std::function reply)> result) = 0; + virtual void InitializeRecaptchaConfig( + const AuthPigeonFirebaseApp& app, + std::function reply)> result) = 0; // The codec used by FirebaseAuthHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseAuthHostApi` to handle messages through the // `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAuthHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAuthHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseAuthHostApi() = default; }; -class FirebaseAuthUserHostApiCodecSerializer - : public flutter::StandardCodecSerializer { - public: - FirebaseAuthUserHostApiCodecSerializer(); - inline static FirebaseAuthUserHostApiCodecSerializer& GetInstance() { - static FirebaseAuthUserHostApiCodecSerializer sInstance; - return sInstance; - } - - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; -}; - // Generated interface from Pigeon that represents a handler of messages from // Flutter. class FirebaseAuthUserHostApi { @@ -1191,80 +1308,63 @@ class FirebaseAuthUserHostApi { std::function reply)> result) = 0; virtual void GetIdToken( const AuthPigeonFirebaseApp& app, bool force_refresh, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void LinkWithCredential( - const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) = 0; + const AuthPigeonFirebaseApp& app, const ::flutter::EncodableMap& input, + std::function reply)> result) = 0; virtual void LinkWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) = 0; + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) = 0; virtual void ReauthenticateWithCredential( - const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) = 0; + const AuthPigeonFirebaseApp& app, const ::flutter::EncodableMap& input, + std::function reply)> result) = 0; virtual void ReauthenticateWithProvider( const AuthPigeonFirebaseApp& app, - const PigeonSignInProvider& sign_in_provider, - std::function reply)> result) = 0; + const InternalSignInProvider& sign_in_provider, + std::function reply)> result) = 0; virtual void Reload( const AuthPigeonFirebaseApp& app, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SendEmailVerification( const AuthPigeonFirebaseApp& app, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) = 0; virtual void Unlink( const AuthPigeonFirebaseApp& app, const std::string& provider_id, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void UpdateEmail( const AuthPigeonFirebaseApp& app, const std::string& new_email, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void UpdatePassword( const AuthPigeonFirebaseApp& app, const std::string& new_password, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void UpdatePhoneNumber( - const AuthPigeonFirebaseApp& app, const flutter::EncodableMap& input, - std::function reply)> result) = 0; + const AuthPigeonFirebaseApp& app, const ::flutter::EncodableMap& input, + std::function reply)> result) = 0; virtual void UpdateProfile( - const AuthPigeonFirebaseApp& app, const PigeonUserProfile& profile, - std::function reply)> result) = 0; + const AuthPigeonFirebaseApp& app, const InternalUserProfile& profile, + std::function reply)> result) = 0; virtual void VerifyBeforeUpdateEmail( const AuthPigeonFirebaseApp& app, const std::string& new_email, - const PigeonActionCodeSettings* action_code_settings, + const InternalActionCodeSettings* action_code_settings, std::function reply)> result) = 0; // The codec used by FirebaseAuthUserHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseAuthUserHostApi` to handle messages through // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAuthUserHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAuthUserHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseAuthUserHostApi() = default; }; -class MultiFactorUserHostApiCodecSerializer - : public flutter::StandardCodecSerializer { - public: - MultiFactorUserHostApiCodecSerializer(); - inline static MultiFactorUserHostApiCodecSerializer& GetInstance() { - static MultiFactorUserHostApiCodecSerializer sInstance; - return sInstance; - } - - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; -}; - // Generated interface from Pigeon that represents a handler of messages from // Flutter. class MultiFactorUserHostApi { @@ -1274,7 +1374,7 @@ class MultiFactorUserHostApi { virtual ~MultiFactorUserHostApi() {} virtual void EnrollPhone( const AuthPigeonFirebaseApp& app, - const PigeonPhoneMultiFactorAssertion& assertion, + const InternalPhoneMultiFactorAssertion& assertion, const std::string* display_name, std::function reply)> result) = 0; virtual void EnrollTotp( @@ -1283,46 +1383,30 @@ class MultiFactorUserHostApi { std::function reply)> result) = 0; virtual void GetSession( const AuthPigeonFirebaseApp& app, - std::function reply)> result) = 0; + std::function reply)> + result) = 0; virtual void Unenroll( const AuthPigeonFirebaseApp& app, const std::string& factor_uid, std::function reply)> result) = 0; virtual void GetEnrolledFactors( const AuthPigeonFirebaseApp& app, - std::function reply)> result) = 0; + std::function reply)> result) = 0; // The codec used by MultiFactorUserHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `MultiFactorUserHostApi` to handle messages through // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorUserHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorUserHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: MultiFactorUserHostApi() = default; }; -class MultiFactoResolverHostApiCodecSerializer - : public flutter::StandardCodecSerializer { - public: - MultiFactoResolverHostApiCodecSerializer(); - inline static MultiFactoResolverHostApiCodecSerializer& GetInstance() { - static MultiFactoResolverHostApiCodecSerializer sInstance; - return sInstance; - } - - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; -}; - // Generated interface from Pigeon that represents a handler of messages from // Flutter. class MultiFactoResolverHostApi { @@ -1333,42 +1417,25 @@ class MultiFactoResolverHostApi { virtual ~MultiFactoResolverHostApi() {} virtual void ResolveSignIn( const std::string& resolver_id, - const PigeonPhoneMultiFactorAssertion* assertion, + const InternalPhoneMultiFactorAssertion* assertion, const std::string* totp_assertion_id, - std::function reply)> result) = 0; + std::function reply)> result) = 0; // The codec used by MultiFactoResolverHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `MultiFactoResolverHostApi` to handle messages // through the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactoResolverHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactoResolverHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: MultiFactoResolverHostApi() = default; }; -class MultiFactorTotpHostApiCodecSerializer - : public flutter::StandardCodecSerializer { - public: - MultiFactorTotpHostApiCodecSerializer(); - inline static MultiFactorTotpHostApiCodecSerializer& GetInstance() { - static MultiFactorTotpHostApiCodecSerializer sInstance; - return sInstance; - } - - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; -}; - // Generated interface from Pigeon that represents a handler of messages from // Flutter. class MultiFactorTotpHostApi { @@ -1378,7 +1445,7 @@ class MultiFactorTotpHostApi { virtual ~MultiFactorTotpHostApi() {} virtual void GenerateSecret( const std::string& session_id, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void GetAssertionForEnrollment( const std::string& secret_key, const std::string& one_time_password, std::function reply)> result) = 0; @@ -1387,16 +1454,16 @@ class MultiFactorTotpHostApi { std::function reply)> result) = 0; // The codec used by MultiFactorTotpHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `MultiFactorTotpHostApi` to handle messages through // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: MultiFactorTotpHostApi() = default; @@ -1418,37 +1485,20 @@ class MultiFactorTotpSecretHostApi { std::function reply)> result) = 0; // The codec used by MultiFactorTotpSecretHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `MultiFactorTotpSecretHostApi` to handle messages // through the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpSecretHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, MultiFactorTotpSecretHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: MultiFactorTotpSecretHostApi() = default; }; -class GenerateInterfacesCodecSerializer - : public flutter::StandardCodecSerializer { - public: - GenerateInterfacesCodecSerializer(); - inline static GenerateInterfacesCodecSerializer& GetInstance() { - static GenerateInterfacesCodecSerializer sInstance; - return sInstance; - } - - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; - - protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; -}; - // Only used to generate the object interface that are use outside of the Pigeon // interface // @@ -1460,19 +1510,19 @@ class GenerateInterfaces { GenerateInterfaces& operator=(const GenerateInterfaces&) = delete; virtual ~GenerateInterfaces() {} virtual std::optional PigeonInterface( - const PigeonMultiFactorInfo& info) = 0; + const InternalMultiFactorInfo& info) = 0; // The codec used by GenerateInterfaces. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `GenerateInterfaces` to handle messages through the // `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, GenerateInterfaces* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, GenerateInterfaces* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: GenerateInterfaces() = default; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart index e373d6935fbf..783afa3774a6 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/firebase_auth_platform_interface.dart @@ -13,10 +13,10 @@ export 'src/firebase_auth_multi_factor_exception.dart'; export 'src/id_token_result.dart'; export 'src/pigeon/messages.pigeon.dart' show - PigeonUserDetails, - PigeonUserInfo, + InternalUserDetails, + InternalUserInfo, ActionCodeInfoOperation, - PigeonIdTokenResult; + InternalIdTokenResult; export 'src/platform_interface/platform_interface_confirmation_result.dart'; export 'src/platform_interface/platform_interface_firebase_auth.dart'; export 'src/platform_interface/platform_interface_multi_factor.dart'; diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart index d58bc4f09b3d..e323a6f6c194 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/id_token_result.dart @@ -19,7 +19,7 @@ class IdTokenResult { @protected IdTokenResult(this._data); - final PigeonIdTokenResult _data; + final InternalIdTokenResult _data; /// The authentication time formatted as UTC string. This is the time the user /// authenticated (signed in) and not the time the token was refreshed. diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart index 28338f32cf8d..8944b736ad51 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart @@ -143,8 +143,8 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { final MethodChannelUser user = MethodChannelUser( instance, multiFactorInstance, - PigeonUserDetails.decode( - [PigeonUserInfo.decode(userList[0]!), userList[1]], + InternalUserDetails.decode( + [InternalUserInfo.decode(userList[0]!), userList[1]], ), ); @@ -183,8 +183,8 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { final MethodChannelUser user = MethodChannelUser( instance, multiFactorInstance, - PigeonUserDetails.decode( - [PigeonUserInfo.decode(userList[0]!), userList[1]], + InternalUserDetails.decode( + [InternalUserInfo.decode(userList[0]!), userList[1]], ), ); @@ -207,7 +207,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { @override MethodChannelFirebaseAuth setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { if (currentUser != null) { @@ -385,7 +385,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { final result = await _api.signInWithProvider( pigeonDefault, - PigeonSignInProvider( + InternalSignInProvider( providerId: convertedProvider.providerId, scopes: convertedProvider is OAuthProvider ? convertedProvider.scopes @@ -475,7 +475,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { email, actionCodeSettings == null ? null - : PigeonActionCodeSettings( + : InternalActionCodeSettings( url: actionCodeSettings.url, handleCodeInApp: actionCodeSettings.handleCodeInApp, iOSBundleId: actionCodeSettings.iOSBundleId, @@ -499,7 +499,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { await _api.sendSignInLinkToEmail( pigeonDefault, email, - PigeonActionCodeSettings( + InternalActionCodeSettings( url: actionCodeSettings.url, handleCodeInApp: actionCodeSettings.handleCodeInApp, iOSBundleId: actionCodeSettings.iOSBundleId, @@ -544,7 +544,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { try { await _api.setSettings( pigeonDefault, - PigeonFirebaseAuthSettings( + InternalFirebaseAuthSettings( appVerificationDisabledForTesting: appVerificationDisabledForTesting, userAccessGroup: userAccessGroup, @@ -597,7 +597,7 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { try { final eventChannelName = await _api.verifyPhoneNumber( pigeonDefault, - PigeonVerifyPhoneNumberRequest( + InternalVerifyPhoneNumberRequest( phoneNumber: phoneNumber, multiFactorInfoId: multiFactorInfo?.uid, timeout: timeout.inMilliseconds, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart index 988ef141ce2c..f0a438aeb0b7 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_multi_factor.dart @@ -55,7 +55,7 @@ class MethodChannelMultiFactor extends MultiFactorPlatform { try { await _api.enrollPhone( pigeonDefault, - PigeonPhoneMultiFactorAssertion( + InternalPhoneMultiFactorAssertion( verificationId: verificationId, verificationCode: verificationCode, ), @@ -150,7 +150,7 @@ class MethodChannelMultiFactorResolver extends MultiFactorResolverPlatform { try { final result = await _api.resolveSignIn( _resolverId, - PigeonPhoneMultiFactorAssertion( + InternalPhoneMultiFactorAssertion( verificationId: verificationId, verificationCode: verificationCode, ), diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart index 977d1736898e..e6a627f8017b 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user.dart @@ -16,7 +16,7 @@ import 'utils/exception.dart'; class MethodChannelUser extends UserPlatform { /// Constructs a new [MethodChannelUser] instance. MethodChannelUser(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - PigeonUserDetails data) + InternalUserDetails data) : super(auth, multiFactor, data); final _api = FirebaseAuthUserHostApi(); @@ -96,7 +96,7 @@ class MethodChannelUser extends UserPlatform { final result = await _api.linkWithProvider( pigeonDefault, - PigeonSignInProvider( + InternalSignInProvider( providerId: convertedProvider.providerId, scopes: convertedProvider is OAuthProvider ? convertedProvider.scopes @@ -147,7 +147,7 @@ class MethodChannelUser extends UserPlatform { final result = await _api.reauthenticateWithProvider( pigeonDefault, - PigeonSignInProvider( + InternalSignInProvider( providerId: convertedProvider.providerId, scopes: convertedProvider is OAuthProvider ? convertedProvider.scopes @@ -191,7 +191,7 @@ class MethodChannelUser extends UserPlatform { pigeonDefault, actionCodeSettings == null ? null - : PigeonActionCodeSettings( + : InternalActionCodeSettings( url: actionCodeSettings.url, handleCodeInApp: actionCodeSettings.handleCodeInApp, iOSBundleId: actionCodeSettings.iOSBundleId, @@ -274,7 +274,7 @@ class MethodChannelUser extends UserPlatform { try { final result = await _api.updateProfile( pigeonDefault, - PigeonUserProfile( + InternalUserProfile( displayName: profile['displayName'], photoUrl: profile['photoURL'], displayNameChanged: profile.containsKey('displayName'), @@ -301,7 +301,7 @@ class MethodChannelUser extends UserPlatform { newEmail, actionCodeSettings == null ? null - : PigeonActionCodeSettings( + : InternalActionCodeSettings( url: actionCodeSettings.url, handleCodeInApp: actionCodeSettings.handleCodeInApp, iOSBundleId: actionCodeSettings.iOSBundleId, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart index 35482d624798..7b65930754a9 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_user_credential.dart @@ -12,7 +12,7 @@ import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart class MethodChannelUserCredential extends UserCredentialPlatform { // ignore: public_member_api_docs MethodChannelUserCredential( - FirebaseAuthPlatform auth, PigeonUserCredential data) + FirebaseAuthPlatform auth, InternalUserCredential data) : super( auth: auth, additionalUserInfo: data.additionalUserInfo == null diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart index f78a4e99669d..e1f83202ff97 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart @@ -62,8 +62,9 @@ FirebaseException platformExceptionToFirebaseAuthException( if (platformException.details != null) { if (platformException.details['authCredential'] != null && - platformException.details['authCredential'] is PigeonAuthCredential) { - PigeonAuthCredential pigeonAuthCredential = + platformException.details['authCredential'] + is InternalAuthCredential) { + InternalAuthCredential pigeonAuthCredential = platformException.details['authCredential']; credential = AuthCredential( @@ -180,7 +181,7 @@ FirebaseAuthMultiFactorExceptionPlatform parseMultiFactorError( (additionalData['multiFactorHints'] as List? ?? []) .nonNulls .map( - PigeonMultiFactorInfo.decode, + InternalMultiFactorInfo.decode, ) .toList(); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/pigeon_helper.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/pigeon_helper.dart index 7b3377c3bf69..66ed6e508946 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/pigeon_helper.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/pigeon_helper.dart @@ -6,7 +6,7 @@ import 'package:firebase_auth_platform_interface/firebase_auth_platform_interfac import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; List multiFactorInfoPigeonToObject( - List pigeonMultiFactorInfo, + List pigeonMultiFactorInfo, ) { return pigeonMultiFactorInfo.nonNulls.map((e) { if (e.phoneNumber != null) { diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart index dac092cd499f..60844c34575c 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,21 +1,40 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v19.0.0), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; - -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } List wrapResponse( @@ -29,6 +48,68 @@ List wrapResponse( return [error.code, error.message, error.details]; } +bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } + if (a is List && b is List) { + return a.length == b.length && + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + } + if (a is Map && b is Map) { + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; + } + return a == b; +} + +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} + /// The type of operation that generated the action code from calling /// [checkActionCode]. enum ActionCodeInfoOperation { @@ -54,29 +135,50 @@ enum ActionCodeInfoOperation { revertSecondFactorAddition, } -class PigeonMultiFactorSession { - PigeonMultiFactorSession({ +class InternalMultiFactorSession { + InternalMultiFactorSession({ required this.id, }); String id; - Object encode() { + List _toList() { return [ id, ]; } - static PigeonMultiFactorSession decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalMultiFactorSession decode(Object result) { result as List; - return PigeonMultiFactorSession( + return InternalMultiFactorSession( id: result[0]! as String, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalMultiFactorSession || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(id, other.id); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonPhoneMultiFactorAssertion { - PigeonPhoneMultiFactorAssertion({ +class InternalPhoneMultiFactorAssertion { + InternalPhoneMultiFactorAssertion({ required this.verificationId, required this.verificationCode, }); @@ -85,24 +187,46 @@ class PigeonPhoneMultiFactorAssertion { String verificationCode; - Object encode() { + List _toList() { return [ verificationId, verificationCode, ]; } - static PigeonPhoneMultiFactorAssertion decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalPhoneMultiFactorAssertion decode(Object result) { result as List; - return PigeonPhoneMultiFactorAssertion( + return InternalPhoneMultiFactorAssertion( verificationId: result[0]! as String, verificationCode: result[1]! as String, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalPhoneMultiFactorAssertion || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(verificationId, other.verificationId) && + _deepEquals(verificationCode, other.verificationCode); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonMultiFactorInfo { - PigeonMultiFactorInfo({ +class InternalMultiFactorInfo { + InternalMultiFactorInfo({ this.displayName, required this.enrollmentTimestamp, this.factorId, @@ -120,7 +244,7 @@ class PigeonMultiFactorInfo { String? phoneNumber; - Object encode() { + List _toList() { return [ displayName, enrollmentTimestamp, @@ -130,9 +254,13 @@ class PigeonMultiFactorInfo { ]; } - static PigeonMultiFactorInfo decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalMultiFactorInfo decode(Object result) { result as List; - return PigeonMultiFactorInfo( + return InternalMultiFactorInfo( displayName: result[0] as String?, enrollmentTimestamp: result[1]! as double, factorId: result[2] as String?, @@ -140,6 +268,26 @@ class PigeonMultiFactorInfo { phoneNumber: result[4] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalMultiFactorInfo || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(displayName, other.displayName) && + _deepEquals(enrollmentTimestamp, other.enrollmentTimestamp) && + _deepEquals(factorId, other.factorId) && + _deepEquals(uid, other.uid) && + _deepEquals(phoneNumber, other.phoneNumber); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class AuthPigeonFirebaseApp { @@ -155,7 +303,7 @@ class AuthPigeonFirebaseApp { String? customAuthDomain; - Object encode() { + List _toList() { return [ appName, tenantId, @@ -163,6 +311,10 @@ class AuthPigeonFirebaseApp { ]; } + Object encode() { + return _toList(); + } + static AuthPigeonFirebaseApp decode(Object result) { result as List; return AuthPigeonFirebaseApp( @@ -171,10 +323,28 @@ class AuthPigeonFirebaseApp { customAuthDomain: result[2] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! AuthPigeonFirebaseApp || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(appName, other.appName) && + _deepEquals(tenantId, other.tenantId) && + _deepEquals(customAuthDomain, other.customAuthDomain); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonActionCodeInfoData { - PigeonActionCodeInfoData({ +class InternalActionCodeInfoData { + InternalActionCodeInfoData({ this.email, this.previousEmail, }); @@ -183,50 +353,93 @@ class PigeonActionCodeInfoData { String? previousEmail; - Object encode() { + List _toList() { return [ email, previousEmail, ]; } - static PigeonActionCodeInfoData decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalActionCodeInfoData decode(Object result) { result as List; - return PigeonActionCodeInfoData( + return InternalActionCodeInfoData( email: result[0] as String?, previousEmail: result[1] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalActionCodeInfoData || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(email, other.email) && + _deepEquals(previousEmail, other.previousEmail); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonActionCodeInfo { - PigeonActionCodeInfo({ +class InternalActionCodeInfo { + InternalActionCodeInfo({ required this.operation, required this.data, }); ActionCodeInfoOperation operation; - PigeonActionCodeInfoData data; + InternalActionCodeInfoData data; - Object encode() { + List _toList() { return [ - operation.index, + operation, data, ]; } - static PigeonActionCodeInfo decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalActionCodeInfo decode(Object result) { result as List; - return PigeonActionCodeInfo( - operation: ActionCodeInfoOperation.values[result[0]! as int], - data: result[1]! as PigeonActionCodeInfoData, + return InternalActionCodeInfo( + operation: result[0]! as ActionCodeInfoOperation, + data: result[1]! as InternalActionCodeInfoData, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalActionCodeInfo || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(operation, other.operation) && + _deepEquals(data, other.data); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonAdditionalUserInfo { - PigeonAdditionalUserInfo({ +class InternalAdditionalUserInfo { + InternalAdditionalUserInfo({ required this.isNewUser, this.providerId, this.username, @@ -244,7 +457,7 @@ class PigeonAdditionalUserInfo { Map? profile; - Object encode() { + List _toList() { return [ isNewUser, providerId, @@ -254,9 +467,13 @@ class PigeonAdditionalUserInfo { ]; } - static PigeonAdditionalUserInfo decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalAdditionalUserInfo decode(Object result) { result as List; - return PigeonAdditionalUserInfo( + return InternalAdditionalUserInfo( isNewUser: result[0]! as bool, providerId: result[1] as String?, username: result[2] as String?, @@ -264,10 +481,31 @@ class PigeonAdditionalUserInfo { profile: (result[4] as Map?)?.cast(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalAdditionalUserInfo || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(isNewUser, other.isNewUser) && + _deepEquals(providerId, other.providerId) && + _deepEquals(username, other.username) && + _deepEquals(authorizationCode, other.authorizationCode) && + _deepEquals(profile, other.profile); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonAuthCredential { - PigeonAuthCredential({ +class InternalAuthCredential { + InternalAuthCredential({ required this.providerId, required this.signInMethod, required this.nativeId, @@ -282,7 +520,7 @@ class PigeonAuthCredential { String? accessToken; - Object encode() { + List _toList() { return [ providerId, signInMethod, @@ -291,19 +529,42 @@ class PigeonAuthCredential { ]; } - static PigeonAuthCredential decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalAuthCredential decode(Object result) { result as List; - return PigeonAuthCredential( + return InternalAuthCredential( providerId: result[0]! as String, signInMethod: result[1]! as String, nativeId: result[2]! as int, accessToken: result[3] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalAuthCredential || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(providerId, other.providerId) && + _deepEquals(signInMethod, other.signInMethod) && + _deepEquals(nativeId, other.nativeId) && + _deepEquals(accessToken, other.accessToken); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonUserInfo { - PigeonUserInfo({ +class InternalUserInfo { + InternalUserInfo({ required this.uid, this.email, this.displayName, @@ -342,7 +603,7 @@ class PigeonUserInfo { int? lastSignInTimestamp; - Object encode() { + List _toList() { return [ uid, email, @@ -359,9 +620,13 @@ class PigeonUserInfo { ]; } - static PigeonUserInfo decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalUserInfo decode(Object result) { result as List; - return PigeonUserInfo( + return InternalUserInfo( uid: result[0]! as String, email: result[1] as String?, displayName: result[2] as String?, @@ -376,49 +641,97 @@ class PigeonUserInfo { lastSignInTimestamp: result[11] as int?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalUserInfo || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(uid, other.uid) && + _deepEquals(email, other.email) && + _deepEquals(displayName, other.displayName) && + _deepEquals(photoUrl, other.photoUrl) && + _deepEquals(phoneNumber, other.phoneNumber) && + _deepEquals(isAnonymous, other.isAnonymous) && + _deepEquals(isEmailVerified, other.isEmailVerified) && + _deepEquals(providerId, other.providerId) && + _deepEquals(tenantId, other.tenantId) && + _deepEquals(refreshToken, other.refreshToken) && + _deepEquals(creationTimestamp, other.creationTimestamp) && + _deepEquals(lastSignInTimestamp, other.lastSignInTimestamp); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonUserDetails { - PigeonUserDetails({ +class InternalUserDetails { + InternalUserDetails({ required this.userInfo, required this.providerData, }); - PigeonUserInfo userInfo; + InternalUserInfo userInfo; List?> providerData; - Object encode() { + List _toList() { return [ userInfo, providerData, ]; } - static PigeonUserDetails decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalUserDetails decode(Object result) { result as List; - return PigeonUserDetails( - userInfo: result[0]! as PigeonUserInfo, + return InternalUserDetails( + userInfo: result[0]! as InternalUserInfo, providerData: - (result[1] as List?)!.cast?>(), + (result[1]! as List).cast?>(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalUserDetails || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(userInfo, other.userInfo) && + _deepEquals(providerData, other.providerData); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonUserCredential { - PigeonUserCredential({ +class InternalUserCredential { + InternalUserCredential({ this.user, this.additionalUserInfo, this.credential, }); - PigeonUserDetails? user; + InternalUserDetails? user; - PigeonAdditionalUserInfo? additionalUserInfo; + InternalAdditionalUserInfo? additionalUserInfo; - PigeonAuthCredential? credential; + InternalAuthCredential? credential; - Object encode() { + List _toList() { return [ user, additionalUserInfo, @@ -426,18 +739,100 @@ class PigeonUserCredential { ]; } - static PigeonUserCredential decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalUserCredential decode(Object result) { + result as List; + return InternalUserCredential( + user: result[0] as InternalUserDetails?, + additionalUserInfo: result[1] as InternalAdditionalUserInfo?, + credential: result[2] as InternalAuthCredential?, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalUserCredential || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(user, other.user) && + _deepEquals(additionalUserInfo, other.additionalUserInfo) && + _deepEquals(credential, other.credential); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); +} + +class InternalAuthCredentialInput { + InternalAuthCredentialInput({ + required this.providerId, + required this.signInMethod, + this.token, + this.accessToken, + }); + + String providerId; + + String signInMethod; + + String? token; + + String? accessToken; + + List _toList() { + return [ + providerId, + signInMethod, + token, + accessToken, + ]; + } + + Object encode() { + return _toList(); + } + + static InternalAuthCredentialInput decode(Object result) { result as List; - return PigeonUserCredential( - user: result[0] as PigeonUserDetails?, - additionalUserInfo: result[1] as PigeonAdditionalUserInfo?, - credential: result[2] as PigeonAuthCredential?, + return InternalAuthCredentialInput( + providerId: result[0]! as String, + signInMethod: result[1]! as String, + token: result[2] as String?, + accessToken: result[3] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalAuthCredentialInput || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(providerId, other.providerId) && + _deepEquals(signInMethod, other.signInMethod) && + _deepEquals(token, other.token) && + _deepEquals(accessToken, other.accessToken); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonActionCodeSettings { - PigeonActionCodeSettings({ +class InternalActionCodeSettings { + InternalActionCodeSettings({ required this.url, this.dynamicLinkDomain, required this.handleCodeInApp, @@ -464,7 +859,7 @@ class PigeonActionCodeSettings { String? linkDomain; - Object encode() { + List _toList() { return [ url, dynamicLinkDomain, @@ -477,9 +872,13 @@ class PigeonActionCodeSettings { ]; } - static PigeonActionCodeSettings decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalActionCodeSettings decode(Object result) { result as List; - return PigeonActionCodeSettings( + return InternalActionCodeSettings( url: result[0]! as String, dynamicLinkDomain: result[1] as String?, handleCodeInApp: result[2]! as bool, @@ -490,10 +889,34 @@ class PigeonActionCodeSettings { linkDomain: result[7] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalActionCodeSettings || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(url, other.url) && + _deepEquals(dynamicLinkDomain, other.dynamicLinkDomain) && + _deepEquals(handleCodeInApp, other.handleCodeInApp) && + _deepEquals(iOSBundleId, other.iOSBundleId) && + _deepEquals(androidPackageName, other.androidPackageName) && + _deepEquals(androidInstallApp, other.androidInstallApp) && + _deepEquals(androidMinimumVersion, other.androidMinimumVersion) && + _deepEquals(linkDomain, other.linkDomain); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonFirebaseAuthSettings { - PigeonFirebaseAuthSettings({ +class InternalFirebaseAuthSettings { + InternalFirebaseAuthSettings({ required this.appVerificationDisabledForTesting, this.userAccessGroup, this.phoneNumber, @@ -511,7 +934,7 @@ class PigeonFirebaseAuthSettings { bool? forceRecaptchaFlow; - Object encode() { + List _toList() { return [ appVerificationDisabledForTesting, userAccessGroup, @@ -521,9 +944,13 @@ class PigeonFirebaseAuthSettings { ]; } - static PigeonFirebaseAuthSettings decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalFirebaseAuthSettings decode(Object result) { result as List; - return PigeonFirebaseAuthSettings( + return InternalFirebaseAuthSettings( appVerificationDisabledForTesting: result[0]! as bool, userAccessGroup: result[1] as String?, phoneNumber: result[2] as String?, @@ -531,10 +958,32 @@ class PigeonFirebaseAuthSettings { forceRecaptchaFlow: result[4] as bool?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalFirebaseAuthSettings || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(appVerificationDisabledForTesting, + other.appVerificationDisabledForTesting) && + _deepEquals(userAccessGroup, other.userAccessGroup) && + _deepEquals(phoneNumber, other.phoneNumber) && + _deepEquals(smsCode, other.smsCode) && + _deepEquals(forceRecaptchaFlow, other.forceRecaptchaFlow); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonSignInProvider { - PigeonSignInProvider({ +class InternalSignInProvider { + InternalSignInProvider({ required this.providerId, this.scopes, this.customParameters, @@ -546,7 +995,7 @@ class PigeonSignInProvider { Map? customParameters; - Object encode() { + List _toList() { return [ providerId, scopes, @@ -554,19 +1003,41 @@ class PigeonSignInProvider { ]; } - static PigeonSignInProvider decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalSignInProvider decode(Object result) { result as List; - return PigeonSignInProvider( + return InternalSignInProvider( providerId: result[0]! as String, scopes: (result[1] as List?)?.cast(), customParameters: (result[2] as Map?)?.cast(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalSignInProvider || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(providerId, other.providerId) && + _deepEquals(scopes, other.scopes) && + _deepEquals(customParameters, other.customParameters); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonVerifyPhoneNumberRequest { - PigeonVerifyPhoneNumberRequest({ +class InternalVerifyPhoneNumberRequest { + InternalVerifyPhoneNumberRequest({ this.phoneNumber, required this.timeout, this.forceResendingToken, @@ -587,7 +1058,7 @@ class PigeonVerifyPhoneNumberRequest { String? multiFactorSessionId; - Object encode() { + List _toList() { return [ phoneNumber, timeout, @@ -598,9 +1069,13 @@ class PigeonVerifyPhoneNumberRequest { ]; } - static PigeonVerifyPhoneNumberRequest decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalVerifyPhoneNumberRequest decode(Object result) { result as List; - return PigeonVerifyPhoneNumberRequest( + return InternalVerifyPhoneNumberRequest( phoneNumber: result[0] as String?, timeout: result[1]! as int, forceResendingToken: result[2] as int?, @@ -609,10 +1084,33 @@ class PigeonVerifyPhoneNumberRequest { multiFactorSessionId: result[5] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalVerifyPhoneNumberRequest || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(phoneNumber, other.phoneNumber) && + _deepEquals(timeout, other.timeout) && + _deepEquals(forceResendingToken, other.forceResendingToken) && + _deepEquals(autoRetrievedSmsCodeForTesting, + other.autoRetrievedSmsCodeForTesting) && + _deepEquals(multiFactorInfoId, other.multiFactorInfoId) && + _deepEquals(multiFactorSessionId, other.multiFactorSessionId); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonIdTokenResult { - PigeonIdTokenResult({ +class InternalIdTokenResult { + InternalIdTokenResult({ this.token, this.expirationTimestamp, this.authTimestamp, @@ -636,7 +1134,7 @@ class PigeonIdTokenResult { String? signInSecondFactor; - Object encode() { + List _toList() { return [ token, expirationTimestamp, @@ -648,9 +1146,13 @@ class PigeonIdTokenResult { ]; } - static PigeonIdTokenResult decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalIdTokenResult decode(Object result) { result as List; - return PigeonIdTokenResult( + return InternalIdTokenResult( token: result[0] as String?, expirationTimestamp: result[1] as int?, authTimestamp: result[2] as int?, @@ -660,10 +1162,32 @@ class PigeonIdTokenResult { signInSecondFactor: result[6] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalIdTokenResult || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(token, other.token) && + _deepEquals(expirationTimestamp, other.expirationTimestamp) && + _deepEquals(authTimestamp, other.authTimestamp) && + _deepEquals(issuedAtTimestamp, other.issuedAtTimestamp) && + _deepEquals(signInProvider, other.signInProvider) && + _deepEquals(claims, other.claims) && + _deepEquals(signInSecondFactor, other.signInSecondFactor); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonUserProfile { - PigeonUserProfile({ +class InternalUserProfile { + InternalUserProfile({ this.displayName, this.photoUrl, required this.displayNameChanged, @@ -678,7 +1202,7 @@ class PigeonUserProfile { bool photoUrlChanged; - Object encode() { + List _toList() { return [ displayName, photoUrl, @@ -687,19 +1211,42 @@ class PigeonUserProfile { ]; } - static PigeonUserProfile decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalUserProfile decode(Object result) { result as List; - return PigeonUserProfile( + return InternalUserProfile( displayName: result[0] as String?, photoUrl: result[1] as String?, displayNameChanged: result[2]! as bool, photoUrlChanged: result[3]! as bool, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalUserProfile || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(displayName, other.displayName) && + _deepEquals(photoUrl, other.photoUrl) && + _deepEquals(displayNameChanged, other.displayNameChanged) && + _deepEquals(photoUrlChanged, other.photoUrlChanged); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonTotpSecret { - PigeonTotpSecret({ +class InternalTotpSecret { + InternalTotpSecret({ this.codeIntervalSeconds, this.codeLength, this.enrollmentCompletionDeadline, @@ -717,7 +1264,7 @@ class PigeonTotpSecret { String secretKey; - Object encode() { + List _toList() { return [ codeIntervalSeconds, codeLength, @@ -727,9 +1274,13 @@ class PigeonTotpSecret { ]; } - static PigeonTotpSecret decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalTotpSecret decode(Object result) { result as List; - return PigeonTotpSecret( + return InternalTotpSecret( codeIntervalSeconds: result[0] as int?, codeLength: result[1] as int?, enrollmentCompletionDeadline: result[2] as int?, @@ -737,66 +1288,96 @@ class PigeonTotpSecret { secretKey: result[4]! as String, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalTotpSecret || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(codeIntervalSeconds, other.codeIntervalSeconds) && + _deepEquals(codeLength, other.codeLength) && + _deepEquals( + enrollmentCompletionDeadline, other.enrollmentCompletionDeadline) && + _deepEquals(hashingAlgorithm, other.hashingAlgorithm) && + _deepEquals(secretKey, other.secretKey); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class _FirebaseAuthHostApiCodec extends StandardMessageCodec { - const _FirebaseAuthHostApiCodec(); +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is AuthPigeonFirebaseApp) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfo) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is ActionCodeInfoOperation) { buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfoData) { + writeValue(buffer, value.index); + } else if (value is InternalMultiFactorSession) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeSettings) { + } else if (value is InternalPhoneMultiFactorAssertion) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is PigeonAdditionalUserInfo) { + } else if (value is InternalMultiFactorInfo) { buffer.putUint8(132); writeValue(buffer, value.encode()); - } else if (value is PigeonAuthCredential) { + } else if (value is AuthPigeonFirebaseApp) { buffer.putUint8(133); writeValue(buffer, value.encode()); - } else if (value is PigeonFirebaseAuthSettings) { + } else if (value is InternalActionCodeInfoData) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is PigeonIdTokenResult) { + } else if (value is InternalActionCodeInfo) { buffer.putUint8(135); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorInfo) { + } else if (value is InternalAdditionalUserInfo) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { + } else if (value is InternalAuthCredential) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { + } else if (value is InternalUserInfo) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonSignInProvider) { + } else if (value is InternalUserDetails) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonTotpSecret) { + } else if (value is InternalUserCredential) { buffer.putUint8(140); writeValue(buffer, value.encode()); - } else if (value is PigeonUserCredential) { + } else if (value is InternalAuthCredentialInput) { buffer.putUint8(141); writeValue(buffer, value.encode()); - } else if (value is PigeonUserDetails) { + } else if (value is InternalActionCodeSettings) { buffer.putUint8(142); writeValue(buffer, value.encode()); - } else if (value is PigeonUserInfo) { + } else if (value is InternalFirebaseAuthSettings) { buffer.putUint8(143); writeValue(buffer, value.encode()); - } else if (value is PigeonUserProfile) { + } else if (value is InternalSignInProvider) { buffer.putUint8(144); writeValue(buffer, value.encode()); - } else if (value is PigeonVerifyPhoneNumberRequest) { + } else if (value is InternalVerifyPhoneNumberRequest) { buffer.putUint8(145); writeValue(buffer, value.encode()); + } else if (value is InternalIdTokenResult) { + buffer.putUint8(146); + writeValue(buffer, value.encode()); + } else if (value is InternalUserProfile) { + buffer.putUint8(147); + writeValue(buffer, value.encode()); + } else if (value is InternalTotpSecret) { + buffer.putUint8(148); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -805,42 +1386,47 @@ class _FirebaseAuthHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: - return AuthPigeonFirebaseApp.decode(readValue(buffer)!); case 129: - return PigeonActionCodeInfo.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : ActionCodeInfoOperation.values[value]; case 130: - return PigeonActionCodeInfoData.decode(readValue(buffer)!); + return InternalMultiFactorSession.decode(readValue(buffer)!); case 131: - return PigeonActionCodeSettings.decode(readValue(buffer)!); + return InternalPhoneMultiFactorAssertion.decode(readValue(buffer)!); case 132: - return PigeonAdditionalUserInfo.decode(readValue(buffer)!); + return InternalMultiFactorInfo.decode(readValue(buffer)!); case 133: - return PigeonAuthCredential.decode(readValue(buffer)!); + return AuthPigeonFirebaseApp.decode(readValue(buffer)!); case 134: - return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); + return InternalActionCodeInfoData.decode(readValue(buffer)!); case 135: - return PigeonIdTokenResult.decode(readValue(buffer)!); + return InternalActionCodeInfo.decode(readValue(buffer)!); case 136: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); + return InternalAdditionalUserInfo.decode(readValue(buffer)!); case 137: - return PigeonMultiFactorSession.decode(readValue(buffer)!); + return InternalAuthCredential.decode(readValue(buffer)!); case 138: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); + return InternalUserInfo.decode(readValue(buffer)!); case 139: - return PigeonSignInProvider.decode(readValue(buffer)!); + return InternalUserDetails.decode(readValue(buffer)!); case 140: - return PigeonTotpSecret.decode(readValue(buffer)!); + return InternalUserCredential.decode(readValue(buffer)!); case 141: - return PigeonUserCredential.decode(readValue(buffer)!); + return InternalAuthCredentialInput.decode(readValue(buffer)!); case 142: - return PigeonUserDetails.decode(readValue(buffer)!); + return InternalActionCodeSettings.decode(readValue(buffer)!); case 143: - return PigeonUserInfo.decode(readValue(buffer)!); + return InternalFirebaseAuthSettings.decode(readValue(buffer)!); case 144: - return PigeonUserProfile.decode(readValue(buffer)!); + return InternalSignInProvider.decode(readValue(buffer)!); case 145: - return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); + return InternalVerifyPhoneNumberRequest.decode(readValue(buffer)!); + case 146: + return InternalIdTokenResult.decode(readValue(buffer)!); + case 147: + return InternalUserProfile.decode(readValue(buffer)!); + case 148: + return InternalTotpSecret.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -853,787 +1439,502 @@ class FirebaseAuthHostApi { /// BinaryMessenger will be used which routes to the host platform. FirebaseAuthHostApi( {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? __pigeon_binaryMessenger; + final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - _FirebaseAuthHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - final String __pigeon_messageChannelSuffix; + final String pigeonVar_messageChannelSuffix; Future registerIdTokenListener(AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerIdTokenListener$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerIdTokenListener$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future registerAuthStateListener(AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerAuthStateListener$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerAuthStateListener$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future useEmulator( AuthPigeonFirebaseApp app, String host, int port) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.useEmulator$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.useEmulator$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, host, port]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, host, port]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future applyActionCode(AuthPigeonFirebaseApp app, String code) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.applyActionCode$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.applyActionCode$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, code]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, code]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future checkActionCode( + Future checkActionCode( AuthPigeonFirebaseApp app, String code) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.checkActionCode$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.checkActionCode$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, code]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonActionCodeInfo?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, code]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalActionCodeInfo; } Future confirmPasswordReset( AuthPigeonFirebaseApp app, String code, String newPassword) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.confirmPasswordReset$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.confirmPasswordReset$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, code, newPassword]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, code, newPassword]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future createUserWithEmailAndPassword( + Future createUserWithEmailAndPassword( AuthPigeonFirebaseApp app, String email, String password) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.createUserWithEmailAndPassword$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.createUserWithEmailAndPassword$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, email, password]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, email, password]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future signInAnonymously( + Future signInAnonymously( AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInAnonymously$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInAnonymously$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future signInWithCredential( + Future signInWithCredential( AuthPigeonFirebaseApp app, Map input) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCredential$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCredential$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, input]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, input]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future signInWithCustomToken( + Future signInWithCustomToken( AuthPigeonFirebaseApp app, String token) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCustomToken$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCustomToken$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, token]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, token]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future signInWithEmailAndPassword( + Future signInWithEmailAndPassword( AuthPigeonFirebaseApp app, String email, String password) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailAndPassword$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailAndPassword$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, email, password]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, email, password]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future signInWithEmailLink( + Future signInWithEmailLink( AuthPigeonFirebaseApp app, String email, String emailLink) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailLink$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailLink$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, email, emailLink]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, email, emailLink]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future signInWithProvider( - AuthPigeonFirebaseApp app, PigeonSignInProvider signInProvider) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithProvider$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future signInWithProvider( + AuthPigeonFirebaseApp app, InternalSignInProvider signInProvider) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithProvider$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, signInProvider]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, signInProvider]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } Future signOut(AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signOut$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signOut$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future> fetchSignInMethodsForEmail( + Future> fetchSignInMethodsForEmail( AuthPigeonFirebaseApp app, String email) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.fetchSignInMethodsForEmail$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.fetchSignInMethodsForEmail$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, email]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as List?)!.cast(); - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, email]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List).cast(); } Future sendPasswordResetEmail(AuthPigeonFirebaseApp app, String email, - PigeonActionCodeSettings? actionCodeSettings) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendPasswordResetEmail$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + InternalActionCodeSettings? actionCodeSettings) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendPasswordResetEmail$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, email, actionCodeSettings]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, email, actionCodeSettings]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future sendSignInLinkToEmail(AuthPigeonFirebaseApp app, String email, - PigeonActionCodeSettings actionCodeSettings) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendSignInLinkToEmail$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + InternalActionCodeSettings actionCodeSettings) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendSignInLinkToEmail$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, email, actionCodeSettings]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, email, actionCodeSettings]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setLanguageCode( AuthPigeonFirebaseApp app, String? languageCode) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setLanguageCode$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setLanguageCode$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, languageCode]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, languageCode]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future setSettings( - AuthPigeonFirebaseApp app, PigeonFirebaseAuthSettings settings) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setSettings$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + AuthPigeonFirebaseApp app, InternalFirebaseAuthSettings settings) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setSettings$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, settings]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, settings]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future verifyPasswordResetCode( AuthPigeonFirebaseApp app, String code) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPasswordResetCode$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPasswordResetCode$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, code]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, code]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } - Future verifyPhoneNumber( - AuthPigeonFirebaseApp app, PigeonVerifyPhoneNumberRequest request) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPhoneNumber$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future verifyPhoneNumber(AuthPigeonFirebaseApp app, + InternalVerifyPhoneNumberRequest request) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPhoneNumber$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, request]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, request]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future revokeTokenWithAuthorizationCode( AuthPigeonFirebaseApp app, String authorizationCode) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeTokenWithAuthorizationCode$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeTokenWithAuthorizationCode$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, authorizationCode]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, authorizationCode]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future revokeAccessToken( AuthPigeonFirebaseApp app, String accessToken) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, accessToken]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, accessToken]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future initializeRecaptchaConfig(AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.initializeRecaptchaConfig$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.initializeRecaptchaConfig$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } - } -} - -class _FirebaseAuthUserHostApiCodec extends StandardMessageCodec { - const _FirebaseAuthUserHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is AuthPigeonFirebaseApp) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfo) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfoData) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeSettings) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else if (value is PigeonAdditionalUserInfo) { - buffer.putUint8(132); - writeValue(buffer, value.encode()); - } else if (value is PigeonAuthCredential) { - buffer.putUint8(133); - writeValue(buffer, value.encode()); - } else if (value is PigeonFirebaseAuthSettings) { - buffer.putUint8(134); - writeValue(buffer, value.encode()); - } else if (value is PigeonIdTokenResult) { - buffer.putUint8(135); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorInfo) { - buffer.putUint8(136); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { - buffer.putUint8(137); - writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { - buffer.putUint8(138); - writeValue(buffer, value.encode()); - } else if (value is PigeonSignInProvider) { - buffer.putUint8(139); - writeValue(buffer, value.encode()); - } else if (value is PigeonTotpSecret) { - buffer.putUint8(140); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserCredential) { - buffer.putUint8(141); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserDetails) { - buffer.putUint8(142); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserInfo) { - buffer.putUint8(143); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserProfile) { - buffer.putUint8(144); - writeValue(buffer, value.encode()); - } else if (value is PigeonVerifyPhoneNumberRequest) { - buffer.putUint8(145); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return AuthPigeonFirebaseApp.decode(readValue(buffer)!); - case 129: - return PigeonActionCodeInfo.decode(readValue(buffer)!); - case 130: - return PigeonActionCodeInfoData.decode(readValue(buffer)!); - case 131: - return PigeonActionCodeSettings.decode(readValue(buffer)!); - case 132: - return PigeonAdditionalUserInfo.decode(readValue(buffer)!); - case 133: - return PigeonAuthCredential.decode(readValue(buffer)!); - case 134: - return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); - case 135: - return PigeonIdTokenResult.decode(readValue(buffer)!); - case 136: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - case 137: - return PigeonMultiFactorSession.decode(readValue(buffer)!); - case 138: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - case 139: - return PigeonSignInProvider.decode(readValue(buffer)!); - case 140: - return PigeonTotpSecret.decode(readValue(buffer)!); - case 141: - return PigeonUserCredential.decode(readValue(buffer)!); - case 142: - return PigeonUserDetails.decode(readValue(buffer)!); - case 143: - return PigeonUserInfo.decode(readValue(buffer)!); - case 144: - return PigeonUserProfile.decode(readValue(buffer)!); - case 145: - return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -1643,455 +1944,302 @@ class FirebaseAuthUserHostApi { /// BinaryMessenger will be used which routes to the host platform. FirebaseAuthUserHostApi( {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? __pigeon_binaryMessenger; + final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - _FirebaseAuthUserHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - final String __pigeon_messageChannelSuffix; + final String pigeonVar_messageChannelSuffix; Future delete(AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.delete$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.delete$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future getIdToken( + Future getIdToken( AuthPigeonFirebaseApp app, bool forceRefresh) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.getIdToken$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.getIdToken$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, forceRefresh]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonIdTokenResult?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, forceRefresh]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalIdTokenResult; } - Future linkWithCredential( + Future linkWithCredential( AuthPigeonFirebaseApp app, Map input) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithCredential$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithCredential$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, input]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, input]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future linkWithProvider( - AuthPigeonFirebaseApp app, PigeonSignInProvider signInProvider) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithProvider$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future linkWithProvider( + AuthPigeonFirebaseApp app, InternalSignInProvider signInProvider) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithProvider$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, signInProvider]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, signInProvider]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future reauthenticateWithCredential( + Future reauthenticateWithCredential( AuthPigeonFirebaseApp app, Map input) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithCredential$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithCredential$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, input]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, input]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future reauthenticateWithProvider( - AuthPigeonFirebaseApp app, PigeonSignInProvider signInProvider) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithProvider$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future reauthenticateWithProvider( + AuthPigeonFirebaseApp app, InternalSignInProvider signInProvider) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithProvider$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, signInProvider]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, signInProvider]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future reload(AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reload$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future reload(AuthPigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reload$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserDetails?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserDetails; } Future sendEmailVerification(AuthPigeonFirebaseApp app, - PigeonActionCodeSettings? actionCodeSettings) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.sendEmailVerification$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + InternalActionCodeSettings? actionCodeSettings) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.sendEmailVerification$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, actionCodeSettings]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, actionCodeSettings]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future unlink( + Future unlink( AuthPigeonFirebaseApp app, String providerId) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.unlink$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.unlink$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, providerId]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, providerId]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } - Future updateEmail( + Future updateEmail( AuthPigeonFirebaseApp app, String newEmail) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateEmail$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateEmail$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, newEmail]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserDetails?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, newEmail]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserDetails; } - Future updatePassword( + Future updatePassword( AuthPigeonFirebaseApp app, String newPassword) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePassword$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePassword$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, newPassword]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserDetails?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, newPassword]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserDetails; } - Future updatePhoneNumber( + Future updatePhoneNumber( AuthPigeonFirebaseApp app, Map input) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePhoneNumber$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePhoneNumber$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, input]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserDetails?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, input]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserDetails; } - Future updateProfile( - AuthPigeonFirebaseApp app, PigeonUserProfile profile) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateProfile$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future updateProfile( + AuthPigeonFirebaseApp app, InternalUserProfile profile) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateProfile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app, profile]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserDetails?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, profile]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserDetails; } Future verifyBeforeUpdateEmail(AuthPigeonFirebaseApp app, - String newEmail, PigeonActionCodeSettings? actionCodeSettings) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + String newEmail, InternalActionCodeSettings? actionCodeSettings) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, newEmail, actionCodeSettings]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } - } -} - -class _MultiFactorUserHostApiCodec extends StandardMessageCodec { - const _MultiFactorUserHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is AuthPigeonFirebaseApp) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorInfo) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, newEmail, actionCodeSettings]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return AuthPigeonFirebaseApp.decode(readValue(buffer)!); - case 129: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - case 130: - return PigeonMultiFactorSession.decode(readValue(buffer)!); - case 131: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -2101,196 +2249,115 @@ class MultiFactorUserHostApi { /// BinaryMessenger will be used which routes to the host platform. MultiFactorUserHostApi( {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? __pigeon_binaryMessenger; + final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - _MultiFactorUserHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - final String __pigeon_messageChannelSuffix; + final String pigeonVar_messageChannelSuffix; Future enrollPhone(AuthPigeonFirebaseApp app, - PigeonPhoneMultiFactorAssertion assertion, String? displayName) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollPhone$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + InternalPhoneMultiFactorAssertion assertion, String? displayName) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollPhone$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, assertion, displayName]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, assertion, displayName]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future enrollTotp(AuthPigeonFirebaseApp app, String assertionId, String? displayName) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollTotp$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollTotp$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, assertionId, displayName]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, assertionId, displayName]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future getSession(AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getSession$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future getSession( + AuthPigeonFirebaseApp app) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getSession$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonMultiFactorSession?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalMultiFactorSession; } Future unenroll(AuthPigeonFirebaseApp app, String factorUid) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.unenroll$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.unenroll$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([app, factorUid]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, factorUid]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future> getEnrolledFactors( + Future> getEnrolledFactors( AuthPigeonFirebaseApp app) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getEnrolledFactors$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getEnrolledFactors$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([app]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as List?)! - .cast(); - } - } -} - -class _MultiFactoResolverHostApiCodec extends StandardMessageCodec { - const _MultiFactoResolverHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonAdditionalUserInfo) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonAuthCredential) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserCredential) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserDetails) { - buffer.putUint8(132); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserInfo) { - buffer.putUint8(133); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return PigeonAdditionalUserInfo.decode(readValue(buffer)!); - case 129: - return PigeonAuthCredential.decode(readValue(buffer)!); - case 130: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - case 131: - return PigeonUserCredential.decode(readValue(buffer)!); - case 132: - return PigeonUserDetails.decode(readValue(buffer)!); - case 133: - return PigeonUserInfo.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List) + .cast(); } } @@ -2300,70 +2367,36 @@ class MultiFactoResolverHostApi { /// BinaryMessenger will be used which routes to the host platform. MultiFactoResolverHostApi( {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? __pigeon_binaryMessenger; + final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - _MultiFactoResolverHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - final String __pigeon_messageChannelSuffix; + final String pigeonVar_messageChannelSuffix; - Future resolveSignIn( + Future resolveSignIn( String resolverId, - PigeonPhoneMultiFactorAssertion? assertion, + InternalPhoneMultiFactorAssertion? assertion, String? totpAssertionId) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactoResolverHostApi.resolveSignIn$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactoResolverHostApi.resolveSignIn$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([resolverId, assertion, totpAssertionId]) - as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonUserCredential?)!; - } - } -} - -class _MultiFactorTotpHostApiCodec extends StandardMessageCodec { - const _MultiFactorTotpHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonTotpSecret) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([resolverId, assertion, totpAssertionId]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return PigeonTotpSecret.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalUserCredential; } } @@ -2373,103 +2406,75 @@ class MultiFactorTotpHostApi { /// BinaryMessenger will be used which routes to the host platform. MultiFactorTotpHostApi( {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? __pigeon_binaryMessenger; + final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - _MultiFactorTotpHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - final String __pigeon_messageChannelSuffix; + final String pigeonVar_messageChannelSuffix; - Future generateSecret(String sessionId) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.generateSecret$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future generateSecret(String sessionId) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.generateSecret$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([sessionId]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as PigeonTotpSecret?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([sessionId]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalTotpSecret; } Future getAssertionForEnrollment( String secretKey, String oneTimePassword) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForEnrollment$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForEnrollment$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([secretKey, oneTimePassword]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([secretKey, oneTimePassword]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future getAssertionForSignIn( String enrollmentId, String oneTimePassword) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForSignIn$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForSignIn$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([enrollmentId, oneTimePassword]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([enrollmentId, oneTimePassword]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } } @@ -2479,91 +2484,53 @@ class MultiFactorTotpSecretHostApi { /// BinaryMessenger will be used which routes to the host platform. MultiFactorTotpSecretHostApi( {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? __pigeon_binaryMessenger; + final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - StandardMessageCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - final String __pigeon_messageChannelSuffix; + final String pigeonVar_messageChannelSuffix; Future generateQrCodeUrl( String secretKey, String? accountName, String? issuer) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.generateQrCodeUrl$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.generateQrCodeUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([secretKey, accountName, issuer]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else if (__pigeon_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (__pigeon_replyList[0] as String?)!; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([secretKey, accountName, issuer]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future openInOtpApp(String secretKey, String qrCodeUrl) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.openInOtpApp$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.openInOtpApp$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = await __pigeon_channel - .send([secretKey, qrCodeUrl]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } - } -} - -class _GenerateInterfacesCodec extends StandardMessageCodec { - const _GenerateInterfacesCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonMultiFactorInfo) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([secretKey, qrCodeUrl]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } @@ -2574,37 +2541,31 @@ class GenerateInterfaces { /// BinaryMessenger will be used which routes to the host platform. GenerateInterfaces( {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : __pigeon_binaryMessenger = binaryMessenger, - __pigeon_messageChannelSuffix = + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? __pigeon_binaryMessenger; + final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - _GenerateInterfacesCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - final String __pigeon_messageChannelSuffix; + final String pigeonVar_messageChannelSuffix; - Future pigeonInterface(PigeonMultiFactorInfo info) async { - final String __pigeon_channelName = - 'dev.flutter.pigeon.firebase_auth_platform_interface.GenerateInterfaces.pigeonInterface$__pigeon_messageChannelSuffix'; - final BasicMessageChannel __pigeon_channel = - BasicMessageChannel( - __pigeon_channelName, + Future pigeonInterface(InternalMultiFactorInfo info) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_auth_platform_interface.GenerateInterfaces.pigeonInterface$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, pigeonChannelCodec, - binaryMessenger: __pigeon_binaryMessenger, - ); - final List? __pigeon_replyList = - await __pigeon_channel.send([info]) as List?; - if (__pigeon_replyList == null) { - throw _createConnectionError(__pigeon_channelName); - } else if (__pigeon_replyList.length > 1) { - throw PlatformException( - code: __pigeon_replyList[0]! as String, - message: __pigeon_replyList[1] as String?, - details: __pigeon_replyList[2], - ); - } else { - return; - } + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([info]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart index 7b5feff9d4e5..daa5b730a3b6 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart @@ -64,9 +64,9 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { if (currentUser != null) { currentUser as List; - final firstElement = PigeonUserInfo.decode(currentUser[0]!); + final firstElement = InternalUserInfo.decode(currentUser[0]!); final secondElement = currentUser[1]!; - currentUser = PigeonUserDetails.decode([firstElement, secondElement]); + currentUser = InternalUserDetails.decode([firstElement, secondElement]); } return FirebaseAuthPlatform.instance.delegateFor(app: app).setInitialValues( languageCode: pluginConstants['APP_LANGUAGE_CODE'], @@ -107,7 +107,7 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { /// calls. @protected FirebaseAuthPlatform setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { throw UnimplementedError('setInitialValues() is not implemented'); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart index 3d442b33b9af..52a5988059e0 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_user.dart @@ -11,7 +11,7 @@ import 'package:plugin_platform_interface/plugin_platform_interface.dart'; /// A user account. abstract class UserPlatform extends PlatformInterface { // ignore: public_member_api_docs - UserPlatform(this.auth, this.multiFactor, PigeonUserDetails user) + UserPlatform(this.auth, this.multiFactor, InternalUserDetails user) : _user = user, super(token: _token); @@ -27,7 +27,7 @@ abstract class UserPlatform extends PlatformInterface { final MultiFactorPlatform multiFactor; - final PigeonUserDetails _user; + final InternalUserDetails _user; /// The users display name. /// diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart index ddccb0f8cded..b4936290a156 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/user_info.dart @@ -14,7 +14,7 @@ class UserInfo { @protected UserInfo.fromJson(Map data) - : _data = PigeonUserInfo( + : _data = InternalUserInfo( uid: data['uid'] as String, email: data['email'] as String?, displayName: data['displayName'] as String?, @@ -29,7 +29,7 @@ class UserInfo { lastSignInTimestamp: data['lastSignInTimestamp'] as int?, ); - final PigeonUserInfo _data; + final InternalUserInfo _data; /// The users display name. /// diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart b/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart index 6a2e99337c5c..943fa1693b87 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/pigeons/messages.dart @@ -27,16 +27,16 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) -class PigeonMultiFactorSession { - const PigeonMultiFactorSession({ +class InternalMultiFactorSession { + const InternalMultiFactorSession({ required this.id, }); final String id; } -class PigeonPhoneMultiFactorAssertion { - const PigeonPhoneMultiFactorAssertion({ +class InternalPhoneMultiFactorAssertion { + const InternalPhoneMultiFactorAssertion({ required this.verificationId, required this.verificationCode, }); @@ -45,8 +45,8 @@ class PigeonPhoneMultiFactorAssertion { final String verificationCode; } -class PigeonMultiFactorInfo { - const PigeonMultiFactorInfo({ +class InternalMultiFactorInfo { + const InternalMultiFactorInfo({ this.displayName, required this.enrollmentTimestamp, this.factorId, @@ -100,8 +100,8 @@ enum ActionCodeInfoOperation { revertSecondFactorAddition, } -class PigeonActionCodeInfoData { - const PigeonActionCodeInfoData({ +class InternalActionCodeInfoData { + const InternalActionCodeInfoData({ this.email, this.previousEmail, }); @@ -110,18 +110,18 @@ class PigeonActionCodeInfoData { final String? previousEmail; } -class PigeonActionCodeInfo { - const PigeonActionCodeInfo({ +class InternalActionCodeInfo { + const InternalActionCodeInfo({ required this.operation, required this.data, }); final ActionCodeInfoOperation operation; - final PigeonActionCodeInfoData data; + final InternalActionCodeInfoData data; } -class PigeonAdditionalUserInfo { - const PigeonAdditionalUserInfo({ +class InternalAdditionalUserInfo { + const InternalAdditionalUserInfo({ required this.isNewUser, required this.providerId, required this.username, @@ -136,8 +136,8 @@ class PigeonAdditionalUserInfo { final Map? profile; } -class PigeonAuthCredential { - const PigeonAuthCredential({ +class InternalAuthCredential { + const InternalAuthCredential({ required this.providerId, required this.signInMethod, required this.nativeId, @@ -150,8 +150,8 @@ class PigeonAuthCredential { final String? accessToken; } -class PigeonUserInfo { - const PigeonUserInfo({ +class InternalUserInfo { + const InternalUserInfo({ required this.uid, required this.email, required this.displayName, @@ -180,30 +180,30 @@ class PigeonUserInfo { final int? lastSignInTimestamp; } -class PigeonUserDetails { - const PigeonUserDetails({ +class InternalUserDetails { + const InternalUserDetails({ required this.userInfo, required this.providerData, }); - final PigeonUserInfo userInfo; + final InternalUserInfo userInfo; final List?> providerData; } -class PigeonUserCredential { - const PigeonUserCredential({ +class InternalUserCredential { + const InternalUserCredential({ required this.user, required this.additionalUserInfo, required this.credential, }); - final PigeonUserDetails? user; - final PigeonAdditionalUserInfo? additionalUserInfo; - final PigeonAuthCredential? credential; + final InternalUserDetails? user; + final InternalAdditionalUserInfo? additionalUserInfo; + final InternalAuthCredential? credential; } -class PigeonAuthCredentialInput { - const PigeonAuthCredentialInput({ +class InternalAuthCredentialInput { + const InternalAuthCredentialInput({ required this.providerId, required this.signInMethod, required this.token, @@ -216,8 +216,8 @@ class PigeonAuthCredentialInput { final String? accessToken; } -class PigeonActionCodeSettings { - const PigeonActionCodeSettings({ +class InternalActionCodeSettings { + const InternalActionCodeSettings({ required this.url, required this.dynamicLinkDomain, required this.linkDomain, @@ -238,8 +238,8 @@ class PigeonActionCodeSettings { final String? linkDomain; } -class PigeonFirebaseAuthSettings { - const PigeonFirebaseAuthSettings({ +class InternalFirebaseAuthSettings { + const InternalFirebaseAuthSettings({ required this.appVerificationDisabledForTesting, required this.userAccessGroup, required this.phoneNumber, @@ -254,8 +254,8 @@ class PigeonFirebaseAuthSettings { final bool? forceRecaptchaFlow; } -class PigeonSignInProvider { - const PigeonSignInProvider({ +class InternalSignInProvider { + const InternalSignInProvider({ required this.providerId, required this.scopes, required this.customParameters, @@ -266,8 +266,8 @@ class PigeonSignInProvider { final Map? customParameters; } -class PigeonVerifyPhoneNumberRequest { - const PigeonVerifyPhoneNumberRequest({ +class InternalVerifyPhoneNumberRequest { + const InternalVerifyPhoneNumberRequest({ required this.phoneNumber, required this.timeout, required this.forceResendingToken, @@ -310,7 +310,7 @@ abstract class FirebaseAuthHostApi { ); @async - PigeonActionCodeInfo checkActionCode( + InternalActionCodeInfo checkActionCode( AuthPigeonFirebaseApp app, String code, ); @@ -323,47 +323,47 @@ abstract class FirebaseAuthHostApi { ); @async - PigeonUserCredential createUserWithEmailAndPassword( + InternalUserCredential createUserWithEmailAndPassword( AuthPigeonFirebaseApp app, String email, String password, ); @async - PigeonUserCredential signInAnonymously( + InternalUserCredential signInAnonymously( AuthPigeonFirebaseApp app, ); @async - PigeonUserCredential signInWithCredential( + InternalUserCredential signInWithCredential( AuthPigeonFirebaseApp app, - Map input, + Map input, ); @async - PigeonUserCredential signInWithCustomToken( + InternalUserCredential signInWithCustomToken( AuthPigeonFirebaseApp app, String token, ); @async - PigeonUserCredential signInWithEmailAndPassword( + InternalUserCredential signInWithEmailAndPassword( AuthPigeonFirebaseApp app, String email, String password, ); @async - PigeonUserCredential signInWithEmailLink( + InternalUserCredential signInWithEmailLink( AuthPigeonFirebaseApp app, String email, String emailLink, ); @async - PigeonUserCredential signInWithProvider( + InternalUserCredential signInWithProvider( AuthPigeonFirebaseApp app, - PigeonSignInProvider signInProvider, + InternalSignInProvider signInProvider, ); @async @@ -381,14 +381,14 @@ abstract class FirebaseAuthHostApi { void sendPasswordResetEmail( AuthPigeonFirebaseApp app, String email, - PigeonActionCodeSettings? actionCodeSettings, + InternalActionCodeSettings? actionCodeSettings, ); @async void sendSignInLinkToEmail( AuthPigeonFirebaseApp app, String email, - PigeonActionCodeSettings actionCodeSettings, + InternalActionCodeSettings actionCodeSettings, ); @async @@ -400,7 +400,7 @@ abstract class FirebaseAuthHostApi { @async void setSettings( AuthPigeonFirebaseApp app, - PigeonFirebaseAuthSettings settings, + InternalFirebaseAuthSettings settings, ); @async @@ -412,7 +412,7 @@ abstract class FirebaseAuthHostApi { @async String verifyPhoneNumber( AuthPigeonFirebaseApp app, - PigeonVerifyPhoneNumberRequest request, + InternalVerifyPhoneNumberRequest request, ); @async void revokeTokenWithAuthorizationCode( @@ -432,8 +432,8 @@ abstract class FirebaseAuthHostApi { ); } -class PigeonIdTokenResult { - const PigeonIdTokenResult({ +class InternalIdTokenResult { + const InternalIdTokenResult({ required this.token, required this.expirationTimestamp, required this.authTimestamp, @@ -452,8 +452,8 @@ class PigeonIdTokenResult { final String? signInSecondFactor; } -class PigeonUserProfile { - const PigeonUserProfile({ +class InternalUserProfile { + const InternalUserProfile({ required this.displayName, required this.photoUrl, required this.displayNameChanged, @@ -474,81 +474,81 @@ abstract class FirebaseAuthUserHostApi { ); @async - PigeonIdTokenResult getIdToken( + InternalIdTokenResult getIdToken( AuthPigeonFirebaseApp app, bool forceRefresh, ); @async - PigeonUserCredential linkWithCredential( + InternalUserCredential linkWithCredential( AuthPigeonFirebaseApp app, - Map input, + Map input, ); @async - PigeonUserCredential linkWithProvider( + InternalUserCredential linkWithProvider( AuthPigeonFirebaseApp app, - PigeonSignInProvider signInProvider, + InternalSignInProvider signInProvider, ); @async - PigeonUserCredential reauthenticateWithCredential( + InternalUserCredential reauthenticateWithCredential( AuthPigeonFirebaseApp app, - Map input, + Map input, ); @async - PigeonUserCredential reauthenticateWithProvider( + InternalUserCredential reauthenticateWithProvider( AuthPigeonFirebaseApp app, - PigeonSignInProvider signInProvider, + InternalSignInProvider signInProvider, ); @async - PigeonUserDetails reload( + InternalUserDetails reload( AuthPigeonFirebaseApp app, ); @async void sendEmailVerification( AuthPigeonFirebaseApp app, - PigeonActionCodeSettings? actionCodeSettings, + InternalActionCodeSettings? actionCodeSettings, ); @async - PigeonUserCredential unlink( + InternalUserCredential unlink( AuthPigeonFirebaseApp app, String providerId, ); @async - PigeonUserDetails updateEmail( + InternalUserDetails updateEmail( AuthPigeonFirebaseApp app, String newEmail, ); @async - PigeonUserDetails updatePassword( + InternalUserDetails updatePassword( AuthPigeonFirebaseApp app, String newPassword, ); @async - PigeonUserDetails updatePhoneNumber( + InternalUserDetails updatePhoneNumber( AuthPigeonFirebaseApp app, - Map input, + Map input, ); @async - PigeonUserDetails updateProfile( + InternalUserDetails updateProfile( AuthPigeonFirebaseApp app, - PigeonUserProfile profile, + InternalUserProfile profile, ); @async void verifyBeforeUpdateEmail( AuthPigeonFirebaseApp app, String newEmail, - PigeonActionCodeSettings? actionCodeSettings, + InternalActionCodeSettings? actionCodeSettings, ); } @@ -557,7 +557,7 @@ abstract class MultiFactorUserHostApi { @async void enrollPhone( AuthPigeonFirebaseApp app, - PigeonPhoneMultiFactorAssertion assertion, + InternalPhoneMultiFactorAssertion assertion, String? displayName, ); @@ -569,7 +569,7 @@ abstract class MultiFactorUserHostApi { ); @async - PigeonMultiFactorSession getSession( + InternalMultiFactorSession getSession( AuthPigeonFirebaseApp app, ); @@ -580,7 +580,7 @@ abstract class MultiFactorUserHostApi { ); @async - List getEnrolledFactors( + List getEnrolledFactors( AuthPigeonFirebaseApp app, ); } @@ -588,15 +588,15 @@ abstract class MultiFactorUserHostApi { @HostApi(dartHostTestHandler: 'TestMultiFactoResolverHostApi') abstract class MultiFactoResolverHostApi { @async - PigeonUserCredential resolveSignIn( + InternalUserCredential resolveSignIn( String resolverId, - PigeonPhoneMultiFactorAssertion? assertion, + InternalPhoneMultiFactorAssertion? assertion, String? totpAssertionId, ); } -class PigeonTotpSecret { - const PigeonTotpSecret({ +class InternalTotpSecret { + const InternalTotpSecret({ required this.codeIntervalSeconds, required this.codeLength, required this.enrollmentCompletionDeadline, @@ -614,7 +614,7 @@ class PigeonTotpSecret { @HostApi(dartHostTestHandler: 'TestMultiFactoResolverHostApi') abstract class MultiFactorTotpHostApi { @async - PigeonTotpSecret generateSecret( + InternalTotpSecret generateSecret( String sessionId, ); @@ -650,5 +650,5 @@ abstract class MultiFactorTotpSecretHostApi { /// Only used to generate the object interface that are use outside of the Pigeon interface @HostApi() abstract class GenerateInterfaces { - void pigeonInterface(PigeonMultiFactorInfo info); + void pigeonInterface(InternalMultiFactorInfo info); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml index 5e6e5a694c1b..41c73626e13c 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml @@ -25,7 +25,7 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.4.0 - pigeon: 19.0.0 + pigeon: 26.3.4 # NOTE: This is a temporary workaround for Flutter 3.13 watcher: ^1.1.0 diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart index 556f6645a33e..9a13f6b58be6 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/id_token_result_test.dart @@ -18,7 +18,7 @@ void main() { 'claim1': 'value1', }; - final kMockData = PigeonIdTokenResult( + final kMockData = InternalIdTokenResult( claims: kMockClaims, issuedAtTimestamp: kMockIssuedAtTimestamp, authTimestamp: kMockAuthTimestamp, @@ -52,7 +52,7 @@ void main() { }); test('returns null when data[claims] is null', () { - final kMockData = PigeonIdTokenResult( + final kMockData = InternalIdTokenResult( issuedAtTimestamp: kMockIssuedAtTimestamp, authTimestamp: kMockAuthTimestamp, expirationTimestamp: kMockExpirationTimestamp, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart index d35bcefe3bba..47fcbbd849d5 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/method_channel_user_credential_test.dart @@ -24,9 +24,9 @@ void main() { group('$MethodChannelUserCredential()', () { late MethodChannelUserCredential userCredential; - PigeonUserCredential userData = PigeonUserCredential( - user: PigeonUserDetails( - userInfo: PigeonUserInfo( + InternalUserCredential userData = InternalUserCredential( + user: InternalUserDetails( + userInfo: InternalUserInfo( uid: kMockUid, email: kMockEmail, isAnonymous: false, @@ -34,13 +34,13 @@ void main() { ), providerData: [], ), - additionalUserInfo: PigeonAdditionalUserInfo( + additionalUserInfo: InternalAdditionalUserInfo( isNewUser: true, profile: {'foo': 'bar'}, providerId: 'info$kMockProviderId', username: 'info$kMockUsername', ), - credential: PigeonAuthCredential( + credential: InternalAuthCredential( providerId: 'auth$kMockProviderId', signInMethod: kMockSignInMethod, nativeId: 0, @@ -55,9 +55,9 @@ void main() { }); setUp(() { - final kMockInitialUserData = PigeonUserCredential( - user: PigeonUserDetails( - userInfo: PigeonUserInfo( + final kMockInitialUserData = InternalUserCredential( + user: InternalUserDetails( + userInfo: InternalUserInfo( uid: kMockUid, email: kMockEmail, isAnonymous: false, @@ -65,13 +65,13 @@ void main() { ), providerData: [], ), - additionalUserInfo: PigeonAdditionalUserInfo( + additionalUserInfo: InternalAdditionalUserInfo( isNewUser: true, profile: {'foo': 'bar'}, providerId: 'info$kMockProviderId', username: 'info$kMockUsername', ), - credential: PigeonAuthCredential( + credential: InternalAuthCredential( providerId: 'auth$kMockProviderId', signInMethod: kMockSignInMethod, nativeId: 0, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart index b252487d4592..5dcc22207592 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/pigeon/test_api.dart @@ -1,9 +1,9 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v19.0.0), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; @@ -13,64 +13,73 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart'; -class _TestFirebaseAuthHostApiCodec extends StandardMessageCodec { - const _TestFirebaseAuthHostApiCodec(); +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is AuthPigeonFirebaseApp) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfo) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is ActionCodeInfoOperation) { buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfoData) { + writeValue(buffer, value.index); + } else if (value is InternalMultiFactorSession) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeSettings) { + } else if (value is InternalPhoneMultiFactorAssertion) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is PigeonAdditionalUserInfo) { + } else if (value is InternalMultiFactorInfo) { buffer.putUint8(132); writeValue(buffer, value.encode()); - } else if (value is PigeonAuthCredential) { + } else if (value is AuthPigeonFirebaseApp) { buffer.putUint8(133); writeValue(buffer, value.encode()); - } else if (value is PigeonFirebaseAuthSettings) { + } else if (value is InternalActionCodeInfoData) { buffer.putUint8(134); writeValue(buffer, value.encode()); - } else if (value is PigeonIdTokenResult) { + } else if (value is InternalActionCodeInfo) { buffer.putUint8(135); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorInfo) { + } else if (value is InternalAdditionalUserInfo) { buffer.putUint8(136); writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { + } else if (value is InternalAuthCredential) { buffer.putUint8(137); writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { + } else if (value is InternalUserInfo) { buffer.putUint8(138); writeValue(buffer, value.encode()); - } else if (value is PigeonSignInProvider) { + } else if (value is InternalUserDetails) { buffer.putUint8(139); writeValue(buffer, value.encode()); - } else if (value is PigeonTotpSecret) { + } else if (value is InternalUserCredential) { buffer.putUint8(140); writeValue(buffer, value.encode()); - } else if (value is PigeonUserCredential) { + } else if (value is InternalAuthCredentialInput) { buffer.putUint8(141); writeValue(buffer, value.encode()); - } else if (value is PigeonUserDetails) { + } else if (value is InternalActionCodeSettings) { buffer.putUint8(142); writeValue(buffer, value.encode()); - } else if (value is PigeonUserInfo) { + } else if (value is InternalFirebaseAuthSettings) { buffer.putUint8(143); writeValue(buffer, value.encode()); - } else if (value is PigeonUserProfile) { + } else if (value is InternalSignInProvider) { buffer.putUint8(144); writeValue(buffer, value.encode()); - } else if (value is PigeonVerifyPhoneNumberRequest) { + } else if (value is InternalVerifyPhoneNumberRequest) { buffer.putUint8(145); writeValue(buffer, value.encode()); + } else if (value is InternalIdTokenResult) { + buffer.putUint8(146); + writeValue(buffer, value.encode()); + } else if (value is InternalUserProfile) { + buffer.putUint8(147); + writeValue(buffer, value.encode()); + } else if (value is InternalTotpSecret) { + buffer.putUint8(148); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -79,42 +88,47 @@ class _TestFirebaseAuthHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: - return AuthPigeonFirebaseApp.decode(readValue(buffer)!); case 129: - return PigeonActionCodeInfo.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : ActionCodeInfoOperation.values[value]; case 130: - return PigeonActionCodeInfoData.decode(readValue(buffer)!); + return InternalMultiFactorSession.decode(readValue(buffer)!); case 131: - return PigeonActionCodeSettings.decode(readValue(buffer)!); + return InternalPhoneMultiFactorAssertion.decode(readValue(buffer)!); case 132: - return PigeonAdditionalUserInfo.decode(readValue(buffer)!); + return InternalMultiFactorInfo.decode(readValue(buffer)!); case 133: - return PigeonAuthCredential.decode(readValue(buffer)!); + return AuthPigeonFirebaseApp.decode(readValue(buffer)!); case 134: - return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); + return InternalActionCodeInfoData.decode(readValue(buffer)!); case 135: - return PigeonIdTokenResult.decode(readValue(buffer)!); + return InternalActionCodeInfo.decode(readValue(buffer)!); case 136: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); + return InternalAdditionalUserInfo.decode(readValue(buffer)!); case 137: - return PigeonMultiFactorSession.decode(readValue(buffer)!); + return InternalAuthCredential.decode(readValue(buffer)!); case 138: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); + return InternalUserInfo.decode(readValue(buffer)!); case 139: - return PigeonSignInProvider.decode(readValue(buffer)!); + return InternalUserDetails.decode(readValue(buffer)!); case 140: - return PigeonTotpSecret.decode(readValue(buffer)!); + return InternalUserCredential.decode(readValue(buffer)!); case 141: - return PigeonUserCredential.decode(readValue(buffer)!); + return InternalAuthCredentialInput.decode(readValue(buffer)!); case 142: - return PigeonUserDetails.decode(readValue(buffer)!); + return InternalActionCodeSettings.decode(readValue(buffer)!); case 143: - return PigeonUserInfo.decode(readValue(buffer)!); + return InternalFirebaseAuthSettings.decode(readValue(buffer)!); case 144: - return PigeonUserProfile.decode(readValue(buffer)!); + return InternalSignInProvider.decode(readValue(buffer)!); case 145: - return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); + return InternalVerifyPhoneNumberRequest.decode(readValue(buffer)!); + case 146: + return InternalIdTokenResult.decode(readValue(buffer)!); + case 147: + return InternalUserProfile.decode(readValue(buffer)!); + case 148: + return InternalTotpSecret.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -124,8 +138,7 @@ class _TestFirebaseAuthHostApiCodec extends StandardMessageCodec { abstract class TestFirebaseAuthHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec pigeonChannelCodec = - _TestFirebaseAuthHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); Future registerIdTokenListener(AuthPigeonFirebaseApp app); @@ -135,54 +148,54 @@ abstract class TestFirebaseAuthHostApi { Future applyActionCode(AuthPigeonFirebaseApp app, String code); - Future checkActionCode( + Future checkActionCode( AuthPigeonFirebaseApp app, String code); Future confirmPasswordReset( AuthPigeonFirebaseApp app, String code, String newPassword); - Future createUserWithEmailAndPassword( + Future createUserWithEmailAndPassword( AuthPigeonFirebaseApp app, String email, String password); - Future signInAnonymously(AuthPigeonFirebaseApp app); + Future signInAnonymously(AuthPigeonFirebaseApp app); - Future signInWithCredential( + Future signInWithCredential( AuthPigeonFirebaseApp app, Map input); - Future signInWithCustomToken( + Future signInWithCustomToken( AuthPigeonFirebaseApp app, String token); - Future signInWithEmailAndPassword( + Future signInWithEmailAndPassword( AuthPigeonFirebaseApp app, String email, String password); - Future signInWithEmailLink( + Future signInWithEmailLink( AuthPigeonFirebaseApp app, String email, String emailLink); - Future signInWithProvider( - AuthPigeonFirebaseApp app, PigeonSignInProvider signInProvider); + Future signInWithProvider( + AuthPigeonFirebaseApp app, InternalSignInProvider signInProvider); Future signOut(AuthPigeonFirebaseApp app); - Future> fetchSignInMethodsForEmail( + Future> fetchSignInMethodsForEmail( AuthPigeonFirebaseApp app, String email); Future sendPasswordResetEmail(AuthPigeonFirebaseApp app, String email, - PigeonActionCodeSettings? actionCodeSettings); + InternalActionCodeSettings? actionCodeSettings); Future sendSignInLinkToEmail(AuthPigeonFirebaseApp app, String email, - PigeonActionCodeSettings actionCodeSettings); + InternalActionCodeSettings actionCodeSettings); Future setLanguageCode( AuthPigeonFirebaseApp app, String? languageCode); Future setSettings( - AuthPigeonFirebaseApp app, PigeonFirebaseAuthSettings settings); + AuthPigeonFirebaseApp app, InternalFirebaseAuthSettings settings); Future verifyPasswordResetCode( AuthPigeonFirebaseApp app, String code); Future verifyPhoneNumber( - AuthPigeonFirebaseApp app, PigeonVerifyPhoneNumberRequest request); + AuthPigeonFirebaseApp app, InternalVerifyPhoneNumberRequest request); Future revokeTokenWithAuthorizationCode( AuthPigeonFirebaseApp app, String authorizationCode); @@ -199,27 +212,22 @@ abstract class TestFirebaseAuthHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerIdTokenListener$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerIdTokenListener was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerIdTokenListener was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - final String output = await api.registerIdTokenListener(arg_app!); + final String output = await api.registerIdTokenListener(arg_app); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -231,27 +239,22 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerAuthStateListener$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerAuthStateListener was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.registerAuthStateListener was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - final String output = await api.registerAuthStateListener(arg_app!); + final String output = await api.registerAuthStateListener(arg_app); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -263,33 +266,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.useEmulator$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.useEmulator was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.useEmulator was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_host = (args[1] as String?); - assert(arg_host != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.useEmulator was null, expected non-null String.'); - final int? arg_port = (args[2] as int?); - assert(arg_port != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.useEmulator was null, expected non-null int.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_host = args[1]! as String; + final int arg_port = args[2]! as int; try { - await api.useEmulator(arg_app!, arg_host!, arg_port!); + await api.useEmulator(arg_app, arg_host, arg_port); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -301,30 +295,23 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.applyActionCode$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.applyActionCode was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.applyActionCode was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_code = (args[1] as String?); - assert(arg_code != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.applyActionCode was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_code = args[1]! as String; try { - await api.applyActionCode(arg_app!, arg_code!); + await api.applyActionCode(arg_app, arg_code); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -336,31 +323,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.checkActionCode$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.checkActionCode was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.checkActionCode was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_code = (args[1] as String?); - assert(arg_code != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.checkActionCode was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_code = args[1]! as String; try { - final PigeonActionCodeInfo output = - await api.checkActionCode(arg_app!, arg_code!); + final InternalActionCodeInfo output = + await api.checkActionCode(arg_app, arg_code); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -372,34 +352,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.confirmPasswordReset$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.confirmPasswordReset was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.confirmPasswordReset was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_code = (args[1] as String?); - assert(arg_code != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.confirmPasswordReset was null, expected non-null String.'); - final String? arg_newPassword = (args[2] as String?); - assert(arg_newPassword != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.confirmPasswordReset was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_code = args[1]! as String; + final String arg_newPassword = args[2]! as String; try { - await api.confirmPasswordReset( - arg_app!, arg_code!, arg_newPassword!); + await api.confirmPasswordReset(arg_app, arg_code, arg_newPassword); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -411,35 +381,26 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.createUserWithEmailAndPassword$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.createUserWithEmailAndPassword was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.createUserWithEmailAndPassword was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_email = (args[1] as String?); - assert(arg_email != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.createUserWithEmailAndPassword was null, expected non-null String.'); - final String? arg_password = (args[2] as String?); - assert(arg_password != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.createUserWithEmailAndPassword was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_email = args[1]! as String; + final String arg_password = args[2]! as String; try { - final PigeonUserCredential output = + final InternalUserCredential output = await api.createUserWithEmailAndPassword( - arg_app!, arg_email!, arg_password!); + arg_app, arg_email, arg_password); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -451,28 +412,23 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInAnonymously$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInAnonymously was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInAnonymously was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - final PigeonUserCredential output = - await api.signInAnonymously(arg_app!); + final InternalUserCredential output = + await api.signInAnonymously(arg_app); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -484,32 +440,25 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCredential$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCredential was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCredential was null, expected non-null AuthPigeonFirebaseApp.'); - final Map? arg_input = - (args[1] as Map?)?.cast(); - assert(arg_input != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCredential was null, expected non-null Map.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final Map arg_input = + (args[1]! as Map).cast(); try { - final PigeonUserCredential output = - await api.signInWithCredential(arg_app!, arg_input!); + final InternalUserCredential output = + await api.signInWithCredential(arg_app, arg_input); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -521,31 +470,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCustomToken$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCustomToken was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCustomToken was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_token = (args[1] as String?); - assert(arg_token != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithCustomToken was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_token = args[1]! as String; try { - final PigeonUserCredential output = - await api.signInWithCustomToken(arg_app!, arg_token!); + final InternalUserCredential output = + await api.signInWithCustomToken(arg_app, arg_token); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -557,35 +499,25 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailAndPassword$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailAndPassword was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailAndPassword was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_email = (args[1] as String?); - assert(arg_email != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailAndPassword was null, expected non-null String.'); - final String? arg_password = (args[2] as String?); - assert(arg_password != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailAndPassword was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_email = args[1]! as String; + final String arg_password = args[2]! as String; try { - final PigeonUserCredential output = - await api.signInWithEmailAndPassword( - arg_app!, arg_email!, arg_password!); + final InternalUserCredential output = await api + .signInWithEmailAndPassword(arg_app, arg_email, arg_password); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -597,34 +529,25 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailLink$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailLink was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailLink was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_email = (args[1] as String?); - assert(arg_email != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailLink was null, expected non-null String.'); - final String? arg_emailLink = (args[2] as String?); - assert(arg_emailLink != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithEmailLink was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_email = args[1]! as String; + final String arg_emailLink = args[2]! as String; try { - final PigeonUserCredential output = await api.signInWithEmailLink( - arg_app!, arg_email!, arg_emailLink!); + final InternalUserCredential output = await api.signInWithEmailLink( + arg_app, arg_email, arg_emailLink); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -636,32 +559,25 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithProvider$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithProvider was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithProvider was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonSignInProvider? arg_signInProvider = - (args[1] as PigeonSignInProvider?); - assert(arg_signInProvider != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signInWithProvider was null, expected non-null PigeonSignInProvider.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalSignInProvider arg_signInProvider = + args[1]! as InternalSignInProvider; try { - final PigeonUserCredential output = - await api.signInWithProvider(arg_app!, arg_signInProvider!); + final InternalUserCredential output = + await api.signInWithProvider(arg_app, arg_signInProvider); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -673,27 +589,22 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signOut$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signOut was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.signOut was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - await api.signOut(arg_app!); + await api.signOut(arg_app); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -705,31 +616,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.fetchSignInMethodsForEmail$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.fetchSignInMethodsForEmail was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.fetchSignInMethodsForEmail was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_email = (args[1] as String?); - assert(arg_email != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.fetchSignInMethodsForEmail was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_email = args[1]! as String; try { - final List output = - await api.fetchSignInMethodsForEmail(arg_app!, arg_email!); + final List output = + await api.fetchSignInMethodsForEmail(arg_app, arg_email); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -741,33 +645,26 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendPasswordResetEmail$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendPasswordResetEmail was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendPasswordResetEmail was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_email = (args[1] as String?); - assert(arg_email != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendPasswordResetEmail was null, expected non-null String.'); - final PigeonActionCodeSettings? arg_actionCodeSettings = - (args[2] as PigeonActionCodeSettings?); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_email = args[1]! as String; + final InternalActionCodeSettings? arg_actionCodeSettings = + args[2] as InternalActionCodeSettings?; try { await api.sendPasswordResetEmail( - arg_app!, arg_email!, arg_actionCodeSettings); + arg_app, arg_email, arg_actionCodeSettings); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -779,35 +676,26 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendSignInLinkToEmail$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendSignInLinkToEmail was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendSignInLinkToEmail was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_email = (args[1] as String?); - assert(arg_email != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendSignInLinkToEmail was null, expected non-null String.'); - final PigeonActionCodeSettings? arg_actionCodeSettings = - (args[2] as PigeonActionCodeSettings?); - assert(arg_actionCodeSettings != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.sendSignInLinkToEmail was null, expected non-null PigeonActionCodeSettings.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_email = args[1]! as String; + final InternalActionCodeSettings arg_actionCodeSettings = + args[2]! as InternalActionCodeSettings; try { await api.sendSignInLinkToEmail( - arg_app!, arg_email!, arg_actionCodeSettings!); + arg_app, arg_email, arg_actionCodeSettings); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -819,29 +707,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setLanguageCode$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setLanguageCode was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setLanguageCode was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_languageCode = (args[1] as String?); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String? arg_languageCode = args[1] as String?; try { final String output = - await api.setLanguageCode(arg_app!, arg_languageCode); + await api.setLanguageCode(arg_app, arg_languageCode); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -853,31 +736,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setSettings$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setSettings was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setSettings was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonFirebaseAuthSettings? arg_settings = - (args[1] as PigeonFirebaseAuthSettings?); - assert(arg_settings != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.setSettings was null, expected non-null PigeonFirebaseAuthSettings.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalFirebaseAuthSettings arg_settings = + args[1]! as InternalFirebaseAuthSettings; try { - await api.setSettings(arg_app!, arg_settings!); + await api.setSettings(arg_app, arg_settings); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -889,31 +765,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPasswordResetCode$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPasswordResetCode was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPasswordResetCode was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_code = (args[1] as String?); - assert(arg_code != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPasswordResetCode was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_code = args[1]! as String; try { final String output = - await api.verifyPasswordResetCode(arg_app!, arg_code!); + await api.verifyPasswordResetCode(arg_app, arg_code); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -925,32 +794,25 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPhoneNumber$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPhoneNumber was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPhoneNumber was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonVerifyPhoneNumberRequest? arg_request = - (args[1] as PigeonVerifyPhoneNumberRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.verifyPhoneNumber was null, expected non-null PigeonVerifyPhoneNumberRequest.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalVerifyPhoneNumberRequest arg_request = + args[1]! as InternalVerifyPhoneNumberRequest; try { final String output = - await api.verifyPhoneNumber(arg_app!, arg_request!); + await api.verifyPhoneNumber(arg_app, arg_request); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -962,31 +824,24 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeTokenWithAuthorizationCode$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeTokenWithAuthorizationCode was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeTokenWithAuthorizationCode was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_authorizationCode = (args[1] as String?); - assert(arg_authorizationCode != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeTokenWithAuthorizationCode was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_authorizationCode = args[1]! as String; try { await api.revokeTokenWithAuthorizationCode( - arg_app!, arg_authorizationCode!); + arg_app, arg_authorizationCode); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -998,30 +853,23 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_accessToken = (args[1] as String?); - assert(arg_accessToken != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.revokeAccessToken was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_accessToken = args[1]! as String; try { - await api.revokeAccessToken(arg_app!, arg_accessToken!); + await api.revokeAccessToken(arg_app, arg_accessToken); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1033,27 +881,22 @@ abstract class TestFirebaseAuthHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.initializeRecaptchaConfig$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.initializeRecaptchaConfig was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthHostApi.initializeRecaptchaConfig was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - await api.initializeRecaptchaConfig(arg_app!); + await api.initializeRecaptchaConfig(arg_app); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1067,159 +910,50 @@ abstract class TestFirebaseAuthHostApi { } } -class _TestFirebaseAuthUserHostApiCodec extends StandardMessageCodec { - const _TestFirebaseAuthUserHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is AuthPigeonFirebaseApp) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfo) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeInfoData) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is PigeonActionCodeSettings) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else if (value is PigeonAdditionalUserInfo) { - buffer.putUint8(132); - writeValue(buffer, value.encode()); - } else if (value is PigeonAuthCredential) { - buffer.putUint8(133); - writeValue(buffer, value.encode()); - } else if (value is PigeonFirebaseAuthSettings) { - buffer.putUint8(134); - writeValue(buffer, value.encode()); - } else if (value is PigeonIdTokenResult) { - buffer.putUint8(135); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorInfo) { - buffer.putUint8(136); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { - buffer.putUint8(137); - writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { - buffer.putUint8(138); - writeValue(buffer, value.encode()); - } else if (value is PigeonSignInProvider) { - buffer.putUint8(139); - writeValue(buffer, value.encode()); - } else if (value is PigeonTotpSecret) { - buffer.putUint8(140); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserCredential) { - buffer.putUint8(141); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserDetails) { - buffer.putUint8(142); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserInfo) { - buffer.putUint8(143); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserProfile) { - buffer.putUint8(144); - writeValue(buffer, value.encode()); - } else if (value is PigeonVerifyPhoneNumberRequest) { - buffer.putUint8(145); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return AuthPigeonFirebaseApp.decode(readValue(buffer)!); - case 129: - return PigeonActionCodeInfo.decode(readValue(buffer)!); - case 130: - return PigeonActionCodeInfoData.decode(readValue(buffer)!); - case 131: - return PigeonActionCodeSettings.decode(readValue(buffer)!); - case 132: - return PigeonAdditionalUserInfo.decode(readValue(buffer)!); - case 133: - return PigeonAuthCredential.decode(readValue(buffer)!); - case 134: - return PigeonFirebaseAuthSettings.decode(readValue(buffer)!); - case 135: - return PigeonIdTokenResult.decode(readValue(buffer)!); - case 136: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - case 137: - return PigeonMultiFactorSession.decode(readValue(buffer)!); - case 138: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - case 139: - return PigeonSignInProvider.decode(readValue(buffer)!); - case 140: - return PigeonTotpSecret.decode(readValue(buffer)!); - case 141: - return PigeonUserCredential.decode(readValue(buffer)!); - case 142: - return PigeonUserDetails.decode(readValue(buffer)!); - case 143: - return PigeonUserInfo.decode(readValue(buffer)!); - case 144: - return PigeonUserProfile.decode(readValue(buffer)!); - case 145: - return PigeonVerifyPhoneNumberRequest.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - abstract class TestFirebaseAuthUserHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec pigeonChannelCodec = - _TestFirebaseAuthUserHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); Future delete(AuthPigeonFirebaseApp app); - Future getIdToken( + Future getIdToken( AuthPigeonFirebaseApp app, bool forceRefresh); - Future linkWithCredential( + Future linkWithCredential( AuthPigeonFirebaseApp app, Map input); - Future linkWithProvider( - AuthPigeonFirebaseApp app, PigeonSignInProvider signInProvider); + Future linkWithProvider( + AuthPigeonFirebaseApp app, InternalSignInProvider signInProvider); - Future reauthenticateWithCredential( + Future reauthenticateWithCredential( AuthPigeonFirebaseApp app, Map input); - Future reauthenticateWithProvider( - AuthPigeonFirebaseApp app, PigeonSignInProvider signInProvider); + Future reauthenticateWithProvider( + AuthPigeonFirebaseApp app, InternalSignInProvider signInProvider); - Future reload(AuthPigeonFirebaseApp app); + Future reload(AuthPigeonFirebaseApp app); - Future sendEmailVerification( - AuthPigeonFirebaseApp app, PigeonActionCodeSettings? actionCodeSettings); + Future sendEmailVerification(AuthPigeonFirebaseApp app, + InternalActionCodeSettings? actionCodeSettings); - Future unlink( + Future unlink( AuthPigeonFirebaseApp app, String providerId); - Future updateEmail( + Future updateEmail( AuthPigeonFirebaseApp app, String newEmail); - Future updatePassword( + Future updatePassword( AuthPigeonFirebaseApp app, String newPassword); - Future updatePhoneNumber( + Future updatePhoneNumber( AuthPigeonFirebaseApp app, Map input); - Future updateProfile( - AuthPigeonFirebaseApp app, PigeonUserProfile profile); + Future updateProfile( + AuthPigeonFirebaseApp app, InternalUserProfile profile); Future verifyBeforeUpdateEmail(AuthPigeonFirebaseApp app, - String newEmail, PigeonActionCodeSettings? actionCodeSettings); + String newEmail, InternalActionCodeSettings? actionCodeSettings); static void setUp( TestFirebaseAuthUserHostApi? api, { @@ -1229,27 +963,22 @@ abstract class TestFirebaseAuthUserHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.delete$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.delete was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.delete was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - await api.delete(arg_app!); + await api.delete(arg_app); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1261,31 +990,24 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.getIdToken$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.getIdToken was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.getIdToken was null, expected non-null AuthPigeonFirebaseApp.'); - final bool? arg_forceRefresh = (args[1] as bool?); - assert(arg_forceRefresh != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.getIdToken was null, expected non-null bool.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final bool arg_forceRefresh = args[1]! as bool; try { - final PigeonIdTokenResult output = - await api.getIdToken(arg_app!, arg_forceRefresh!); + final InternalIdTokenResult output = + await api.getIdToken(arg_app, arg_forceRefresh); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1297,32 +1019,25 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithCredential$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithCredential was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithCredential was null, expected non-null AuthPigeonFirebaseApp.'); - final Map? arg_input = - (args[1] as Map?)?.cast(); - assert(arg_input != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithCredential was null, expected non-null Map.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final Map arg_input = + (args[1]! as Map).cast(); try { - final PigeonUserCredential output = - await api.linkWithCredential(arg_app!, arg_input!); + final InternalUserCredential output = + await api.linkWithCredential(arg_app, arg_input); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1334,32 +1049,25 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithProvider$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithProvider was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithProvider was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonSignInProvider? arg_signInProvider = - (args[1] as PigeonSignInProvider?); - assert(arg_signInProvider != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.linkWithProvider was null, expected non-null PigeonSignInProvider.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalSignInProvider arg_signInProvider = + args[1]! as InternalSignInProvider; try { - final PigeonUserCredential output = - await api.linkWithProvider(arg_app!, arg_signInProvider!); + final InternalUserCredential output = + await api.linkWithProvider(arg_app, arg_signInProvider); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1371,32 +1079,25 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithCredential$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithCredential was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithCredential was null, expected non-null AuthPigeonFirebaseApp.'); - final Map? arg_input = - (args[1] as Map?)?.cast(); - assert(arg_input != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithCredential was null, expected non-null Map.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final Map arg_input = + (args[1]! as Map).cast(); try { - final PigeonUserCredential output = - await api.reauthenticateWithCredential(arg_app!, arg_input!); + final InternalUserCredential output = + await api.reauthenticateWithCredential(arg_app, arg_input); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1408,32 +1109,25 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithProvider$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithProvider was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithProvider was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonSignInProvider? arg_signInProvider = - (args[1] as PigeonSignInProvider?); - assert(arg_signInProvider != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reauthenticateWithProvider was null, expected non-null PigeonSignInProvider.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalSignInProvider arg_signInProvider = + args[1]! as InternalSignInProvider; try { - final PigeonUserCredential output = await api - .reauthenticateWithProvider(arg_app!, arg_signInProvider!); + final InternalUserCredential output = await api + .reauthenticateWithProvider(arg_app, arg_signInProvider); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1445,27 +1139,22 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reload$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reload was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.reload was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - final PigeonUserDetails output = await api.reload(arg_app!); + final InternalUserDetails output = await api.reload(arg_app); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1477,29 +1166,24 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.sendEmailVerification$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.sendEmailVerification was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.sendEmailVerification was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonActionCodeSettings? arg_actionCodeSettings = - (args[1] as PigeonActionCodeSettings?); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalActionCodeSettings? arg_actionCodeSettings = + args[1] as InternalActionCodeSettings?; try { - await api.sendEmailVerification(arg_app!, arg_actionCodeSettings); + await api.sendEmailVerification(arg_app, arg_actionCodeSettings); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1511,31 +1195,24 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.unlink$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.unlink was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.unlink was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_providerId = (args[1] as String?); - assert(arg_providerId != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.unlink was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_providerId = args[1]! as String; try { - final PigeonUserCredential output = - await api.unlink(arg_app!, arg_providerId!); + final InternalUserCredential output = + await api.unlink(arg_app, arg_providerId); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1547,31 +1224,24 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateEmail$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateEmail was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateEmail was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_newEmail = (args[1] as String?); - assert(arg_newEmail != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateEmail was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_newEmail = args[1]! as String; try { - final PigeonUserDetails output = - await api.updateEmail(arg_app!, arg_newEmail!); + final InternalUserDetails output = + await api.updateEmail(arg_app, arg_newEmail); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1583,31 +1253,24 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePassword$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePassword was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePassword was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_newPassword = (args[1] as String?); - assert(arg_newPassword != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePassword was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_newPassword = args[1]! as String; try { - final PigeonUserDetails output = - await api.updatePassword(arg_app!, arg_newPassword!); + final InternalUserDetails output = + await api.updatePassword(arg_app, arg_newPassword); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1619,32 +1282,25 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePhoneNumber$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePhoneNumber was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePhoneNumber was null, expected non-null AuthPigeonFirebaseApp.'); - final Map? arg_input = - (args[1] as Map?)?.cast(); - assert(arg_input != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updatePhoneNumber was null, expected non-null Map.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final Map arg_input = + (args[1]! as Map).cast(); try { - final PigeonUserDetails output = - await api.updatePhoneNumber(arg_app!, arg_input!); + final InternalUserDetails output = + await api.updatePhoneNumber(arg_app, arg_input); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1656,32 +1312,25 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateProfile$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateProfile was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateProfile was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonUserProfile? arg_profile = - (args[1] as PigeonUserProfile?); - assert(arg_profile != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.updateProfile was null, expected non-null PigeonUserProfile.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalUserProfile arg_profile = + args[1]! as InternalUserProfile; try { - final PigeonUserDetails output = - await api.updateProfile(arg_app!, arg_profile!); + final InternalUserDetails output = + await api.updateProfile(arg_app, arg_profile); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1693,33 +1342,26 @@ abstract class TestFirebaseAuthUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_newEmail = (args[1] as String?); - assert(arg_newEmail != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.FirebaseAuthUserHostApi.verifyBeforeUpdateEmail was null, expected non-null String.'); - final PigeonActionCodeSettings? arg_actionCodeSettings = - (args[2] as PigeonActionCodeSettings?); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_newEmail = args[1]! as String; + final InternalActionCodeSettings? arg_actionCodeSettings = + args[2] as InternalActionCodeSettings?; try { await api.verifyBeforeUpdateEmail( - arg_app!, arg_newEmail!, arg_actionCodeSettings); + arg_app, arg_newEmail, arg_actionCodeSettings); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1733,61 +1375,22 @@ abstract class TestFirebaseAuthUserHostApi { } } -class _TestMultiFactorUserHostApiCodec extends StandardMessageCodec { - const _TestMultiFactorUserHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is AuthPigeonFirebaseApp) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorInfo) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonMultiFactorSession) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return AuthPigeonFirebaseApp.decode(readValue(buffer)!); - case 129: - return PigeonMultiFactorInfo.decode(readValue(buffer)!); - case 130: - return PigeonMultiFactorSession.decode(readValue(buffer)!); - case 131: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - abstract class TestMultiFactorUserHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec pigeonChannelCodec = - _TestMultiFactorUserHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); Future enrollPhone(AuthPigeonFirebaseApp app, - PigeonPhoneMultiFactorAssertion assertion, String? displayName); + InternalPhoneMultiFactorAssertion assertion, String? displayName); Future enrollTotp( AuthPigeonFirebaseApp app, String assertionId, String? displayName); - Future getSession(AuthPigeonFirebaseApp app); + Future getSession(AuthPigeonFirebaseApp app); Future unenroll(AuthPigeonFirebaseApp app, String factorUid); - Future> getEnrolledFactors( + Future> getEnrolledFactors( AuthPigeonFirebaseApp app); static void setUp( @@ -1798,32 +1401,25 @@ abstract class TestMultiFactorUserHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollPhone$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollPhone was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollPhone was null, expected non-null AuthPigeonFirebaseApp.'); - final PigeonPhoneMultiFactorAssertion? arg_assertion = - (args[1] as PigeonPhoneMultiFactorAssertion?); - assert(arg_assertion != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollPhone was null, expected non-null PigeonPhoneMultiFactorAssertion.'); - final String? arg_displayName = (args[2] as String?); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final InternalPhoneMultiFactorAssertion arg_assertion = + args[1]! as InternalPhoneMultiFactorAssertion; + final String? arg_displayName = args[2] as String?; try { - await api.enrollPhone(arg_app!, arg_assertion!, arg_displayName); + await api.enrollPhone(arg_app, arg_assertion, arg_displayName); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1835,31 +1431,24 @@ abstract class TestMultiFactorUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollTotp$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollTotp was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollTotp was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_assertionId = (args[1] as String?); - assert(arg_assertionId != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.enrollTotp was null, expected non-null String.'); - final String? arg_displayName = (args[2] as String?); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_assertionId = args[1]! as String; + final String? arg_displayName = args[2] as String?; try { - await api.enrollTotp(arg_app!, arg_assertionId!, arg_displayName); + await api.enrollTotp(arg_app, arg_assertionId, arg_displayName); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1871,28 +1460,23 @@ abstract class TestMultiFactorUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getSession$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getSession was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getSession was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - final PigeonMultiFactorSession output = - await api.getSession(arg_app!); + final InternalMultiFactorSession output = + await api.getSession(arg_app); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1904,30 +1488,23 @@ abstract class TestMultiFactorUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.unenroll$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.unenroll was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.unenroll was null, expected non-null AuthPigeonFirebaseApp.'); - final String? arg_factorUid = (args[1] as String?); - assert(arg_factorUid != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.unenroll was null, expected non-null String.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; + final String arg_factorUid = args[1]! as String; try { - await api.unenroll(arg_app!, arg_factorUid!); + await api.unenroll(arg_app, arg_factorUid); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1939,28 +1516,23 @@ abstract class TestMultiFactorUserHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getEnrolledFactors$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getEnrolledFactors was null.'); - final List args = (message as List?)!; - final AuthPigeonFirebaseApp? arg_app = - (args[0] as AuthPigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorUserHostApi.getEnrolledFactors was null, expected non-null AuthPigeonFirebaseApp.'); + final List args = message! as List; + final AuthPigeonFirebaseApp arg_app = + args[0]! as AuthPigeonFirebaseApp; try { - final List output = - await api.getEnrolledFactors(arg_app!); + final List output = + await api.getEnrolledFactors(arg_app); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1974,62 +1546,13 @@ abstract class TestMultiFactorUserHostApi { } } -class _TestMultiFactoResolverHostApiCodec extends StandardMessageCodec { - const _TestMultiFactoResolverHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonAdditionalUserInfo) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonAuthCredential) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonPhoneMultiFactorAssertion) { - buffer.putUint8(130); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserCredential) { - buffer.putUint8(131); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserDetails) { - buffer.putUint8(132); - writeValue(buffer, value.encode()); - } else if (value is PigeonUserInfo) { - buffer.putUint8(133); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return PigeonAdditionalUserInfo.decode(readValue(buffer)!); - case 129: - return PigeonAuthCredential.decode(readValue(buffer)!); - case 130: - return PigeonPhoneMultiFactorAssertion.decode(readValue(buffer)!); - case 131: - return PigeonUserCredential.decode(readValue(buffer)!); - case 132: - return PigeonUserDetails.decode(readValue(buffer)!); - case 133: - return PigeonUserInfo.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - abstract class TestMultiFactoResolverHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec pigeonChannelCodec = - _TestMultiFactoResolverHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - Future resolveSignIn(String resolverId, - PigeonPhoneMultiFactorAssertion? assertion, String? totpAssertionId); + Future resolveSignIn(String resolverId, + InternalPhoneMultiFactorAssertion? assertion, String? totpAssertionId); static void setUp( TestMultiFactoResolverHostApi? api, { @@ -2039,30 +1562,25 @@ abstract class TestMultiFactoResolverHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactoResolverHostApi.resolveSignIn$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactoResolverHostApi.resolveSignIn was null.'); - final List args = (message as List?)!; - final String? arg_resolverId = (args[0] as String?); - assert(arg_resolverId != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactoResolverHostApi.resolveSignIn was null, expected non-null String.'); - final PigeonPhoneMultiFactorAssertion? arg_assertion = - (args[1] as PigeonPhoneMultiFactorAssertion?); - final String? arg_totpAssertionId = (args[2] as String?); + final List args = message! as List; + final String arg_resolverId = args[0]! as String; + final InternalPhoneMultiFactorAssertion? arg_assertion = + args[1] as InternalPhoneMultiFactorAssertion?; + final String? arg_totpAssertionId = args[2] as String?; try { - final PigeonUserCredential output = await api.resolveSignIn( - arg_resolverId!, arg_assertion, arg_totpAssertionId); + final InternalUserCredential output = await api.resolveSignIn( + arg_resolverId, arg_assertion, arg_totpAssertionId); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -2076,36 +1594,12 @@ abstract class TestMultiFactoResolverHostApi { } } -class _TestMultiFactoResolverHostApiCodec extends StandardMessageCodec { - const _TestMultiFactoResolverHostApiCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonTotpSecret) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return PigeonTotpSecret.decode(readValue(buffer)!); - default: - return super.readValueOfType(type, buffer); - } - } -} - abstract class TestMultiFactoResolverHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec pigeonChannelCodec = - _TestMultiFactoResolverHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - Future generateSecret(String sessionId); + Future generateSecret(String sessionId); Future getAssertionForEnrollment( String secretKey, String oneTimePassword); @@ -2121,27 +1615,22 @@ abstract class TestMultiFactoResolverHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.generateSecret$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.generateSecret was null.'); - final List args = (message as List?)!; - final String? arg_sessionId = (args[0] as String?); - assert(arg_sessionId != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.generateSecret was null, expected non-null String.'); + final List args = message! as List; + final String arg_sessionId = args[0]! as String; try { - final PigeonTotpSecret output = - await api.generateSecret(arg_sessionId!); + final InternalTotpSecret output = + await api.generateSecret(arg_sessionId); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -2153,30 +1642,23 @@ abstract class TestMultiFactoResolverHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForEnrollment$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForEnrollment was null.'); - final List args = (message as List?)!; - final String? arg_secretKey = (args[0] as String?); - assert(arg_secretKey != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForEnrollment was null, expected non-null String.'); - final String? arg_oneTimePassword = (args[1] as String?); - assert(arg_oneTimePassword != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForEnrollment was null, expected non-null String.'); + final List args = message! as List; + final String arg_secretKey = args[0]! as String; + final String arg_oneTimePassword = args[1]! as String; try { final String output = await api.getAssertionForEnrollment( - arg_secretKey!, arg_oneTimePassword!); + arg_secretKey, arg_oneTimePassword); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -2188,30 +1670,23 @@ abstract class TestMultiFactoResolverHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForSignIn$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForSignIn was null.'); - final List args = (message as List?)!; - final String? arg_enrollmentId = (args[0] as String?); - assert(arg_enrollmentId != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForSignIn was null, expected non-null String.'); - final String? arg_oneTimePassword = (args[1] as String?); - assert(arg_oneTimePassword != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpHostApi.getAssertionForSignIn was null, expected non-null String.'); + final List args = message! as List; + final String arg_enrollmentId = args[0]! as String; + final String arg_oneTimePassword = args[1]! as String; try { final String output = await api.getAssertionForSignIn( - arg_enrollmentId!, arg_oneTimePassword!); + arg_enrollmentId, arg_oneTimePassword); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -2228,8 +1703,7 @@ abstract class TestMultiFactoResolverHostApi { abstract class TestMultiFactoResolverHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec pigeonChannelCodec = - StandardMessageCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); Future generateQrCodeUrl( String secretKey, String? accountName, String? issuer); @@ -2244,29 +1718,24 @@ abstract class TestMultiFactoResolverHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.generateQrCodeUrl$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.generateQrCodeUrl was null.'); - final List args = (message as List?)!; - final String? arg_secretKey = (args[0] as String?); - assert(arg_secretKey != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.generateQrCodeUrl was null, expected non-null String.'); - final String? arg_accountName = (args[1] as String?); - final String? arg_issuer = (args[2] as String?); + final List args = message! as List; + final String arg_secretKey = args[0]! as String; + final String? arg_accountName = args[1] as String?; + final String? arg_issuer = args[2] as String?; try { final String output = await api.generateQrCodeUrl( - arg_secretKey!, arg_accountName, arg_issuer); + arg_secretKey, arg_accountName, arg_issuer); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -2278,29 +1747,22 @@ abstract class TestMultiFactoResolverHostApi { } } { - final BasicMessageChannel __pigeon_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.openInOtpApp$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(__pigeon_channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.openInOtpApp was null.'); - final List args = (message as List?)!; - final String? arg_secretKey = (args[0] as String?); - assert(arg_secretKey != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.openInOtpApp was null, expected non-null String.'); - final String? arg_qrCodeUrl = (args[1] as String?); - assert(arg_qrCodeUrl != null, - 'Argument for dev.flutter.pigeon.firebase_auth_platform_interface.MultiFactorTotpSecretHostApi.openInOtpApp was null, expected non-null String.'); + final List args = message! as List; + final String arg_secretKey = args[0]! as String; + final String arg_qrCodeUrl = args[1]! as String; try { - await api.openInOtpApp(arg_secretKey!, arg_qrCodeUrl!); + await api.openInOtpApp(arg_secretKey, arg_qrCodeUrl); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart index 5adffbf2faf3..ea8540a8842d 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_credential_test.dart @@ -19,8 +19,8 @@ void main() { const String kMockEmail = 'test@example.com'; const String kMockPassword = 'test-password'; - final kMockUserData = PigeonUserDetails( - userInfo: PigeonUserInfo( + final kMockUserData = InternalUserDetails( + userInfo: InternalUserInfo( uid: kMockUid, email: kMockEmail, isAnonymous: false, @@ -103,7 +103,7 @@ void main() { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, - MultiFactorPlatform multiFactorPlatform, PigeonUserDetails data) + MultiFactorPlatform multiFactorPlatform, InternalUserDetails data) : super(auth, multiFactorPlatform, data); } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart index abc49090f128..9247c1796229 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/platform_interface_tests/platform_interface_user_test.dart @@ -40,13 +40,13 @@ void main() { }, ]; group('$UserPlatform()', () { - PigeonUserDetails kMockUser; + InternalUserDetails kMockUser; setUpAll(() async { await Firebase.initializeApp(); auth = FirebaseAuthPlatform.instance; - kMockUser = PigeonUserDetails( - userInfo: PigeonUserInfo( + kMockUser = InternalUserDetails( + userInfo: InternalUserInfo( uid: kMockUid, isAnonymous: true, email: kMockEmail, @@ -289,6 +289,6 @@ void main() { class TestUserPlatform extends UserPlatform { TestUserPlatform(FirebaseAuthPlatform auth, MultiFactorPlatform multiFactor, - PigeonUserDetails data) + InternalUserDetails data) : super(auth, multiFactor, data); } diff --git a/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart b/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart index 62dd3bc843b2..5ee8031d52ac 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/firebase_auth_web.dart @@ -219,7 +219,7 @@ class FirebaseAuthWeb extends FirebaseAuthPlatform { @override FirebaseAuthWeb setInitialValues({ - PigeonUserDetails? currentUser, + InternalUserDetails? currentUser, String? languageCode, }) { // Values are already set on web diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart index 28f6efeb6fe4..20c345d90a32 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_web_user.dart @@ -25,8 +25,8 @@ class UserWeb extends UserPlatform { ) : super( auth, multiFactor, - PigeonUserDetails( - userInfo: PigeonUserInfo( + InternalUserDetails( + userInfo: InternalUserInfo( displayName: _webUser.displayName, email: _webUser.email, isEmailVerified: _webUser.emailVerified, diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart b/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart index 7e215a3299b4..1dd2681fc52e 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/utils/web_utils.dart @@ -221,7 +221,7 @@ IdTokenResult convertWebIdTokenResult( auth_interop.IdTokenResult webIdTokenResult, ) { return IdTokenResult( - PigeonIdTokenResult( + InternalIdTokenResult( claims: webIdTokenResult.claims, token: webIdTokenResult.token, authTimestamp: webIdTokenResult.authTime.millisecondsSinceEpoch, diff --git a/packages/firebase_core/analysis_options.yaml b/packages/firebase_core/analysis_options.yaml index 9afc3598d90a..9d4eb42ab944 100644 --- a/packages/firebase_core/analysis_options.yaml +++ b/packages/firebase_core/analysis_options.yaml @@ -9,6 +9,7 @@ analyzer: exclude: - firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart - firebase_core_platform_interface/lib/src/pigeon/test_api.dart + - firebase_core_platform_interface/pigeons/messages.dart linter: rules: diff --git a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java index af1dec848522..8a5db2e48066 100644 --- a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java +++ b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon package io.flutter.plugins.firebase.core; @@ -21,13 +21,170 @@ import java.lang.annotation.Target; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Objects; /** Generated class from Pigeon. */ @SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) public class GeneratedAndroidFirebaseCore { + static boolean pigeonDoubleEquals(double a, double b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == 0.0 ? 0.0 : a) == (b == 0.0 ? 0.0 : b) || (Double.isNaN(a) && Double.isNaN(b)); + } + + static boolean pigeonFloatEquals(float a, float b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == 0.0f ? 0.0f : a) == (b == 0.0f ? 0.0f : b) || (Float.isNaN(a) && Float.isNaN(b)); + } + + static int pigeonDoubleHashCode(double d) { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + if (d == 0.0) { + d = 0.0; + } + long bits = Double.doubleToLongBits(d); + return (int) (bits ^ (bits >>> 32)); + } + + static int pigeonFloatHashCode(float f) { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + if (f == 0.0f) { + f = 0.0f; + } + return Float.floatToIntBits(f); + } + + static boolean pigeonDeepEquals(Object a, Object b) { + if (a == b) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a instanceof byte[] && b instanceof byte[]) { + return Arrays.equals((byte[]) a, (byte[]) b); + } + if (a instanceof int[] && b instanceof int[]) { + return Arrays.equals((int[]) a, (int[]) b); + } + if (a instanceof long[] && b instanceof long[]) { + return Arrays.equals((long[]) a, (long[]) b); + } + if (a instanceof double[] && b instanceof double[]) { + double[] da = (double[]) a; + double[] db = (double[]) b; + if (da.length != db.length) { + return false; + } + for (int i = 0; i < da.length; i++) { + if (!pigeonDoubleEquals(da[i], db[i])) { + return false; + } + } + return true; + } + if (a instanceof List && b instanceof List) { + List listA = (List) a; + List listB = (List) b; + if (listA.size() != listB.size()) { + return false; + } + for (int i = 0; i < listA.size(); i++) { + if (!pigeonDeepEquals(listA.get(i), listB.get(i))) { + return false; + } + } + return true; + } + if (a instanceof Map && b instanceof Map) { + Map mapA = (Map) a; + Map mapB = (Map) b; + if (mapA.size() != mapB.size()) { + return false; + } + for (Map.Entry entryA : mapA.entrySet()) { + Object keyA = entryA.getKey(); + Object valueA = entryA.getValue(); + boolean found = false; + for (Map.Entry entryB : mapB.entrySet()) { + Object keyB = entryB.getKey(); + if (pigeonDeepEquals(keyA, keyB)) { + Object valueB = entryB.getValue(); + if (pigeonDeepEquals(valueA, valueB)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; + } + if (a instanceof Double && b instanceof Double) { + return pigeonDoubleEquals((double) a, (double) b); + } + if (a instanceof Float && b instanceof Float) { + return pigeonFloatEquals((float) a, (float) b); + } + return a.equals(b); + } + + static int pigeonDeepHashCode(Object value) { + if (value == null) { + return 0; + } + if (value instanceof byte[]) { + return Arrays.hashCode((byte[]) value); + } + if (value instanceof int[]) { + return Arrays.hashCode((int[]) value); + } + if (value instanceof long[]) { + return Arrays.hashCode((long[]) value); + } + if (value instanceof double[]) { + double[] da = (double[]) value; + int result = 1; + for (double d : da) { + result = 31 * result + pigeonDoubleHashCode(d); + } + return result; + } + if (value instanceof List) { + int result = 1; + for (Object item : (List) value) { + result = 31 * result + pigeonDeepHashCode(item); + } + return result; + } + if (value instanceof Map) { + int result = 0; + for (Map.Entry entry : ((Map) value).entrySet()) { + result += + ((pigeonDeepHashCode(entry.getKey()) * 31) ^ pigeonDeepHashCode(entry.getValue())); + } + return result; + } + if (value instanceof Object[]) { + int result = 1; + for (Object item : (Object[]) value) { + result = 31 * result + pigeonDeepHashCode(item); + } + return result; + } + if (value instanceof Double) { + return pigeonDoubleHashCode((double) value); + } + if (value instanceof Float) { + return pigeonFloatHashCode((float) value); + } + return value.hashCode(); + } /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ public static class FlutterError extends RuntimeException { @@ -232,39 +389,43 @@ public boolean equals(Object o) { return false; } CoreFirebaseOptions that = (CoreFirebaseOptions) o; - return apiKey.equals(that.apiKey) - && appId.equals(that.appId) - && messagingSenderId.equals(that.messagingSenderId) - && projectId.equals(that.projectId) - && Objects.equals(authDomain, that.authDomain) - && Objects.equals(databaseURL, that.databaseURL) - && Objects.equals(storageBucket, that.storageBucket) - && Objects.equals(measurementId, that.measurementId) - && Objects.equals(trackingId, that.trackingId) - && Objects.equals(deepLinkURLScheme, that.deepLinkURLScheme) - && Objects.equals(androidClientId, that.androidClientId) - && Objects.equals(iosClientId, that.iosClientId) - && Objects.equals(iosBundleId, that.iosBundleId) - && Objects.equals(appGroupId, that.appGroupId); + return pigeonDeepEquals(apiKey, that.apiKey) + && pigeonDeepEquals(appId, that.appId) + && pigeonDeepEquals(messagingSenderId, that.messagingSenderId) + && pigeonDeepEquals(projectId, that.projectId) + && pigeonDeepEquals(authDomain, that.authDomain) + && pigeonDeepEquals(databaseURL, that.databaseURL) + && pigeonDeepEquals(storageBucket, that.storageBucket) + && pigeonDeepEquals(measurementId, that.measurementId) + && pigeonDeepEquals(trackingId, that.trackingId) + && pigeonDeepEquals(deepLinkURLScheme, that.deepLinkURLScheme) + && pigeonDeepEquals(androidClientId, that.androidClientId) + && pigeonDeepEquals(iosClientId, that.iosClientId) + && pigeonDeepEquals(iosBundleId, that.iosBundleId) + && pigeonDeepEquals(appGroupId, that.appGroupId); } @Override public int hashCode() { - return Objects.hash( - apiKey, - appId, - messagingSenderId, - projectId, - authDomain, - databaseURL, - storageBucket, - measurementId, - trackingId, - deepLinkURLScheme, - androidClientId, - iosClientId, - iosBundleId, - appGroupId); + Object[] fields = + new Object[] { + getClass(), + apiKey, + appId, + messagingSenderId, + projectId, + authDomain, + databaseURL, + storageBucket, + measurementId, + trackingId, + deepLinkURLScheme, + androidClientId, + iosClientId, + iosBundleId, + appGroupId + }; + return pigeonDeepHashCode(fields); } public static final class Builder { @@ -518,15 +679,20 @@ public boolean equals(Object o) { return false; } CoreInitializeResponse that = (CoreInitializeResponse) o; - return name.equals(that.name) - && options.equals(that.options) - && Objects.equals(isAutomaticDataCollectionEnabled, that.isAutomaticDataCollectionEnabled) - && pluginConstants.equals(that.pluginConstants); + return pigeonDeepEquals(name, that.name) + && pigeonDeepEquals(options, that.options) + && pigeonDeepEquals( + isAutomaticDataCollectionEnabled, that.isAutomaticDataCollectionEnabled) + && pigeonDeepEquals(pluginConstants, that.pluginConstants); } @Override public int hashCode() { - return Objects.hash(name, options, isAutomaticDataCollectionEnabled, pluginConstants); + Object[] fields = + new Object[] { + getClass(), name, options, isAutomaticDataCollectionEnabled, pluginConstants + }; + return pigeonDeepHashCode(fields); } public static final class Builder { diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h index cc06241e7cb1..913fdbbd3e43 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h @@ -1,10 +1,10 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import +@import Foundation; @protocol FlutterBinaryMessenger; @protocol FlutterMessageCodec; diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m index cf3e439b92ac..c0d58e28a6f3 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m @@ -1,24 +1,107 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#if __has_include("include/firebase_core/messages.g.h") -#import "include/firebase_core/messages.g.h" -#else -#import "include/messages.g.h" -#endif +#import "messages.g.h" #if TARGET_OS_OSX -#import +@import FlutterMacOS; #else -#import +@import Flutter; #endif -#if !__has_feature(objc_arc) -#error File requires ARC to be enabled. -#endif +static BOOL __attribute__((unused)) FLTPigeonDeepEquals(id _Nullable a, id _Nullable b) { + if (a == b) { + return YES; + } + if (a == nil) { + return b == [NSNull null]; + } + if (b == nil) { + return a == [NSNull null]; + } + if ([a isKindOfClass:[NSNumber class]] && [b isKindOfClass:[NSNumber class]]) { + return + [a isEqual:b] || (isnan([(NSNumber *)a doubleValue]) && isnan([(NSNumber *)b doubleValue])); + } + if ([a isKindOfClass:[NSArray class]] && [b isKindOfClass:[NSArray class]]) { + NSArray *arrayA = (NSArray *)a; + NSArray *arrayB = (NSArray *)b; + if (arrayA.count != arrayB.count) { + return NO; + } + for (NSUInteger i = 0; i < arrayA.count; i++) { + if (!FLTPigeonDeepEquals(arrayA[i], arrayB[i])) { + return NO; + } + } + return YES; + } + if ([a isKindOfClass:[NSDictionary class]] && [b isKindOfClass:[NSDictionary class]]) { + NSDictionary *dictA = (NSDictionary *)a; + NSDictionary *dictB = (NSDictionary *)b; + if (dictA.count != dictB.count) { + return NO; + } + for (id keyA in dictA) { + id valueA = dictA[keyA]; + BOOL found = NO; + for (id keyB in dictB) { + if (FLTPigeonDeepEquals(keyA, keyB)) { + id valueB = dictB[keyB]; + if (FLTPigeonDeepEquals(valueA, valueB)) { + found = YES; + break; + } else { + return NO; + } + } + } + if (!found) { + return NO; + } + } + return YES; + } + return [a isEqual:b]; +} + +static NSUInteger __attribute__((unused)) FLTPigeonDeepHash(id _Nullable value) { + if (value == nil || value == (id)[NSNull null]) { + return 0; + } + if ([value isKindOfClass:[NSNumber class]]) { + NSNumber *n = (NSNumber *)value; + double d = n.doubleValue; + if (isnan(d)) { + // Normalize NaN to a consistent hash. + return (NSUInteger)0x7FF8000000000000; + } + if (d == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + d = 0.0; + } + return @(d).hash; + } + if ([value isKindOfClass:[NSArray class]]) { + NSUInteger result = 1; + for (id item in (NSArray *)value) { + result = result * 31 + FLTPigeonDeepHash(item); + } + return result; + } + if ([value isKindOfClass:[NSDictionary class]]) { + NSUInteger result = 0; + NSDictionary *dict = (NSDictionary *)value; + for (id key in dict) { + result += ((FLTPigeonDeepHash(key) * 31) ^ FLTPigeonDeepHash(dict[key])); + } + return result; + } + return [value hash]; +} static NSArray *wrapResult(id result, FlutterError *error) { if (error) { @@ -117,6 +200,48 @@ + (nullable CoreFirebaseOptions *)nullableFromList:(NSArray *)list { self.appGroupId ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + CoreFirebaseOptions *other = (CoreFirebaseOptions *)object; + return FLTPigeonDeepEquals(self.apiKey, other.apiKey) && + FLTPigeonDeepEquals(self.appId, other.appId) && + FLTPigeonDeepEquals(self.messagingSenderId, other.messagingSenderId) && + FLTPigeonDeepEquals(self.projectId, other.projectId) && + FLTPigeonDeepEquals(self.authDomain, other.authDomain) && + FLTPigeonDeepEquals(self.databaseURL, other.databaseURL) && + FLTPigeonDeepEquals(self.storageBucket, other.storageBucket) && + FLTPigeonDeepEquals(self.measurementId, other.measurementId) && + FLTPigeonDeepEquals(self.trackingId, other.trackingId) && + FLTPigeonDeepEquals(self.deepLinkURLScheme, other.deepLinkURLScheme) && + FLTPigeonDeepEquals(self.androidClientId, other.androidClientId) && + FLTPigeonDeepEquals(self.iosClientId, other.iosClientId) && + FLTPigeonDeepEquals(self.iosBundleId, other.iosBundleId) && + FLTPigeonDeepEquals(self.appGroupId, other.appGroupId); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.apiKey); + result = result * 31 + FLTPigeonDeepHash(self.appId); + result = result * 31 + FLTPigeonDeepHash(self.messagingSenderId); + result = result * 31 + FLTPigeonDeepHash(self.projectId); + result = result * 31 + FLTPigeonDeepHash(self.authDomain); + result = result * 31 + FLTPigeonDeepHash(self.databaseURL); + result = result * 31 + FLTPigeonDeepHash(self.storageBucket); + result = result * 31 + FLTPigeonDeepHash(self.measurementId); + result = result * 31 + FLTPigeonDeepHash(self.trackingId); + result = result * 31 + FLTPigeonDeepHash(self.deepLinkURLScheme); + result = result * 31 + FLTPigeonDeepHash(self.androidClientId); + result = result * 31 + FLTPigeonDeepHash(self.iosClientId); + result = result * 31 + FLTPigeonDeepHash(self.iosBundleId); + result = result * 31 + FLTPigeonDeepHash(self.appGroupId); + return result; +} @end @implementation CoreInitializeResponse @@ -150,6 +275,29 @@ + (nullable CoreInitializeResponse *)nullableFromList:(NSArray *)list { self.pluginConstants ?: [NSNull null], ]; } +- (BOOL)isEqual:(id)object { + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + CoreInitializeResponse *other = (CoreInitializeResponse *)object; + return FLTPigeonDeepEquals(self.name, other.name) && + FLTPigeonDeepEquals(self.options, other.options) && + FLTPigeonDeepEquals(self.isAutomaticDataCollectionEnabled, + other.isAutomaticDataCollectionEnabled) && + FLTPigeonDeepEquals(self.pluginConstants, other.pluginConstants); +} + +- (NSUInteger)hash { + NSUInteger result = [self class].hash; + result = result * 31 + FLTPigeonDeepHash(self.name); + result = result * 31 + FLTPigeonDeepHash(self.options); + result = result * 31 + FLTPigeonDeepHash(self.isAutomaticDataCollectionEnabled); + result = result * 31 + FLTPigeonDeepHash(self.pluginConstants); + return result; +} @end @interface nullMessagesPigeonCodecReader : FlutterStandardReader diff --git a/packages/firebase_core/firebase_core/windows/messages.g.cpp b/packages/firebase_core/firebase_core/windows/messages.g.cpp index dfa5388d5c6c..42e8046a21e1 100644 --- a/packages/firebase_core/firebase_core/windows/messages.g.cpp +++ b/packages/firebase_core/firebase_core/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_core_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,6 +33,212 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace // CoreFirebaseOptions CoreFirebaseOptions::CoreFirebaseOptions(const std::string& api_key, @@ -326,6 +534,51 @@ CoreFirebaseOptions CoreFirebaseOptions::FromEncodableList( return decoded; } +bool CoreFirebaseOptions::operator==(const CoreFirebaseOptions& other) const { + return PigeonInternalDeepEquals(api_key_, other.api_key_) && + PigeonInternalDeepEquals(app_id_, other.app_id_) && + PigeonInternalDeepEquals(messaging_sender_id_, + other.messaging_sender_id_) && + PigeonInternalDeepEquals(project_id_, other.project_id_) && + PigeonInternalDeepEquals(auth_domain_, other.auth_domain_) && + PigeonInternalDeepEquals(database_u_r_l_, other.database_u_r_l_) && + PigeonInternalDeepEquals(storage_bucket_, other.storage_bucket_) && + PigeonInternalDeepEquals(measurement_id_, other.measurement_id_) && + PigeonInternalDeepEquals(tracking_id_, other.tracking_id_) && + PigeonInternalDeepEquals(deep_link_u_r_l_scheme_, + other.deep_link_u_r_l_scheme_) && + PigeonInternalDeepEquals(android_client_id_, + other.android_client_id_) && + PigeonInternalDeepEquals(ios_client_id_, other.ios_client_id_) && + PigeonInternalDeepEquals(ios_bundle_id_, other.ios_bundle_id_) && + PigeonInternalDeepEquals(app_group_id_, other.app_group_id_); +} + +bool CoreFirebaseOptions::operator!=(const CoreFirebaseOptions& other) const { + return !(*this == other); +} + +size_t CoreFirebaseOptions::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(api_key_); + result = result * 31 + PigeonInternalDeepHash(app_id_); + result = result * 31 + PigeonInternalDeepHash(messaging_sender_id_); + result = result * 31 + PigeonInternalDeepHash(project_id_); + result = result * 31 + PigeonInternalDeepHash(auth_domain_); + result = result * 31 + PigeonInternalDeepHash(database_u_r_l_); + result = result * 31 + PigeonInternalDeepHash(storage_bucket_); + result = result * 31 + PigeonInternalDeepHash(measurement_id_); + result = result * 31 + PigeonInternalDeepHash(tracking_id_); + result = result * 31 + PigeonInternalDeepHash(deep_link_u_r_l_scheme_); + result = result * 31 + PigeonInternalDeepHash(android_client_id_); + result = result * 31 + PigeonInternalDeepHash(ios_client_id_); + result = result * 31 + PigeonInternalDeepHash(ios_bundle_id_); + result = result * 31 + PigeonInternalDeepHash(app_group_id_); + return result; +} + +size_t PigeonInternalDeepHash(const CoreFirebaseOptions& v) { return v.Hash(); } + // CoreInitializeResponse CoreInitializeResponse::CoreInitializeResponse( @@ -435,10 +688,39 @@ CoreInitializeResponse CoreInitializeResponse::FromEncodableList( return decoded; } +bool CoreInitializeResponse::operator==( + const CoreInitializeResponse& other) const { + return PigeonInternalDeepEquals(name_, other.name_) && + PigeonInternalDeepEquals(options_, other.options_) && + PigeonInternalDeepEquals( + is_automatic_data_collection_enabled_, + other.is_automatic_data_collection_enabled_) && + PigeonInternalDeepEquals(plugin_constants_, other.plugin_constants_); +} + +bool CoreInitializeResponse::operator!=( + const CoreInitializeResponse& other) const { + return !(*this == other); +} + +size_t CoreInitializeResponse::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(name_); + result = result * 31 + PigeonInternalDeepHash(options_); + result = result * 31 + + PigeonInternalDeepHash(is_automatic_data_collection_enabled_); + result = result * 31 + PigeonInternalDeepHash(plugin_constants_); + return result; +} + +size_t PigeonInternalDeepHash(const CoreInitializeResponse& v) { + return v.Hash(); +} + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { case 129: { return CustomEncodableValue(CoreFirebaseOptions::FromEncodableList( @@ -449,12 +731,12 @@ EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( std::get(ReadValue(stream)))); } default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { if (custom_value->type() == typeid(CoreFirebaseOptions)) { @@ -474,23 +756,23 @@ void PigeonInternalCodecSerializer::WriteValue( return; } } - flutter::StandardCodecSerializer::WriteValue(value, stream); + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseCoreHostApi. -const flutter::StandardMessageCodec& FirebaseCoreHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseCoreHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseCoreHostApi` to handle messages through the // `binary_messenger`. -void FirebaseCoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void FirebaseCoreHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseCoreHostApi* api) { FirebaseCoreHostApi::SetUp(binary_messenger, api, ""); } -void FirebaseCoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void FirebaseCoreHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseCoreHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -507,7 +789,7 @@ void FirebaseCoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -557,7 +839,7 @@ void FirebaseCoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { api->InitializeCore([reply](ErrorOr&& output) { if (output.has_error()) { @@ -587,7 +869,7 @@ void FirebaseCoreHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { api->OptionsFromResource( [reply](ErrorOr&& output) { @@ -623,19 +905,19 @@ EncodableValue FirebaseCoreHostApi::WrapError(const FlutterError& error) { } /// The codec used by FirebaseAppHostApi. -const flutter::StandardMessageCodec& FirebaseAppHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseAppHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseAppHostApi` to handle messages through the // `binary_messenger`. -void FirebaseAppHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void FirebaseAppHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAppHostApi* api) { FirebaseAppHostApi::SetUp(binary_messenger, api, ""); } -void FirebaseAppHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void FirebaseAppHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAppHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -652,7 +934,7 @@ void FirebaseAppHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -697,7 +979,7 @@ void FirebaseAppHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -741,7 +1023,7 @@ void FirebaseAppHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); diff --git a/packages/firebase_core/firebase_core/windows/messages.g.h b/packages/firebase_core/firebase_core/windows/messages.g.h index 68a41114984b..bce0a6a81f24 100644 --- a/packages/firebase_core/firebase_core/windows/messages.g.h +++ b/packages/firebase_core/firebase_core/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -130,10 +130,22 @@ class CoreFirebaseOptions { void set_app_group_id(const std::string_view* value_arg); void set_app_group_id(std::string_view value_arg); + bool operator==(const CoreFirebaseOptions& other) const; + bool operator!=(const CoreFirebaseOptions& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static CoreFirebaseOptions FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class CoreInitializeResponse; friend class FirebaseCoreHostApi; friend class FirebaseAppHostApi; @@ -160,13 +172,13 @@ class CoreInitializeResponse { // Constructs an object setting all non-nullable fields. explicit CoreInitializeResponse( const std::string& name, const CoreFirebaseOptions& options, - const flutter::EncodableMap& plugin_constants); + const ::flutter::EncodableMap& plugin_constants); // Constructs an object setting all fields. explicit CoreInitializeResponse( const std::string& name, const CoreFirebaseOptions& options, const bool* is_automatic_data_collection_enabled, - const flutter::EncodableMap& plugin_constants); + const ::flutter::EncodableMap& plugin_constants); ~CoreInitializeResponse() = default; CoreInitializeResponse(const CoreInitializeResponse& other); @@ -184,23 +196,36 @@ class CoreInitializeResponse { void set_is_automatic_data_collection_enabled(const bool* value_arg); void set_is_automatic_data_collection_enabled(bool value_arg); - const flutter::EncodableMap& plugin_constants() const; - void set_plugin_constants(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap& plugin_constants() const; + void set_plugin_constants(const ::flutter::EncodableMap& value_arg); + + bool operator==(const CoreInitializeResponse& other) const; + bool operator!=(const CoreInitializeResponse& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; private: static CoreInitializeResponse FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseCoreHostApi; friend class FirebaseAppHostApi; friend class PigeonInternalCodecSerializer; std::string name_; std::unique_ptr options_; std::optional is_automatic_data_collection_enabled_; - flutter::EncodableMap plugin_constants_; + ::flutter::EncodableMap plugin_constants_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -208,12 +233,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -228,21 +253,21 @@ class FirebaseCoreHostApi { const CoreFirebaseOptions& initialize_app_request, std::function reply)> result) = 0; virtual void InitializeCore( - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void OptionsFromResource( std::function reply)> result) = 0; // The codec used by FirebaseCoreHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseCoreHostApi` to handle messages through the // `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseCoreHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseCoreHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseCoreHostApi() = default; @@ -265,16 +290,16 @@ class FirebaseAppHostApi { std::function reply)> result) = 0; // The codec used by FirebaseAppHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseAppHostApi` to handle messages through the // `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAppHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAppHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseAppHostApi() = default; diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart index d07a1ca4b84a..6d4123a1f1cb 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,21 +1,40 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; - -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } List wrapResponse( @@ -30,20 +49,67 @@ List wrapResponse( } bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } if (a is List && b is List) { return a.length == b.length && a.indexed .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; } return a == b; } +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} + class CoreFirebaseOptions { CoreFirebaseOptions({ required this.apiKey, @@ -142,12 +208,25 @@ class CoreFirebaseOptions { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(apiKey, other.apiKey) && + _deepEquals(appId, other.appId) && + _deepEquals(messagingSenderId, other.messagingSenderId) && + _deepEquals(projectId, other.projectId) && + _deepEquals(authDomain, other.authDomain) && + _deepEquals(databaseURL, other.databaseURL) && + _deepEquals(storageBucket, other.storageBucket) && + _deepEquals(measurementId, other.measurementId) && + _deepEquals(trackingId, other.trackingId) && + _deepEquals(deepLinkURLScheme, other.deepLinkURLScheme) && + _deepEquals(androidClientId, other.androidClientId) && + _deepEquals(iosClientId, other.iosClientId) && + _deepEquals(iosBundleId, other.iosBundleId) && + _deepEquals(appGroupId, other.appGroupId); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class CoreInitializeResponse { @@ -186,7 +265,7 @@ class CoreInitializeResponse { options: result[1]! as CoreFirebaseOptions, isAutomaticDataCollectionEnabled: result[2] as bool?, pluginConstants: - (result[3] as Map?)!.cast(), + (result[3]! as Map).cast(), ); } @@ -199,12 +278,16 @@ class CoreInitializeResponse { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(name, other.name) && + _deepEquals(options, other.options) && + _deepEquals(isAutomaticDataCollectionEnabled, + other.isAutomaticDataCollectionEnabled) && + _deepEquals(pluginConstants, other.pluginConstants); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class _PigeonCodec extends StandardMessageCodec { @@ -255,95 +338,62 @@ class FirebaseCoreHostApi { Future initializeApp( String appName, CoreFirebaseOptions initializeAppRequest) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeApp$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, initializeAppRequest]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as CoreInitializeResponse?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as CoreInitializeResponse; } Future> initializeCore() async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeCore$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as List?)! - .cast(); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as List) + .cast(); } Future optionsFromResource() async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.optionsFromResource$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as CoreFirebaseOptions?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as CoreFirebaseOptions; } } @@ -364,81 +414,60 @@ class FirebaseAppHostApi { Future setAutomaticDataCollectionEnabled( String appName, bool enabled) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticDataCollectionEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, enabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setAutomaticResourceManagementEnabled( String appName, bool enabled) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticResourceManagementEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, enabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future delete(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.delete$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/test_api.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/test_api.dart index fbf2394b4022..9dd32fe50dba 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/test_api.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/test_api.dart @@ -1,9 +1,9 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; @@ -64,9 +64,7 @@ abstract class TestFirebaseCoreHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeApp$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -77,19 +75,13 @@ abstract class TestFirebaseCoreHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeApp was null.'); - final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeApp was null, expected non-null String.'); - final CoreFirebaseOptions? arg_initializeAppRequest = - (args[1] as CoreFirebaseOptions?); - assert(arg_initializeAppRequest != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeApp was null, expected non-null CoreFirebaseOptions.'); + final List args = message! as List; + final String arg_appName = args[0]! as String; + final CoreFirebaseOptions arg_initializeAppRequest = + args[1]! as CoreFirebaseOptions; try { - final CoreInitializeResponse output = await api.initializeApp( - arg_appName!, arg_initializeAppRequest!); + final CoreInitializeResponse output = + await api.initializeApp(arg_appName, arg_initializeAppRequest); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -101,9 +93,7 @@ abstract class TestFirebaseCoreHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeCore$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -128,9 +118,7 @@ abstract class TestFirebaseCoreHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.optionsFromResource$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -176,9 +164,7 @@ abstract class TestFirebaseAppHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticDataCollectionEnabled$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -189,18 +175,12 @@ abstract class TestFirebaseAppHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticDataCollectionEnabled was null.'); - final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticDataCollectionEnabled was null, expected non-null String.'); - final bool? arg_enabled = (args[1] as bool?); - assert(arg_enabled != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticDataCollectionEnabled was null, expected non-null bool.'); + final List args = message! as List; + final String arg_appName = args[0]! as String; + final bool arg_enabled = args[1]! as bool; try { await api.setAutomaticDataCollectionEnabled( - arg_appName!, arg_enabled!); + arg_appName, arg_enabled); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -212,9 +192,7 @@ abstract class TestFirebaseAppHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticResourceManagementEnabled$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -225,18 +203,12 @@ abstract class TestFirebaseAppHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticResourceManagementEnabled was null.'); - final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticResourceManagementEnabled was null, expected non-null String.'); - final bool? arg_enabled = (args[1] as bool?); - assert(arg_enabled != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.setAutomaticResourceManagementEnabled was null, expected non-null bool.'); + final List args = message! as List; + final String arg_appName = args[0]! as String; + final bool arg_enabled = args[1]! as bool; try { await api.setAutomaticResourceManagementEnabled( - arg_appName!, arg_enabled!); + arg_appName, arg_enabled); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -248,9 +220,7 @@ abstract class TestFirebaseAppHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.delete$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -261,14 +231,10 @@ abstract class TestFirebaseAppHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.delete was null.'); - final List args = (message as List?)!; - final String? arg_appName = (args[0] as String?); - assert(arg_appName != null, - 'Argument for dev.flutter.pigeon.firebase_core_platform_interface.FirebaseAppHostApi.delete was null, expected non-null String.'); + final List args = message! as List; + final String arg_appName = args[0]! as String; try { - await api.delete(arg_appName!); + await api.delete(arg_appName); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); diff --git a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml index 907abb8617f6..e299ccf9d279 100644 --- a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml +++ b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml @@ -22,4 +22,4 @@ dependencies: dev_dependencies: mockito: ^5.4.0 - pigeon: 25.3.2 + pigeon: 26.3.4 diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt index ddef8fb19c37..1d8dd75cfbb5 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -40,36 +40,150 @@ private object GeneratedAndroidFirebaseDatabasePigeonUtils { ) } } + fun doubleEquals(a: Double, b: Double): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) + } + + fun floatEquals(a: Float, b: Float): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN()) + } + + fun doubleHash(d: Double): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (d == 0.0) 0.0 else d + val bits = java.lang.Double.doubleToLongBits(normalized) + return (bits xor (bits ushr 32)).toInt() + } + + fun floatHash(f: Float): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (f == 0.0f) 0.0f else f + return java.lang.Float.floatToIntBits(normalized) + } + fun deepEquals(a: Any?, b: Any?): Boolean { + if (a === b) { + return true + } + if (a == null || b == null) { + return false + } if (a is ByteArray && b is ByteArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is IntArray && b is IntArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is LongArray && b is LongArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is DoubleArray && b is DoubleArray) { - return a.contentEquals(b) + if (a.size != b.size) return false + for (i in a.indices) { + if (!doubleEquals(a[i], b[i])) return false + } + return true + } + if (a is FloatArray && b is FloatArray) { + if (a.size != b.size) return false + for (i in a.indices) { + if (!floatEquals(a[i], b[i])) return false + } + return true } if (a is Array<*> && b is Array<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + for (i in a.indices) { + if (!deepEquals(a[i], b[i])) return false + } + return true } if (a is List<*> && b is List<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + val iterA = a.iterator() + val iterB = b.iterator() + while (iterA.hasNext() && iterB.hasNext()) { + if (!deepEquals(iterA.next(), iterB.next())) return false + } + return true } if (a is Map<*, *> && b is Map<*, *>) { - return a.size == b.size && a.all { - (b as Map).containsKey(it.key) && - deepEquals(it.value, b[it.key]) + if (a.size != b.size) return false + for (entry in a) { + val key = entry.key + var found = false + for (bEntry in b) { + if (deepEquals(key, bEntry.key)) { + if (deepEquals(entry.value, bEntry.value)) { + found = true + break + } else { + return false + } + } + } + if (!found) return false } + return true + } + if (a is Double && b is Double) { + return doubleEquals(a, b) + } + if (a is Float && b is Float) { + return floatEquals(a, b) } return a == b } - + + fun deepHash(value: Any?): Int { + return when (value) { + null -> 0 + is ByteArray -> value.contentHashCode() + is IntArray -> value.contentHashCode() + is LongArray -> value.contentHashCode() + is DoubleArray -> { + var result = 1 + for (item in value) { + result = 31 * result + doubleHash(item) + } + result + } + is FloatArray -> { + var result = 1 + for (item in value) { + result = 31 * result + floatHash(item) + } + result + } + is Array<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is List<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is Map<*, *> -> { + var result = 0 + for (entry in value) { + result += ((deepHash(entry.key) * 31) xor deepHash(entry.value)) + } + result + } + is Double -> doubleHash(value) + is Float -> floatHash(value) + else -> value.hashCode() + } + } + } /** @@ -82,7 +196,7 @@ class FlutterError ( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() /** Generated class from Pigeon that represents data sent in messages. */ data class DatabasePigeonSettings ( @@ -113,15 +227,25 @@ data class DatabasePigeonSettings ( ) } override fun equals(other: Any?): Boolean { - if (other !is DatabasePigeonSettings) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as DatabasePigeonSettings + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.persistenceEnabled, other.persistenceEnabled) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.cacheSizeBytes, other.cacheSizeBytes) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.loggingEnabled, other.loggingEnabled) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.emulatorHost, other.emulatorHost) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.emulatorPort, other.emulatorPort) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.persistenceEnabled) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.cacheSizeBytes) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.loggingEnabled) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.emulatorHost) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.emulatorPort) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -147,15 +271,23 @@ data class DatabasePigeonFirebaseApp ( ) } override fun equals(other: Any?): Boolean { - if (other !is DatabasePigeonFirebaseApp) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as DatabasePigeonFirebaseApp + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.appName, other.appName) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.databaseURL, other.databaseURL) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.settings, other.settings) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.appName) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.databaseURL) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.settings) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -175,15 +307,21 @@ data class DatabaseReferencePlatform ( ) } override fun equals(other: Any?): Boolean { - if (other !is DatabaseReferencePlatform) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as DatabaseReferencePlatform + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.path) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -209,15 +347,23 @@ data class DatabaseReferenceRequest ( ) } override fun equals(other: Any?): Boolean { - if (other !is DatabaseReferenceRequest) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as DatabaseReferenceRequest + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.priority, other.priority) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.path) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.value) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.priority) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -240,15 +386,22 @@ data class UpdateRequest ( ) } override fun equals(other: Any?): Boolean { - if (other !is UpdateRequest) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as UpdateRequest + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.path) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.value) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -274,15 +427,23 @@ data class TransactionRequest ( ) } override fun equals(other: Any?): Boolean { - if (other !is TransactionRequest) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as TransactionRequest + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.transactionKey, other.transactionKey) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.applyLocally, other.applyLocally) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.path) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.transactionKey) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.applyLocally) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -308,15 +469,23 @@ data class QueryRequest ( ) } override fun equals(other: Any?): Boolean { - if (other !is QueryRequest) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as QueryRequest + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.modifiers, other.modifiers) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.path) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.modifiers) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.value) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -342,15 +511,23 @@ data class TransactionHandlerResult ( ) } override fun equals(other: Any?): Boolean { - if (other !is TransactionHandlerResult) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as TransactionHandlerResult + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.aborted, other.aborted) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.exception, other.exception) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.value) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.aborted) + result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.exception) + return result + } } private open class GeneratedAndroidFirebaseDatabasePigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift index e91097627f7e..5e0d5707382d 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -52,7 +52,7 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } @@ -74,6 +74,19 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } +private func doubleEqualsFirebaseDatabaseMessages(_ lhs: Double, _ rhs: Double) -> Bool { + (lhs.isNaN && rhs.isNaN) || lhs == rhs +} + +private func doubleHashFirebaseDatabaseMessages(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } +} + func deepEqualsFirebaseDatabaseMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { let cleanLhs = nilOrValue(lhs) as Any? let cleanRhs = nilOrValue(rhs) as Any? @@ -84,59 +97,90 @@ func deepEqualsFirebaseDatabaseMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case is (Void, Void): + case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: return true - case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): - return cleanLhsHashable == cleanRhsHashable + case is (Void, Void): + return true - case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): - guard cleanLhsArray.count == cleanRhsArray.count else { return false } - for (index, element) in cleanLhsArray.enumerated() { - if !deepEqualsFirebaseDatabaseMessages(element, cleanRhsArray[index]) { + case let (lhsArray, rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEqualsFirebaseDatabaseMessages(element, rhsArray[index]) { return false } } return true - case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } - for (key, cleanLhsValue) in cleanLhsDictionary { - guard cleanRhsDictionary.index(forKey: key) != nil else { return false } - if !deepEqualsFirebaseDatabaseMessages(cleanLhsValue, cleanRhsDictionary[key]!) { + case let (lhsArray, rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEqualsFirebaseDatabaseMessages(element, rhsArray[index]) { return false } } return true + case let (lhsDictionary, rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEqualsFirebaseDatabaseMessages(lhsKey, rhsKey) { + if deepEqualsFirebaseDatabaseMessages(lhsValue, rhsValue) { + found = true + break + } else { + return false + } + } + } + if !found { return false } + } + return true + + case let (lhs as Double, rhs as Double): + return doubleEqualsFirebaseDatabaseMessages(lhs, rhs) + + case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable + default: - // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be - // untrue. return false } } func deepHashFirebaseDatabaseMessages(value: Any?, hasher: inout Hasher) { - if let valueList = value as? [AnyHashable] { - for item in valueList { - deepHashFirebaseDatabaseMessages(value: item, hasher: &hasher) - } - return - } - - if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { - hasher.combine(key) - deepHashFirebaseDatabaseMessages(value: valueDict[key]!, hasher: &hasher) + let cleanValue = nilOrValue(value) as Any? + if let cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHashFirebaseDatabaseMessages(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHashFirebaseDatabaseMessages(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHashFirebaseDatabaseMessages(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHashFirebaseDatabaseMessages(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHashFirebaseDatabaseMessages(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) } - return - } - - if let hashableValue = value as? AnyHashable { - hasher.combine(hashableValue.hashValue) + } else { + hasher.combine(0) } - - return hasher.combine(String(describing: value)) } /// Generated class from Pigeon that represents data sent in messages. @@ -175,11 +219,27 @@ struct DatabasePigeonSettings: Hashable { } static func == (lhs: DatabasePigeonSettings, rhs: DatabasePigeonSettings) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.persistenceEnabled, rhs.persistenceEnabled) && + deepEqualsFirebaseDatabaseMessages( + lhs.cacheSizeBytes, + rhs.cacheSizeBytes + ) && deepEqualsFirebaseDatabaseMessages(lhs.loggingEnabled, rhs.loggingEnabled) && + deepEqualsFirebaseDatabaseMessages( + lhs.emulatorHost, + rhs.emulatorHost + ) && deepEqualsFirebaseDatabaseMessages(lhs.emulatorPort, rhs.emulatorPort) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("DatabasePigeonSettings") + deepHashFirebaseDatabaseMessages(value: persistenceEnabled, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: cacheSizeBytes, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: loggingEnabled, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: emulatorHost, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: emulatorPort, hasher: &hasher) } } @@ -211,11 +271,21 @@ struct DatabasePigeonFirebaseApp: Hashable { } static func == (lhs: DatabasePigeonFirebaseApp, rhs: DatabasePigeonFirebaseApp) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.appName, rhs.appName) && + deepEqualsFirebaseDatabaseMessages( + lhs.databaseURL, + rhs.databaseURL + ) && deepEqualsFirebaseDatabaseMessages(lhs.settings, rhs.settings) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("DatabasePigeonFirebaseApp") + deepHashFirebaseDatabaseMessages(value: appName, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: databaseURL, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: settings, hasher: &hasher) } } @@ -239,11 +309,15 @@ struct DatabaseReferencePlatform: Hashable { } static func == (lhs: DatabaseReferencePlatform, rhs: DatabaseReferencePlatform) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("DatabaseReferencePlatform") + deepHashFirebaseDatabaseMessages(value: path, hasher: &hasher) } } @@ -275,11 +349,21 @@ struct DatabaseReferenceRequest: Hashable { } static func == (lhs: DatabaseReferenceRequest, rhs: DatabaseReferenceRequest) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && + deepEqualsFirebaseDatabaseMessages( + lhs.value, + rhs.value + ) && deepEqualsFirebaseDatabaseMessages(lhs.priority, rhs.priority) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("DatabaseReferenceRequest") + deepHashFirebaseDatabaseMessages(value: path, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: value, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: priority, hasher: &hasher) } } @@ -307,11 +391,20 @@ struct UpdateRequest: Hashable { } static func == (lhs: UpdateRequest, rhs: UpdateRequest) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && + deepEqualsFirebaseDatabaseMessages( + lhs.value, + rhs.value + ) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("UpdateRequest") + deepHashFirebaseDatabaseMessages(value: path, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: value, hasher: &hasher) } } @@ -343,11 +436,21 @@ struct TransactionRequest: Hashable { } static func == (lhs: TransactionRequest, rhs: TransactionRequest) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && + deepEqualsFirebaseDatabaseMessages( + lhs.transactionKey, + rhs.transactionKey + ) && deepEqualsFirebaseDatabaseMessages(lhs.applyLocally, rhs.applyLocally) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("TransactionRequest") + deepHashFirebaseDatabaseMessages(value: path, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: transactionKey, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: applyLocally, hasher: &hasher) } } @@ -379,11 +482,21 @@ struct QueryRequest: Hashable { } static func == (lhs: QueryRequest, rhs: QueryRequest) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && + deepEqualsFirebaseDatabaseMessages( + lhs.modifiers, + rhs.modifiers + ) && deepEqualsFirebaseDatabaseMessages(lhs.value, rhs.value) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("QueryRequest") + deepHashFirebaseDatabaseMessages(value: path, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: modifiers, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: value, hasher: &hasher) } } @@ -415,11 +528,21 @@ struct TransactionHandlerResult: Hashable { } static func == (lhs: TransactionHandlerResult, rhs: TransactionHandlerResult) -> Bool { - deepEqualsFirebaseDatabaseMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseDatabaseMessages(lhs.value, rhs.value) && + deepEqualsFirebaseDatabaseMessages( + lhs.aborted, + rhs.aborted + ) && deepEqualsFirebaseDatabaseMessages(lhs.exception, rhs.exception) } func hash(into hasher: inout Hasher) { - deepHashFirebaseDatabaseMessages(value: toList(), hasher: &hasher) + hasher.combine("TransactionHandlerResult") + deepHashFirebaseDatabaseMessages(value: value, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: aborted, hasher: &hasher) + deepHashFirebaseDatabaseMessages(value: exception, hasher: &hasher) } } diff --git a/packages/firebase_database/firebase_database/windows/messages.g.cpp b/packages/firebase_database/firebase_database/windows/messages.g.cpp index 8c0aeeb54adc..f503c24680bf 100644 --- a/packages/firebase_database/firebase_database/windows/messages.g.cpp +++ b/packages/firebase_database/firebase_database/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_database_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,6 +33,212 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace // DatabasePigeonSettings DatabasePigeonSettings::DatabasePigeonSettings() {} @@ -161,6 +369,35 @@ DatabasePigeonSettings DatabasePigeonSettings::FromEncodableList( return decoded; } +bool DatabasePigeonSettings::operator==( + const DatabasePigeonSettings& other) const { + return PigeonInternalDeepEquals(persistence_enabled_, + other.persistence_enabled_) && + PigeonInternalDeepEquals(cache_size_bytes_, other.cache_size_bytes_) && + PigeonInternalDeepEquals(logging_enabled_, other.logging_enabled_) && + PigeonInternalDeepEquals(emulator_host_, other.emulator_host_) && + PigeonInternalDeepEquals(emulator_port_, other.emulator_port_); +} + +bool DatabasePigeonSettings::operator!=( + const DatabasePigeonSettings& other) const { + return !(*this == other); +} + +size_t DatabasePigeonSettings::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(persistence_enabled_); + result = result * 31 + PigeonInternalDeepHash(cache_size_bytes_); + result = result * 31 + PigeonInternalDeepHash(logging_enabled_); + result = result * 31 + PigeonInternalDeepHash(emulator_host_); + result = result * 31 + PigeonInternalDeepHash(emulator_port_); + return result; +} + +size_t PigeonInternalDeepHash(const DatabasePigeonSettings& v) { + return v.Hash(); +} + // DatabasePigeonFirebaseApp DatabasePigeonFirebaseApp::DatabasePigeonFirebaseApp( @@ -247,6 +484,30 @@ DatabasePigeonFirebaseApp DatabasePigeonFirebaseApp::FromEncodableList( return decoded; } +bool DatabasePigeonFirebaseApp::operator==( + const DatabasePigeonFirebaseApp& other) const { + return PigeonInternalDeepEquals(app_name_, other.app_name_) && + PigeonInternalDeepEquals(database_u_r_l_, other.database_u_r_l_) && + PigeonInternalDeepEquals(settings_, other.settings_); +} + +bool DatabasePigeonFirebaseApp::operator!=( + const DatabasePigeonFirebaseApp& other) const { + return !(*this == other); +} + +size_t DatabasePigeonFirebaseApp::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(app_name_); + result = result * 31 + PigeonInternalDeepHash(database_u_r_l_); + result = result * 31 + PigeonInternalDeepHash(settings_); + return result; +} + +size_t PigeonInternalDeepHash(const DatabasePigeonFirebaseApp& v) { + return v.Hash(); +} + // DatabaseReferencePlatform DatabaseReferencePlatform::DatabaseReferencePlatform(const std::string& path) @@ -271,6 +532,26 @@ DatabaseReferencePlatform DatabaseReferencePlatform::FromEncodableList( return decoded; } +bool DatabaseReferencePlatform::operator==( + const DatabaseReferencePlatform& other) const { + return PigeonInternalDeepEquals(path_, other.path_); +} + +bool DatabaseReferencePlatform::operator!=( + const DatabaseReferencePlatform& other) const { + return !(*this == other); +} + +size_t DatabaseReferencePlatform::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(path_); + return result; +} + +size_t PigeonInternalDeepHash(const DatabaseReferencePlatform& v) { + return v.Hash(); +} + // DatabaseReferenceRequest DatabaseReferenceRequest::DatabaseReferenceRequest(const std::string& path) @@ -338,6 +619,30 @@ DatabaseReferenceRequest DatabaseReferenceRequest::FromEncodableList( return decoded; } +bool DatabaseReferenceRequest::operator==( + const DatabaseReferenceRequest& other) const { + return PigeonInternalDeepEquals(path_, other.path_) && + PigeonInternalDeepEquals(value_, other.value_) && + PigeonInternalDeepEquals(priority_, other.priority_); +} + +bool DatabaseReferenceRequest::operator!=( + const DatabaseReferenceRequest& other) const { + return !(*this == other); +} + +size_t DatabaseReferenceRequest::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(path_); + result = result * 31 + PigeonInternalDeepHash(value_); + result = result * 31 + PigeonInternalDeepHash(priority_); + return result; +} + +size_t PigeonInternalDeepHash(const DatabaseReferenceRequest& v) { + return v.Hash(); +} + // UpdateRequest UpdateRequest::UpdateRequest(const std::string& path, const EncodableMap& value) @@ -367,6 +672,24 @@ UpdateRequest UpdateRequest::FromEncodableList(const EncodableList& list) { return decoded; } +bool UpdateRequest::operator==(const UpdateRequest& other) const { + return PigeonInternalDeepEquals(path_, other.path_) && + PigeonInternalDeepEquals(value_, other.value_); +} + +bool UpdateRequest::operator!=(const UpdateRequest& other) const { + return !(*this == other); +} + +size_t UpdateRequest::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(path_); + result = result * 31 + PigeonInternalDeepHash(value_); + return result; +} + +size_t PigeonInternalDeepHash(const UpdateRequest& v) { return v.Hash(); } + // TransactionRequest TransactionRequest::TransactionRequest(const std::string& path, @@ -411,6 +734,26 @@ TransactionRequest TransactionRequest::FromEncodableList( return decoded; } +bool TransactionRequest::operator==(const TransactionRequest& other) const { + return PigeonInternalDeepEquals(path_, other.path_) && + PigeonInternalDeepEquals(transaction_key_, other.transaction_key_) && + PigeonInternalDeepEquals(apply_locally_, other.apply_locally_); +} + +bool TransactionRequest::operator!=(const TransactionRequest& other) const { + return !(*this == other); +} + +size_t TransactionRequest::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(path_); + result = result * 31 + PigeonInternalDeepHash(transaction_key_); + result = result * 31 + PigeonInternalDeepHash(apply_locally_); + return result; +} + +size_t PigeonInternalDeepHash(const TransactionRequest& v) { return v.Hash(); } + // QueryRequest QueryRequest::QueryRequest(const std::string& path, @@ -462,6 +805,26 @@ QueryRequest QueryRequest::FromEncodableList(const EncodableList& list) { return decoded; } +bool QueryRequest::operator==(const QueryRequest& other) const { + return PigeonInternalDeepEquals(path_, other.path_) && + PigeonInternalDeepEquals(modifiers_, other.modifiers_) && + PigeonInternalDeepEquals(value_, other.value_); +} + +bool QueryRequest::operator!=(const QueryRequest& other) const { + return !(*this == other); +} + +size_t QueryRequest::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(path_); + result = result * 31 + PigeonInternalDeepHash(modifiers_); + result = result * 31 + PigeonInternalDeepHash(value_); + return result; +} + +size_t PigeonInternalDeepHash(const QueryRequest& v) { return v.Hash(); } + // TransactionHandlerResult TransactionHandlerResult::TransactionHandlerResult(bool aborted, bool exception) @@ -517,10 +880,34 @@ TransactionHandlerResult TransactionHandlerResult::FromEncodableList( return decoded; } +bool TransactionHandlerResult::operator==( + const TransactionHandlerResult& other) const { + return PigeonInternalDeepEquals(value_, other.value_) && + PigeonInternalDeepEquals(aborted_, other.aborted_) && + PigeonInternalDeepEquals(exception_, other.exception_); +} + +bool TransactionHandlerResult::operator!=( + const TransactionHandlerResult& other) const { + return !(*this == other); +} + +size_t TransactionHandlerResult::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(value_); + result = result * 31 + PigeonInternalDeepHash(aborted_); + result = result * 31 + PigeonInternalDeepHash(exception_); + return result; +} + +size_t PigeonInternalDeepHash(const TransactionHandlerResult& v) { + return v.Hash(); +} + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { case 129: { return CustomEncodableValue(DatabasePigeonSettings::FromEncodableList( @@ -555,12 +942,12 @@ EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( std::get(ReadValue(stream)))); } default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { if (custom_value->type() == typeid(DatabasePigeonSettings)) { @@ -627,25 +1014,26 @@ void PigeonInternalCodecSerializer::WriteValue( return; } } - flutter::StandardCodecSerializer::WriteValue(value, stream); + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseDatabaseHostApi. -const flutter::StandardMessageCodec& FirebaseDatabaseHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseDatabaseHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseDatabaseHostApi` to handle messages through // the `binary_messenger`. -void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseDatabaseHostApi* api) { +void FirebaseDatabaseHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseDatabaseHostApi* api) { FirebaseDatabaseHostApi::SetUp(binary_messenger, api, ""); } -void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseDatabaseHostApi* api, - const std::string& message_channel_suffix) { +void FirebaseDatabaseHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, FirebaseDatabaseHostApi* api, + const std::string& message_channel_suffix) { const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix @@ -660,7 +1048,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -699,7 +1087,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -738,7 +1126,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -784,7 +1172,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -831,7 +1219,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -877,7 +1265,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -929,7 +1317,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -972,7 +1360,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1019,7 +1407,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1058,7 +1446,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1106,7 +1494,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1154,7 +1542,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1201,7 +1589,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1249,7 +1637,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1297,7 +1685,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1345,7 +1733,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1393,7 +1781,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1441,7 +1829,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1488,7 +1876,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1534,7 +1922,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1581,7 +1969,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1628,7 +2016,7 @@ void FirebaseDatabaseHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1683,19 +2071,19 @@ EncodableValue FirebaseDatabaseHostApi::WrapError(const FlutterError& error) { // Generated class from Pigeon that represents Flutter messages that can be // called from C++. FirebaseDatabaseFlutterApi::FirebaseDatabaseFlutterApi( - flutter::BinaryMessenger* binary_messenger) + ::flutter::BinaryMessenger* binary_messenger) : binary_messenger_(binary_messenger), message_channel_suffix_("") {} FirebaseDatabaseFlutterApi::FirebaseDatabaseFlutterApi( - flutter::BinaryMessenger* binary_messenger, + ::flutter::BinaryMessenger* binary_messenger, const std::string& message_channel_suffix) : binary_messenger_(binary_messenger), message_channel_suffix_(message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix : "") {} -const flutter::StandardMessageCodec& FirebaseDatabaseFlutterApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseDatabaseFlutterApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } diff --git a/packages/firebase_database/firebase_database/windows/messages.g.h b/packages/firebase_database/firebase_database/windows/messages.g.h index 0a44f40b593f..a25163618fcc 100644 --- a/packages/firebase_database/firebase_database/windows/messages.g.h +++ b/packages/firebase_database/firebase_database/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -92,10 +92,22 @@ class DatabasePigeonSettings { void set_emulator_port(const int64_t* value_arg); void set_emulator_port(int64_t value_arg); + bool operator==(const DatabasePigeonSettings& other) const; + bool operator!=(const DatabasePigeonSettings& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static DatabasePigeonSettings FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class DatabasePigeonFirebaseApp; friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; @@ -135,10 +147,22 @@ class DatabasePigeonFirebaseApp { const DatabasePigeonSettings& settings() const; void set_settings(const DatabasePigeonSettings& value_arg); + bool operator==(const DatabasePigeonFirebaseApp& other) const; + bool operator!=(const DatabasePigeonFirebaseApp& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static DatabasePigeonFirebaseApp FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; friend class PigeonInternalCodecSerializer; @@ -156,10 +180,22 @@ class DatabaseReferencePlatform { const std::string& path() const; void set_path(std::string_view value_arg); + bool operator==(const DatabaseReferencePlatform& other) const; + bool operator!=(const DatabaseReferencePlatform& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static DatabaseReferencePlatform FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; friend class PigeonInternalCodecSerializer; @@ -174,30 +210,42 @@ class DatabaseReferenceRequest { // Constructs an object setting all fields. explicit DatabaseReferenceRequest(const std::string& path, - const flutter::EncodableValue* value, - const flutter::EncodableValue* priority); + const ::flutter::EncodableValue* value, + const ::flutter::EncodableValue* priority); const std::string& path() const; void set_path(std::string_view value_arg); - const flutter::EncodableValue* value() const; - void set_value(const flutter::EncodableValue* value_arg); - void set_value(const flutter::EncodableValue& value_arg); + const ::flutter::EncodableValue* value() const; + void set_value(const ::flutter::EncodableValue* value_arg); + void set_value(const ::flutter::EncodableValue& value_arg); - const flutter::EncodableValue* priority() const; - void set_priority(const flutter::EncodableValue* value_arg); - void set_priority(const flutter::EncodableValue& value_arg); + const ::flutter::EncodableValue* priority() const; + void set_priority(const ::flutter::EncodableValue* value_arg); + void set_priority(const ::flutter::EncodableValue& value_arg); + + bool operator==(const DatabaseReferenceRequest& other) const; + bool operator!=(const DatabaseReferenceRequest& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; private: static DatabaseReferenceRequest FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; friend class PigeonInternalCodecSerializer; std::string path_; - std::optional value_; - std::optional priority_; + std::optional<::flutter::EncodableValue> value_; + std::optional<::flutter::EncodableValue> priority_; }; // Generated class from Pigeon that represents data sent in messages. @@ -205,22 +253,34 @@ class UpdateRequest { public: // Constructs an object setting all fields. explicit UpdateRequest(const std::string& path, - const flutter::EncodableMap& value); + const ::flutter::EncodableMap& value); const std::string& path() const; void set_path(std::string_view value_arg); - const flutter::EncodableMap& value() const; - void set_value(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap& value() const; + void set_value(const ::flutter::EncodableMap& value_arg); + bool operator==(const UpdateRequest& other) const; + bool operator!=(const UpdateRequest& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static UpdateRequest FromEncodableList(const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static UpdateRequest FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; friend class PigeonInternalCodecSerializer; std::string path_; - flutter::EncodableMap value_; + ::flutter::EncodableMap value_; }; // Generated class from Pigeon that represents data sent in messages. @@ -239,10 +299,22 @@ class TransactionRequest { bool apply_locally() const; void set_apply_locally(bool value_arg); + bool operator==(const TransactionRequest& other) const; + bool operator!=(const TransactionRequest& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static TransactionRequest FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; friend class PigeonInternalCodecSerializer; @@ -256,31 +328,43 @@ class QueryRequest { public: // Constructs an object setting all non-nullable fields. explicit QueryRequest(const std::string& path, - const flutter::EncodableList& modifiers); + const ::flutter::EncodableList& modifiers); // Constructs an object setting all fields. explicit QueryRequest(const std::string& path, - const flutter::EncodableList& modifiers, + const ::flutter::EncodableList& modifiers, const bool* value); const std::string& path() const; void set_path(std::string_view value_arg); - const flutter::EncodableList& modifiers() const; - void set_modifiers(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList& modifiers() const; + void set_modifiers(const ::flutter::EncodableList& value_arg); const bool* value() const; void set_value(const bool* value_arg); void set_value(bool value_arg); + bool operator==(const QueryRequest& other) const; + bool operator!=(const QueryRequest& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static QueryRequest FromEncodableList(const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static QueryRequest FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; friend class PigeonInternalCodecSerializer; std::string path_; - flutter::EncodableList modifiers_; + ::flutter::EncodableList modifiers_; std::optional value_; }; @@ -291,12 +375,12 @@ class TransactionHandlerResult { explicit TransactionHandlerResult(bool aborted, bool exception); // Constructs an object setting all fields. - explicit TransactionHandlerResult(const flutter::EncodableValue* value, + explicit TransactionHandlerResult(const ::flutter::EncodableValue* value, bool aborted, bool exception); - const flutter::EncodableValue* value() const; - void set_value(const flutter::EncodableValue* value_arg); - void set_value(const flutter::EncodableValue& value_arg); + const ::flutter::EncodableValue* value() const; + void set_value(const ::flutter::EncodableValue* value_arg); + void set_value(const ::flutter::EncodableValue& value_arg); bool aborted() const; void set_aborted(bool value_arg); @@ -304,19 +388,32 @@ class TransactionHandlerResult { bool exception() const; void set_exception(bool value_arg); + bool operator==(const TransactionHandlerResult& other) const; + bool operator!=(const TransactionHandlerResult& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static TransactionHandlerResult FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseDatabaseHostApi; friend class FirebaseDatabaseFlutterApi; friend class PigeonInternalCodecSerializer; - std::optional value_; + std::optional<::flutter::EncodableValue> value_; bool aborted_; bool exception_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -324,12 +421,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -387,7 +484,7 @@ class FirebaseDatabaseHostApi { std::function reply)> result) = 0; virtual void DatabaseReferenceGetTransactionResult( const DatabasePigeonFirebaseApp& app, int64_t transaction_key, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void OnDisconnectSet( const DatabasePigeonFirebaseApp& app, const DatabaseReferenceRequest& request, @@ -410,19 +507,19 @@ class FirebaseDatabaseHostApi { std::function reply)> result) = 0; virtual void QueryGet( const DatabasePigeonFirebaseApp& app, const QueryRequest& request, - std::function reply)> result) = 0; + std::function reply)> result) = 0; // The codec used by FirebaseDatabaseHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseDatabaseHostApi` to handle messages through // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseDatabaseHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseDatabaseHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseDatabaseHostApi() = default; @@ -431,17 +528,17 @@ class FirebaseDatabaseHostApi { // called from C++. class FirebaseDatabaseFlutterApi { public: - FirebaseDatabaseFlutterApi(flutter::BinaryMessenger* binary_messenger); - FirebaseDatabaseFlutterApi(flutter::BinaryMessenger* binary_messenger, + FirebaseDatabaseFlutterApi(::flutter::BinaryMessenger* binary_messenger); + FirebaseDatabaseFlutterApi(::flutter::BinaryMessenger* binary_messenger, const std::string& message_channel_suffix); - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); void CallTransactionHandler( - int64_t transaction_key, const flutter::EncodableValue* snapshot_value, + int64_t transaction_key, const ::flutter::EncodableValue* snapshot_value, std::function&& on_success, std::function&& on_error); private: - flutter::BinaryMessenger* binary_messenger_; + ::flutter::BinaryMessenger* binary_messenger_; std::string message_channel_suffix_; }; diff --git a/packages/firebase_database/firebase_database_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_database/firebase_database_platform_interface/lib/src/pigeon/messages.pigeon.dart index 592d072fca61..f8b622a7016a 100644 --- a/packages/firebase_database/firebase_database_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_database/firebase_database_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,21 +1,40 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; - -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } List wrapResponse( @@ -30,20 +49,67 @@ List wrapResponse( } bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } if (a is List && b is List) { return a.length == b.length && a.indexed .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; } return a == b; } +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} + class DatabasePigeonSettings { DatabasePigeonSettings({ this.persistenceEnabled, @@ -97,12 +163,16 @@ class DatabasePigeonSettings { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(persistenceEnabled, other.persistenceEnabled) && + _deepEquals(cacheSizeBytes, other.cacheSizeBytes) && + _deepEquals(loggingEnabled, other.loggingEnabled) && + _deepEquals(emulatorHost, other.emulatorHost) && + _deepEquals(emulatorPort, other.emulatorPort); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class DatabasePigeonFirebaseApp { @@ -149,12 +219,14 @@ class DatabasePigeonFirebaseApp { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(appName, other.appName) && + _deepEquals(databaseURL, other.databaseURL) && + _deepEquals(settings, other.settings); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class DatabaseReferencePlatform { @@ -191,12 +263,12 @@ class DatabaseReferencePlatform { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(path, other.path); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class DatabaseReferenceRequest { @@ -243,12 +315,14 @@ class DatabaseReferenceRequest { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(path, other.path) && + _deepEquals(value, other.value) && + _deepEquals(priority, other.priority); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class UpdateRequest { @@ -276,7 +350,7 @@ class UpdateRequest { result as List; return UpdateRequest( path: result[0]! as String, - value: (result[1] as Map?)!.cast(), + value: (result[1]! as Map).cast(), ); } @@ -289,12 +363,12 @@ class UpdateRequest { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(path, other.path) && _deepEquals(value, other.value); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class TransactionRequest { @@ -340,12 +414,14 @@ class TransactionRequest { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(path, other.path) && + _deepEquals(transactionKey, other.transactionKey) && + _deepEquals(applyLocally, other.applyLocally); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class QueryRequest { @@ -377,7 +453,7 @@ class QueryRequest { result as List; return QueryRequest( path: result[0]! as String, - modifiers: (result[1] as List?)!.cast>(), + modifiers: (result[1]! as List).cast>(), value: result[2] as bool?, ); } @@ -391,12 +467,14 @@ class QueryRequest { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(path, other.path) && + _deepEquals(modifiers, other.modifiers) && + _deepEquals(value, other.value); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class TransactionHandlerResult { @@ -443,12 +521,14 @@ class TransactionHandlerResult { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(value, other.value) && + _deepEquals(aborted, other.aborted) && + _deepEquals(exception, other.exception); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class _PigeonCodec extends StandardMessageCodec { @@ -528,621 +608,447 @@ class FirebaseDatabaseHostApi { final String pigeonVar_messageChannelSuffix; Future goOnline(DatabasePigeonFirebaseApp app) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future goOffline(DatabasePigeonFirebaseApp app) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setPersistenceEnabled( DatabasePigeonFirebaseApp app, bool enabled) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, enabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setPersistenceCacheSizeBytes( DatabasePigeonFirebaseApp app, int cacheSize) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, cacheSize]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setLoggingEnabled( DatabasePigeonFirebaseApp app, bool enabled) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, enabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future useDatabaseEmulator( DatabasePigeonFirebaseApp app, String host, int port) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, host, port]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future ref(DatabasePigeonFirebaseApp app, [String? path]) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, path]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as DatabaseReferencePlatform?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as DatabaseReferencePlatform; } Future refFromURL( DatabasePigeonFirebaseApp app, String url) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, url]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as DatabaseReferencePlatform?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as DatabaseReferencePlatform; } Future purgeOutstandingWrites(DatabasePigeonFirebaseApp app) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future databaseReferenceSet( DatabasePigeonFirebaseApp app, DatabaseReferenceRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future databaseReferenceSetWithPriority( DatabasePigeonFirebaseApp app, DatabaseReferenceRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future databaseReferenceUpdate( DatabasePigeonFirebaseApp app, UpdateRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future databaseReferenceSetPriority( DatabasePigeonFirebaseApp app, DatabaseReferenceRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future databaseReferenceRunTransaction( DatabasePigeonFirebaseApp app, TransactionRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future> databaseReferenceGetTransactionResult( DatabasePigeonFirebaseApp app, int transactionKey) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, transactionKey]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as Map?)! - .cast(); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } Future onDisconnectSet( DatabasePigeonFirebaseApp app, DatabaseReferenceRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future onDisconnectSetWithPriority( DatabasePigeonFirebaseApp app, DatabaseReferenceRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future onDisconnectUpdate( DatabasePigeonFirebaseApp app, UpdateRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future onDisconnectCancel( DatabasePigeonFirebaseApp app, String path) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, path]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future queryObserve( DatabasePigeonFirebaseApp app, QueryRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as String?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future queryKeepSynced( DatabasePigeonFirebaseApp app, QueryRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future> queryGet( DatabasePigeonFirebaseApp app, QueryRequest request) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([app, request]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as Map?)! - .cast(); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } } @@ -1160,9 +1066,7 @@ abstract class FirebaseDatabaseFlutterApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -1170,16 +1074,12 @@ abstract class FirebaseDatabaseFlutterApi { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler was null.'); - final List args = (message as List?)!; - final int? arg_transactionKey = (args[0] as int?); - assert(arg_transactionKey != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler was null, expected non-null int.'); - final Object? arg_snapshotValue = (args[1] as Object?); + final List args = message! as List; + final int arg_transactionKey = args[0]! as int; + final Object? arg_snapshotValue = args[1]; try { final TransactionHandlerResult output = await api - .callTransactionHandler(arg_transactionKey!, arg_snapshotValue); + .callTransactionHandler(arg_transactionKey, arg_snapshotValue); return wrapResponse(result: output); } on PlatformException catch (e) { return wrapResponse(error: e); diff --git a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml index 6333f8bc6b3c..fc60b133c334 100755 --- a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml +++ b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml @@ -21,4 +21,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.2 - pigeon: 25.3.2 + pigeon: 26.3.4 diff --git a/packages/firebase_database/firebase_database_platform_interface/test/pigeon/test_api.dart b/packages/firebase_database/firebase_database_platform_interface/test/pigeon/test_api.dart index 9c08cae382af..da5370c5adb2 100644 --- a/packages/firebase_database/firebase_database_platform_interface/test/pigeon/test_api.dart +++ b/packages/firebase_database/firebase_database_platform_interface/test/pigeon/test_api.dart @@ -1,9 +1,9 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; @@ -148,9 +148,7 @@ abstract class TestFirebaseDatabaseHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -161,15 +159,11 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline was null, expected non-null DatabasePigeonFirebaseApp.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; try { - await api.goOnline(arg_app!); + await api.goOnline(arg_app); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -181,9 +175,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -194,15 +186,11 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline was null, expected non-null DatabasePigeonFirebaseApp.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; try { - await api.goOffline(arg_app!); + await api.goOffline(arg_app); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -214,9 +202,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -227,18 +213,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled was null, expected non-null DatabasePigeonFirebaseApp.'); - final bool? arg_enabled = (args[1] as bool?); - assert(arg_enabled != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled was null, expected non-null bool.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final bool arg_enabled = args[1]! as bool; try { - await api.setPersistenceEnabled(arg_app!, arg_enabled!); + await api.setPersistenceEnabled(arg_app, arg_enabled); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -250,9 +230,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -263,18 +241,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes was null, expected non-null DatabasePigeonFirebaseApp.'); - final int? arg_cacheSize = (args[1] as int?); - assert(arg_cacheSize != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes was null, expected non-null int.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final int arg_cacheSize = args[1]! as int; try { - await api.setPersistenceCacheSizeBytes(arg_app!, arg_cacheSize!); + await api.setPersistenceCacheSizeBytes(arg_app, arg_cacheSize); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -286,9 +258,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -299,18 +269,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled was null, expected non-null DatabasePigeonFirebaseApp.'); - final bool? arg_enabled = (args[1] as bool?); - assert(arg_enabled != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled was null, expected non-null bool.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final bool arg_enabled = args[1]! as bool; try { - await api.setLoggingEnabled(arg_app!, arg_enabled!); + await api.setLoggingEnabled(arg_app, arg_enabled); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -322,9 +286,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -335,21 +297,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator was null, expected non-null DatabasePigeonFirebaseApp.'); - final String? arg_host = (args[1] as String?); - assert(arg_host != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator was null, expected non-null String.'); - final int? arg_port = (args[2] as int?); - assert(arg_port != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator was null, expected non-null int.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final String arg_host = args[1]! as String; + final int arg_port = args[2]! as int; try { - await api.useDatabaseEmulator(arg_app!, arg_host!, arg_port!); + await api.useDatabaseEmulator(arg_app, arg_host, arg_port); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -361,9 +315,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -374,17 +326,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref was null, expected non-null DatabasePigeonFirebaseApp.'); - final String? arg_path = (args[1] as String?); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final String? arg_path = args[1] as String?; try { final DatabaseReferencePlatform output = - await api.ref(arg_app!, arg_path); + await api.ref(arg_app, arg_path); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -396,9 +344,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -409,19 +355,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL was null, expected non-null DatabasePigeonFirebaseApp.'); - final String? arg_url = (args[1] as String?); - assert(arg_url != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL was null, expected non-null String.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final String arg_url = args[1]! as String; try { final DatabaseReferencePlatform output = - await api.refFromURL(arg_app!, arg_url!); + await api.refFromURL(arg_app, arg_url); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -433,9 +373,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -446,15 +384,11 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites was null, expected non-null DatabasePigeonFirebaseApp.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; try { - await api.purgeOutstandingWrites(arg_app!); + await api.purgeOutstandingWrites(arg_app); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -466,9 +400,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -479,19 +411,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet was null, expected non-null DatabasePigeonFirebaseApp.'); - final DatabaseReferenceRequest? arg_request = - (args[1] as DatabaseReferenceRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet was null, expected non-null DatabaseReferenceRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final DatabaseReferenceRequest arg_request = + args[1]! as DatabaseReferenceRequest; try { - await api.databaseReferenceSet(arg_app!, arg_request!); + await api.databaseReferenceSet(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -503,9 +429,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -516,19 +440,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority was null, expected non-null DatabasePigeonFirebaseApp.'); - final DatabaseReferenceRequest? arg_request = - (args[1] as DatabaseReferenceRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority was null, expected non-null DatabaseReferenceRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final DatabaseReferenceRequest arg_request = + args[1]! as DatabaseReferenceRequest; try { - await api.databaseReferenceSetWithPriority(arg_app!, arg_request!); + await api.databaseReferenceSetWithPriority(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -540,9 +458,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -553,18 +469,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate was null, expected non-null DatabasePigeonFirebaseApp.'); - final UpdateRequest? arg_request = (args[1] as UpdateRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate was null, expected non-null UpdateRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final UpdateRequest arg_request = args[1]! as UpdateRequest; try { - await api.databaseReferenceUpdate(arg_app!, arg_request!); + await api.databaseReferenceUpdate(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -576,9 +486,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -589,19 +497,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority was null, expected non-null DatabasePigeonFirebaseApp.'); - final DatabaseReferenceRequest? arg_request = - (args[1] as DatabaseReferenceRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority was null, expected non-null DatabaseReferenceRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final DatabaseReferenceRequest arg_request = + args[1]! as DatabaseReferenceRequest; try { - await api.databaseReferenceSetPriority(arg_app!, arg_request!); + await api.databaseReferenceSetPriority(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -613,9 +515,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -626,19 +526,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction was null, expected non-null DatabasePigeonFirebaseApp.'); - final TransactionRequest? arg_request = - (args[1] as TransactionRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction was null, expected non-null TransactionRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final TransactionRequest arg_request = args[1]! as TransactionRequest; try { - await api.databaseReferenceRunTransaction(arg_app!, arg_request!); + await api.databaseReferenceRunTransaction(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -650,9 +543,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -663,20 +554,14 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult was null, expected non-null DatabasePigeonFirebaseApp.'); - final int? arg_transactionKey = (args[1] as int?); - assert(arg_transactionKey != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult was null, expected non-null int.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final int arg_transactionKey = args[1]! as int; try { final Map output = await api.databaseReferenceGetTransactionResult( - arg_app!, arg_transactionKey!); + arg_app, arg_transactionKey); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -688,9 +573,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -701,19 +584,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet was null, expected non-null DatabasePigeonFirebaseApp.'); - final DatabaseReferenceRequest? arg_request = - (args[1] as DatabaseReferenceRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet was null, expected non-null DatabaseReferenceRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final DatabaseReferenceRequest arg_request = + args[1]! as DatabaseReferenceRequest; try { - await api.onDisconnectSet(arg_app!, arg_request!); + await api.onDisconnectSet(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -725,9 +602,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -738,19 +613,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority was null, expected non-null DatabasePigeonFirebaseApp.'); - final DatabaseReferenceRequest? arg_request = - (args[1] as DatabaseReferenceRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority was null, expected non-null DatabaseReferenceRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final DatabaseReferenceRequest arg_request = + args[1]! as DatabaseReferenceRequest; try { - await api.onDisconnectSetWithPriority(arg_app!, arg_request!); + await api.onDisconnectSetWithPriority(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -762,9 +631,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -775,18 +642,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate was null, expected non-null DatabasePigeonFirebaseApp.'); - final UpdateRequest? arg_request = (args[1] as UpdateRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate was null, expected non-null UpdateRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final UpdateRequest arg_request = args[1]! as UpdateRequest; try { - await api.onDisconnectUpdate(arg_app!, arg_request!); + await api.onDisconnectUpdate(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -798,9 +659,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -811,18 +670,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel was null, expected non-null DatabasePigeonFirebaseApp.'); - final String? arg_path = (args[1] as String?); - assert(arg_path != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel was null, expected non-null String.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final String arg_path = args[1]! as String; try { - await api.onDisconnectCancel(arg_app!, arg_path!); + await api.onDisconnectCancel(arg_app, arg_path); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -834,9 +687,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -847,19 +698,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve was null, expected non-null DatabasePigeonFirebaseApp.'); - final QueryRequest? arg_request = (args[1] as QueryRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve was null, expected non-null QueryRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final QueryRequest arg_request = args[1]! as QueryRequest; try { - final String output = - await api.queryObserve(arg_app!, arg_request!); + final String output = await api.queryObserve(arg_app, arg_request); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -871,9 +715,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -884,18 +726,12 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced was null, expected non-null DatabasePigeonFirebaseApp.'); - final QueryRequest? arg_request = (args[1] as QueryRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced was null, expected non-null QueryRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final QueryRequest arg_request = args[1]! as QueryRequest; try { - await api.queryKeepSynced(arg_app!, arg_request!); + await api.queryKeepSynced(arg_app, arg_request); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -907,9 +743,7 @@ abstract class TestFirebaseDatabaseHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -920,19 +754,13 @@ abstract class TestFirebaseDatabaseHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet was null.'); - final List args = (message as List?)!; - final DatabasePigeonFirebaseApp? arg_app = - (args[0] as DatabasePigeonFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet was null, expected non-null DatabasePigeonFirebaseApp.'); - final QueryRequest? arg_request = (args[1] as QueryRequest?); - assert(arg_request != null, - 'Argument for dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet was null, expected non-null QueryRequest.'); + final List args = message! as List; + final DatabasePigeonFirebaseApp arg_app = + args[0]! as DatabasePigeonFirebaseApp; + final QueryRequest arg_request = args[1]! as QueryRequest; try { final Map output = - await api.queryGet(arg_app!, arg_request!); + await api.queryGet(arg_app, arg_request); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); diff --git a/packages/firebase_performance/analysis_options.yaml b/packages/firebase_performance/analysis_options.yaml index a9341971bf6a..e8ee91e2edaa 100644 --- a/packages/firebase_performance/analysis_options.yaml +++ b/packages/firebase_performance/analysis_options.yaml @@ -7,4 +7,5 @@ include: ../../analysis_options.yaml analyzer: exclude: - firebase_performance_platform_interface/lib/src/pigeon/messages.pigeon.dart - - firebase_performance_platform_interface/test/pigeon/test_api.dart \ No newline at end of file + - firebase_performance_platform_interface/test/pigeon/test_api.dart + - firebase_performance_platform_interface/pigeons/messages.dart \ No newline at end of file diff --git a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt index 39423870b952..666c2379ab10 100644 --- a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt +++ b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -37,36 +37,150 @@ private object GeneratedAndroidFirebasePerformancePigeonUtils { ) } } + fun doubleEquals(a: Double, b: Double): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) + } + + fun floatEquals(a: Float, b: Float): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN()) + } + + fun doubleHash(d: Double): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (d == 0.0) 0.0 else d + val bits = java.lang.Double.doubleToLongBits(normalized) + return (bits xor (bits ushr 32)).toInt() + } + + fun floatHash(f: Float): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (f == 0.0f) 0.0f else f + return java.lang.Float.floatToIntBits(normalized) + } + fun deepEquals(a: Any?, b: Any?): Boolean { + if (a === b) { + return true + } + if (a == null || b == null) { + return false + } if (a is ByteArray && b is ByteArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is IntArray && b is IntArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is LongArray && b is LongArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is DoubleArray && b is DoubleArray) { - return a.contentEquals(b) + if (a.size != b.size) return false + for (i in a.indices) { + if (!doubleEquals(a[i], b[i])) return false + } + return true + } + if (a is FloatArray && b is FloatArray) { + if (a.size != b.size) return false + for (i in a.indices) { + if (!floatEquals(a[i], b[i])) return false + } + return true } if (a is Array<*> && b is Array<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + for (i in a.indices) { + if (!deepEquals(a[i], b[i])) return false + } + return true } if (a is List<*> && b is List<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + val iterA = a.iterator() + val iterB = b.iterator() + while (iterA.hasNext() && iterB.hasNext()) { + if (!deepEquals(iterA.next(), iterB.next())) return false + } + return true } if (a is Map<*, *> && b is Map<*, *>) { - return a.size == b.size && a.all { - (b as Map).containsKey(it.key) && - deepEquals(it.value, b[it.key]) + if (a.size != b.size) return false + for (entry in a) { + val key = entry.key + var found = false + for (bEntry in b) { + if (deepEquals(key, bEntry.key)) { + if (deepEquals(entry.value, bEntry.value)) { + found = true + break + } else { + return false + } + } + } + if (!found) return false } + return true + } + if (a is Double && b is Double) { + return doubleEquals(a, b) + } + if (a is Float && b is Float) { + return floatEquals(a, b) } return a == b } - + + fun deepHash(value: Any?): Int { + return when (value) { + null -> 0 + is ByteArray -> value.contentHashCode() + is IntArray -> value.contentHashCode() + is LongArray -> value.contentHashCode() + is DoubleArray -> { + var result = 1 + for (item in value) { + result = 31 * result + doubleHash(item) + } + result + } + is FloatArray -> { + var result = 1 + for (item in value) { + result = 31 * result + floatHash(item) + } + result + } + is Array<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is List<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is Map<*, *> -> { + var result = 0 + for (entry in value) { + result += ((deepHash(entry.key) * 31) xor deepHash(entry.value)) + } + result + } + is Double -> doubleHash(value) + is Float -> floatHash(value) + else -> value.hashCode() + } + } + } /** @@ -79,7 +193,7 @@ class FlutterError ( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() enum class HttpMethod(val raw: Int) { CONNECT(0), @@ -119,15 +233,22 @@ data class HttpMetricOptions ( ) } override fun equals(other: Any?): Boolean { - if (other !is HttpMetricOptions) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as HttpMetricOptions + return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.url, other.url) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.httpMethod, other.httpMethod) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.url) + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.httpMethod) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -159,15 +280,25 @@ data class HttpMetricAttributes ( ) } override fun equals(other: Any?): Boolean { - if (other !is HttpMetricAttributes) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as HttpMetricAttributes + return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.httpResponseCode, other.httpResponseCode) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.requestPayloadSize, other.requestPayloadSize) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.responsePayloadSize, other.responsePayloadSize) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.responseContentType, other.responseContentType) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.attributes, other.attributes) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.httpResponseCode) + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.requestPayloadSize) + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.responsePayloadSize) + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.responseContentType) + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.attributes) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ @@ -190,15 +321,22 @@ data class TraceAttributes ( ) } override fun equals(other: Any?): Boolean { - if (other !is TraceAttributes) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as TraceAttributes + return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.metrics, other.metrics) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.attributes, other.attributes) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.metrics) + result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.attributes) + return result + } } private open class GeneratedAndroidFirebasePerformancePigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { @@ -230,7 +368,7 @@ private open class GeneratedAndroidFirebasePerformancePigeonCodec : StandardMess when (value) { is HttpMethod -> { stream.write(129) - writeValue(stream, value.raw) + writeValue(stream, value.raw.toLong()) } is HttpMetricOptions -> { stream.write(130) diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift index 2ff69619ed50..47f32896fcb5 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -52,7 +52,7 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } @@ -66,6 +66,19 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } +private func doubleEqualsFirebasePerformanceMessages(_ lhs: Double, _ rhs: Double) -> Bool { + (lhs.isNaN && rhs.isNaN) || lhs == rhs +} + +private func doubleHashFirebasePerformanceMessages(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } +} + func deepEqualsFirebasePerformanceMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { let cleanLhs = nilOrValue(lhs) as Any? let cleanRhs = nilOrValue(rhs) as Any? @@ -76,59 +89,90 @@ func deepEqualsFirebasePerformanceMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case is (Void, Void): + case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: return true - case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): - return cleanLhsHashable == cleanRhsHashable + case is (Void, Void): + return true - case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): - guard cleanLhsArray.count == cleanRhsArray.count else { return false } - for (index, element) in cleanLhsArray.enumerated() { - if !deepEqualsFirebasePerformanceMessages(element, cleanRhsArray[index]) { + case let (lhsArray, rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEqualsFirebasePerformanceMessages(element, rhsArray[index]) { return false } } return true - case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } - for (key, cleanLhsValue) in cleanLhsDictionary { - guard cleanRhsDictionary.index(forKey: key) != nil else { return false } - if !deepEqualsFirebasePerformanceMessages(cleanLhsValue, cleanRhsDictionary[key]!) { + case let (lhsArray, rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEqualsFirebasePerformanceMessages(element, rhsArray[index]) { return false } } return true + case let (lhsDictionary, rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEqualsFirebasePerformanceMessages(lhsKey, rhsKey) { + if deepEqualsFirebasePerformanceMessages(lhsValue, rhsValue) { + found = true + break + } else { + return false + } + } + } + if !found { return false } + } + return true + + case let (lhs as Double, rhs as Double): + return doubleEqualsFirebasePerformanceMessages(lhs, rhs) + + case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable + default: - // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be - // untrue. return false } } func deepHashFirebasePerformanceMessages(value: Any?, hasher: inout Hasher) { - if let valueList = value as? [AnyHashable] { - for item in valueList { - deepHashFirebasePerformanceMessages(value: item, hasher: &hasher) - } - return - } - - if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { - hasher.combine(key) - deepHashFirebasePerformanceMessages(value: valueDict[key]!, hasher: &hasher) + let cleanValue = nilOrValue(value) as Any? + if let cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHashFirebasePerformanceMessages(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHashFirebasePerformanceMessages(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHashFirebasePerformanceMessages(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHashFirebasePerformanceMessages(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHashFirebasePerformanceMessages(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) } - return - } - - if let hashableValue = value as? AnyHashable { - hasher.combine(hashableValue.hashValue) + } else { + hasher.combine(0) } - - return hasher.combine(String(describing: value)) } enum HttpMethod: Int { @@ -167,11 +211,20 @@ struct HttpMetricOptions: Hashable { } static func == (lhs: HttpMetricOptions, rhs: HttpMetricOptions) -> Bool { - deepEqualsFirebasePerformanceMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebasePerformanceMessages(lhs.url, rhs.url) && + deepEqualsFirebasePerformanceMessages( + lhs.httpMethod, + rhs.httpMethod + ) } func hash(into hasher: inout Hasher) { - deepHashFirebasePerformanceMessages(value: toList(), hasher: &hasher) + hasher.combine("HttpMetricOptions") + deepHashFirebasePerformanceMessages(value: url, hasher: &hasher) + deepHashFirebasePerformanceMessages(value: httpMethod, hasher: &hasher) } } @@ -211,11 +264,30 @@ struct HttpMetricAttributes: Hashable { } static func == (lhs: HttpMetricAttributes, rhs: HttpMetricAttributes) -> Bool { - deepEqualsFirebasePerformanceMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebasePerformanceMessages(lhs.httpResponseCode, rhs.httpResponseCode) && + deepEqualsFirebasePerformanceMessages( + lhs.requestPayloadSize, + rhs.requestPayloadSize + ) && deepEqualsFirebasePerformanceMessages( + lhs.responsePayloadSize, + rhs.responsePayloadSize + ) && + deepEqualsFirebasePerformanceMessages( + lhs.responseContentType, + rhs.responseContentType + ) && deepEqualsFirebasePerformanceMessages(lhs.attributes, rhs.attributes) } func hash(into hasher: inout Hasher) { - deepHashFirebasePerformanceMessages(value: toList(), hasher: &hasher) + hasher.combine("HttpMetricAttributes") + deepHashFirebasePerformanceMessages(value: httpResponseCode, hasher: &hasher) + deepHashFirebasePerformanceMessages(value: requestPayloadSize, hasher: &hasher) + deepHashFirebasePerformanceMessages(value: responsePayloadSize, hasher: &hasher) + deepHashFirebasePerformanceMessages(value: responseContentType, hasher: &hasher) + deepHashFirebasePerformanceMessages(value: attributes, hasher: &hasher) } } @@ -243,11 +315,20 @@ struct TraceAttributes: Hashable { } static func == (lhs: TraceAttributes, rhs: TraceAttributes) -> Bool { - deepEqualsFirebasePerformanceMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebasePerformanceMessages(lhs.metrics, rhs.metrics) && + deepEqualsFirebasePerformanceMessages( + lhs.attributes, + rhs.attributes + ) } func hash(into hasher: inout Hasher) { - deepHashFirebasePerformanceMessages(value: toList(), hasher: &hasher) + hasher.combine("TraceAttributes") + deepHashFirebasePerformanceMessages(value: metrics, hasher: &hasher) + deepHashFirebasePerformanceMessages(value: attributes, hasher: &hasher) } } diff --git a/packages/firebase_performance/firebase_performance/windows/messages.g.cpp b/packages/firebase_performance/firebase_performance/windows/messages.g.cpp index f5934afda061..4efec43167f6 100644 --- a/packages/firebase_performance/firebase_performance/windows/messages.g.cpp +++ b/packages/firebase_performance/firebase_performance/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_performance_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,6 +33,212 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace // HttpMetricOptions HttpMetricOptions::HttpMetricOptions(const std::string& url, @@ -67,6 +275,24 @@ HttpMetricOptions HttpMetricOptions::FromEncodableList( return decoded; } +bool HttpMetricOptions::operator==(const HttpMetricOptions& other) const { + return PigeonInternalDeepEquals(url_, other.url_) && + PigeonInternalDeepEquals(http_method_, other.http_method_); +} + +bool HttpMetricOptions::operator!=(const HttpMetricOptions& other) const { + return !(*this == other); +} + +size_t HttpMetricOptions::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(url_); + result = result * 31 + PigeonInternalDeepHash(http_method_); + return result; +} + +size_t PigeonInternalDeepHash(const HttpMetricOptions& v) { return v.Hash(); } + // HttpMetricAttributes HttpMetricAttributes::HttpMetricAttributes() {} @@ -204,6 +430,36 @@ HttpMetricAttributes HttpMetricAttributes::FromEncodableList( return decoded; } +bool HttpMetricAttributes::operator==(const HttpMetricAttributes& other) const { + return PigeonInternalDeepEquals(http_response_code_, + other.http_response_code_) && + PigeonInternalDeepEquals(request_payload_size_, + other.request_payload_size_) && + PigeonInternalDeepEquals(response_payload_size_, + other.response_payload_size_) && + PigeonInternalDeepEquals(response_content_type_, + other.response_content_type_) && + PigeonInternalDeepEquals(attributes_, other.attributes_); +} + +bool HttpMetricAttributes::operator!=(const HttpMetricAttributes& other) const { + return !(*this == other); +} + +size_t HttpMetricAttributes::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(http_response_code_); + result = result * 31 + PigeonInternalDeepHash(request_payload_size_); + result = result * 31 + PigeonInternalDeepHash(response_payload_size_); + result = result * 31 + PigeonInternalDeepHash(response_content_type_); + result = result * 31 + PigeonInternalDeepHash(attributes_); + return result; +} + +size_t PigeonInternalDeepHash(const HttpMetricAttributes& v) { + return v.Hash(); +} + // TraceAttributes TraceAttributes::TraceAttributes() {} @@ -260,10 +516,28 @@ TraceAttributes TraceAttributes::FromEncodableList(const EncodableList& list) { return decoded; } +bool TraceAttributes::operator==(const TraceAttributes& other) const { + return PigeonInternalDeepEquals(metrics_, other.metrics_) && + PigeonInternalDeepEquals(attributes_, other.attributes_); +} + +bool TraceAttributes::operator!=(const TraceAttributes& other) const { + return !(*this == other); +} + +size_t TraceAttributes::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(metrics_); + result = result * 31 + PigeonInternalDeepHash(attributes_); + return result; +} + +size_t PigeonInternalDeepHash(const TraceAttributes& v) { return v.Hash(); } + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { case 129: { const auto& encodable_enum_arg = ReadValue(stream); @@ -287,12 +561,12 @@ EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( std::get(ReadValue(stream)))); } default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { if (custom_value->type() == typeid(HttpMethod)) { @@ -326,25 +600,26 @@ void PigeonInternalCodecSerializer::WriteValue( return; } } - flutter::StandardCodecSerializer::WriteValue(value, stream); + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebasePerformanceHostApi. -const flutter::StandardMessageCodec& FirebasePerformanceHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebasePerformanceHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebasePerformanceHostApi` to handle messages // through the `binary_messenger`. void FirebasePerformanceHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, + ::flutter::BinaryMessenger* binary_messenger, FirebasePerformanceHostApi* api) { FirebasePerformanceHostApi::SetUp(binary_messenger, api, ""); } void FirebasePerformanceHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, FirebasePerformanceHostApi* api, + ::flutter::BinaryMessenger* binary_messenger, + FirebasePerformanceHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = message_channel_suffix.length() > 0 @@ -360,7 +635,7 @@ void FirebasePerformanceHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_enabled_arg = args.at(0); @@ -397,7 +672,7 @@ void FirebasePerformanceHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { api->IsPerformanceCollectionEnabled( [reply](ErrorOr&& output) { @@ -428,7 +703,7 @@ void FirebasePerformanceHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_name_arg = args.at(0); @@ -465,7 +740,7 @@ void FirebasePerformanceHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_handle_arg = args.at(0); @@ -510,7 +785,7 @@ void FirebasePerformanceHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_options_arg = args.at(0); @@ -549,7 +824,7 @@ void FirebasePerformanceHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_handle_arg = args.at(0); diff --git a/packages/firebase_performance/firebase_performance/windows/messages.g.h b/packages/firebase_performance/firebase_performance/windows/messages.g.h index a9802f4c703a..cf8d9bfd9ebb 100644 --- a/packages/firebase_performance/firebase_performance/windows/messages.g.h +++ b/packages/firebase_performance/firebase_performance/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -83,10 +83,22 @@ class HttpMetricOptions { const HttpMethod& http_method() const; void set_http_method(const HttpMethod& value_arg); + bool operator==(const HttpMetricOptions& other) const; + bool operator!=(const HttpMetricOptions& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static HttpMetricOptions FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebasePerformanceHostApi; friend class PigeonInternalCodecSerializer; std::string url_; @@ -104,7 +116,7 @@ class HttpMetricAttributes { const int64_t* request_payload_size, const int64_t* response_payload_size, const std::string* response_content_type, - const flutter::EncodableMap* attributes); + const ::flutter::EncodableMap* attributes); const int64_t* http_response_code() const; void set_http_response_code(const int64_t* value_arg); @@ -122,21 +134,33 @@ class HttpMetricAttributes { void set_response_content_type(const std::string_view* value_arg); void set_response_content_type(std::string_view value_arg); - const flutter::EncodableMap* attributes() const; - void set_attributes(const flutter::EncodableMap* value_arg); - void set_attributes(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* attributes() const; + void set_attributes(const ::flutter::EncodableMap* value_arg); + void set_attributes(const ::flutter::EncodableMap& value_arg); + + bool operator==(const HttpMetricAttributes& other) const; + bool operator!=(const HttpMetricAttributes& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; private: static HttpMetricAttributes FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebasePerformanceHostApi; friend class PigeonInternalCodecSerializer; std::optional http_response_code_; std::optional request_payload_size_; std::optional response_payload_size_; std::optional response_content_type_; - std::optional attributes_; + std::optional<::flutter::EncodableMap> attributes_; }; // Generated class from Pigeon that represents data sent in messages. @@ -146,27 +170,41 @@ class TraceAttributes { TraceAttributes(); // Constructs an object setting all fields. - explicit TraceAttributes(const flutter::EncodableMap* metrics, - const flutter::EncodableMap* attributes); + explicit TraceAttributes(const ::flutter::EncodableMap* metrics, + const ::flutter::EncodableMap* attributes); + + const ::flutter::EncodableMap* metrics() const; + void set_metrics(const ::flutter::EncodableMap* value_arg); + void set_metrics(const ::flutter::EncodableMap& value_arg); + + const ::flutter::EncodableMap* attributes() const; + void set_attributes(const ::flutter::EncodableMap* value_arg); + void set_attributes(const ::flutter::EncodableMap& value_arg); - const flutter::EncodableMap* metrics() const; - void set_metrics(const flutter::EncodableMap* value_arg); - void set_metrics(const flutter::EncodableMap& value_arg); + bool operator==(const TraceAttributes& other) const; + bool operator!=(const TraceAttributes& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; - const flutter::EncodableMap* attributes() const; - void set_attributes(const flutter::EncodableMap* value_arg); - void set_attributes(const flutter::EncodableMap& value_arg); + private: + static TraceAttributes FromEncodableList( + const ::flutter::EncodableList& list); + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static TraceAttributes FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebasePerformanceHostApi; friend class PigeonInternalCodecSerializer; - std::optional metrics_; - std::optional attributes_; + std::optional<::flutter::EncodableMap> metrics_; + std::optional<::flutter::EncodableMap> attributes_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -174,12 +212,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -209,16 +247,16 @@ class FirebasePerformanceHostApi { std::function reply)> result) = 0; // The codec used by FirebasePerformanceHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebasePerformanceHostApi` to handle messages // through the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebasePerformanceHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebasePerformanceHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebasePerformanceHostApi() = default; diff --git a/packages/firebase_performance/firebase_performance_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_performance/firebase_performance_platform_interface/lib/src/pigeon/messages.pigeon.dart index b01f643749c4..df055af51a47 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_performance/firebase_performance_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,21 +1,40 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; - -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } List wrapResponse( @@ -30,20 +49,67 @@ List wrapResponse( } bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } if (a is List && b is List) { return a.length == b.length && a.indexed .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; } return a == b; } +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} + enum HttpMethod { connect, delete, @@ -94,12 +160,13 @@ class HttpMetricOptions { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(url, other.url) && + _deepEquals(httpMethod, other.httpMethod); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class HttpMetricAttributes { @@ -155,12 +222,16 @@ class HttpMetricAttributes { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(httpResponseCode, other.httpResponseCode) && + _deepEquals(requestPayloadSize, other.requestPayloadSize) && + _deepEquals(responsePayloadSize, other.responsePayloadSize) && + _deepEquals(responseContentType, other.responseContentType) && + _deepEquals(attributes, other.attributes); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class TraceAttributes { @@ -201,12 +272,13 @@ class TraceAttributes { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(metrics, other.metrics) && + _deepEquals(attributes, other.attributes); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class _PigeonCodec extends StandardMessageCodec { @@ -237,7 +309,7 @@ class _PigeonCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 129: - final int? value = readValue(buffer) as int?; + final value = readValue(buffer) as int?; return value == null ? null : HttpMethod.values[value]; case 130: return HttpMetricOptions.decode(readValue(buffer)!); @@ -267,173 +339,119 @@ class FirebasePerformanceHostApi { final String pigeonVar_messageChannelSuffix; Future setPerformanceCollectionEnabled(bool enabled) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([enabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future isPerformanceCollectionEnabled() async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.isPerformanceCollectionEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as bool; } Future startTrace(String name) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([name]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as int?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as int; } Future stopTrace(int handle, TraceAttributes attributes) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([handle, attributes]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future startHttpMetric(HttpMetricOptions options) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([options]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as int?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as int; } Future stopHttpMetric( int handle, HttpMetricAttributes attributes) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([handle, attributes]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } diff --git a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml index 9f8b80674720..5470c22a2612 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml @@ -12,10 +12,11 @@ dependencies: firebase_core: ^4.7.0 flutter: sdk: flutter + meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: firebase_core_platform_interface: ^6.0.3 flutter_test: sdk: flutter - pigeon: 25.3.2 + pigeon: 26.3.4 diff --git a/packages/firebase_performance/firebase_performance_platform_interface/test/pigeon/test_api.dart b/packages/firebase_performance/firebase_performance_platform_interface/test/pigeon/test_api.dart index 4426bc6d19af..e1bf4fe97659 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/test/pigeon/test_api.dart +++ b/packages/firebase_performance/firebase_performance_platform_interface/test/pigeon/test_api.dart @@ -1,9 +1,9 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; @@ -41,7 +41,7 @@ class _PigeonCodec extends StandardMessageCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 129: - final int? value = readValue(buffer) as int?; + final value = readValue(buffer) as int?; return value == null ? null : HttpMethod.values[value]; case 130: return HttpMetricOptions.decode(readValue(buffer)!); @@ -80,9 +80,7 @@ abstract class TestFirebasePerformanceHostApi { messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -93,14 +91,10 @@ abstract class TestFirebasePerformanceHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled was null.'); - final List args = (message as List?)!; - final bool? arg_enabled = (args[0] as bool?); - assert(arg_enabled != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled was null, expected non-null bool.'); + final List args = message! as List; + final bool arg_enabled = args[0]! as bool; try { - await api.setPerformanceCollectionEnabled(arg_enabled!); + await api.setPerformanceCollectionEnabled(arg_enabled); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -112,9 +106,7 @@ abstract class TestFirebasePerformanceHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.isPerformanceCollectionEnabled$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -138,9 +130,7 @@ abstract class TestFirebasePerformanceHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -151,14 +141,10 @@ abstract class TestFirebasePerformanceHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace was null.'); - final List args = (message as List?)!; - final String? arg_name = (args[0] as String?); - assert(arg_name != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace was null, expected non-null String.'); + final List args = message! as List; + final String arg_name = args[0]! as String; try { - final int output = await api.startTrace(arg_name!); + final int output = await api.startTrace(arg_name); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -170,9 +156,7 @@ abstract class TestFirebasePerformanceHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -183,17 +167,11 @@ abstract class TestFirebasePerformanceHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace was null.'); - final List args = (message as List?)!; - final int? arg_handle = (args[0] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace was null, expected non-null int.'); - final TraceAttributes? arg_attributes = (args[1] as TraceAttributes?); - assert(arg_attributes != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace was null, expected non-null TraceAttributes.'); + final List args = message! as List; + final int arg_handle = args[0]! as int; + final TraceAttributes arg_attributes = args[1]! as TraceAttributes; try { - await api.stopTrace(arg_handle!, arg_attributes!); + await api.stopTrace(arg_handle, arg_attributes); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -205,9 +183,7 @@ abstract class TestFirebasePerformanceHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -218,15 +194,10 @@ abstract class TestFirebasePerformanceHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric was null.'); - final List args = (message as List?)!; - final HttpMetricOptions? arg_options = - (args[0] as HttpMetricOptions?); - assert(arg_options != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric was null, expected non-null HttpMetricOptions.'); + final List args = message! as List; + final HttpMetricOptions arg_options = args[0]! as HttpMetricOptions; try { - final int output = await api.startHttpMetric(arg_options!); + final int output = await api.startHttpMetric(arg_options); return [output]; } on PlatformException catch (e) { return wrapResponse(error: e); @@ -238,9 +209,7 @@ abstract class TestFirebasePerformanceHostApi { } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( + final pigeonVar_channel = BasicMessageChannel( 'dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); @@ -251,18 +220,12 @@ abstract class TestFirebasePerformanceHostApi { _testBinaryMessengerBinding!.defaultBinaryMessenger .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric was null.'); - final List args = (message as List?)!; - final int? arg_handle = (args[0] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric was null, expected non-null int.'); - final HttpMetricAttributes? arg_attributes = - (args[1] as HttpMetricAttributes?); - assert(arg_attributes != null, - 'Argument for dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric was null, expected non-null HttpMetricAttributes.'); + final List args = message! as List; + final int arg_handle = args[0]! as int; + final HttpMetricAttributes arg_attributes = + args[1]! as HttpMetricAttributes; try { - await api.stopHttpMetric(arg_handle!, arg_attributes!); + await api.stopHttpMetric(arg_handle, arg_attributes); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); diff --git a/packages/firebase_remote_config/analysis_options.yaml b/packages/firebase_remote_config/analysis_options.yaml index 75a21d21f70b..02c4d6a7e39a 100644 --- a/packages/firebase_remote_config/analysis_options.yaml +++ b/packages/firebase_remote_config/analysis_options.yaml @@ -8,3 +8,4 @@ analyzer: exclude: - firebase_remote_config_platform_interface/lib/src/pigeon/messages.pigeon.dart - firebase_remote_config_platform_interface/test/pigeon/test_api.dart + - firebase_remote_config_platform_interface/pigeons/messages.dart diff --git a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt index 40c1056cf62c..4a3d096eafdc 100644 --- a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt +++ b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -37,36 +37,150 @@ private object GeneratedAndroidFirebaseRemoteConfigPigeonUtils { ) } } + fun doubleEquals(a: Double, b: Double): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) + } + + fun floatEquals(a: Float, b: Float): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN()) + } + + fun doubleHash(d: Double): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (d == 0.0) 0.0 else d + val bits = java.lang.Double.doubleToLongBits(normalized) + return (bits xor (bits ushr 32)).toInt() + } + + fun floatHash(f: Float): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (f == 0.0f) 0.0f else f + return java.lang.Float.floatToIntBits(normalized) + } + fun deepEquals(a: Any?, b: Any?): Boolean { + if (a === b) { + return true + } + if (a == null || b == null) { + return false + } if (a is ByteArray && b is ByteArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is IntArray && b is IntArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is LongArray && b is LongArray) { - return a.contentEquals(b) + return a.contentEquals(b) } if (a is DoubleArray && b is DoubleArray) { - return a.contentEquals(b) + if (a.size != b.size) return false + for (i in a.indices) { + if (!doubleEquals(a[i], b[i])) return false + } + return true + } + if (a is FloatArray && b is FloatArray) { + if (a.size != b.size) return false + for (i in a.indices) { + if (!floatEquals(a[i], b[i])) return false + } + return true } if (a is Array<*> && b is Array<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + for (i in a.indices) { + if (!deepEquals(a[i], b[i])) return false + } + return true } if (a is List<*> && b is List<*>) { - return a.size == b.size && - a.indices.all{ deepEquals(a[it], b[it]) } + if (a.size != b.size) return false + val iterA = a.iterator() + val iterB = b.iterator() + while (iterA.hasNext() && iterB.hasNext()) { + if (!deepEquals(iterA.next(), iterB.next())) return false + } + return true } if (a is Map<*, *> && b is Map<*, *>) { - return a.size == b.size && a.all { - (b as Map).containsKey(it.key) && - deepEquals(it.value, b[it.key]) + if (a.size != b.size) return false + for (entry in a) { + val key = entry.key + var found = false + for (bEntry in b) { + if (deepEquals(key, bEntry.key)) { + if (deepEquals(entry.value, bEntry.value)) { + found = true + break + } else { + return false + } + } + } + if (!found) return false } + return true + } + if (a is Double && b is Double) { + return doubleEquals(a, b) + } + if (a is Float && b is Float) { + return floatEquals(a, b) } return a == b } - + + fun deepHash(value: Any?): Int { + return when (value) { + null -> 0 + is ByteArray -> value.contentHashCode() + is IntArray -> value.contentHashCode() + is LongArray -> value.contentHashCode() + is DoubleArray -> { + var result = 1 + for (item in value) { + result = 31 * result + doubleHash(item) + } + result + } + is FloatArray -> { + var result = 1 + for (item in value) { + result = 31 * result + floatHash(item) + } + result + } + is Array<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is List<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is Map<*, *> -> { + var result = 0 + for (entry in value) { + result += ((deepHash(entry.key) * 31) xor deepHash(entry.value)) + } + result + } + is Double -> doubleHash(value) + is Float -> floatHash(value) + else -> value.hashCode() + } + } + } /** @@ -79,7 +193,7 @@ class FlutterError ( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() /** Generated class from Pigeon that represents data sent in messages. */ data class RemoteConfigPigeonSettings ( @@ -101,15 +215,22 @@ data class RemoteConfigPigeonSettings ( ) } override fun equals(other: Any?): Boolean { - if (other !is RemoteConfigPigeonSettings) { + if (other == null || other.javaClass != javaClass) { return false } if (this === other) { return true } - return GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepEquals(toList(), other.toList()) } + val other = other as RemoteConfigPigeonSettings + return GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepEquals(this.fetchTimeoutSeconds, other.fetchTimeoutSeconds) && GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepEquals(this.minimumFetchIntervalSeconds, other.minimumFetchIntervalSeconds) + } - override fun hashCode(): Int = toList().hashCode() + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepHash(this.fetchTimeoutSeconds) + result = 31 * result + GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepHash(this.minimumFetchIntervalSeconds) + return result + } } private open class GeneratedAndroidFirebaseRemoteConfigPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift index ac749f8cdb7f..15be7c5b33a7 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -52,7 +52,7 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } @@ -66,6 +66,19 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } +private func doubleEqualsFirebaseRemoteConfigMessages(_ lhs: Double, _ rhs: Double) -> Bool { + (lhs.isNaN && rhs.isNaN) || lhs == rhs +} + +private func doubleHashFirebaseRemoteConfigMessages(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } +} + func deepEqualsFirebaseRemoteConfigMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { let cleanLhs = nilOrValue(lhs) as Any? let cleanRhs = nilOrValue(rhs) as Any? @@ -76,59 +89,90 @@ func deepEqualsFirebaseRemoteConfigMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case is (Void, Void): + case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: return true - case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): - return cleanLhsHashable == cleanRhsHashable + case is (Void, Void): + return true - case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): - guard cleanLhsArray.count == cleanRhsArray.count else { return false } - for (index, element) in cleanLhsArray.enumerated() { - if !deepEqualsFirebaseRemoteConfigMessages(element, cleanRhsArray[index]) { + case let (lhsArray, rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEqualsFirebaseRemoteConfigMessages(element, rhsArray[index]) { return false } } return true - case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } - for (key, cleanLhsValue) in cleanLhsDictionary { - guard cleanRhsDictionary.index(forKey: key) != nil else { return false } - if !deepEqualsFirebaseRemoteConfigMessages(cleanLhsValue, cleanRhsDictionary[key]!) { + case let (lhsArray, rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEqualsFirebaseRemoteConfigMessages(element, rhsArray[index]) { return false } } return true + case let (lhsDictionary, rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEqualsFirebaseRemoteConfigMessages(lhsKey, rhsKey) { + if deepEqualsFirebaseRemoteConfigMessages(lhsValue, rhsValue) { + found = true + break + } else { + return false + } + } + } + if !found { return false } + } + return true + + case let (lhs as Double, rhs as Double): + return doubleEqualsFirebaseRemoteConfigMessages(lhs, rhs) + + case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable + default: - // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be - // untrue. return false } } func deepHashFirebaseRemoteConfigMessages(value: Any?, hasher: inout Hasher) { - if let valueList = value as? [AnyHashable] { - for item in valueList { - deepHashFirebaseRemoteConfigMessages(value: item, hasher: &hasher) - } - return - } - - if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { - hasher.combine(key) - deepHashFirebaseRemoteConfigMessages(value: valueDict[key]!, hasher: &hasher) + let cleanValue = nilOrValue(value) as Any? + if let cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHashFirebaseRemoteConfigMessages(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHashFirebaseRemoteConfigMessages(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHashFirebaseRemoteConfigMessages(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHashFirebaseRemoteConfigMessages(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHashFirebaseRemoteConfigMessages(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) } - return - } - - if let hashableValue = value as? AnyHashable { - hasher.combine(hashableValue.hashValue) + } else { + hasher.combine(0) } - - return hasher.combine(String(describing: value)) } /// Generated class from Pigeon that represents data sent in messages. @@ -155,11 +199,23 @@ struct RemoteConfigPigeonSettings: Hashable { } static func == (lhs: RemoteConfigPigeonSettings, rhs: RemoteConfigPigeonSettings) -> Bool { - deepEqualsFirebaseRemoteConfigMessages(lhs.toList(), rhs.toList()) + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseRemoteConfigMessages( + lhs.fetchTimeoutSeconds, + rhs.fetchTimeoutSeconds + ) && + deepEqualsFirebaseRemoteConfigMessages( + lhs.minimumFetchIntervalSeconds, + rhs.minimumFetchIntervalSeconds + ) } func hash(into hasher: inout Hasher) { - deepHashFirebaseRemoteConfigMessages(value: toList(), hasher: &hasher) + hasher.combine("RemoteConfigPigeonSettings") + deepHashFirebaseRemoteConfigMessages(value: fetchTimeoutSeconds, hasher: &hasher) + deepHashFirebaseRemoteConfigMessages(value: minimumFetchIntervalSeconds, hasher: &hasher) } } diff --git a/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.cpp b/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.cpp index f8f200289fff..bf13f7b7ad47 100644 --- a/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.cpp +++ b/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_remote_config_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,6 +33,212 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace // RemoteConfigPigeonSettings RemoteConfigPigeonSettings::RemoteConfigPigeonSettings( @@ -70,22 +278,47 @@ RemoteConfigPigeonSettings RemoteConfigPigeonSettings::FromEncodableList( return decoded; } +bool RemoteConfigPigeonSettings::operator==( + const RemoteConfigPigeonSettings& other) const { + return PigeonInternalDeepEquals(fetch_timeout_seconds_, + other.fetch_timeout_seconds_) && + PigeonInternalDeepEquals(minimum_fetch_interval_seconds_, + other.minimum_fetch_interval_seconds_); +} + +bool RemoteConfigPigeonSettings::operator!=( + const RemoteConfigPigeonSettings& other) const { + return !(*this == other); +} + +size_t RemoteConfigPigeonSettings::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(fetch_timeout_seconds_); + result = + result * 31 + PigeonInternalDeepHash(minimum_fetch_interval_seconds_); + return result; +} + +size_t PigeonInternalDeepHash(const RemoteConfigPigeonSettings& v) { + return v.Hash(); +} + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { case 129: { return CustomEncodableValue(RemoteConfigPigeonSettings::FromEncodableList( std::get(ReadValue(stream)))); } default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { if (custom_value->type() == typeid(RemoteConfigPigeonSettings)) { @@ -97,25 +330,25 @@ void PigeonInternalCodecSerializer::WriteValue( return; } } - flutter::StandardCodecSerializer::WriteValue(value, stream); + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseRemoteConfigHostApi. -const flutter::StandardMessageCodec& FirebaseRemoteConfigHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseRemoteConfigHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseRemoteConfigHostApi` to handle messages // through the `binary_messenger`. void FirebaseRemoteConfigHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, + ::flutter::BinaryMessenger* binary_messenger, FirebaseRemoteConfigHostApi* api) { FirebaseRemoteConfigHostApi::SetUp(binary_messenger, api, ""); } void FirebaseRemoteConfigHostApi::SetUp( - flutter::BinaryMessenger* binary_messenger, + ::flutter::BinaryMessenger* binary_messenger, FirebaseRemoteConfigHostApi* api, const std::string& message_channel_suffix) { const std::string prepended_suffix = @@ -132,7 +365,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -170,7 +403,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -209,7 +442,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -247,7 +480,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -294,7 +527,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -339,7 +572,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -377,7 +610,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -423,7 +656,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -462,7 +695,7 @@ void FirebaseRemoteConfigHostApi::SetUp( if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); diff --git a/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.h b/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.h index c325943b6d22..43ddff65edaa 100644 --- a/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.h +++ b/packages/firebase_remote_config/firebase_remote_config/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -71,17 +71,30 @@ class RemoteConfigPigeonSettings { int64_t minimum_fetch_interval_seconds() const; void set_minimum_fetch_interval_seconds(int64_t value_arg); + bool operator==(const RemoteConfigPigeonSettings& other) const; + bool operator!=(const RemoteConfigPigeonSettings& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + private: static RemoteConfigPigeonSettings FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseRemoteConfigHostApi; friend class PigeonInternalCodecSerializer; int64_t fetch_timeout_seconds_; int64_t minimum_fetch_interval_seconds_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -89,12 +102,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -118,32 +131,33 @@ class FirebaseRemoteConfigHostApi { std::function reply)> result) = 0; virtual void SetDefaults( const std::string& app_name, - const flutter::EncodableMap& default_parameters, + const ::flutter::EncodableMap& default_parameters, std::function reply)> result) = 0; virtual void EnsureInitialized( const std::string& app_name, std::function reply)> result) = 0; virtual void SetCustomSignals( - const std::string& app_name, const flutter::EncodableMap& custom_signals, + const std::string& app_name, + const ::flutter::EncodableMap& custom_signals, std::function reply)> result) = 0; virtual void GetAll( const std::string& app_name, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void GetProperties( const std::string& app_name, - std::function reply)> result) = 0; + std::function reply)> result) = 0; // The codec used by FirebaseRemoteConfigHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseRemoteConfigHostApi` to handle messages // through the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseRemoteConfigHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseRemoteConfigHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseRemoteConfigHostApi() = default; diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_remote_config/firebase_remote_config_platform_interface/lib/src/pigeon/messages.pigeon.dart index c9ed1ec45a6a..f1d5c1686e7d 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,49 +1,104 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); -} - -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { - if (empty) { - return []; - } - if (error == null) { - return [result]; +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); } - return [error.code, error.message, error.details]; + return replyList.firstOrNull; } bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } if (a is List && b is List) { return a.length == b.length && a.indexed .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; } return a == b; } +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} + class RemoteConfigPigeonSettings { RemoteConfigPigeonSettings({ required this.fetchTimeoutSeconds, @@ -83,12 +138,14 @@ class RemoteConfigPigeonSettings { if (identical(this, other)) { return true; } - return _deepEquals(encode(), other.encode()); + return _deepEquals(fetchTimeoutSeconds, other.fetchTimeoutSeconds) && + _deepEquals( + minimumFetchIntervalSeconds, other.minimumFetchIntervalSeconds); } @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => _deepHash([runtimeType, ..._toList()]); } class _PigeonCodec extends StandardMessageCodec { @@ -133,261 +190,182 @@ class FirebaseRemoteConfigHostApi { final String pigeonVar_messageChannelSuffix; Future fetch(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetch$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future fetchAndActivate(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetchAndActivate$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as bool; } Future activate(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.activate$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as bool; } Future setConfigSettings( String appName, RemoteConfigPigeonSettings settings) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setConfigSettings$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, settings]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setDefaults( String appName, Map defaultParameters) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setDefaults$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, defaultParameters]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future ensureInitialized(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.ensureInitialized$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setCustomSignals( String appName, Map customSignals) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setCustomSignals$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, customSignals]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future> getAll(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getAll$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as Map?)! - .cast(); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } Future> getProperties(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getProperties$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as Map?)! - .cast(); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } } diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml index 26430f70ed34..57ffffc5c647 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml @@ -23,4 +23,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 - pigeon: 25.3.2 + pigeon: 26.3.4 diff --git a/packages/firebase_storage/analysis_options.yaml b/packages/firebase_storage/analysis_options.yaml index 5004d8c56d8c..ad032c876e0e 100644 --- a/packages/firebase_storage/analysis_options.yaml +++ b/packages/firebase_storage/analysis_options.yaml @@ -10,6 +10,10 @@ analyzer: # We explicitly enabled even conflicting rules and are fixing the conflict # in this file included_file_warning: ignore + exclude: + - firebase_storage_platform_interface/lib/src/pigeon/messages.pigeon.dart + - firebase_storage_platform_interface/test/pigeon/test_api.dart + - firebase_storage_platform_interface/pigeons/messages.dart linter: rules: diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt index 7453d5040713..466c44c98220 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt @@ -81,38 +81,38 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } } - private fun getStorageFromPigeon(app: PigeonStorageFirebaseApp): FirebaseStorage { + private fun getStorageFromPigeon(app: InternalStorageFirebaseApp): FirebaseStorage { val androidApp = FirebaseApp.getInstance(app.appName) return FirebaseStorage.getInstance(androidApp, "gs://${app.bucket}") } private fun getReferenceFromPigeon( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference + app: InternalStorageFirebaseApp, + reference: InternalStorageReference ): StorageReference { val androidStorage = getStorageFromPigeon(app) return androidStorage.getReference(reference.fullPath) } - private fun convertToPigeonReference(reference: StorageReference): PigeonStorageReference { - return PigeonStorageReference( + private fun convertToPigeonReference(reference: StorageReference): InternalStorageReference { + return InternalStorageReference( bucket = reference.bucket, fullPath = reference.path, name = reference.name ) } - private fun convertToPigeonMetaData(storageMetadata: StorageMetadata?): PigeonFullMetaData { - return PigeonFullMetaData(metadata = parseMetadataToMap(storageMetadata)) + private fun convertToPigeonMetaData(storageMetadata: StorageMetadata?): InternalFullMetaData { + return InternalFullMetaData(metadata = parseMetadataToMap(storageMetadata)) } - private fun convertToPigeonListResult(listResult: ListResult): PigeonListResult { + private fun convertToPigeonListResult(listResult: ListResult): InternalListResult { val items = listResult.items.map { convertToPigeonReference(it) } val prefixes = listResult.prefixes.map { convertToPigeonReference(it) } - return PigeonListResult(items = items, pageToken = listResult.pageToken, prefixs = prefixes) + return InternalListResult(items = items, pageToken = listResult.pageToken, prefixs = prefixes) } - private fun getMetaDataFromPigeon(pigeonSettableMetatdata: PigeonSettableMetadata): StorageMetadata { + private fun getMetaDataFromPigeon(pigeonSettableMetatdata: InternalSettableMetadata): StorageMetadata { val builder = StorageMetadata.Builder() pigeonSettableMetatdata.contentType?.let { builder.setContentType(it) } pigeonSettableMetatdata.cacheControl?.let { builder.setCacheControl(it) } @@ -132,17 +132,17 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun getReferencebyPath( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, path: String, bucket: String?, - callback: (Result) -> Unit + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(path) callback(Result.success(convertToPigeonReference(androidReference))) } override fun useStorageEmulator( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, host: String, port: Long, callback: (Result) -> Unit @@ -157,8 +157,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceDelete( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) @@ -169,8 +169,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceGetDownloadURL( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) @@ -181,8 +181,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceGetData( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, maxSize: Long, callback: (Result) -> Unit ) { @@ -194,9 +194,9 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceGetMetaData( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.metadata.addOnCompleteListener { task -> @@ -206,10 +206,10 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceList( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, - options: PigeonListOptions, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + options: InternalListOptions, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) val task = if (options.pageToken != null) { @@ -224,9 +224,9 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceListAll( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.listAll().addOnCompleteListener { task -> @@ -236,10 +236,10 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceUpdateMetadata( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, - metadata: PigeonSettableMetadata, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + metadata: InternalSettableMetadata, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.updateMetadata(getMetaDataFromPigeon(metadata)).addOnCompleteListener { task -> @@ -249,10 +249,10 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referencePutData( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, data: ByteArray, - settableMetaData: PigeonSettableMetadata, + settableMetaData: InternalSettableMetadata, handle: Long, callback: (Result) -> Unit ) { @@ -269,11 +269,11 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referencePutString( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, data: String, format: Long, - settableMetaData: PigeonSettableMetadata, + settableMetaData: InternalSettableMetadata, handle: Long, callback: (Result) -> Unit ) { @@ -291,10 +291,10 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referencePutFile( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, filePath: String, - settableMetaData: PigeonSettableMetadata?, + settableMetaData: InternalSettableMetadata?, handle: Long, callback: (Result) -> Unit ) { @@ -315,8 +315,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceDownloadFile( - app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference, + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, filePath: String, handle: Long, callback: (Result) -> Unit @@ -333,7 +333,7 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun taskPause( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit ) { @@ -361,7 +361,7 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun taskResume( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit ) { @@ -389,7 +389,7 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun taskCancel( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit ) { @@ -414,7 +414,7 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun setMaxOperationRetryTime( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit ) { @@ -424,7 +424,7 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun setMaxUploadRetryTime( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit ) { @@ -434,7 +434,7 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun setMaxDownloadRetryTime( - app: PigeonStorageFirebaseApp, + app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit ) { diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt index 66149daa3d82..ffd0cf5a58d8 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt @@ -1,37 +1,186 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") package io.flutter.plugins.firebase.storage import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer +private object GeneratedAndroidFirebaseStoragePigeonUtils { -private fun wrapResult(result: Any?): List { - return listOf(result) -} + fun wrapResult(result: Any?): List { + return listOf(result) + } -private fun wrapError(exception: Throwable): List { - if (exception is FlutterError) { - return listOf( - exception.code, - exception.message, - exception.details - ) - } else { - return listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } + } + fun doubleEquals(a: Double, b: Double): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) + } + + fun floatEquals(a: Float, b: Float): Boolean { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN()) + } + + fun doubleHash(d: Double): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (d == 0.0) 0.0 else d + val bits = java.lang.Double.doubleToLongBits(normalized) + return (bits xor (bits ushr 32)).toInt() + } + + fun floatHash(f: Float): Int { + // Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes. + val normalized = if (f == 0.0f) 0.0f else f + return java.lang.Float.floatToIntBits(normalized) + } + + fun deepEquals(a: Any?, b: Any?): Boolean { + if (a === b) { + return true + } + if (a == null || b == null) { + return false + } + if (a is ByteArray && b is ByteArray) { + return a.contentEquals(b) + } + if (a is IntArray && b is IntArray) { + return a.contentEquals(b) + } + if (a is LongArray && b is LongArray) { + return a.contentEquals(b) + } + if (a is DoubleArray && b is DoubleArray) { + if (a.size != b.size) return false + for (i in a.indices) { + if (!doubleEquals(a[i], b[i])) return false + } + return true + } + if (a is FloatArray && b is FloatArray) { + if (a.size != b.size) return false + for (i in a.indices) { + if (!floatEquals(a[i], b[i])) return false + } + return true + } + if (a is Array<*> && b is Array<*>) { + if (a.size != b.size) return false + for (i in a.indices) { + if (!deepEquals(a[i], b[i])) return false + } + return true + } + if (a is List<*> && b is List<*>) { + if (a.size != b.size) return false + val iterA = a.iterator() + val iterB = b.iterator() + while (iterA.hasNext() && iterB.hasNext()) { + if (!deepEquals(iterA.next(), iterB.next())) return false + } + return true + } + if (a is Map<*, *> && b is Map<*, *>) { + if (a.size != b.size) return false + for (entry in a) { + val key = entry.key + var found = false + for (bEntry in b) { + if (deepEquals(key, bEntry.key)) { + if (deepEquals(entry.value, bEntry.value)) { + found = true + break + } else { + return false + } + } + } + if (!found) return false + } + return true + } + if (a is Double && b is Double) { + return doubleEquals(a, b) + } + if (a is Float && b is Float) { + return floatEquals(a, b) + } + return a == b } + + fun deepHash(value: Any?): Int { + return when (value) { + null -> 0 + is ByteArray -> value.contentHashCode() + is IntArray -> value.contentHashCode() + is LongArray -> value.contentHashCode() + is DoubleArray -> { + var result = 1 + for (item in value) { + result = 31 * result + doubleHash(item) + } + result + } + is FloatArray -> { + var result = 1 + for (item in value) { + result = 31 * result + floatHash(item) + } + result + } + is Array<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is List<*> -> { + var result = 1 + for (item in value) { + result = 31 * result + deepHash(item) + } + result + } + is Map<*, *> -> { + var result = 0 + for (entry in value) { + result += ((deepHash(entry.key) * 31) xor deepHash(entry.value)) + } + result + } + is Double -> doubleHash(value) + is Float -> floatHash(value) + else -> value.hashCode() + } + } + } /** @@ -44,13 +193,13 @@ class FlutterError ( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() /** * The type of operation that generated the action code from calling * [TaskState]. */ -enum class PigeonStorageTaskState(val raw: Int) { +enum class InternalStorageTaskState(val raw: Int) { /** Indicates the task has been paused by the user. */ PAUSED(0), /** Indicates the task is currently in-progress. */ @@ -63,83 +212,132 @@ enum class PigeonStorageTaskState(val raw: Int) { ERROR(4); companion object { - fun ofRaw(raw: Int): PigeonStorageTaskState? { + fun ofRaw(raw: Int): InternalStorageTaskState? { return values().firstOrNull { it.raw == raw } } } } /** Generated class from Pigeon that represents data sent in messages. */ -data class PigeonStorageFirebaseApp ( +data class InternalStorageFirebaseApp ( val appName: String, val tenantId: String? = null, val bucket: String - -) { +) + { companion object { - @Suppress("UNCHECKED_CAST") - fun fromList(list: List): PigeonStorageFirebaseApp { - val appName = list[0] as String - val tenantId = list[1] as String? - val bucket = list[2] as String - return PigeonStorageFirebaseApp(appName, tenantId, bucket) + fun fromList(pigeonVar_list: List): InternalStorageFirebaseApp { + val appName = pigeonVar_list[0] as String + val tenantId = pigeonVar_list[1] as String? + val bucket = pigeonVar_list[2] as String + return InternalStorageFirebaseApp(appName, tenantId, bucket) } } fun toList(): List { - return listOf( + return listOf( appName, tenantId, bucket, ) } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as InternalStorageFirebaseApp + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.appName, other.appName) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.tenantId, other.tenantId) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bucket, other.bucket) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.appName) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.tenantId) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.bucket) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ -data class PigeonStorageReference ( +data class InternalStorageReference ( val bucket: String, val fullPath: String, val name: String - -) { +) + { companion object { - @Suppress("UNCHECKED_CAST") - fun fromList(list: List): PigeonStorageReference { - val bucket = list[0] as String - val fullPath = list[1] as String - val name = list[2] as String - return PigeonStorageReference(bucket, fullPath, name) + fun fromList(pigeonVar_list: List): InternalStorageReference { + val bucket = pigeonVar_list[0] as String + val fullPath = pigeonVar_list[1] as String + val name = pigeonVar_list[2] as String + return InternalStorageReference(bucket, fullPath, name) } } fun toList(): List { - return listOf( + return listOf( bucket, fullPath, name, ) } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as InternalStorageReference + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bucket, other.bucket) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.fullPath, other.fullPath) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.name, other.name) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.bucket) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.fullPath) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.name) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ -data class PigeonFullMetaData ( +data class InternalFullMetaData ( val metadata: Map? = null - -) { +) + { companion object { - @Suppress("UNCHECKED_CAST") - fun fromList(list: List): PigeonFullMetaData { - val metadata = list[0] as Map? - return PigeonFullMetaData(metadata) + fun fromList(pigeonVar_list: List): InternalFullMetaData { + val metadata = pigeonVar_list[0] as Map? + return InternalFullMetaData(metadata) } } fun toList(): List { - return listOf( + return listOf( metadata, ) } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as InternalFullMetaData + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.metadata, other.metadata) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.metadata) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ -data class PigeonListOptions ( +data class InternalListOptions ( /** * If set, limits the total number of `prefixes` and `items` to return. * @@ -152,26 +350,42 @@ data class PigeonListOptions ( * If provided, listing is resumed from the previous position. */ val pageToken: String? = null - -) { +) + { companion object { - @Suppress("UNCHECKED_CAST") - fun fromList(list: List): PigeonListOptions { - val maxResults = list[0].let { if (it is Int) it.toLong() else it as Long } - val pageToken = list[1] as String? - return PigeonListOptions(maxResults, pageToken) + fun fromList(pigeonVar_list: List): InternalListOptions { + val maxResults = pigeonVar_list[0] as Long + val pageToken = pigeonVar_list[1] as String? + return InternalListOptions(maxResults, pageToken) } } fun toList(): List { - return listOf( + return listOf( maxResults, pageToken, ) } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as InternalListOptions + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.maxResults, other.maxResults) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.pageToken, other.pageToken) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.maxResults) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.pageToken) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ -data class PigeonSettableMetadata ( +data class InternalSettableMetadata ( /** * Served as the 'Cache-Control' header on object download. * @@ -204,22 +418,21 @@ data class PigeonSettableMetadata ( val contentType: String? = null, /** Additional user-defined custom metadata. */ val customMetadata: Map? = null - -) { +) + { companion object { - @Suppress("UNCHECKED_CAST") - fun fromList(list: List): PigeonSettableMetadata { - val cacheControl = list[0] as String? - val contentDisposition = list[1] as String? - val contentEncoding = list[2] as String? - val contentLanguage = list[3] as String? - val contentType = list[4] as String? - val customMetadata = list[5] as Map? - return PigeonSettableMetadata(cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType, customMetadata) + fun fromList(pigeonVar_list: List): InternalSettableMetadata { + val cacheControl = pigeonVar_list[0] as String? + val contentDisposition = pigeonVar_list[1] as String? + val contentEncoding = pigeonVar_list[2] as String? + val contentLanguage = pigeonVar_list[3] as String? + val contentType = pigeonVar_list[4] as String? + val customMetadata = pigeonVar_list[5] as Map? + return InternalSettableMetadata(cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType, customMetadata) } } fun toList(): List { - return listOf( + return listOf( cacheControl, contentDisposition, contentEncoding, @@ -228,65 +441,157 @@ data class PigeonSettableMetadata ( customMetadata, ) } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as InternalSettableMetadata + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.cacheControl, other.cacheControl) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentDisposition, other.contentDisposition) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentEncoding, other.contentEncoding) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentLanguage, other.contentLanguage) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentType, other.contentType) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.customMetadata, other.customMetadata) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.cacheControl) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentDisposition) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentEncoding) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentLanguage) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentType) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.customMetadata) + return result + } } /** Generated class from Pigeon that represents data sent in messages. */ -data class PigeonListResult ( - val items: List, - val pageToken: String? = null, - val prefixs: List +data class InternalStorageTaskSnapShot ( + val bytesTransferred: Long, + val metadata: InternalFullMetaData? = null, + val state: InternalStorageTaskState, + val totalBytes: Long +) + { + companion object { + fun fromList(pigeonVar_list: List): InternalStorageTaskSnapShot { + val bytesTransferred = pigeonVar_list[0] as Long + val metadata = pigeonVar_list[1] as InternalFullMetaData? + val state = pigeonVar_list[2] as InternalStorageTaskState + val totalBytes = pigeonVar_list[3] as Long + return InternalStorageTaskSnapShot(bytesTransferred, metadata, state, totalBytes) + } + } + fun toList(): List { + return listOf( + bytesTransferred, + metadata, + state, + totalBytes, + ) + } + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as InternalStorageTaskSnapShot + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bytesTransferred, other.bytesTransferred) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.metadata, other.metadata) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.state, other.state) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.totalBytes, other.totalBytes) + } + + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.bytesTransferred) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.metadata) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.state) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.totalBytes) + return result + } +} -) { +/** Generated class from Pigeon that represents data sent in messages. */ +data class InternalListResult ( + val items: List, + val pageToken: String? = null, + val prefixs: List +) + { companion object { - @Suppress("UNCHECKED_CAST") - fun fromList(list: List): PigeonListResult { - val items = list[0] as List - val pageToken = list[1] as String? - val prefixs = list[2] as List - return PigeonListResult(items, pageToken, prefixs) + fun fromList(pigeonVar_list: List): InternalListResult { + val items = pigeonVar_list[0] as List + val pageToken = pigeonVar_list[1] as String? + val prefixs = pigeonVar_list[2] as List + return InternalListResult(items, pageToken, prefixs) } } fun toList(): List { - return listOf( + return listOf( items, pageToken, prefixs, ) } -} + override fun equals(other: Any?): Boolean { + if (other == null || other.javaClass != javaClass) { + return false + } + if (this === other) { + return true + } + val other = other as InternalListResult + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.items, other.items) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.pageToken, other.pageToken) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.prefixs, other.prefixs) + } -@Suppress("UNCHECKED_CAST") -private object FirebaseStorageHostApiCodec : StandardMessageCodec() { + override fun hashCode(): Int { + var result = javaClass.hashCode() + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.items) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.pageToken) + result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.prefixs) + return result + } +} +private open class GeneratedAndroidFirebaseStoragePigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { - 128.toByte() -> { - return (readValue(buffer) as? List)?.let { - PigeonFullMetaData.fromList(it) - } - } 129.toByte() -> { - return (readValue(buffer) as? List)?.let { - PigeonListOptions.fromList(it) + return (readValue(buffer) as Long?)?.let { + InternalStorageTaskState.ofRaw(it.toInt()) } } 130.toByte() -> { return (readValue(buffer) as? List)?.let { - PigeonListResult.fromList(it) + InternalStorageFirebaseApp.fromList(it) } } 131.toByte() -> { return (readValue(buffer) as? List)?.let { - PigeonSettableMetadata.fromList(it) + InternalStorageReference.fromList(it) } } 132.toByte() -> { return (readValue(buffer) as? List)?.let { - PigeonStorageFirebaseApp.fromList(it) + InternalFullMetaData.fromList(it) } } 133.toByte() -> { return (readValue(buffer) as? List)?.let { - PigeonStorageReference.fromList(it) + InternalListOptions.fromList(it) + } + } + 134.toByte() -> { + return (readValue(buffer) as? List)?.let { + InternalSettableMetadata.fromList(it) + } + } + 135.toByte() -> { + return (readValue(buffer) as? List)?.let { + InternalStorageTaskSnapShot.fromList(it) + } + } + 136.toByte() -> { + return (readValue(buffer) as? List)?.let { + InternalListResult.fromList(it) } } else -> super.readValueOfType(type, buffer) @@ -294,80 +599,90 @@ private object FirebaseStorageHostApiCodec : StandardMessageCodec() { } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { when (value) { - is PigeonFullMetaData -> { - stream.write(128) - writeValue(stream, value.toList()) - } - is PigeonListOptions -> { + is InternalStorageTaskState -> { stream.write(129) - writeValue(stream, value.toList()) + writeValue(stream, value.raw.toLong()) } - is PigeonListResult -> { + is InternalStorageFirebaseApp -> { stream.write(130) writeValue(stream, value.toList()) } - is PigeonSettableMetadata -> { + is InternalStorageReference -> { stream.write(131) writeValue(stream, value.toList()) } - is PigeonStorageFirebaseApp -> { + is InternalFullMetaData -> { stream.write(132) writeValue(stream, value.toList()) } - is PigeonStorageReference -> { + is InternalListOptions -> { stream.write(133) writeValue(stream, value.toList()) } + is InternalSettableMetadata -> { + stream.write(134) + writeValue(stream, value.toList()) + } + is InternalStorageTaskSnapShot -> { + stream.write(135) + writeValue(stream, value.toList()) + } + is InternalListResult -> { + stream.write(136) + writeValue(stream, value.toList()) + } else -> super.writeValue(stream, value) } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseStorageHostApi { - fun getReferencebyPath(app: PigeonStorageFirebaseApp, path: String, bucket: String?, callback: (Result) -> Unit) - fun setMaxOperationRetryTime(app: PigeonStorageFirebaseApp, time: Long, callback: (Result) -> Unit) - fun setMaxUploadRetryTime(app: PigeonStorageFirebaseApp, time: Long, callback: (Result) -> Unit) - fun setMaxDownloadRetryTime(app: PigeonStorageFirebaseApp, time: Long, callback: (Result) -> Unit) - fun useStorageEmulator(app: PigeonStorageFirebaseApp, host: String, port: Long, callback: (Result) -> Unit) - fun referenceDelete(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, callback: (Result) -> Unit) - fun referenceGetDownloadURL(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, callback: (Result) -> Unit) - fun referenceGetMetaData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, callback: (Result) -> Unit) - fun referenceList(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, options: PigeonListOptions, callback: (Result) -> Unit) - fun referenceListAll(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, callback: (Result) -> Unit) - fun referenceGetData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, maxSize: Long, callback: (Result) -> Unit) - fun referencePutData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, data: ByteArray, settableMetaData: PigeonSettableMetadata, handle: Long, callback: (Result) -> Unit) - fun referencePutString(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, data: String, format: Long, settableMetaData: PigeonSettableMetadata, handle: Long, callback: (Result) -> Unit) - fun referencePutFile(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, filePath: String, settableMetaData: PigeonSettableMetadata?, handle: Long, callback: (Result) -> Unit) - fun referenceDownloadFile(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, filePath: String, handle: Long, callback: (Result) -> Unit) - fun referenceUpdateMetadata(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, metadata: PigeonSettableMetadata, callback: (Result) -> Unit) - fun taskPause(app: PigeonStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) - fun taskResume(app: PigeonStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) - fun taskCancel(app: PigeonStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) + fun getReferencebyPath(app: InternalStorageFirebaseApp, path: String, bucket: String?, callback: (Result) -> Unit) + fun setMaxOperationRetryTime(app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit) + fun setMaxUploadRetryTime(app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit) + fun setMaxDownloadRetryTime(app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit) + fun useStorageEmulator(app: InternalStorageFirebaseApp, host: String, port: Long, callback: (Result) -> Unit) + fun referenceDelete(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) + fun referenceGetDownloadURL(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) + fun referenceGetMetaData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) + fun referenceList(app: InternalStorageFirebaseApp, reference: InternalStorageReference, options: InternalListOptions, callback: (Result) -> Unit) + fun referenceListAll(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) + fun referenceGetData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, maxSize: Long, callback: (Result) -> Unit) + fun referencePutData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, data: ByteArray, settableMetaData: InternalSettableMetadata, handle: Long, callback: (Result) -> Unit) + fun referencePutString(app: InternalStorageFirebaseApp, reference: InternalStorageReference, data: String, format: Long, settableMetaData: InternalSettableMetadata, handle: Long, callback: (Result) -> Unit) + fun referencePutFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, filePath: String, settableMetaData: InternalSettableMetadata?, handle: Long, callback: (Result) -> Unit) + fun referenceDownloadFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, filePath: String, handle: Long, callback: (Result) -> Unit) + fun referenceUpdateMetadata(app: InternalStorageFirebaseApp, reference: InternalStorageReference, metadata: InternalSettableMetadata, callback: (Result) -> Unit) + fun taskPause(app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) + fun taskResume(app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) + fun taskCancel(app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) companion object { /** The codec used by FirebaseStorageHostApi. */ val codec: MessageCodec by lazy { - FirebaseStorageHostApiCodec + GeneratedAndroidFirebaseStoragePigeonCodec() } /** Sets up an instance of `FirebaseStorageHostApi` to handle messages through the `binaryMessenger`. */ - @Suppress("UNCHECKED_CAST") - fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseStorageHostApi?) { + @JvmOverloads + fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseStorageHostApi?, messageChannelSuffix: String = "") { + val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp + val appArg = args[0] as InternalStorageFirebaseApp val pathArg = args[1] as String val bucketArg = args[2] as String? - api.getReferencebyPath(appArg, pathArg, bucketArg) { result: Result -> + api.getReferencebyPath(appArg, pathArg, bucketArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -376,18 +691,18 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val timeArg = args[1].let { if (it is Int) it.toLong() else it as Long } + val appArg = args[0] as InternalStorageFirebaseApp + val timeArg = args[1] as Long api.setMaxOperationRetryTime(appArg, timeArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { - reply.reply(wrapResult(null)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(null)) } } } @@ -396,18 +711,18 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val timeArg = args[1].let { if (it is Int) it.toLong() else it as Long } + val appArg = args[0] as InternalStorageFirebaseApp + val timeArg = args[1] as Long api.setMaxUploadRetryTime(appArg, timeArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { - reply.reply(wrapResult(null)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(null)) } } } @@ -416,18 +731,18 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val timeArg = args[1].let { if (it is Int) it.toLong() else it as Long } + val appArg = args[0] as InternalStorageFirebaseApp + val timeArg = args[1] as Long api.setMaxDownloadRetryTime(appArg, timeArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { - reply.reply(wrapResult(null)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(null)) } } } @@ -436,19 +751,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp + val appArg = args[0] as InternalStorageFirebaseApp val hostArg = args[1] as String - val portArg = args[2].let { if (it is Int) it.toLong() else it as Long } + val portArg = args[2] as Long api.useStorageEmulator(appArg, hostArg, portArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { - reply.reply(wrapResult(null)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(null)) } } } @@ -457,18 +772,18 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference api.referenceDelete(appArg, referenceArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { - reply.reply(wrapResult(null)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(null)) } } } @@ -477,19 +792,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference api.referenceGetDownloadURL(appArg, referenceArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -498,19 +813,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference - api.referenceGetMetaData(appArg, referenceArg) { result: Result -> + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference + api.referenceGetMetaData(appArg, referenceArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -519,20 +834,20 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference - val optionsArg = args[2] as PigeonListOptions - api.referenceList(appArg, referenceArg, optionsArg) { result: Result -> + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference + val optionsArg = args[2] as InternalListOptions + api.referenceList(appArg, referenceArg, optionsArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -541,19 +856,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference - api.referenceListAll(appArg, referenceArg) { result: Result -> + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference + api.referenceListAll(appArg, referenceArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -562,20 +877,20 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference - val maxSizeArg = args[2].let { if (it is Int) it.toLong() else it as Long } + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference + val maxSizeArg = args[2] as Long api.referenceGetData(appArg, referenceArg, maxSizeArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -584,22 +899,22 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference val dataArg = args[2] as ByteArray - val settableMetaDataArg = args[3] as PigeonSettableMetadata - val handleArg = args[4].let { if (it is Int) it.toLong() else it as Long } + val settableMetaDataArg = args[3] as InternalSettableMetadata + val handleArg = args[4] as Long api.referencePutData(appArg, referenceArg, dataArg, settableMetaDataArg, handleArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -608,23 +923,23 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference val dataArg = args[2] as String - val formatArg = args[3].let { if (it is Int) it.toLong() else it as Long } - val settableMetaDataArg = args[4] as PigeonSettableMetadata - val handleArg = args[5].let { if (it is Int) it.toLong() else it as Long } + val formatArg = args[3] as Long + val settableMetaDataArg = args[4] as InternalSettableMetadata + val handleArg = args[5] as Long api.referencePutString(appArg, referenceArg, dataArg, formatArg, settableMetaDataArg, handleArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -633,22 +948,22 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference val filePathArg = args[2] as String - val settableMetaDataArg = args[3] as PigeonSettableMetadata? - val handleArg = args[4].let { if (it is Int) it.toLong() else it as Long } + val settableMetaDataArg = args[3] as InternalSettableMetadata? + val handleArg = args[4] as Long api.referencePutFile(appArg, referenceArg, filePathArg, settableMetaDataArg, handleArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -657,21 +972,21 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference val filePathArg = args[2] as String - val handleArg = args[3].let { if (it is Int) it.toLong() else it as Long } + val handleArg = args[3] as Long api.referenceDownloadFile(appArg, referenceArg, filePathArg, handleArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -680,20 +995,20 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val referenceArg = args[1] as PigeonStorageReference - val metadataArg = args[2] as PigeonSettableMetadata - api.referenceUpdateMetadata(appArg, referenceArg, metadataArg) { result: Result -> + val appArg = args[0] as InternalStorageFirebaseApp + val referenceArg = args[1] as InternalStorageReference + val metadataArg = args[2] as InternalSettableMetadata + api.referenceUpdateMetadata(appArg, referenceArg, metadataArg) { result: Result -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -702,19 +1017,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val handleArg = args[1].let { if (it is Int) it.toLong() else it as Long } + val appArg = args[0] as InternalStorageFirebaseApp + val handleArg = args[1] as Long api.taskPause(appArg, handleArg) { result: Result> -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -723,19 +1038,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val handleArg = args[1].let { if (it is Int) it.toLong() else it as Long } + val appArg = args[0] as InternalStorageFirebaseApp + val handleArg = args[1] as Long api.taskResume(appArg, handleArg) { result: Result> -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } @@ -744,19 +1059,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel$separatedMessageChannelSuffix", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List - val appArg = args[0] as PigeonStorageFirebaseApp - val handleArg = args[1].let { if (it is Int) it.toLong() else it as Long } + val appArg = args[0] as InternalStorageFirebaseApp + val handleArg = args[1] as Long api.taskCancel(appArg, handleArg) { result: Result> -> val error = result.exceptionOrNull() if (error != null) { - reply.reply(wrapError(error)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) } else { val data = result.getOrNull() - reply.reply(wrapResult(data)) + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) } } } diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt index 06cc7eddaadb..5efa6415dae7 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt @@ -31,7 +31,7 @@ internal class TaskStateChannelStreamHandler( androidTask.addOnProgressListener { taskSnapshot -> if (flutterTask.isDestroyed()) return@addOnProgressListener val event = getTaskEventMap(taskSnapshot, null) - event[TASK_STATE_NAME] = PigeonStorageTaskState.RUNNING.raw + event[TASK_STATE_NAME] = InternalStorageTaskState.RUNNING.raw events.success(event) flutterTask.notifyResumeObjects() } @@ -39,7 +39,7 @@ internal class TaskStateChannelStreamHandler( androidTask.addOnPausedListener { taskSnapshot -> if (flutterTask.isDestroyed()) return@addOnPausedListener val event = getTaskEventMap(taskSnapshot, null) - event[TASK_STATE_NAME] = PigeonStorageTaskState.PAUSED.raw + event[TASK_STATE_NAME] = InternalStorageTaskState.PAUSED.raw events.success(event) flutterTask.notifyPauseObjects() } @@ -47,7 +47,7 @@ internal class TaskStateChannelStreamHandler( androidTask.addOnSuccessListener { taskSnapshot -> if (flutterTask.isDestroyed()) return@addOnSuccessListener val event = getTaskEventMap(taskSnapshot, null) - event[TASK_STATE_NAME] = PigeonStorageTaskState.SUCCESS.raw + event[TASK_STATE_NAME] = InternalStorageTaskState.SUCCESS.raw events.success(event) flutterTask.destroy() } @@ -55,7 +55,7 @@ internal class TaskStateChannelStreamHandler( androidTask.addOnCanceledListener { if (flutterTask.isDestroyed()) return@addOnCanceledListener val event = getTaskEventMap(null, null) - event[TASK_STATE_NAME] = PigeonStorageTaskState.ERROR.raw + event[TASK_STATE_NAME] = InternalStorageTaskState.ERROR.raw val syntheticException: MutableMap = HashMap() syntheticException["code"] = FlutterFirebaseStorageException.getCode(StorageException.ERROR_CANCELED) syntheticException["message"] = FlutterFirebaseStorageException.getMessage(StorageException.ERROR_CANCELED) @@ -68,7 +68,7 @@ internal class TaskStateChannelStreamHandler( androidTask.addOnFailureListener { exception -> if (flutterTask.isDestroyed()) return@addOnFailureListener val event = getTaskEventMap(null, exception) - event[TASK_STATE_NAME] = PigeonStorageTaskState.ERROR.raw + event[TASK_STATE_NAME] = InternalStorageTaskState.ERROR.raw events.success(event) flutterTask.destroy() } diff --git a/packages/firebase_storage/firebase_storage/example/android/app/build.gradle b/packages/firebase_storage/firebase_storage/example/android/app/build.gradle index 45de20db120a..e85ee381169d 100644 --- a/packages/firebase_storage/firebase_storage/example/android/app/build.gradle +++ b/packages/firebase_storage/firebase_storage/example/android/app/build.gradle @@ -45,7 +45,7 @@ android { applicationId = "io.flutter.plugins.firebasestorageexample" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdk = 23 + minSdkVersion = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutterVersionCode.toInteger() versionName = flutterVersionName diff --git a/packages/firebase_storage/firebase_storage/example/ios/Flutter/AppFrameworkInfo.plist b/packages/firebase_storage/firebase_storage/example/ios/Flutter/AppFrameworkInfo.plist index b3aaa733dfbb..6fe4034356ac 100755 --- a/packages/firebase_storage/firebase_storage/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/firebase_storage/firebase_storage/example/ios/Flutter/AppFrameworkInfo.plist @@ -24,7 +24,5 @@ arm64 - MinimumOSVersion - 12.0 diff --git a/packages/firebase_storage/firebase_storage/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_storage/firebase_storage/example/ios/Runner.xcodeproj/project.pbxproj index 25c8e390af78..3fffed27f781 100644 --- a/packages/firebase_storage/firebase_storage/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_storage/firebase_storage/example/ios/Runner.xcodeproj/project.pbxproj @@ -39,6 +39,7 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 5C6F5A6F1EC3CCCC008D64B5 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 5C6F5A701EC3CCCC008D64B5 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7A1ECC901E8EDB6900309407 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; @@ -72,6 +73,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -248,26 +250,10 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/FirebaseAppCheckInterop/FirebaseAppCheckInterop.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseAuthInterop/FirebaseAuthInterop.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreExtension/FirebaseCoreExtension.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseStorage/FirebaseStorage.framework", - "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", - "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", "${BUILT_PRODUCTS_DIR}/image_picker_ios/image_picker_ios.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAppCheckInterop.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseAuthInterop.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreExtension.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseStorage.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/image_picker_ios.framework", ); runOnlyForDeploymentPostprocessing = 0; diff --git a/packages/firebase_storage/firebase_storage/example/macos/Podfile b/packages/firebase_storage/firebase_storage/example/macos/Podfile index b4134e5ac6ca..c60870efea08 100644 --- a/packages/firebase_storage/firebase_storage/example/macos/Podfile +++ b/packages/firebase_storage/firebase_storage/example/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.14' +platform :osx, '10.15' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/project.pbxproj index e688261c0c0b..75f513426b4b 100644 --- a/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/project.pbxproj @@ -70,6 +70,7 @@ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; 623F4E175EF0069D1AA8A1AE /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; B567FAAE240D1F2E0031F210 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; @@ -135,6 +136,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -188,6 +190,7 @@ 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 0E2E82C8DA2AA4C782E46D76 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -264,6 +267,24 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0E2E82C8DA2AA4C782E46D76 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/file_selector_macos/file_selector_macos.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_selector_macos.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; diff --git a/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 8de585b49f18..126b4eb8ea7d 100644 --- a/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_storage/firebase_storage/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -78,6 +78,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift index bd35fb32d196..9b7693378a7a 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift @@ -57,50 +57,50 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt result(FlutterMethodNotImplemented) } - private func storage(app: PigeonStorageFirebaseApp) -> Storage { + private func storage(app: InternalStorageFirebaseApp) -> Storage { let base = "gs://" + app.bucket let firApp = FLTFirebasePlugin.firebaseAppNamed(app.appName)! return Storage.storage(app: firApp, url: base) } - private func ref(app: PigeonStorageFirebaseApp, - reference: PigeonStorageReference) -> StorageReference { + private func ref(app: InternalStorageFirebaseApp, + reference: InternalStorageReference) -> StorageReference { storage(app: app).reference(withPath: reference.fullPath) } - private func toPigeon(_ ref: StorageReference) -> PigeonStorageReference { - PigeonStorageReference(bucket: ref.bucket, fullPath: ref.fullPath, name: ref.name) + private func toPigeon(_ ref: StorageReference) -> InternalStorageReference { + InternalStorageReference(bucket: ref.bucket, fullPath: ref.fullPath, name: ref.name) } - func getReferencebyPath(app: PigeonStorageFirebaseApp, path: String, bucket: String?, - completion: @escaping (Result) -> Void) { + func getReferencebyPath(app: InternalStorageFirebaseApp, path: String, bucket: String?, + completion: @escaping (Result) -> Void) { let r = storage(app: app).reference(withPath: path) - completion(.success(PigeonStorageReference( + completion(.success(InternalStorageReference( bucket: r.bucket, fullPath: r.fullPath, name: r.name ))) } - func setMaxOperationRetryTime(app: PigeonStorageFirebaseApp, time: Int64, + func setMaxOperationRetryTime(app: InternalStorageFirebaseApp, time: Int64, completion: @escaping (Result) -> Void) { storage(app: app).maxOperationRetryTime = TimeInterval(Double(time) / 1000.0) completion(.success(())) } - func setMaxUploadRetryTime(app: PigeonStorageFirebaseApp, time: Int64, + func setMaxUploadRetryTime(app: InternalStorageFirebaseApp, time: Int64, completion: @escaping (Result) -> Void) { storage(app: app).maxUploadRetryTime = TimeInterval(Double(time) / 1000.0) completion(.success(())) } - func setMaxDownloadRetryTime(app: PigeonStorageFirebaseApp, time: Int64, + func setMaxDownloadRetryTime(app: InternalStorageFirebaseApp, time: Int64, completion: @escaping (Result) -> Void) { storage(app: app).maxDownloadRetryTime = TimeInterval(Double(time) / 1000.0) completion(.success(())) } - func useStorageEmulator(app: PigeonStorageFirebaseApp, host: String, port: Int64, + func useStorageEmulator(app: InternalStorageFirebaseApp, host: String, port: Int64, completion: @escaping (Result) -> Void) { guard emulatorBooted[app.bucket] == nil else { completion(.success(())) @@ -112,7 +112,7 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt completion(.success(())) } - func referenceDelete(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referenceDelete(app: InternalStorageFirebaseApp, reference: InternalStorageReference, completion: @escaping (Result) -> Void) { ref(app: app, reference: reference).delete { error in if let e = error { completion(.failure(self.toFlutterError(e))) } @@ -120,7 +120,7 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func referenceGetDownloadURL(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referenceGetDownloadURL(app: InternalStorageFirebaseApp, reference: InternalStorageReference, completion: @escaping (Result) -> Void) { ref(app: app, reference: reference).downloadURL { url, error in if let e = error { completion(.failure(self.toFlutterError(e))) } @@ -131,18 +131,18 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func referenceGetMetaData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - completion: @escaping (Result) -> Void) { + func referenceGetMetaData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) { ref(app: app, reference: reference).getMetadata { md, error in if let e = error { completion(.failure(self.toFlutterError(e))) } else { - completion(.success(PigeonFullMetaData(metadata: self.metaToDict(md)))) + completion(.success(InternalFullMetaData(metadata: self.metaToDict(md)))) } } } - func referenceList(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - options: PigeonListOptions, - completion: @escaping (Result) -> Void) { + func referenceList(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + options: InternalListOptions, + completion: @escaping (Result) -> Void) { let r = ref(app: app, reference: reference) let block: (StorageListResult?, Error?) -> Void = { list, error in if let e = error { completion(.failure(self.toFlutterError(e))) } else { @@ -156,15 +156,15 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func referenceListAll(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - completion: @escaping (Result) -> Void) { + func referenceListAll(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) { ref(app: app, reference: reference).listAll { list, error in if let e = error { completion(.failure(self.toFlutterError(e))) } else { completion(.success(self.listToPigeon(list!))) } } } - func referenceGetData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referenceGetData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, maxSize: Int64, completion: @escaping (Result) -> Void) { ref(app: app, reference: reference).getData(maxSize: maxSize) { data, error in @@ -178,8 +178,8 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func referencePutData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - data: FlutterStandardTypedData, settableMetaData: PigeonSettableMetadata, + func referencePutData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: FlutterStandardTypedData, settableMetaData: InternalSettableMetadata, handle: Int64, completion: @escaping (Result) -> Void) { let r = ref(app: app, reference: reference) let task = r.putData(data.data, metadata: toMeta(settableMetaData)) @@ -191,8 +191,8 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt ))) } - func referencePutString(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - data: String, format: Int64, settableMetaData: PigeonSettableMetadata, + func referencePutString(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: String, format: Int64, settableMetaData: InternalSettableMetadata, handle: Int64, completion: @escaping (Result) -> Void) { let r = ref(app: app, reference: reference) let d: Data @@ -212,8 +212,9 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt ))) } - func referencePutFile(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - filePath: String, settableMetaData: PigeonSettableMetadata?, handle: Int64, + func referencePutFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + filePath: String, settableMetaData: InternalSettableMetadata?, + handle: Int64, completion: @escaping (Result) -> Void) { let r = ref(app: app, reference: reference) let url = URL(fileURLWithPath: filePath) @@ -228,7 +229,7 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt ))) } - func referenceDownloadFile(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referenceDownloadFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, filePath: String, handle: Int64, completion: @escaping (Result) -> Void) { let r = ref(app: app, reference: reference) @@ -242,16 +243,17 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt ))) } - func referenceUpdateMetadata(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - metadata: PigeonSettableMetadata, - completion: @escaping (Result) -> Void) { + func referenceUpdateMetadata(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + metadata: InternalSettableMetadata, + completion: @escaping (Result) + -> Void) { ref(app: app, reference: reference).updateMetadata(toMeta(metadata)) { md, error in if let e = error { completion(.failure(self.toFlutterError(e))) } - else { completion(.success(PigeonFullMetaData(metadata: self.metaToDict(md)))) } + else { completion(.success(InternalFullMetaData(metadata: self.metaToDict(md)))) } } } - func taskPause(app: PigeonStorageFirebaseApp, handle: Int64, + func taskPause(app: InternalStorageFirebaseApp, handle: Int64, completion: @escaping (Result<[String: Any], Error>) -> Void) { if let task = handleToTask[handle] as? StorageUploadTask { task.pause() @@ -264,7 +266,7 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func taskResume(app: PigeonStorageFirebaseApp, handle: Int64, + func taskResume(app: InternalStorageFirebaseApp, handle: Int64, completion: @escaping (Result<[String: Any], Error>) -> Void) { if let task = handleToTask[handle] as? StorageUploadTask { task.resume() @@ -277,7 +279,7 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func taskCancel(app: PigeonStorageFirebaseApp, handle: Int64, + func taskCancel(app: InternalStorageFirebaseApp, handle: Int64, completion: @escaping (Result<[String: Any], Error>) -> Void) { if let task = handleToTask[handle] as? StorageUploadTask { task.cancel() @@ -296,7 +298,7 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - private func toMeta(_ m: PigeonSettableMetadata) -> StorageMetadata { + private func toMeta(_ m: InternalSettableMetadata) -> StorageMetadata { let md = StorageMetadata() if let v = m.cacheControl { md.cacheControl = v } if let v = m.contentType { md.contentType = v } @@ -328,12 +330,12 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt return out } - private func listToPigeon(_ list: StorageListResult) -> PigeonListResult { + private func listToPigeon(_ list: StorageListResult) -> InternalListResult { let items = list.items.map { toPigeon($0) } let prefixes = list.prefixes.map { toPigeon($0) } - let itemsOpt: [PigeonStorageReference?] = items.map { Optional($0) } - let prefixesOpt: [PigeonStorageReference?] = prefixes.map { Optional($0) } - return PigeonListResult(items: itemsOpt, pageToken: list.pageToken, prefixs: prefixesOpt) + let itemsOpt: [InternalStorageReference?] = items.map { Optional($0) } + let prefixesOpt: [InternalStorageReference?] = prefixes.map { Optional($0) } + return InternalListResult(items: itemsOpt, pageToken: list.pageToken, prefixs: prefixesOpt) } private func registerTask(task: StorageObservableTask, appName: String, handle: Int64, diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift index be06489ca8f0..71d157a36414 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift @@ -1,10 +1,11 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation + #if os(iOS) import Flutter #elseif os(macOS) @@ -13,8 +14,21 @@ import Foundation #error("Unsupported platform.") #endif -private func isNullish(_ value: Any?) -> Bool { - value is NSNull || value == nil +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } } private func wrapResult(_ result: Any?) -> [Any?] { @@ -22,6 +36,13 @@ private func wrapResult(_ result: Any?) -> [Any?] { } private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } if let flutterError = error as? FlutterError { return [ flutterError.code, @@ -31,19 +52,132 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } +private func isNullish(_ value: Any?) -> Bool { + value is NSNull || value == nil +} + private func nilOrValue(_ value: Any?) -> T? { if value is NSNull { return nil } return value as! T? } +private func doubleEqualsFirebaseStorageMessages(_ lhs: Double, _ rhs: Double) -> Bool { + (lhs.isNaN && rhs.isNaN) || lhs == rhs +} + +private func doubleHashFirebaseStorageMessages(_ value: Double, _ hasher: inout Hasher) { + if value.isNaN { + hasher.combine(0x7FF8_0000_0000_0000) + } else { + // Normalize -0.0 to 0.0 + hasher.combine(value == 0 ? 0 : value) + } +} + +func deepEqualsFirebaseStorageMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true + + case (nil, _), (_, nil): + return false + + case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: + return true + + case is (Void, Void): + return true + + case let (lhsArray, rhsArray) as ([Any?], [Any?]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !deepEqualsFirebaseStorageMessages(element, rhsArray[index]) { + return false + } + } + return true + + case let (lhsArray, rhsArray) as ([Double], [Double]): + guard lhsArray.count == rhsArray.count else { return false } + for (index, element) in lhsArray.enumerated() { + if !doubleEqualsFirebaseStorageMessages(element, rhsArray[index]) { + return false + } + } + return true + + case let (lhsDictionary, rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard lhsDictionary.count == rhsDictionary.count else { return false } + for (lhsKey, lhsValue) in lhsDictionary { + var found = false + for (rhsKey, rhsValue) in rhsDictionary { + if deepEqualsFirebaseStorageMessages(lhsKey, rhsKey) { + if deepEqualsFirebaseStorageMessages(lhsValue, rhsValue) { + found = true + break + } else { + return false + } + } + } + if !found { return false } + } + return true + + case let (lhs as Double, rhs as Double): + return doubleEqualsFirebaseStorageMessages(lhs, rhs) + + case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): + return lhsHashable == rhsHashable + + default: + return false + } +} + +func deepHashFirebaseStorageMessages(value: Any?, hasher: inout Hasher) { + let cleanValue = nilOrValue(value) as Any? + if let cleanValue { + if let doubleValue = cleanValue as? Double { + doubleHashFirebaseStorageMessages(doubleValue, &hasher) + } else if let valueList = cleanValue as? [Any?] { + for item in valueList { + deepHashFirebaseStorageMessages(value: item, hasher: &hasher) + } + } else if let valueList = cleanValue as? [Double] { + for item in valueList { + doubleHashFirebaseStorageMessages(item, &hasher) + } + } else if let valueDict = cleanValue as? [AnyHashable: Any?] { + var result = 0 + for (key, value) in valueDict { + var entryKeyHasher = Hasher() + deepHashFirebaseStorageMessages(value: key, hasher: &entryKeyHasher) + var entryValueHasher = Hasher() + deepHashFirebaseStorageMessages(value: value, hasher: &entryValueHasher) + result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize()) + } + hasher.combine(result) + } else if let hashableValue = cleanValue as? AnyHashable { + hasher.combine(hashableValue) + } else { + hasher.combine(String(describing: cleanValue)) + } + } else { + hasher.combine(0) + } +} + /// The type of operation that generated the action code from calling /// [TaskState]. -enum PigeonStorageTaskState: Int { +enum InternalStorageTaskState: Int { /// Indicates the task has been paused by the user. case paused = 0 /// Indicates the task is currently in-progress. @@ -57,17 +191,18 @@ enum PigeonStorageTaskState: Int { } /// Generated class from Pigeon that represents data sent in messages. -struct PigeonStorageFirebaseApp { +struct InternalStorageFirebaseApp: Hashable { var appName: String var tenantId: String? var bucket: String - static func fromList(_ list: [Any?]) -> PigeonStorageFirebaseApp? { - let appName = list[0] as! String - let tenantId: String? = nilOrValue(list[1]) - let bucket = list[2] as! String + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> InternalStorageFirebaseApp? { + let appName = pigeonVar_list[0] as! String + let tenantId: String? = nilOrValue(pigeonVar_list[1]) + let bucket = pigeonVar_list[2] as! String - return PigeonStorageFirebaseApp( + return InternalStorageFirebaseApp( appName: appName, tenantId: tenantId, bucket: bucket @@ -81,20 +216,39 @@ struct PigeonStorageFirebaseApp { bucket, ] } + + static func == (lhs: InternalStorageFirebaseApp, rhs: InternalStorageFirebaseApp) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseStorageMessages(lhs.appName, rhs.appName) && + deepEqualsFirebaseStorageMessages( + lhs.tenantId, + rhs.tenantId + ) && deepEqualsFirebaseStorageMessages(lhs.bucket, rhs.bucket) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("InternalStorageFirebaseApp") + deepHashFirebaseStorageMessages(value: appName, hasher: &hasher) + deepHashFirebaseStorageMessages(value: tenantId, hasher: &hasher) + deepHashFirebaseStorageMessages(value: bucket, hasher: &hasher) + } } /// Generated class from Pigeon that represents data sent in messages. -struct PigeonStorageReference { +struct InternalStorageReference: Hashable { var bucket: String var fullPath: String var name: String - static func fromList(_ list: [Any?]) -> PigeonStorageReference? { - let bucket = list[0] as! String - let fullPath = list[1] as! String - let name = list[2] as! String + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> InternalStorageReference? { + let bucket = pigeonVar_list[0] as! String + let fullPath = pigeonVar_list[1] as! String + let name = pigeonVar_list[2] as! String - return PigeonStorageReference( + return InternalStorageReference( bucket: bucket, fullPath: fullPath, name: name @@ -108,16 +262,35 @@ struct PigeonStorageReference { name, ] } + + static func == (lhs: InternalStorageReference, rhs: InternalStorageReference) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseStorageMessages(lhs.bucket, rhs.bucket) && + deepEqualsFirebaseStorageMessages( + lhs.fullPath, + rhs.fullPath + ) && deepEqualsFirebaseStorageMessages(lhs.name, rhs.name) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("InternalStorageReference") + deepHashFirebaseStorageMessages(value: bucket, hasher: &hasher) + deepHashFirebaseStorageMessages(value: fullPath, hasher: &hasher) + deepHashFirebaseStorageMessages(value: name, hasher: &hasher) + } } /// Generated class from Pigeon that represents data sent in messages. -struct PigeonFullMetaData { +struct InternalFullMetaData: Hashable { var metadata: [String?: Any?]? - static func fromList(_ list: [Any?]) -> PigeonFullMetaData? { - let metadata: [String?: Any?]? = nilOrValue(list[0]) + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> InternalFullMetaData? { + let metadata: [String?: Any?]? = nilOrValue(pigeonVar_list[0]) - return PigeonFullMetaData( + return InternalFullMetaData( metadata: metadata ) } @@ -127,10 +300,22 @@ struct PigeonFullMetaData { metadata, ] } + + static func == (lhs: InternalFullMetaData, rhs: InternalFullMetaData) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseStorageMessages(lhs.metadata, rhs.metadata) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("InternalFullMetaData") + deepHashFirebaseStorageMessages(value: metadata, hasher: &hasher) + } } /// Generated class from Pigeon that represents data sent in messages. -struct PigeonListOptions { +struct InternalListOptions: Hashable { /// If set, limits the total number of `prefixes` and `items` to return. /// /// The default and maximum maxResults is 1000. @@ -140,11 +325,12 @@ struct PigeonListOptions { /// If provided, listing is resumed from the previous position. var pageToken: String? - static func fromList(_ list: [Any?]) -> PigeonListOptions? { - let maxResults = list[0] is Int64 ? list[0] as! Int64 : Int64(list[0] as! Int32) - let pageToken: String? = nilOrValue(list[1]) + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> InternalListOptions? { + let maxResults = pigeonVar_list[0] as! Int64 + let pageToken: String? = nilOrValue(pigeonVar_list[1]) - return PigeonListOptions( + return InternalListOptions( maxResults: maxResults, pageToken: pageToken ) @@ -156,10 +342,27 @@ struct PigeonListOptions { pageToken, ] } + + static func == (lhs: InternalListOptions, rhs: InternalListOptions) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseStorageMessages(lhs.maxResults, rhs.maxResults) && + deepEqualsFirebaseStorageMessages( + lhs.pageToken, + rhs.pageToken + ) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("InternalListOptions") + deepHashFirebaseStorageMessages(value: maxResults, hasher: &hasher) + deepHashFirebaseStorageMessages(value: pageToken, hasher: &hasher) + } } /// Generated class from Pigeon that represents data sent in messages. -struct PigeonSettableMetadata { +struct InternalSettableMetadata: Hashable { /// Served as the 'Cache-Control' header on object download. /// /// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control. @@ -183,15 +386,16 @@ struct PigeonSettableMetadata { /// Additional user-defined custom metadata. var customMetadata: [String?: String?]? - static func fromList(_ list: [Any?]) -> PigeonSettableMetadata? { - let cacheControl: String? = nilOrValue(list[0]) - let contentDisposition: String? = nilOrValue(list[1]) - let contentEncoding: String? = nilOrValue(list[2]) - let contentLanguage: String? = nilOrValue(list[3]) - let contentType: String? = nilOrValue(list[4]) - let customMetadata: [String?: String?]? = nilOrValue(list[5]) + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> InternalSettableMetadata? { + let cacheControl: String? = nilOrValue(pigeonVar_list[0]) + let contentDisposition: String? = nilOrValue(pigeonVar_list[1]) + let contentEncoding: String? = nilOrValue(pigeonVar_list[2]) + let contentLanguage: String? = nilOrValue(pigeonVar_list[3]) + let contentType: String? = nilOrValue(pigeonVar_list[4]) + let customMetadata: [String?: String?]? = nilOrValue(pigeonVar_list[5]) - return PigeonSettableMetadata( + return InternalSettableMetadata( cacheControl: cacheControl, contentDisposition: contentDisposition, contentEncoding: contentEncoding, @@ -211,20 +415,105 @@ struct PigeonSettableMetadata { customMetadata, ] } + + static func == (lhs: InternalSettableMetadata, rhs: InternalSettableMetadata) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseStorageMessages(lhs.cacheControl, rhs.cacheControl) && + deepEqualsFirebaseStorageMessages( + lhs.contentDisposition, + rhs.contentDisposition + ) && deepEqualsFirebaseStorageMessages(lhs.contentEncoding, rhs.contentEncoding) && + deepEqualsFirebaseStorageMessages( + lhs.contentLanguage, + rhs.contentLanguage + ) && deepEqualsFirebaseStorageMessages(lhs.contentType, rhs.contentType) && + deepEqualsFirebaseStorageMessages( + lhs.customMetadata, + rhs.customMetadata + ) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("InternalSettableMetadata") + deepHashFirebaseStorageMessages(value: cacheControl, hasher: &hasher) + deepHashFirebaseStorageMessages(value: contentDisposition, hasher: &hasher) + deepHashFirebaseStorageMessages(value: contentEncoding, hasher: &hasher) + deepHashFirebaseStorageMessages(value: contentLanguage, hasher: &hasher) + deepHashFirebaseStorageMessages(value: contentType, hasher: &hasher) + deepHashFirebaseStorageMessages(value: customMetadata, hasher: &hasher) + } } /// Generated class from Pigeon that represents data sent in messages. -struct PigeonListResult { - var items: [PigeonStorageReference?] +struct InternalStorageTaskSnapShot: Hashable { + var bytesTransferred: Int64 + var metadata: InternalFullMetaData? + var state: InternalStorageTaskState + var totalBytes: Int64 + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> InternalStorageTaskSnapShot? { + let bytesTransferred = pigeonVar_list[0] as! Int64 + let metadata: InternalFullMetaData? = nilOrValue(pigeonVar_list[1]) + let state = pigeonVar_list[2] as! InternalStorageTaskState + let totalBytes = pigeonVar_list[3] as! Int64 + + return InternalStorageTaskSnapShot( + bytesTransferred: bytesTransferred, + metadata: metadata, + state: state, + totalBytes: totalBytes + ) + } + + func toList() -> [Any?] { + [ + bytesTransferred, + metadata, + state, + totalBytes, + ] + } + + static func == (lhs: InternalStorageTaskSnapShot, rhs: InternalStorageTaskSnapShot) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseStorageMessages(lhs.bytesTransferred, rhs.bytesTransferred) && + deepEqualsFirebaseStorageMessages( + lhs.metadata, + rhs.metadata + ) && deepEqualsFirebaseStorageMessages(lhs.state, rhs.state) && + deepEqualsFirebaseStorageMessages( + lhs.totalBytes, + rhs.totalBytes + ) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("InternalStorageTaskSnapShot") + deepHashFirebaseStorageMessages(value: bytesTransferred, hasher: &hasher) + deepHashFirebaseStorageMessages(value: metadata, hasher: &hasher) + deepHashFirebaseStorageMessages(value: state, hasher: &hasher) + deepHashFirebaseStorageMessages(value: totalBytes, hasher: &hasher) + } +} + +/// Generated class from Pigeon that represents data sent in messages. +struct InternalListResult: Hashable { + var items: [InternalStorageReference?] var pageToken: String? - var prefixs: [PigeonStorageReference?] + var prefixs: [InternalStorageReference?] - static func fromList(_ list: [Any?]) -> PigeonListResult? { - let items = list[0] as! [PigeonStorageReference?] - let pageToken: String? = nilOrValue(list[1]) - let prefixs = list[2] as! [PigeonStorageReference?] + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> InternalListResult? { + let items = pigeonVar_list[0] as! [InternalStorageReference?] + let pageToken: String? = nilOrValue(pigeonVar_list[1]) + let prefixs = pigeonVar_list[2] as! [InternalStorageReference?] - return PigeonListResult( + return InternalListResult( items: items, pageToken: pageToken, prefixs: prefixs @@ -238,138 +527,173 @@ struct PigeonListResult { prefixs, ] } + + static func == (lhs: InternalListResult, rhs: InternalListResult) -> Bool { + if Swift.type(of: lhs) != Swift.type(of: rhs) { + return false + } + return deepEqualsFirebaseStorageMessages(lhs.items, rhs.items) && + deepEqualsFirebaseStorageMessages( + lhs.pageToken, + rhs.pageToken + ) && deepEqualsFirebaseStorageMessages(lhs.prefixs, rhs.prefixs) + } + + func hash(into hasher: inout Hasher) { + hasher.combine("InternalListResult") + deepHashFirebaseStorageMessages(value: items, hasher: &hasher) + deepHashFirebaseStorageMessages(value: pageToken, hasher: &hasher) + deepHashFirebaseStorageMessages(value: prefixs, hasher: &hasher) + } } -private class FirebaseStorageHostApiCodecReader: FlutterStandardReader { +private class FirebaseStorageMessagesPigeonCodecReader: FlutterStandardReader { override func readValue(ofType type: UInt8) -> Any? { switch type { - case 128: - return PigeonFullMetaData.fromList(readValue() as! [Any?]) case 129: - return PigeonListOptions.fromList(readValue() as! [Any?]) + let enumResultAsInt: Int? = nilOrValue(readValue() as! Int?) + if let enumResultAsInt { + return InternalStorageTaskState(rawValue: enumResultAsInt) + } + return nil case 130: - return PigeonListResult.fromList(readValue() as! [Any?]) + return InternalStorageFirebaseApp.fromList(readValue() as! [Any?]) case 131: - return PigeonSettableMetadata.fromList(readValue() as! [Any?]) + return InternalStorageReference.fromList(readValue() as! [Any?]) case 132: - return PigeonStorageFirebaseApp.fromList(readValue() as! [Any?]) + return InternalFullMetaData.fromList(readValue() as! [Any?]) case 133: - return PigeonStorageReference.fromList(readValue() as! [Any?]) + return InternalListOptions.fromList(readValue() as! [Any?]) + case 134: + return InternalSettableMetadata.fromList(readValue() as! [Any?]) + case 135: + return InternalStorageTaskSnapShot.fromList(readValue() as! [Any?]) + case 136: + return InternalListResult.fromList(readValue() as! [Any?]) default: return super.readValue(ofType: type) } } } -private class FirebaseStorageHostApiCodecWriter: FlutterStandardWriter { +private class FirebaseStorageMessagesPigeonCodecWriter: FlutterStandardWriter { override func writeValue(_ value: Any) { - if let value = value as? PigeonFullMetaData { - super.writeByte(128) - super.writeValue(value.toList()) - } else if let value = value as? PigeonListOptions { + if let value = value as? InternalStorageTaskState { super.writeByte(129) - super.writeValue(value.toList()) - } else if let value = value as? PigeonListResult { + super.writeValue(value.rawValue) + } else if let value = value as? InternalStorageFirebaseApp { super.writeByte(130) super.writeValue(value.toList()) - } else if let value = value as? PigeonSettableMetadata { + } else if let value = value as? InternalStorageReference { super.writeByte(131) super.writeValue(value.toList()) - } else if let value = value as? PigeonStorageFirebaseApp { + } else if let value = value as? InternalFullMetaData { super.writeByte(132) super.writeValue(value.toList()) - } else if let value = value as? PigeonStorageReference { + } else if let value = value as? InternalListOptions { super.writeByte(133) super.writeValue(value.toList()) + } else if let value = value as? InternalSettableMetadata { + super.writeByte(134) + super.writeValue(value.toList()) + } else if let value = value as? InternalStorageTaskSnapShot { + super.writeByte(135) + super.writeValue(value.toList()) + } else if let value = value as? InternalListResult { + super.writeByte(136) + super.writeValue(value.toList()) } else { super.writeValue(value) } } } -private class FirebaseStorageHostApiCodecReaderWriter: FlutterStandardReaderWriter { +private class FirebaseStorageMessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { override func reader(with data: Data) -> FlutterStandardReader { - FirebaseStorageHostApiCodecReader(data: data) + FirebaseStorageMessagesPigeonCodecReader(data: data) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - FirebaseStorageHostApiCodecWriter(data: data) + FirebaseStorageMessagesPigeonCodecWriter(data: data) } } -class FirebaseStorageHostApiCodec: FlutterStandardMessageCodec { +class FirebaseStorageMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { static let shared = - FirebaseStorageHostApiCodec(readerWriter: FirebaseStorageHostApiCodecReaderWriter()) + FirebaseStorageMessagesPigeonCodec( + readerWriter: FirebaseStorageMessagesPigeonCodecReaderWriter() + ) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseStorageHostApi { - func getReferencebyPath(app: PigeonStorageFirebaseApp, path: String, bucket: String?, - completion: @escaping (Result) -> Void) - func setMaxOperationRetryTime(app: PigeonStorageFirebaseApp, time: Int64, + func getReferencebyPath(app: InternalStorageFirebaseApp, path: String, bucket: String?, + completion: @escaping (Result) -> Void) + func setMaxOperationRetryTime(app: InternalStorageFirebaseApp, time: Int64, completion: @escaping (Result) -> Void) - func setMaxUploadRetryTime(app: PigeonStorageFirebaseApp, time: Int64, + func setMaxUploadRetryTime(app: InternalStorageFirebaseApp, time: Int64, completion: @escaping (Result) -> Void) - func setMaxDownloadRetryTime(app: PigeonStorageFirebaseApp, time: Int64, + func setMaxDownloadRetryTime(app: InternalStorageFirebaseApp, time: Int64, completion: @escaping (Result) -> Void) - func useStorageEmulator(app: PigeonStorageFirebaseApp, host: String, port: Int64, + func useStorageEmulator(app: InternalStorageFirebaseApp, host: String, port: Int64, completion: @escaping (Result) -> Void) - func referenceDelete(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referenceDelete(app: InternalStorageFirebaseApp, reference: InternalStorageReference, completion: @escaping (Result) -> Void) - func referenceGetDownloadURL(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referenceGetDownloadURL(app: InternalStorageFirebaseApp, reference: InternalStorageReference, completion: @escaping (Result) -> Void) - func referenceGetMetaData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - completion: @escaping (Result) -> Void) - func referenceList(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - options: PigeonListOptions, - completion: @escaping (Result) -> Void) - func referenceListAll(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - completion: @escaping (Result) -> Void) - func referenceGetData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referenceGetMetaData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) + func referenceList(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + options: InternalListOptions, + completion: @escaping (Result) -> Void) + func referenceListAll(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) + func referenceGetData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, maxSize: Int64, completion: @escaping (Result) -> Void) - func referencePutData(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - data: FlutterStandardTypedData, settableMetaData: PigeonSettableMetadata, + func referencePutData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: FlutterStandardTypedData, settableMetaData: InternalSettableMetadata, handle: Int64, completion: @escaping (Result) -> Void) - func referencePutString(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - data: String, format: Int64, settableMetaData: PigeonSettableMetadata, + func referencePutString(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: String, format: Int64, settableMetaData: InternalSettableMetadata, handle: Int64, completion: @escaping (Result) -> Void) - func referencePutFile(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - filePath: String, settableMetaData: PigeonSettableMetadata?, handle: Int64, - completion: @escaping (Result) -> Void) - func referenceDownloadFile(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, + func referencePutFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + filePath: String, settableMetaData: InternalSettableMetadata?, + handle: Int64, completion: @escaping (Result) -> Void) + func referenceDownloadFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, filePath: String, handle: Int64, completion: @escaping (Result) -> Void) - func referenceUpdateMetadata(app: PigeonStorageFirebaseApp, reference: PigeonStorageReference, - metadata: PigeonSettableMetadata, - completion: @escaping (Result) -> Void) - func taskPause(app: PigeonStorageFirebaseApp, handle: Int64, + func referenceUpdateMetadata(app: InternalStorageFirebaseApp, reference: InternalStorageReference, + metadata: InternalSettableMetadata, + completion: @escaping (Result) -> Void) + func taskPause(app: InternalStorageFirebaseApp, handle: Int64, completion: @escaping (Result<[String: Any], Error>) -> Void) - func taskResume(app: PigeonStorageFirebaseApp, handle: Int64, + func taskResume(app: InternalStorageFirebaseApp, handle: Int64, completion: @escaping (Result<[String: Any], Error>) -> Void) - func taskCancel(app: PigeonStorageFirebaseApp, handle: Int64, + func taskCancel(app: InternalStorageFirebaseApp, handle: Int64, completion: @escaping (Result<[String: Any], Error>) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class FirebaseStorageHostApiSetup { - /// The codec used by FirebaseStorageHostApi. static var codec: FlutterStandardMessageCodec { - FirebaseStorageHostApiCodec.shared + FirebaseStorageMessagesPigeonCodec.shared } /// Sets up an instance of `FirebaseStorageHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseStorageHostApi?) { + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseStorageHostApi?, + messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let getReferencebyPathChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { getReferencebyPathChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp + let appArg = args[0] as! InternalStorageFirebaseApp let pathArg = args[1] as! String let bucketArg: String? = nilOrValue(args[2]) api.getReferencebyPath(app: appArg, path: pathArg, bucket: bucketArg) { result in @@ -385,15 +709,15 @@ class FirebaseStorageHostApiSetup { getReferencebyPathChannel.setMessageHandler(nil) } let setMaxOperationRetryTimeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { setMaxOperationRetryTimeChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let timeArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32) + let appArg = args[0] as! InternalStorageFirebaseApp + let timeArg = args[1] as! Int64 api.setMaxOperationRetryTime(app: appArg, time: timeArg) { result in switch result { case .success: @@ -407,15 +731,15 @@ class FirebaseStorageHostApiSetup { setMaxOperationRetryTimeChannel.setMessageHandler(nil) } let setMaxUploadRetryTimeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { setMaxUploadRetryTimeChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let timeArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32) + let appArg = args[0] as! InternalStorageFirebaseApp + let timeArg = args[1] as! Int64 api.setMaxUploadRetryTime(app: appArg, time: timeArg) { result in switch result { case .success: @@ -429,15 +753,15 @@ class FirebaseStorageHostApiSetup { setMaxUploadRetryTimeChannel.setMessageHandler(nil) } let setMaxDownloadRetryTimeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { setMaxDownloadRetryTimeChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let timeArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32) + let appArg = args[0] as! InternalStorageFirebaseApp + let timeArg = args[1] as! Int64 api.setMaxDownloadRetryTime(app: appArg, time: timeArg) { result in switch result { case .success: @@ -451,16 +775,16 @@ class FirebaseStorageHostApiSetup { setMaxDownloadRetryTimeChannel.setMessageHandler(nil) } let useStorageEmulatorChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { useStorageEmulatorChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp + let appArg = args[0] as! InternalStorageFirebaseApp let hostArg = args[1] as! String - let portArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32) + let portArg = args[2] as! Int64 api.useStorageEmulator(app: appArg, host: hostArg, port: portArg) { result in switch result { case .success: @@ -474,15 +798,15 @@ class FirebaseStorageHostApiSetup { useStorageEmulatorChannel.setMessageHandler(nil) } let referenceDeleteChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceDeleteChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference api.referenceDelete(app: appArg, reference: referenceArg) { result in switch result { case .success: @@ -496,15 +820,15 @@ class FirebaseStorageHostApiSetup { referenceDeleteChannel.setMessageHandler(nil) } let referenceGetDownloadURLChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceGetDownloadURLChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference api.referenceGetDownloadURL(app: appArg, reference: referenceArg) { result in switch result { case let .success(res): @@ -518,15 +842,15 @@ class FirebaseStorageHostApiSetup { referenceGetDownloadURLChannel.setMessageHandler(nil) } let referenceGetMetaDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceGetMetaDataChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference api.referenceGetMetaData(app: appArg, reference: referenceArg) { result in switch result { case let .success(res): @@ -540,16 +864,16 @@ class FirebaseStorageHostApiSetup { referenceGetMetaDataChannel.setMessageHandler(nil) } let referenceListChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceListChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference - let optionsArg = args[2] as! PigeonListOptions + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference + let optionsArg = args[2] as! InternalListOptions api.referenceList(app: appArg, reference: referenceArg, options: optionsArg) { result in switch result { case let .success(res): @@ -563,15 +887,15 @@ class FirebaseStorageHostApiSetup { referenceListChannel.setMessageHandler(nil) } let referenceListAllChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceListAllChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference api.referenceListAll(app: appArg, reference: referenceArg) { result in switch result { case let .success(res): @@ -585,16 +909,16 @@ class FirebaseStorageHostApiSetup { referenceListAllChannel.setMessageHandler(nil) } let referenceGetDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceGetDataChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference - let maxSizeArg = args[2] is Int64 ? args[2] as! Int64 : Int64(args[2] as! Int32) + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference + let maxSizeArg = args[2] as! Int64 api.referenceGetData(app: appArg, reference: referenceArg, maxSize: maxSizeArg) { result in switch result { case let .success(res): @@ -608,18 +932,18 @@ class FirebaseStorageHostApiSetup { referenceGetDataChannel.setMessageHandler(nil) } let referencePutDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referencePutDataChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference let dataArg = args[2] as! FlutterStandardTypedData - let settableMetaDataArg = args[3] as! PigeonSettableMetadata - let handleArg = args[4] is Int64 ? args[4] as! Int64 : Int64(args[4] as! Int32) + let settableMetaDataArg = args[3] as! InternalSettableMetadata + let handleArg = args[4] as! Int64 api.referencePutData( app: appArg, reference: referenceArg, @@ -639,19 +963,19 @@ class FirebaseStorageHostApiSetup { referencePutDataChannel.setMessageHandler(nil) } let referencePutStringChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referencePutStringChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference let dataArg = args[2] as! String - let formatArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32) - let settableMetaDataArg = args[4] as! PigeonSettableMetadata - let handleArg = args[5] is Int64 ? args[5] as! Int64 : Int64(args[5] as! Int32) + let formatArg = args[3] as! Int64 + let settableMetaDataArg = args[4] as! InternalSettableMetadata + let handleArg = args[5] as! Int64 api.referencePutString( app: appArg, reference: referenceArg, @@ -672,18 +996,18 @@ class FirebaseStorageHostApiSetup { referencePutStringChannel.setMessageHandler(nil) } let referencePutFileChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referencePutFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference let filePathArg = args[2] as! String - let settableMetaDataArg: PigeonSettableMetadata? = nilOrValue(args[3]) - let handleArg = args[4] is Int64 ? args[4] as! Int64 : Int64(args[4] as! Int32) + let settableMetaDataArg: InternalSettableMetadata? = nilOrValue(args[3]) + let handleArg = args[4] as! Int64 api.referencePutFile( app: appArg, reference: referenceArg, @@ -703,17 +1027,17 @@ class FirebaseStorageHostApiSetup { referencePutFileChannel.setMessageHandler(nil) } let referenceDownloadFileChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceDownloadFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference let filePathArg = args[2] as! String - let handleArg = args[3] is Int64 ? args[3] as! Int64 : Int64(args[3] as! Int32) + let handleArg = args[3] as! Int64 api.referenceDownloadFile( app: appArg, reference: referenceArg, @@ -732,16 +1056,16 @@ class FirebaseStorageHostApiSetup { referenceDownloadFileChannel.setMessageHandler(nil) } let referenceUpdateMetadataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { referenceUpdateMetadataChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let referenceArg = args[1] as! PigeonStorageReference - let metadataArg = args[2] as! PigeonSettableMetadata + let appArg = args[0] as! InternalStorageFirebaseApp + let referenceArg = args[1] as! InternalStorageReference + let metadataArg = args[2] as! InternalSettableMetadata api .referenceUpdateMetadata(app: appArg, reference: referenceArg, metadata: metadataArg) { result in @@ -757,15 +1081,15 @@ class FirebaseStorageHostApiSetup { referenceUpdateMetadataChannel.setMessageHandler(nil) } let taskPauseChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { taskPauseChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let handleArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32) + let appArg = args[0] as! InternalStorageFirebaseApp + let handleArg = args[1] as! Int64 api.taskPause(app: appArg, handle: handleArg) { result in switch result { case let .success(res): @@ -779,15 +1103,15 @@ class FirebaseStorageHostApiSetup { taskPauseChannel.setMessageHandler(nil) } let taskResumeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { taskResumeChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let handleArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32) + let appArg = args[0] as! InternalStorageFirebaseApp + let handleArg = args[1] as! Int64 api.taskResume(app: appArg, handle: handleArg) { result in switch result { case let .success(res): @@ -801,15 +1125,15 @@ class FirebaseStorageHostApiSetup { taskResumeChannel.setMessageHandler(nil) } let taskCancelChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel", + name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) if let api { taskCancelChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let appArg = args[0] as! PigeonStorageFirebaseApp - let handleArg = args[1] is Int64 ? args[1] as! Int64 : Int64(args[1] as! Int32) + let appArg = args[0] as! InternalStorageFirebaseApp + let handleArg = args[1] as! Int64 api.taskCancel(app: appArg, handle: handleArg) { result in switch result { case let .success(res): diff --git a/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.cpp b/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.cpp index 8d318c57196e..6ae3a7e1d69d 100644 --- a/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.cpp +++ b/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.cpp @@ -69,7 +69,7 @@ FirebaseStoragePlugin::FirebaseStoragePlugin() {} FirebaseStoragePlugin::~FirebaseStoragePlugin() = default; -Storage* GetCPPStorageFromPigeon(const PigeonStorageFirebaseApp& pigeonApp, +Storage* GetCPPStorageFromPigeon(const InternalStorageFirebaseApp& pigeonApp, const std::string& bucket_path) { std::string default_url = std::string("gs://") + bucket_path; App* app = App::GetInstance(pigeonApp.app_name().c_str()); @@ -79,8 +79,8 @@ Storage* GetCPPStorageFromPigeon(const PigeonStorageFirebaseApp& pigeonApp, } StorageReference GetCPPStorageReferenceFromPigeon( - const PigeonStorageFirebaseApp& pigeonApp, - const PigeonStorageReference& pigeonReference) { + const InternalStorageFirebaseApp& pigeonApp, + const InternalStorageReference& pigeonReference) { Storage* cpp_storage = GetCPPStorageFromPigeon(pigeonApp, pigeonReference.bucket()); return cpp_storage->GetReference(pigeonReference.full_path()); @@ -215,8 +215,8 @@ flutter::EncodableMap FirebaseStoragePlugin::ErrorStreamEvent( flutter::EncodableMap event; event[flutter::EncodableValue("appName")] = flutter::EncodableValue(app_name); - event[flutter::EncodableValue("taskState")] = - flutter::EncodableValue(static_cast(PigeonStorageTaskState::error)); + event[flutter::EncodableValue("taskState")] = flutter::EncodableValue( + static_cast(InternalStorageTaskState::kError)); event[flutter::EncodableValue("error")] = error; return event; @@ -231,39 +231,40 @@ FlutterError FirebaseStoragePlugin::ParseError( } void FirebaseStoragePlugin::GetReferencebyPath( - const PigeonStorageFirebaseApp& app, const std::string& path, + const InternalStorageFirebaseApp& app, const std::string& path, const std::string* bucket, - std::function reply)> result) { + std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(app, *bucket); StorageReference cpp_reference = cpp_storage->GetReference(path); - PigeonStorageReference* value_ptr = new PigeonStorageReference( + InternalStorageReference* value_ptr = new InternalStorageReference( cpp_reference.bucket(), cpp_reference.full_path(), cpp_reference.name()); result(*value_ptr); } void FirebaseStoragePlugin::SetMaxOperationRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(app, ""); cpp_storage->set_max_operation_retry_time((double)time); } void FirebaseStoragePlugin::SetMaxUploadRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(app, ""); cpp_storage->set_max_upload_retry_time((double)time); } void FirebaseStoragePlugin::SetMaxDownloadRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(app, ""); cpp_storage->set_max_download_retry_time((double)time); } void FirebaseStoragePlugin::UseStorageEmulator( - const PigeonStorageFirebaseApp& app, const std::string& host, int64_t port, + const InternalStorageFirebaseApp& app, const std::string& host, + int64_t port, std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(app, ""); cpp_storage->UseEmulator(host, static_cast(port)); @@ -271,8 +272,8 @@ void FirebaseStoragePlugin::UseStorageEmulator( } void FirebaseStoragePlugin::ReferenceDelete( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, std::function reply)> result) { StorageReference cpp_reference = GetCPPStorageReferenceFromPigeon(app, reference); @@ -287,8 +288,8 @@ void FirebaseStoragePlugin::ReferenceDelete( }); } void FirebaseStoragePlugin::ReferenceGetDownloadURL( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, std::function reply)> result) { StorageReference cpp_reference = GetCPPStorageReferenceFromPigeon(app, reference); @@ -306,7 +307,7 @@ void FirebaseStoragePlugin::ReferenceGetDownloadURL( firebase::storage::Metadata* FirebaseStoragePlugin::CreateStorageMetadataFromPigeon( - const PigeonSettableMetadata* pigeonMetaData) { + const InternalSettableMetadata* pigeonMetaData) { if (pigeonMetaData == nullptr) { return nullptr; // No metadata to process } @@ -444,16 +445,16 @@ flutter::EncodableMap ConvertMedadataToPigeon(const Metadata* meta) { } void FirebaseStoragePlugin::ReferenceGetMetaData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - std::function reply)> result) { + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + std::function reply)> result) { StorageReference cpp_reference = GetCPPStorageReferenceFromPigeon(app, reference); Future future_result = cpp_reference.GetMetadata(); ::Sleep(1); // timing for c++ sdk grabbing a mutex future_result.OnCompletion([result](const Future& metadata_result) { if (metadata_result.error() == firebase::storage::kErrorNone) { - PigeonFullMetaData pigeon_meta = PigeonFullMetaData(); + InternalFullMetaData pigeon_meta = InternalFullMetaData(); pigeon_meta.set_metadata( ConvertMedadataToPigeon(metadata_result.result())); @@ -465,30 +466,31 @@ void FirebaseStoragePlugin::ReferenceGetMetaData( } void FirebaseStoragePlugin::ReferenceList( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const PigeonListOptions& options, - std::function reply)> result) { + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const InternalListOptions& options, + std::function reply)> result) { // C++ doesn't support list yet flutter::EncodableList items = flutter::EncodableList(); flutter::EncodableList prefixs = flutter::EncodableList(); - PigeonListResult pigeon_result = PigeonListResult(items, prefixs); + InternalListResult pigeon_result = InternalListResult(items, prefixs); result(pigeon_result); } void FirebaseStoragePlugin::ReferenceListAll( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - std::function reply)> result) { + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + std::function reply)> result) { // C++ doesn't support listAll yet flutter::EncodableList items = flutter::EncodableList(); flutter::EncodableList prefixs = flutter::EncodableList(); - PigeonListResult pigeon_result = PigeonListResult(items, prefixs); + InternalListResult pigeon_result = InternalListResult(items, prefixs); result(pigeon_result); } void FirebaseStoragePlugin::ReferenceGetData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, int64_t max_size, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, int64_t max_size, std::function>> reply)> result) { StorageReference cpp_reference = @@ -530,7 +532,8 @@ class TaskStateListener : public Listener { } virtual void OnProgress(firebase::storage::Controller* controller) { flutter::EncodableMap event = flutter::EncodableMap(); - event[kTaskStateName] = static_cast(PigeonStorageTaskState::running); + event[kTaskStateName] = + static_cast(InternalStorageTaskState::kRunning); event[kTaskAppName] = controller->GetReference().storage()->app()->name(); flutter::EncodableMap snapshot = flutter::EncodableMap(); snapshot[kTaskSnapshotPath] = controller->GetReference().full_path(); @@ -543,7 +546,7 @@ class TaskStateListener : public Listener { virtual void OnPaused(firebase::storage::Controller* controller) { flutter::EncodableMap event = flutter::EncodableMap(); - event[kTaskStateName] = static_cast(PigeonStorageTaskState::paused); + event[kTaskStateName] = static_cast(InternalStorageTaskState::kPaused); event[kTaskAppName] = controller->GetReference().storage()->app()->name(); flutter::EncodableMap snapshot = flutter::EncodableMap(); snapshot[kTaskSnapshotPath] = controller->GetReference().full_path(); @@ -563,7 +566,7 @@ class PutDataStreamHandler PutDataStreamHandler(Storage* storage, std::string reference_path, const void* data, size_t buffer_size, Controller* controller, - const PigeonSettableMetadata& pigeon_meta_data) + const InternalSettableMetadata& pigeon_meta_data) : meta_data_(pigeon_meta_data) { storage_ = storage; reference_path_ = reference_path; @@ -600,7 +603,7 @@ class PutDataStreamHandler if (data_result.error() == firebase::storage::kErrorNone) { flutter::EncodableMap event = flutter::EncodableMap(); event[kTaskStateName] = - static_cast(PigeonStorageTaskState::success); + static_cast(InternalStorageTaskState::kSuccess); event[kTaskAppName] = std::string(storage_->app()->name()); flutter::EncodableMap snapshot = flutter::EncodableMap(); snapshot[kTaskSnapshotPath] = data_result.result()->path(); @@ -630,7 +633,7 @@ class PutDataStreamHandler Storage* storage_; std::string reference_path_; std::vector data_; - PigeonSettableMetadata meta_data_; + InternalSettableMetadata meta_data_; Controller* controller_; std::unique_ptr>&& events_ = nullptr; @@ -641,9 +644,9 @@ class PutFileStreamHandler public: PutFileStreamHandler(Storage* storage, std::string reference_path, std::string file_path, Controller* controller, - const PigeonSettableMetadata* pigeon_meta_data) + const InternalSettableMetadata* pigeon_meta_data) : meta_data_( - std::make_unique(*pigeon_meta_data)) { + std::make_unique(*pigeon_meta_data)) { storage_ = storage; reference_path_ = reference_path; file_path_ = file_path; @@ -678,7 +681,7 @@ class PutFileStreamHandler if (data_result.error() == firebase::storage::kErrorNone) { flutter::EncodableMap event = flutter::EncodableMap(); event[kTaskStateName] = - static_cast(PigeonStorageTaskState::success); + static_cast(InternalStorageTaskState::kSuccess); event[kTaskAppName] = std::string(storage_->app()->name()); flutter::EncodableMap snapshot = flutter::EncodableMap(); snapshot[kTaskSnapshotPath] = data_result.result()->path(); @@ -711,7 +714,7 @@ class PutFileStreamHandler Controller* controller_; std::unique_ptr>&& events_ = nullptr; - std::unique_ptr meta_data_; + std::unique_ptr meta_data_; }; class GetFileStreamHandler @@ -743,7 +746,7 @@ class GetFileStreamHandler if (data_result.error() == firebase::storage::kErrorNone) { flutter::EncodableMap event = flutter::EncodableMap(); event[kTaskStateName] = - static_cast(PigeonStorageTaskState::success); + static_cast(InternalStorageTaskState::kSuccess); event[kTaskAppName] = std::string(storage_->app()->name()); flutter::EncodableMap snapshot = flutter::EncodableMap(); size_t data_size = *data_result.result(); @@ -783,10 +786,10 @@ class GetFileStreamHandler }; void FirebaseStoragePlugin::ReferencePutData( - const PigeonStorageFirebaseApp& pigeon_app, - const PigeonStorageReference& pigeon_reference, + const InternalStorageFirebaseApp& pigeon_app, + const InternalStorageReference& pigeon_reference, const std::vector& data, - const PigeonSettableMetadata& pigeon_meta_data, int64_t handle, + const InternalSettableMetadata& pigeon_meta_data, int64_t handle, std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(pigeon_app, pigeon_reference.bucket()); @@ -804,9 +807,9 @@ void FirebaseStoragePlugin::ReferencePutData( } void FirebaseStoragePlugin::ReferencePutString( - const PigeonStorageFirebaseApp& pigeon_app, - const PigeonStorageReference& pigeon_reference, const std::string& data, - int64_t format, const PigeonSettableMetadata& settable_meta_data, + const InternalStorageFirebaseApp& pigeon_app, + const InternalStorageReference& pigeon_reference, const std::string& data, + int64_t format, const InternalSettableMetadata& settable_meta_data, int64_t handle, std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(pigeon_app, pigeon_reference.bucket()); @@ -827,10 +830,10 @@ void FirebaseStoragePlugin::ReferencePutString( } void FirebaseStoragePlugin::ReferencePutFile( - const PigeonStorageFirebaseApp& pigeon_app, - const PigeonStorageReference& pigeon_reference, + const InternalStorageFirebaseApp& pigeon_app, + const InternalStorageReference& pigeon_reference, const std::string& file_path, - const PigeonSettableMetadata* settable_meta_data, int64_t handle, + const InternalSettableMetadata* settable_meta_data, int64_t handle, std::function reply)> result) { Storage* cpp_storage = GetCPPStorageFromPigeon(pigeon_app, pigeon_reference.bucket()); @@ -848,8 +851,8 @@ void FirebaseStoragePlugin::ReferencePutFile( } void FirebaseStoragePlugin::ReferenceDownloadFile( - const PigeonStorageFirebaseApp& pigeon_app, - const PigeonStorageReference& pigeon_reference, + const InternalStorageFirebaseApp& pigeon_app, + const InternalStorageReference& pigeon_reference, const std::string& file_path, int64_t handle, std::function reply)> result) { Storage* cpp_storage = @@ -868,10 +871,10 @@ void FirebaseStoragePlugin::ReferenceDownloadFile( } void FirebaseStoragePlugin::ReferenceUpdateMetadata( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - const PigeonSettableMetadata& metadata, - std::function reply)> result) { + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const InternalSettableMetadata& metadata, + std::function reply)> result) { StorageReference cpp_reference = GetCPPStorageReferenceFromPigeon(app, reference); Metadata* cpp_meta = @@ -882,7 +885,7 @@ void FirebaseStoragePlugin::ReferenceUpdateMetadata( future_result.OnCompletion([result](const Future& data_result) { if (data_result.error() == firebase::storage::kErrorNone) { const Metadata* result_meta = data_result.result(); - PigeonFullMetaData pigeonData; + InternalFullMetaData pigeonData; pigeonData.set_metadata(ConvertMedadataToPigeon(result_meta)); result(pigeonData); @@ -893,7 +896,7 @@ void FirebaseStoragePlugin::ReferenceUpdateMetadata( } void FirebaseStoragePlugin::TaskPause( - const PigeonStorageFirebaseApp& app, int64_t handle, + const InternalStorageFirebaseApp& app, int64_t handle, std::function reply)> result) { bool status = controllers_[handle]->Pause(); flutter::EncodableMap task_result = flutter::EncodableMap(); @@ -911,7 +914,7 @@ void FirebaseStoragePlugin::TaskPause( } void FirebaseStoragePlugin::TaskResume( - const PigeonStorageFirebaseApp& app, int64_t handle, + const InternalStorageFirebaseApp& app, int64_t handle, std::function reply)> result) { bool status = controllers_[handle]->Resume(); flutter::EncodableMap task_result = flutter::EncodableMap(); @@ -928,7 +931,7 @@ void FirebaseStoragePlugin::TaskResume( } void FirebaseStoragePlugin::TaskCancel( - const PigeonStorageFirebaseApp& app, int64_t handle, + const InternalStorageFirebaseApp& app, int64_t handle, std::function reply)> result) { bool status = controllers_[handle]->Cancel(); flutter::EncodableMap task_result = flutter::EncodableMap(); diff --git a/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.h b/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.h index 8c4487d9e351..ed5191fbee8b 100644 --- a/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.h +++ b/packages/firebase_storage/firebase_storage/windows/firebase_storage_plugin.h @@ -37,7 +37,7 @@ class FirebaseStoragePlugin : public flutter::Plugin, // Static function declarations // Helper functions static firebase::storage::Metadata* CreateStorageMetadataFromPigeon( - const PigeonSettableMetadata* pigeonMetaData); + const InternalSettableMetadata* pigeonMetaData); static std::map ProcessCustomMetadataMap( const flutter::EncodableMap& customMetadata); static std::vector StringToByteData(const std::string& data, @@ -53,84 +53,86 @@ class FirebaseStoragePlugin : public flutter::Plugin, // FirebaseStorageHostApi virtual void GetReferencebyPath( - const PigeonStorageFirebaseApp& app, const std::string& path, + const InternalStorageFirebaseApp& app, const std::string& path, const std::string* bucket, - std::function reply)> result) + std::function reply)> result) override; virtual void SetMaxOperationRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) override; virtual void SetMaxUploadRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) override; virtual void SetMaxDownloadRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) override; virtual void UseStorageEmulator( - const PigeonStorageFirebaseApp& app, const std::string& host, + const InternalStorageFirebaseApp& app, const std::string& host, int64_t port, std::function reply)> result) override; virtual void ReferenceDelete( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, std::function reply)> result) override; virtual void ReferenceGetDownloadURL( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, std::function reply)> result) override; virtual void ReferenceGetMetaData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - std::function reply)> result) override; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + std::function reply)> result) override; virtual void ReferenceList( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const PigeonListOptions& options, - std::function reply)> result) override; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const InternalListOptions& options, + std::function reply)> result) override; virtual void ReferenceListAll( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - std::function reply)> result) override; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + std::function reply)> result) override; virtual void ReferenceGetData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, int64_t max_size, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, int64_t max_size, std::function>> reply)> result) override; virtual void ReferencePutData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::vector& data, - const PigeonSettableMetadata& settable_meta_data, int64_t handle, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const std::vector& data, + const InternalSettableMetadata& settable_meta_data, int64_t handle, std::function reply)> result) override; virtual void ReferencePutString( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::string& data, - int64_t format, const PigeonSettableMetadata& settable_meta_data, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, const std::string& data, + int64_t format, const InternalSettableMetadata& settable_meta_data, int64_t handle, std::function reply)> result) override; virtual void ReferencePutFile( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::string& file_path, - const PigeonSettableMetadata* settable_meta_data, int64_t handle, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, const std::string& file_path, + const InternalSettableMetadata* settable_meta_data, int64_t handle, std::function reply)> result) override; virtual void ReferenceDownloadFile( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::string& file_path, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, const std::string& file_path, int64_t handle, std::function reply)> result) override; virtual void ReferenceUpdateMetadata( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - const PigeonSettableMetadata& metadata, - std::function reply)> result) override; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const InternalSettableMetadata& metadata, + std::function reply)> result) override; virtual void TaskPause( - const PigeonStorageFirebaseApp& app, int64_t handle, + const InternalStorageFirebaseApp& app, int64_t handle, std::function reply)> result) override; virtual void TaskResume( - const PigeonStorageFirebaseApp& app, int64_t handle, + const InternalStorageFirebaseApp& app, int64_t handle, std::function reply)> result) override; virtual void TaskCancel( - const PigeonStorageFirebaseApp& app, int64_t handle, + const InternalStorageFirebaseApp& app, int64_t handle, std::function reply)> result) override; diff --git a/packages/firebase_storage/firebase_storage/windows/messages.g.cpp b/packages/firebase_storage/firebase_storage/windows/messages.g.cpp index c4f093b94f48..ace21074604b 100644 --- a/packages/firebase_storage/firebase_storage/windows/messages.g.cpp +++ b/packages/firebase_storage/firebase_storage/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,60 +13,277 @@ #include #include +#include +#include #include #include #include namespace firebase_storage_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; + +FlutterError CreateConnectionError(const std::string channel_name) { + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); +} + +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} -// PigeonStorageFirebaseApp +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} -PigeonStorageFirebaseApp::PigeonStorageFirebaseApp(const std::string& app_name, - const std::string& bucket) +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace +// InternalStorageFirebaseApp + +InternalStorageFirebaseApp::InternalStorageFirebaseApp( + const std::string& app_name, const std::string& bucket) : app_name_(app_name), bucket_(bucket) {} -PigeonStorageFirebaseApp::PigeonStorageFirebaseApp(const std::string& app_name, - const std::string* tenant_id, - const std::string& bucket) +InternalStorageFirebaseApp::InternalStorageFirebaseApp( + const std::string& app_name, const std::string* tenant_id, + const std::string& bucket) : app_name_(app_name), tenant_id_(tenant_id ? std::optional(*tenant_id) : std::nullopt), bucket_(bucket) {} -const std::string& PigeonStorageFirebaseApp::app_name() const { +const std::string& InternalStorageFirebaseApp::app_name() const { return app_name_; } -void PigeonStorageFirebaseApp::set_app_name(std::string_view value_arg) { +void InternalStorageFirebaseApp::set_app_name(std::string_view value_arg) { app_name_ = value_arg; } -const std::string* PigeonStorageFirebaseApp::tenant_id() const { +const std::string* InternalStorageFirebaseApp::tenant_id() const { return tenant_id_ ? &(*tenant_id_) : nullptr; } -void PigeonStorageFirebaseApp::set_tenant_id( +void InternalStorageFirebaseApp::set_tenant_id( const std::string_view* value_arg) { tenant_id_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonStorageFirebaseApp::set_tenant_id(std::string_view value_arg) { +void InternalStorageFirebaseApp::set_tenant_id(std::string_view value_arg) { tenant_id_ = value_arg; } -const std::string& PigeonStorageFirebaseApp::bucket() const { return bucket_; } +const std::string& InternalStorageFirebaseApp::bucket() const { + return bucket_; +} -void PigeonStorageFirebaseApp::set_bucket(std::string_view value_arg) { +void InternalStorageFirebaseApp::set_bucket(std::string_view value_arg) { bucket_ = value_arg; } -EncodableList PigeonStorageFirebaseApp::ToEncodableList() const { +EncodableList InternalStorageFirebaseApp::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(EncodableValue(app_name_)); @@ -75,10 +292,10 @@ EncodableList PigeonStorageFirebaseApp::ToEncodableList() const { return list; } -PigeonStorageFirebaseApp PigeonStorageFirebaseApp::FromEncodableList( +InternalStorageFirebaseApp InternalStorageFirebaseApp::FromEncodableList( const EncodableList& list) { - PigeonStorageFirebaseApp decoded(std::get(list[0]), - std::get(list[2])); + InternalStorageFirebaseApp decoded(std::get(list[0]), + std::get(list[2])); auto& encodable_tenant_id = list[1]; if (!encodable_tenant_id.IsNull()) { decoded.set_tenant_id(std::get(encodable_tenant_id)); @@ -86,34 +303,58 @@ PigeonStorageFirebaseApp PigeonStorageFirebaseApp::FromEncodableList( return decoded; } -// PigeonStorageReference +bool InternalStorageFirebaseApp::operator==( + const InternalStorageFirebaseApp& other) const { + return PigeonInternalDeepEquals(app_name_, other.app_name_) && + PigeonInternalDeepEquals(tenant_id_, other.tenant_id_) && + PigeonInternalDeepEquals(bucket_, other.bucket_); +} -PigeonStorageReference::PigeonStorageReference(const std::string& bucket, - const std::string& full_path, - const std::string& name) +bool InternalStorageFirebaseApp::operator!=( + const InternalStorageFirebaseApp& other) const { + return !(*this == other); +} + +size_t InternalStorageFirebaseApp::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(app_name_); + result = result * 31 + PigeonInternalDeepHash(tenant_id_); + result = result * 31 + PigeonInternalDeepHash(bucket_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalStorageFirebaseApp& v) { + return v.Hash(); +} + +// InternalStorageReference + +InternalStorageReference::InternalStorageReference(const std::string& bucket, + const std::string& full_path, + const std::string& name) : bucket_(bucket), full_path_(full_path), name_(name) {} -const std::string& PigeonStorageReference::bucket() const { return bucket_; } +const std::string& InternalStorageReference::bucket() const { return bucket_; } -void PigeonStorageReference::set_bucket(std::string_view value_arg) { +void InternalStorageReference::set_bucket(std::string_view value_arg) { bucket_ = value_arg; } -const std::string& PigeonStorageReference::full_path() const { +const std::string& InternalStorageReference::full_path() const { return full_path_; } -void PigeonStorageReference::set_full_path(std::string_view value_arg) { +void InternalStorageReference::set_full_path(std::string_view value_arg) { full_path_ = value_arg; } -const std::string& PigeonStorageReference::name() const { return name_; } +const std::string& InternalStorageReference::name() const { return name_; } -void PigeonStorageReference::set_name(std::string_view value_arg) { +void InternalStorageReference::set_name(std::string_view value_arg) { name_ = value_arg; } -EncodableList PigeonStorageReference::ToEncodableList() const { +EncodableList InternalStorageReference::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(EncodableValue(bucket_)); @@ -122,45 +363,69 @@ EncodableList PigeonStorageReference::ToEncodableList() const { return list; } -PigeonStorageReference PigeonStorageReference::FromEncodableList( +InternalStorageReference InternalStorageReference::FromEncodableList( const EncodableList& list) { - PigeonStorageReference decoded(std::get(list[0]), - std::get(list[1]), - std::get(list[2])); + InternalStorageReference decoded(std::get(list[0]), + std::get(list[1]), + std::get(list[2])); return decoded; } -// PigeonFullMetaData +bool InternalStorageReference::operator==( + const InternalStorageReference& other) const { + return PigeonInternalDeepEquals(bucket_, other.bucket_) && + PigeonInternalDeepEquals(full_path_, other.full_path_) && + PigeonInternalDeepEquals(name_, other.name_); +} + +bool InternalStorageReference::operator!=( + const InternalStorageReference& other) const { + return !(*this == other); +} + +size_t InternalStorageReference::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(bucket_); + result = result * 31 + PigeonInternalDeepHash(full_path_); + result = result * 31 + PigeonInternalDeepHash(name_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalStorageReference& v) { + return v.Hash(); +} + +// InternalFullMetaData -PigeonFullMetaData::PigeonFullMetaData() {} +InternalFullMetaData::InternalFullMetaData() {} -PigeonFullMetaData::PigeonFullMetaData(const EncodableMap* metadata) +InternalFullMetaData::InternalFullMetaData(const EncodableMap* metadata) : metadata_(metadata ? std::optional(*metadata) : std::nullopt) {} -const EncodableMap* PigeonFullMetaData::metadata() const { +const EncodableMap* InternalFullMetaData::metadata() const { return metadata_ ? &(*metadata_) : nullptr; } -void PigeonFullMetaData::set_metadata(const EncodableMap* value_arg) { +void InternalFullMetaData::set_metadata(const EncodableMap* value_arg) { metadata_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonFullMetaData::set_metadata(const EncodableMap& value_arg) { +void InternalFullMetaData::set_metadata(const EncodableMap& value_arg) { metadata_ = value_arg; } -EncodableList PigeonFullMetaData::ToEncodableList() const { +EncodableList InternalFullMetaData::ToEncodableList() const { EncodableList list; list.reserve(1); list.push_back(metadata_ ? EncodableValue(*metadata_) : EncodableValue()); return list; } -PigeonFullMetaData PigeonFullMetaData::FromEncodableList( +InternalFullMetaData InternalFullMetaData::FromEncodableList( const EncodableList& list) { - PigeonFullMetaData decoded; + InternalFullMetaData decoded; auto& encodable_metadata = list[0]; if (!encodable_metadata.IsNull()) { decoded.set_metadata(std::get(encodable_metadata)); @@ -168,37 +433,55 @@ PigeonFullMetaData PigeonFullMetaData::FromEncodableList( return decoded; } -// PigeonListOptions +bool InternalFullMetaData::operator==(const InternalFullMetaData& other) const { + return PigeonInternalDeepEquals(metadata_, other.metadata_); +} + +bool InternalFullMetaData::operator!=(const InternalFullMetaData& other) const { + return !(*this == other); +} -PigeonListOptions::PigeonListOptions(int64_t max_results) +size_t InternalFullMetaData::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(metadata_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalFullMetaData& v) { + return v.Hash(); +} + +// InternalListOptions + +InternalListOptions::InternalListOptions(int64_t max_results) : max_results_(max_results) {} -PigeonListOptions::PigeonListOptions(int64_t max_results, - const std::string* page_token) +InternalListOptions::InternalListOptions(int64_t max_results, + const std::string* page_token) : max_results_(max_results), page_token_(page_token ? std::optional(*page_token) : std::nullopt) {} -int64_t PigeonListOptions::max_results() const { return max_results_; } +int64_t InternalListOptions::max_results() const { return max_results_; } -void PigeonListOptions::set_max_results(int64_t value_arg) { +void InternalListOptions::set_max_results(int64_t value_arg) { max_results_ = value_arg; } -const std::string* PigeonListOptions::page_token() const { +const std::string* InternalListOptions::page_token() const { return page_token_ ? &(*page_token_) : nullptr; } -void PigeonListOptions::set_page_token(const std::string_view* value_arg) { +void InternalListOptions::set_page_token(const std::string_view* value_arg) { page_token_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonListOptions::set_page_token(std::string_view value_arg) { +void InternalListOptions::set_page_token(std::string_view value_arg) { page_token_ = value_arg; } -EncodableList PigeonListOptions::ToEncodableList() const { +EncodableList InternalListOptions::ToEncodableList() const { EncodableList list; list.reserve(2); list.push_back(EncodableValue(max_results_)); @@ -206,9 +489,9 @@ EncodableList PigeonListOptions::ToEncodableList() const { return list; } -PigeonListOptions PigeonListOptions::FromEncodableList( +InternalListOptions InternalListOptions::FromEncodableList( const EncodableList& list) { - PigeonListOptions decoded(list[0].LongValue()); + InternalListOptions decoded(std::get(list[0])); auto& encodable_page_token = list[1]; if (!encodable_page_token.IsNull()) { decoded.set_page_token(std::get(encodable_page_token)); @@ -216,11 +499,29 @@ PigeonListOptions PigeonListOptions::FromEncodableList( return decoded; } -// PigeonSettableMetadata +bool InternalListOptions::operator==(const InternalListOptions& other) const { + return PigeonInternalDeepEquals(max_results_, other.max_results_) && + PigeonInternalDeepEquals(page_token_, other.page_token_); +} -PigeonSettableMetadata::PigeonSettableMetadata() {} +bool InternalListOptions::operator!=(const InternalListOptions& other) const { + return !(*this == other); +} -PigeonSettableMetadata::PigeonSettableMetadata( +size_t InternalListOptions::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(max_results_); + result = result * 31 + PigeonInternalDeepHash(page_token_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalListOptions& v) { return v.Hash(); } + +// InternalSettableMetadata + +InternalSettableMetadata::InternalSettableMetadata() {} + +InternalSettableMetadata::InternalSettableMetadata( const std::string* cache_control, const std::string* content_disposition, const std::string* content_encoding, const std::string* content_language, const std::string* content_type, const EncodableMap* custom_metadata) @@ -241,93 +542,95 @@ PigeonSettableMetadata::PigeonSettableMetadata( ? std::optional(*custom_metadata) : std::nullopt) {} -const std::string* PigeonSettableMetadata::cache_control() const { +const std::string* InternalSettableMetadata::cache_control() const { return cache_control_ ? &(*cache_control_) : nullptr; } -void PigeonSettableMetadata::set_cache_control( +void InternalSettableMetadata::set_cache_control( const std::string_view* value_arg) { cache_control_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSettableMetadata::set_cache_control(std::string_view value_arg) { +void InternalSettableMetadata::set_cache_control(std::string_view value_arg) { cache_control_ = value_arg; } -const std::string* PigeonSettableMetadata::content_disposition() const { +const std::string* InternalSettableMetadata::content_disposition() const { return content_disposition_ ? &(*content_disposition_) : nullptr; } -void PigeonSettableMetadata::set_content_disposition( +void InternalSettableMetadata::set_content_disposition( const std::string_view* value_arg) { content_disposition_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSettableMetadata::set_content_disposition( +void InternalSettableMetadata::set_content_disposition( std::string_view value_arg) { content_disposition_ = value_arg; } -const std::string* PigeonSettableMetadata::content_encoding() const { +const std::string* InternalSettableMetadata::content_encoding() const { return content_encoding_ ? &(*content_encoding_) : nullptr; } -void PigeonSettableMetadata::set_content_encoding( +void InternalSettableMetadata::set_content_encoding( const std::string_view* value_arg) { content_encoding_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSettableMetadata::set_content_encoding(std::string_view value_arg) { +void InternalSettableMetadata::set_content_encoding( + std::string_view value_arg) { content_encoding_ = value_arg; } -const std::string* PigeonSettableMetadata::content_language() const { +const std::string* InternalSettableMetadata::content_language() const { return content_language_ ? &(*content_language_) : nullptr; } -void PigeonSettableMetadata::set_content_language( +void InternalSettableMetadata::set_content_language( const std::string_view* value_arg) { content_language_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSettableMetadata::set_content_language(std::string_view value_arg) { +void InternalSettableMetadata::set_content_language( + std::string_view value_arg) { content_language_ = value_arg; } -const std::string* PigeonSettableMetadata::content_type() const { +const std::string* InternalSettableMetadata::content_type() const { return content_type_ ? &(*content_type_) : nullptr; } -void PigeonSettableMetadata::set_content_type( +void InternalSettableMetadata::set_content_type( const std::string_view* value_arg) { content_type_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSettableMetadata::set_content_type(std::string_view value_arg) { +void InternalSettableMetadata::set_content_type(std::string_view value_arg) { content_type_ = value_arg; } -const EncodableMap* PigeonSettableMetadata::custom_metadata() const { +const EncodableMap* InternalSettableMetadata::custom_metadata() const { return custom_metadata_ ? &(*custom_metadata_) : nullptr; } -void PigeonSettableMetadata::set_custom_metadata( +void InternalSettableMetadata::set_custom_metadata( const EncodableMap* value_arg) { custom_metadata_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonSettableMetadata::set_custom_metadata( +void InternalSettableMetadata::set_custom_metadata( const EncodableMap& value_arg) { custom_metadata_ = value_arg; } -EncodableList PigeonSettableMetadata::ToEncodableList() const { +EncodableList InternalSettableMetadata::ToEncodableList() const { EncodableList list; list.reserve(6); list.push_back(cache_control_ ? EncodableValue(*cache_control_) @@ -345,9 +648,9 @@ EncodableList PigeonSettableMetadata::ToEncodableList() const { return list; } -PigeonSettableMetadata PigeonSettableMetadata::FromEncodableList( +InternalSettableMetadata InternalSettableMetadata::FromEncodableList( const EncodableList& list) { - PigeonSettableMetadata decoded; + InternalSettableMetadata decoded; auto& encodable_cache_control = list[0]; if (!encodable_cache_control.IsNull()) { decoded.set_cache_control(std::get(encodable_cache_control)); @@ -379,46 +682,208 @@ PigeonSettableMetadata PigeonSettableMetadata::FromEncodableList( return decoded; } -// PigeonListResult +bool InternalSettableMetadata::operator==( + const InternalSettableMetadata& other) const { + return PigeonInternalDeepEquals(cache_control_, other.cache_control_) && + PigeonInternalDeepEquals(content_disposition_, + other.content_disposition_) && + PigeonInternalDeepEquals(content_encoding_, other.content_encoding_) && + PigeonInternalDeepEquals(content_language_, other.content_language_) && + PigeonInternalDeepEquals(content_type_, other.content_type_) && + PigeonInternalDeepEquals(custom_metadata_, other.custom_metadata_); +} + +bool InternalSettableMetadata::operator!=( + const InternalSettableMetadata& other) const { + return !(*this == other); +} + +size_t InternalSettableMetadata::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(cache_control_); + result = result * 31 + PigeonInternalDeepHash(content_disposition_); + result = result * 31 + PigeonInternalDeepHash(content_encoding_); + result = result * 31 + PigeonInternalDeepHash(content_language_); + result = result * 31 + PigeonInternalDeepHash(content_type_); + result = result * 31 + PigeonInternalDeepHash(custom_metadata_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalSettableMetadata& v) { + return v.Hash(); +} + +// InternalStorageTaskSnapShot + +InternalStorageTaskSnapShot::InternalStorageTaskSnapShot( + int64_t bytes_transferred, const InternalStorageTaskState& state, + int64_t total_bytes) + : bytes_transferred_(bytes_transferred), + state_(state), + total_bytes_(total_bytes) {} + +InternalStorageTaskSnapShot::InternalStorageTaskSnapShot( + int64_t bytes_transferred, const InternalFullMetaData* metadata, + const InternalStorageTaskState& state, int64_t total_bytes) + : bytes_transferred_(bytes_transferred), + metadata_(metadata ? std::make_unique(*metadata) + : nullptr), + state_(state), + total_bytes_(total_bytes) {} + +InternalStorageTaskSnapShot::InternalStorageTaskSnapShot( + const InternalStorageTaskSnapShot& other) + : bytes_transferred_(other.bytes_transferred_), + metadata_(other.metadata_ + ? std::make_unique(*other.metadata_) + : nullptr), + state_(other.state_), + total_bytes_(other.total_bytes_) {} + +InternalStorageTaskSnapShot& InternalStorageTaskSnapShot::operator=( + const InternalStorageTaskSnapShot& other) { + bytes_transferred_ = other.bytes_transferred_; + metadata_ = other.metadata_ + ? std::make_unique(*other.metadata_) + : nullptr; + state_ = other.state_; + total_bytes_ = other.total_bytes_; + return *this; +} + +int64_t InternalStorageTaskSnapShot::bytes_transferred() const { + return bytes_transferred_; +} + +void InternalStorageTaskSnapShot::set_bytes_transferred(int64_t value_arg) { + bytes_transferred_ = value_arg; +} + +const InternalFullMetaData* InternalStorageTaskSnapShot::metadata() const { + return metadata_.get(); +} + +void InternalStorageTaskSnapShot::set_metadata( + const InternalFullMetaData* value_arg) { + metadata_ = + value_arg ? std::make_unique(*value_arg) : nullptr; +} + +void InternalStorageTaskSnapShot::set_metadata( + const InternalFullMetaData& value_arg) { + metadata_ = std::make_unique(value_arg); +} + +const InternalStorageTaskState& InternalStorageTaskSnapShot::state() const { + return state_; +} + +void InternalStorageTaskSnapShot::set_state( + const InternalStorageTaskState& value_arg) { + state_ = value_arg; +} + +int64_t InternalStorageTaskSnapShot::total_bytes() const { + return total_bytes_; +} + +void InternalStorageTaskSnapShot::set_total_bytes(int64_t value_arg) { + total_bytes_ = value_arg; +} + +EncodableList InternalStorageTaskSnapShot::ToEncodableList() const { + EncodableList list; + list.reserve(4); + list.push_back(EncodableValue(bytes_transferred_)); + list.push_back(metadata_ ? CustomEncodableValue(*metadata_) + : EncodableValue()); + list.push_back(CustomEncodableValue(state_)); + list.push_back(EncodableValue(total_bytes_)); + return list; +} + +InternalStorageTaskSnapShot InternalStorageTaskSnapShot::FromEncodableList( + const EncodableList& list) { + InternalStorageTaskSnapShot decoded( + std::get(list[0]), + std::any_cast( + std::get(list[2])), + std::get(list[3])); + auto& encodable_metadata = list[1]; + if (!encodable_metadata.IsNull()) { + decoded.set_metadata(std::any_cast( + std::get(encodable_metadata))); + } + return decoded; +} + +bool InternalStorageTaskSnapShot::operator==( + const InternalStorageTaskSnapShot& other) const { + return PigeonInternalDeepEquals(bytes_transferred_, + other.bytes_transferred_) && + PigeonInternalDeepEquals(metadata_, other.metadata_) && + PigeonInternalDeepEquals(state_, other.state_) && + PigeonInternalDeepEquals(total_bytes_, other.total_bytes_); +} + +bool InternalStorageTaskSnapShot::operator!=( + const InternalStorageTaskSnapShot& other) const { + return !(*this == other); +} + +size_t InternalStorageTaskSnapShot::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(bytes_transferred_); + result = result * 31 + PigeonInternalDeepHash(metadata_); + result = result * 31 + PigeonInternalDeepHash(state_); + result = result * 31 + PigeonInternalDeepHash(total_bytes_); + return result; +} + +size_t PigeonInternalDeepHash(const InternalStorageTaskSnapShot& v) { + return v.Hash(); +} + +// InternalListResult -PigeonListResult::PigeonListResult(const EncodableList& items, - const EncodableList& prefixs) +InternalListResult::InternalListResult(const EncodableList& items, + const EncodableList& prefixs) : items_(items), prefixs_(prefixs) {} -PigeonListResult::PigeonListResult(const EncodableList& items, - const std::string* page_token, - const EncodableList& prefixs) +InternalListResult::InternalListResult(const EncodableList& items, + const std::string* page_token, + const EncodableList& prefixs) : items_(items), page_token_(page_token ? std::optional(*page_token) : std::nullopt), prefixs_(prefixs) {} -const EncodableList& PigeonListResult::items() const { return items_; } +const EncodableList& InternalListResult::items() const { return items_; } -void PigeonListResult::set_items(const EncodableList& value_arg) { +void InternalListResult::set_items(const EncodableList& value_arg) { items_ = value_arg; } -const std::string* PigeonListResult::page_token() const { +const std::string* InternalListResult::page_token() const { return page_token_ ? &(*page_token_) : nullptr; } -void PigeonListResult::set_page_token(const std::string_view* value_arg) { +void InternalListResult::set_page_token(const std::string_view* value_arg) { page_token_ = value_arg ? std::optional(*value_arg) : std::nullopt; } -void PigeonListResult::set_page_token(std::string_view value_arg) { +void InternalListResult::set_page_token(std::string_view value_arg) { page_token_ = value_arg; } -const EncodableList& PigeonListResult::prefixs() const { return prefixs_; } +const EncodableList& InternalListResult::prefixs() const { return prefixs_; } -void PigeonListResult::set_prefixs(const EncodableList& value_arg) { +void InternalListResult::set_prefixs(const EncodableList& value_arg) { prefixs_ = value_arg; } -EncodableList PigeonListResult::ToEncodableList() const { +EncodableList InternalListResult::ToEncodableList() const { EncodableList list; list.reserve(3); list.push_back(EncodableValue(items_)); @@ -427,10 +892,10 @@ EncodableList PigeonListResult::ToEncodableList() const { return list; } -PigeonListResult PigeonListResult::FromEncodableList( +InternalListResult InternalListResult::FromEncodableList( const EncodableList& list) { - PigeonListResult decoded(std::get(list[0]), - std::get(list[2])); + InternalListResult decoded(std::get(list[0]), + std::get(list[2])); auto& encodable_page_token = list[1]; if (!encodable_page_token.IsNull()) { decoded.set_page_token(std::get(encodable_page_token)); @@ -438,109 +903,175 @@ PigeonListResult PigeonListResult::FromEncodableList( return decoded; } -FirebaseStorageHostApiCodecSerializer::FirebaseStorageHostApiCodecSerializer() { +bool InternalListResult::operator==(const InternalListResult& other) const { + return PigeonInternalDeepEquals(items_, other.items_) && + PigeonInternalDeepEquals(page_token_, other.page_token_) && + PigeonInternalDeepEquals(prefixs_, other.prefixs_); +} + +bool InternalListResult::operator!=(const InternalListResult& other) const { + return !(*this == other); +} + +size_t InternalListResult::Hash() const { + size_t result = 1; + result = result * 31 + PigeonInternalDeepHash(items_); + result = result * 31 + PigeonInternalDeepHash(page_token_); + result = result * 31 + PigeonInternalDeepHash(prefixs_); + return result; } -EncodableValue FirebaseStorageHostApiCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { +size_t PigeonInternalDeepHash(const InternalListResult& v) { return v.Hash(); } + +PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} + +EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const { switch (type) { - case 128: - return CustomEncodableValue(PigeonFullMetaData::FromEncodableList( + case 129: { + const auto& encodable_enum_arg = ReadValue(stream); + const int64_t enum_arg_value = + encodable_enum_arg.IsNull() ? 0 : encodable_enum_arg.LongValue(); + return encodable_enum_arg.IsNull() + ? EncodableValue() + : CustomEncodableValue( + static_cast(enum_arg_value)); + } + case 130: { + return CustomEncodableValue(InternalStorageFirebaseApp::FromEncodableList( std::get(ReadValue(stream)))); - case 129: - return CustomEncodableValue(PigeonListOptions::FromEncodableList( + } + case 131: { + return CustomEncodableValue(InternalStorageReference::FromEncodableList( std::get(ReadValue(stream)))); - case 130: - return CustomEncodableValue(PigeonListResult::FromEncodableList( + } + case 132: { + return CustomEncodableValue(InternalFullMetaData::FromEncodableList( std::get(ReadValue(stream)))); - case 131: - return CustomEncodableValue(PigeonSettableMetadata::FromEncodableList( + } + case 133: { + return CustomEncodableValue(InternalListOptions::FromEncodableList( std::get(ReadValue(stream)))); - case 132: - return CustomEncodableValue(PigeonStorageFirebaseApp::FromEncodableList( + } + case 134: { + return CustomEncodableValue(InternalSettableMetadata::FromEncodableList( std::get(ReadValue(stream)))); - case 133: - return CustomEncodableValue(PigeonStorageReference::FromEncodableList( + } + case 135: { + return CustomEncodableValue( + InternalStorageTaskSnapShot::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 136: { + return CustomEncodableValue(InternalListResult::FromEncodableList( std::get(ReadValue(stream)))); + } default: - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } } -void FirebaseStorageHostApiCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { +void PigeonInternalCodecSerializer::WriteValue( + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { if (const CustomEncodableValue* custom_value = std::get_if(&value)) { - if (custom_value->type() == typeid(PigeonFullMetaData)) { - stream->WriteByte(128); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), - stream); - return; - } - if (custom_value->type() == typeid(PigeonListOptions)) { + if (custom_value->type() == typeid(InternalStorageTaskState)) { stream->WriteByte(129); - WriteValue(EncodableValue(std::any_cast(*custom_value) - .ToEncodableList()), + WriteValue(EncodableValue(static_cast( + std::any_cast(*custom_value))), stream); return; } - if (custom_value->type() == typeid(PigeonListResult)) { + if (custom_value->type() == typeid(InternalStorageFirebaseApp)) { stream->WriteByte(130); - WriteValue( - EncodableValue( - std::any_cast(*custom_value).ToEncodableList()), - stream); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); return; } - if (custom_value->type() == typeid(PigeonSettableMetadata)) { + if (custom_value->type() == typeid(InternalStorageReference)) { stream->WriteByte(131); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonStorageFirebaseApp)) { + if (custom_value->type() == typeid(InternalFullMetaData)) { stream->WriteByte(132); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } - if (custom_value->type() == typeid(PigeonStorageReference)) { + if (custom_value->type() == typeid(InternalListOptions)) { stream->WriteByte(133); WriteValue( - EncodableValue(std::any_cast(*custom_value) + EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(InternalSettableMetadata)) { + stream->WriteByte(134); + WriteValue( + EncodableValue(std::any_cast(*custom_value) .ToEncodableList()), stream); return; } + if (custom_value->type() == typeid(InternalStorageTaskSnapShot)) { + stream->WriteByte(135); + WriteValue(EncodableValue( + std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(InternalListResult)) { + stream->WriteByte(136); + WriteValue(EncodableValue(std::any_cast(*custom_value) + .ToEncodableList()), + stream); + return; + } } - flutter::StandardCodecSerializer::WriteValue(value, stream); + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseStorageHostApi. -const flutter::StandardMessageCodec& FirebaseStorageHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( - &FirebaseStorageHostApiCodecSerializer::GetInstance()); +const ::flutter::StandardMessageCodec& FirebaseStorageHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseStorageHostApi` to handle messages through // the `binary_messenger`. -void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, +void FirebaseStorageHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseStorageHostApi* api) { + FirebaseStorageHostApi::SetUp(binary_messenger, api, ""); +} + +void FirebaseStorageHostApi::SetUp(::flutter::BinaryMessenger* binary_messenger, + FirebaseStorageHostApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = + message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : ""; { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.getReferencebyPath", + "FirebaseStorageHostApi.getReferencebyPath" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -549,7 +1080,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_path_arg = args.at(1); if (encodable_path_arg.IsNull()) { @@ -562,7 +1093,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get_if(&encodable_bucket_arg); api->GetReferencebyPath( app_arg, path_arg, bucket_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -577,19 +1108,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.setMaxOperationRetryTime", + "FirebaseStorageHostApi.setMaxOperationRetryTime" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -598,7 +1130,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_time_arg = args.at(1); if (encodable_time_arg.IsNull()) { @@ -622,19 +1154,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.setMaxUploadRetryTime", + "FirebaseStorageHostApi.setMaxUploadRetryTime" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -643,7 +1176,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_time_arg = args.at(1); if (encodable_time_arg.IsNull()) { @@ -667,19 +1200,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.setMaxDownloadRetryTime", + "FirebaseStorageHostApi.setMaxDownloadRetryTime" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -688,7 +1222,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_time_arg = args.at(1); if (encodable_time_arg.IsNull()) { @@ -712,19 +1246,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.useStorageEmulator", + "FirebaseStorageHostApi.useStorageEmulator" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -733,7 +1268,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_host_arg = args.at(1); if (encodable_host_arg.IsNull()) { @@ -763,19 +1298,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceDelete", + "FirebaseStorageHostApi.referenceDelete" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -784,7 +1320,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -792,7 +1328,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); api->ReferenceDelete( app_arg, reference_arg, @@ -810,19 +1346,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceGetDownloadURL", + "FirebaseStorageHostApi.referenceGetDownloadURL" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -831,7 +1368,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -839,7 +1376,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); api->ReferenceGetDownloadURL( app_arg, reference_arg, @@ -858,19 +1395,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceGetMetaData", + "FirebaseStorageHostApi.referenceGetMetaData" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -879,7 +1417,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -887,11 +1425,11 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); api->ReferenceGetMetaData( app_arg, reference_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -906,19 +1444,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceList", + "FirebaseStorageHostApi.referenceList" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -927,7 +1466,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -935,17 +1474,18 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); const auto& encodable_options_arg = args.at(2); if (encodable_options_arg.IsNull()) { reply(WrapError("options_arg unexpectedly null.")); return; } - const auto& options_arg = std::any_cast( - std::get(encodable_options_arg)); + const auto& options_arg = + std::any_cast( + std::get(encodable_options_arg)); api->ReferenceList(app_arg, reference_arg, options_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -960,19 +1500,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceListAll", + "FirebaseStorageHostApi.referenceListAll" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -981,7 +1522,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -989,11 +1530,11 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); api->ReferenceListAll( app_arg, reference_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -1008,19 +1549,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceGetData", + "FirebaseStorageHostApi.referenceGetData" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1029,7 +1571,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -1037,7 +1579,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); const auto& encodable_max_size_arg = args.at(2); if (encodable_max_size_arg.IsNull()) { @@ -1068,19 +1610,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referencePutData", + "FirebaseStorageHostApi.referencePutData" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1089,7 +1632,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -1097,7 +1640,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); const auto& encodable_data_arg = args.at(2); if (encodable_data_arg.IsNull()) { @@ -1112,7 +1655,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& settable_meta_data_arg = - std::any_cast( + std::any_cast( std::get( encodable_settable_meta_data_arg)); const auto& encodable_handle_arg = args.at(4); @@ -1138,19 +1681,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referencePutString", + "FirebaseStorageHostApi.referencePutString" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1159,7 +1703,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -1167,7 +1711,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); const auto& encodable_data_arg = args.at(2); if (encodable_data_arg.IsNull()) { @@ -1187,7 +1731,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& settable_meta_data_arg = - std::any_cast( + std::any_cast( std::get( encodable_settable_meta_data_arg)); const auto& encodable_handle_arg = args.at(5); @@ -1214,19 +1758,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referencePutFile", + "FirebaseStorageHostApi.referencePutFile" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1235,7 +1780,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -1243,7 +1788,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); const auto& encodable_file_path_arg = args.at(2); if (encodable_file_path_arg.IsNull()) { @@ -1254,9 +1799,11 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, std::get(encodable_file_path_arg); const auto& encodable_settable_meta_data_arg = args.at(3); const auto* settable_meta_data_arg = - &(std::any_cast( - std::get( - encodable_settable_meta_data_arg))); + encodable_settable_meta_data_arg.IsNull() + ? nullptr + : &(std::any_cast( + std::get( + encodable_settable_meta_data_arg))); const auto& encodable_handle_arg = args.at(4); if (encodable_handle_arg.IsNull()) { reply(WrapError("handle_arg unexpectedly null.")); @@ -1280,19 +1827,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceDownloadFile", + "FirebaseStorageHostApi.referenceDownloadFile" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1301,7 +1849,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -1309,7 +1857,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); const auto& encodable_file_path_arg = args.at(2); if (encodable_file_path_arg.IsNull()) { @@ -1341,19 +1889,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.referenceUpdateMetadata", + "FirebaseStorageHostApi.referenceUpdateMetadata" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1362,7 +1911,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_reference_arg = args.at(1); if (encodable_reference_arg.IsNull()) { @@ -1370,7 +1919,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& reference_arg = - std::any_cast( + std::any_cast( std::get(encodable_reference_arg)); const auto& encodable_metadata_arg = args.at(2); if (encodable_metadata_arg.IsNull()) { @@ -1378,11 +1927,11 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& metadata_arg = - std::any_cast( + std::any_cast( std::get(encodable_metadata_arg)); api->ReferenceUpdateMetadata( app_arg, reference_arg, metadata_arg, - [reply](ErrorOr&& output) { + [reply](ErrorOr&& output) { if (output.has_error()) { reply(WrapError(output.error())); return; @@ -1397,19 +1946,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.taskPause", + "FirebaseStorageHostApi.taskPause" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1418,7 +1968,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_handle_arg = args.at(1); if (encodable_handle_arg.IsNull()) { @@ -1442,19 +1992,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.taskResume", + "FirebaseStorageHostApi.taskResume" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1463,7 +2014,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_handle_arg = args.at(1); if (encodable_handle_arg.IsNull()) { @@ -1487,19 +2038,20 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } { - auto channel = std::make_unique>( + BasicMessageChannel<> channel( binary_messenger, "dev.flutter.pigeon.firebase_storage_platform_interface." - "FirebaseStorageHostApi.taskCancel", + "FirebaseStorageHostApi.taskCancel" + + prepended_suffix, &GetCodec()); if (api != nullptr) { - channel->SetMessageHandler( + channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_arg = args.at(0); @@ -1508,7 +2060,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, return; } const auto& app_arg = - std::any_cast( + std::any_cast( std::get(encodable_app_arg)); const auto& encodable_handle_arg = args.at(1); if (encodable_handle_arg.IsNull()) { @@ -1532,7 +2084,7 @@ void FirebaseStorageHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, } }); } else { - channel->SetMessageHandler(nullptr); + channel.SetMessageHandler(nullptr); } } } @@ -1550,4 +2102,4 @@ EncodableValue FirebaseStorageHostApi::WrapError(const FlutterError& error) { error.details()}); } -} // namespace firebase_storage_windows \ No newline at end of file +} // namespace firebase_storage_windows diff --git a/packages/firebase_storage/firebase_storage/windows/messages.g.h b/packages/firebase_storage/firebase_storage/windows/messages.g.h index 307747a7320b..35ca69bdf997 100644 --- a/packages/firebase_storage/firebase_storage/windows/messages.g.h +++ b/packages/firebase_storage/firebase_storage/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -60,30 +60,30 @@ class ErrorOr { // The type of operation that generated the action code from calling // [TaskState]. -enum class PigeonStorageTaskState { +enum class InternalStorageTaskState { // Indicates the task has been paused by the user. - paused = 0, + kPaused = 0, // Indicates the task is currently in-progress. - running = 1, + kRunning = 1, // Indicates the task has successfully completed. - success = 2, + kSuccess = 2, // Indicates the task was canceled. - canceled = 3, + kCanceled = 3, // Indicates the task failed with an error. - error = 4 + kError = 4 }; // Generated class from Pigeon that represents data sent in messages. -class PigeonStorageFirebaseApp { +class InternalStorageFirebaseApp { public: // Constructs an object setting all non-nullable fields. - explicit PigeonStorageFirebaseApp(const std::string& app_name, - const std::string& bucket); + explicit InternalStorageFirebaseApp(const std::string& app_name, + const std::string& bucket); // Constructs an object setting all fields. - explicit PigeonStorageFirebaseApp(const std::string& app_name, - const std::string* tenant_id, - const std::string& bucket); + explicit InternalStorageFirebaseApp(const std::string& app_name, + const std::string* tenant_id, + const std::string& bucket); const std::string& app_name() const; void set_app_name(std::string_view value_arg); @@ -95,24 +95,36 @@ class PigeonStorageFirebaseApp { const std::string& bucket() const; void set_bucket(std::string_view value_arg); + bool operator==(const InternalStorageFirebaseApp& other) const; + bool operator!=(const InternalStorageFirebaseApp& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalStorageFirebaseApp FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static PigeonStorageFirebaseApp FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseStorageHostApi; - friend class FirebaseStorageHostApiCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string app_name_; std::optional tenant_id_; std::string bucket_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonStorageReference { +class InternalStorageReference { public: // Constructs an object setting all fields. - explicit PigeonStorageReference(const std::string& bucket, - const std::string& full_path, - const std::string& name); + explicit InternalStorageReference(const std::string& bucket, + const std::string& full_path, + const std::string& name); const std::string& bucket() const; void set_bucket(std::string_view value_arg); @@ -123,48 +135,73 @@ class PigeonStorageReference { const std::string& name() const; void set_name(std::string_view value_arg); + bool operator==(const InternalStorageReference& other) const; + bool operator!=(const InternalStorageReference& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalStorageReference FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static PigeonStorageReference FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseStorageHostApi; - friend class FirebaseStorageHostApiCodecSerializer; + friend class PigeonInternalCodecSerializer; std::string bucket_; std::string full_path_; std::string name_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonFullMetaData { +class InternalFullMetaData { public: // Constructs an object setting all non-nullable fields. - PigeonFullMetaData(); + InternalFullMetaData(); // Constructs an object setting all fields. - explicit PigeonFullMetaData(const flutter::EncodableMap* metadata); + explicit InternalFullMetaData(const ::flutter::EncodableMap* metadata); + + const ::flutter::EncodableMap* metadata() const; + void set_metadata(const ::flutter::EncodableMap* value_arg); + void set_metadata(const ::flutter::EncodableMap& value_arg); - const flutter::EncodableMap* metadata() const; - void set_metadata(const flutter::EncodableMap* value_arg); - void set_metadata(const flutter::EncodableMap& value_arg); + bool operator==(const InternalFullMetaData& other) const; + bool operator!=(const InternalFullMetaData& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; private: - static PigeonFullMetaData FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + static InternalFullMetaData FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: + friend class InternalStorageTaskSnapShot; friend class FirebaseStorageHostApi; - friend class FirebaseStorageHostApiCodecSerializer; - std::optional metadata_; + friend class PigeonInternalCodecSerializer; + std::optional<::flutter::EncodableMap> metadata_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonListOptions { +class InternalListOptions { public: // Constructs an object setting all non-nullable fields. - explicit PigeonListOptions(int64_t max_results); + explicit InternalListOptions(int64_t max_results); // Constructs an object setting all fields. - explicit PigeonListOptions(int64_t max_results, - const std::string* page_token); + explicit InternalListOptions(int64_t max_results, + const std::string* page_token); // If set, limits the total number of `prefixes` and `items` to return. // @@ -179,29 +216,40 @@ class PigeonListOptions { void set_page_token(const std::string_view* value_arg); void set_page_token(std::string_view value_arg); + bool operator==(const InternalListOptions& other) const; + bool operator!=(const InternalListOptions& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalListOptions FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static PigeonListOptions FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseStorageHostApi; - friend class FirebaseStorageHostApiCodecSerializer; + friend class PigeonInternalCodecSerializer; int64_t max_results_; std::optional page_token_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonSettableMetadata { +class InternalSettableMetadata { public: // Constructs an object setting all non-nullable fields. - PigeonSettableMetadata(); + InternalSettableMetadata(); // Constructs an object setting all fields. - explicit PigeonSettableMetadata(const std::string* cache_control, - const std::string* content_disposition, - const std::string* content_encoding, - const std::string* content_language, - const std::string* content_type, - const flutter::EncodableMap* custom_metadata); + explicit InternalSettableMetadata( + const std::string* cache_control, const std::string* content_disposition, + const std::string* content_encoding, const std::string* content_language, + const std::string* content_type, + const ::flutter::EncodableMap* custom_metadata); // Served as the 'Cache-Control' header on object download. // @@ -243,71 +291,154 @@ class PigeonSettableMetadata { void set_content_type(std::string_view value_arg); // Additional user-defined custom metadata. - const flutter::EncodableMap* custom_metadata() const; - void set_custom_metadata(const flutter::EncodableMap* value_arg); - void set_custom_metadata(const flutter::EncodableMap& value_arg); + const ::flutter::EncodableMap* custom_metadata() const; + void set_custom_metadata(const ::flutter::EncodableMap* value_arg); + void set_custom_metadata(const ::flutter::EncodableMap& value_arg); + + bool operator==(const InternalSettableMetadata& other) const; + bool operator!=(const InternalSettableMetadata& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; private: - static PigeonSettableMetadata FromEncodableList( - const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; + static InternalSettableMetadata FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: friend class FirebaseStorageHostApi; - friend class FirebaseStorageHostApiCodecSerializer; + friend class PigeonInternalCodecSerializer; std::optional cache_control_; std::optional content_disposition_; std::optional content_encoding_; std::optional content_language_; std::optional content_type_; - std::optional custom_metadata_; + std::optional<::flutter::EncodableMap> custom_metadata_; }; // Generated class from Pigeon that represents data sent in messages. -class PigeonListResult { +class InternalStorageTaskSnapShot { public: // Constructs an object setting all non-nullable fields. - explicit PigeonListResult(const flutter::EncodableList& items, - const flutter::EncodableList& prefixs); + explicit InternalStorageTaskSnapShot(int64_t bytes_transferred, + const InternalStorageTaskState& state, + int64_t total_bytes); // Constructs an object setting all fields. - explicit PigeonListResult(const flutter::EncodableList& items, - const std::string* page_token, - const flutter::EncodableList& prefixs); + explicit InternalStorageTaskSnapShot(int64_t bytes_transferred, + const InternalFullMetaData* metadata, + const InternalStorageTaskState& state, + int64_t total_bytes); + + ~InternalStorageTaskSnapShot() = default; + InternalStorageTaskSnapShot(const InternalStorageTaskSnapShot& other); + InternalStorageTaskSnapShot& operator=( + const InternalStorageTaskSnapShot& other); + InternalStorageTaskSnapShot(InternalStorageTaskSnapShot&& other) = default; + InternalStorageTaskSnapShot& operator=( + InternalStorageTaskSnapShot&& other) noexcept = default; + int64_t bytes_transferred() const; + void set_bytes_transferred(int64_t value_arg); + + const InternalFullMetaData* metadata() const; + void set_metadata(const InternalFullMetaData* value_arg); + void set_metadata(const InternalFullMetaData& value_arg); + + const InternalStorageTaskState& state() const; + void set_state(const InternalStorageTaskState& value_arg); + + int64_t total_bytes() const; + void set_total_bytes(int64_t value_arg); + + bool operator==(const InternalStorageTaskSnapShot& other) const; + bool operator!=(const InternalStorageTaskSnapShot& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalStorageTaskSnapShot FromEncodableList( + const ::flutter::EncodableList& list); - const flutter::EncodableList& items() const; - void set_items(const flutter::EncodableList& value_arg); + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: + private: + friend class FirebaseStorageHostApi; + friend class PigeonInternalCodecSerializer; + int64_t bytes_transferred_; + std::unique_ptr metadata_; + InternalStorageTaskState state_; + int64_t total_bytes_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class InternalListResult { + public: + // Constructs an object setting all non-nullable fields. + explicit InternalListResult(const ::flutter::EncodableList& items, + const ::flutter::EncodableList& prefixs); + + // Constructs an object setting all fields. + explicit InternalListResult(const ::flutter::EncodableList& items, + const std::string* page_token, + const ::flutter::EncodableList& prefixs); + + const ::flutter::EncodableList& items() const; + void set_items(const ::flutter::EncodableList& value_arg); const std::string* page_token() const; void set_page_token(const std::string_view* value_arg); void set_page_token(std::string_view value_arg); - const flutter::EncodableList& prefixs() const; - void set_prefixs(const flutter::EncodableList& value_arg); + const ::flutter::EncodableList& prefixs() const; + void set_prefixs(const ::flutter::EncodableList& value_arg); + bool operator==(const InternalListResult& other) const; + bool operator!=(const InternalListResult& other) const; + /// Returns a hash code value for the object. This method is supported for the + /// benefit of hash tables. + size_t Hash() const; + + private: + static InternalListResult FromEncodableList( + const ::flutter::EncodableList& list); + + public: + public: + ::flutter::EncodableList ToEncodableList() const; + + private: private: - static PigeonListResult FromEncodableList(const flutter::EncodableList& list); - flutter::EncodableList ToEncodableList() const; friend class FirebaseStorageHostApi; - friend class FirebaseStorageHostApiCodecSerializer; - flutter::EncodableList items_; + friend class PigeonInternalCodecSerializer; + ::flutter::EncodableList items_; std::optional page_token_; - flutter::EncodableList prefixs_; + ::flutter::EncodableList prefixs_; }; -class FirebaseStorageHostApiCodecSerializer - : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: - FirebaseStorageHostApiCodecSerializer(); - inline static FirebaseStorageHostApiCodecSerializer& GetInstance() { - static FirebaseStorageHostApiCodecSerializer sInstance; + PigeonInternalCodecSerializer(); + inline static PigeonInternalCodecSerializer& GetInstance() { + static PigeonInternalCodecSerializer sInstance; return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -318,91 +449,96 @@ class FirebaseStorageHostApi { FirebaseStorageHostApi& operator=(const FirebaseStorageHostApi&) = delete; virtual ~FirebaseStorageHostApi() {} virtual void GetReferencebyPath( - const PigeonStorageFirebaseApp& app, const std::string& path, + const InternalStorageFirebaseApp& app, const std::string& path, const std::string* bucket, - std::function reply)> result) = 0; + std::function reply)> result) = 0; virtual void SetMaxOperationRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) = 0; virtual void SetMaxUploadRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) = 0; virtual void SetMaxDownloadRetryTime( - const PigeonStorageFirebaseApp& app, int64_t time, + const InternalStorageFirebaseApp& app, int64_t time, std::function reply)> result) = 0; virtual void UseStorageEmulator( - const PigeonStorageFirebaseApp& app, const std::string& host, + const InternalStorageFirebaseApp& app, const std::string& host, int64_t port, std::function reply)> result) = 0; virtual void ReferenceDelete( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, std::function reply)> result) = 0; virtual void ReferenceGetDownloadURL( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, std::function reply)> result) = 0; virtual void ReferenceGetMetaData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - std::function reply)> result) = 0; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + std::function reply)> result) = 0; virtual void ReferenceList( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const PigeonListOptions& options, - std::function reply)> result) = 0; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const InternalListOptions& options, + std::function reply)> result) = 0; virtual void ReferenceListAll( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - std::function reply)> result) = 0; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + std::function reply)> result) = 0; virtual void ReferenceGetData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, int64_t max_size, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, int64_t max_size, std::function>> reply)> result) = 0; virtual void ReferencePutData( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::vector& data, - const PigeonSettableMetadata& settable_meta_data, int64_t handle, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const std::vector& data, + const InternalSettableMetadata& settable_meta_data, int64_t handle, std::function reply)> result) = 0; virtual void ReferencePutString( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::string& data, - int64_t format, const PigeonSettableMetadata& settable_meta_data, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, const std::string& data, + int64_t format, const InternalSettableMetadata& settable_meta_data, int64_t handle, std::function reply)> result) = 0; virtual void ReferencePutFile( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::string& file_path, - const PigeonSettableMetadata* settable_meta_data, int64_t handle, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, const std::string& file_path, + const InternalSettableMetadata* settable_meta_data, int64_t handle, std::function reply)> result) = 0; virtual void ReferenceDownloadFile( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, const std::string& file_path, + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, const std::string& file_path, int64_t handle, std::function reply)> result) = 0; virtual void ReferenceUpdateMetadata( - const PigeonStorageFirebaseApp& app, - const PigeonStorageReference& reference, - const PigeonSettableMetadata& metadata, - std::function reply)> result) = 0; + const InternalStorageFirebaseApp& app, + const InternalStorageReference& reference, + const InternalSettableMetadata& metadata, + std::function reply)> result) = 0; virtual void TaskPause( - const PigeonStorageFirebaseApp& app, int64_t handle, - std::function reply)> result) = 0; + const InternalStorageFirebaseApp& app, int64_t handle, + std::function reply)> result) = 0; virtual void TaskResume( - const PigeonStorageFirebaseApp& app, int64_t handle, - std::function reply)> result) = 0; + const InternalStorageFirebaseApp& app, int64_t handle, + std::function reply)> result) = 0; virtual void TaskCancel( - const PigeonStorageFirebaseApp& app, int64_t handle, - std::function reply)> result) = 0; + const InternalStorageFirebaseApp& app, int64_t handle, + std::function reply)> result) = 0; // The codec used by FirebaseStorageHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseStorageHostApi` to handle messages through // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseStorageHostApi* api); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static void SetUp(::flutter::BinaryMessenger* binary_messenger, + FirebaseStorageHostApi* api, + const std::string& message_channel_suffix); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseStorageHostApi() = default; diff --git a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_firebase_storage.dart b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_firebase_storage.dart index ec3544856a96..85cc085517c2 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_firebase_storage.dart +++ b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_firebase_storage.dart @@ -43,8 +43,8 @@ class MethodChannelFirebaseStorage extends FirebaseStoragePlatform { static final FirebaseStorageHostApi pigeonChannel = FirebaseStorageHostApi(); /// FirebaseApp pigeon instance - PigeonStorageFirebaseApp get pigeonFirebaseApp { - return PigeonStorageFirebaseApp( + InternalStorageFirebaseApp get pigeonFirebaseApp { + return InternalStorageFirebaseApp( appName: app.name, bucket: bucket, ); @@ -71,28 +71,28 @@ class MethodChannelFirebaseStorage extends FirebaseStoragePlatform { return MethodChannelFirebaseStorage._(); } - /// Return an instance of a [PigeonStorageReference] - static PigeonStorageReference getPigeonReference( + /// Return an instance of a [InternalStorageReference] + static InternalStorageReference getPigeonReference( String bucket, String fullPath, String name) { - return PigeonStorageReference( + return InternalStorageReference( bucket: bucket, fullPath: fullPath, name: name); } - /// Return an instance of a [PigeonStorageFirebaseApp] - PigeonStorageFirebaseApp getPigeonFirebaseApp(String appName) { - return PigeonStorageFirebaseApp( + /// Return an instance of a [InternalStorageFirebaseApp] + InternalStorageFirebaseApp getPigeonFirebaseApp(String appName) { + return InternalStorageFirebaseApp( appName: appName, bucket: bucket, ); } - /// Convert a [SettableMetadata] to [PigeonSettableMetadata] - static PigeonSettableMetadata getPigeonSettableMetaData( + /// Convert a [SettableMetadata] to [InternalSettableMetadata] + static InternalSettableMetadata getPigeonSettableMetaData( SettableMetadata? metaData) { if (metaData == null) { - return PigeonSettableMetadata(); + return InternalSettableMetadata(); } - return PigeonSettableMetadata( + return InternalSettableMetadata( cacheControl: metaData.cacheControl, contentDisposition: metaData.contentDisposition, contentEncoding: metaData.contentEncoding, diff --git a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_reference.dart b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_reference.dart index 22b05190161a..bc279770919b 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_reference.dart +++ b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_reference.dart @@ -22,16 +22,16 @@ class MethodChannelReference extends ReferencePlatform { : super(storage, path); /// FirebaseApp pigeon instance - PigeonStorageFirebaseApp get pigeonFirebaseApp { - return PigeonStorageFirebaseApp( + InternalStorageFirebaseApp get pigeonFirebaseApp { + return InternalStorageFirebaseApp( appName: storage.app.name, bucket: storage.bucket, ); } /// Default of FirebaseReference pigeon instance - PigeonStorageReference get pigeonReference { - return PigeonStorageReference( + InternalStorageReference get pigeonReference { + return InternalStorageReference( bucket: storage.bucket, fullPath: fullPath, name: name, @@ -59,8 +59,8 @@ class MethodChannelReference extends ReferencePlatform { } } - /// Convert a [PigeonFullMetaData] to [FullMetadata] - static FullMetadata convertMetadata(PigeonFullMetaData pigeonMetadata) { + /// Convert a [InternalFullMetaData] to [FullMetadata] + static FullMetadata convertMetadata(InternalFullMetaData pigeonMetadata) { Map _metadata = {}; pigeonMetadata.metadata?.forEach((key, value) { if (key != null) { @@ -73,7 +73,7 @@ class MethodChannelReference extends ReferencePlatform { @override Future getMetadata() async { try { - PigeonFullMetaData metaData = await MethodChannelFirebaseStorage + InternalFullMetaData metaData = await MethodChannelFirebaseStorage .pigeonChannel .referenceGetMetaData(pigeonFirebaseApp, pigeonReference); return convertMetadata(metaData); @@ -82,20 +82,20 @@ class MethodChannelReference extends ReferencePlatform { } } - /// Convert a [ListOptions] to [PigeonListOptions] - static PigeonListOptions convertOptions(ListOptions? options) { + /// Convert a [ListOptions] to [InternalListOptions] + static InternalListOptions convertOptions(ListOptions? options) { if (options == null) { - return PigeonListOptions(maxResults: 1000); + return InternalListOptions(maxResults: 1000); } - return PigeonListOptions( + return InternalListOptions( maxResults: options.maxResults ?? 1000, pageToken: options.pageToken, ); } - /// Convert a [PigeonListResult] to [ListResultPlatform] + /// Convert a [InternalListResult] to [ListResultPlatform] ListResultPlatform convertListReference( - PigeonListResult pigeonReferenceList) { + InternalListResult pigeonReferenceList) { List referencePaths = []; for (final reference in pigeonReferenceList.items) { referencePaths.add(reference!.fullPath); @@ -115,10 +115,10 @@ class MethodChannelReference extends ReferencePlatform { @override Future list([ListOptions? options]) async { try { - PigeonListOptions pigeonOptions = convertOptions(options); - PigeonListResult pigeonReferenceList = await MethodChannelFirebaseStorage - .pigeonChannel - .referenceList(pigeonFirebaseApp, pigeonReference, pigeonOptions); + InternalListOptions pigeonOptions = convertOptions(options); + InternalListResult pigeonReferenceList = + await MethodChannelFirebaseStorage.pigeonChannel + .referenceList(pigeonFirebaseApp, pigeonReference, pigeonOptions); return convertListReference(pigeonReferenceList); } catch (e, stack) { convertPlatformException(e, stack); @@ -128,9 +128,9 @@ class MethodChannelReference extends ReferencePlatform { @override Future listAll() async { try { - PigeonListResult pigeonReferenceList = await MethodChannelFirebaseStorage - .pigeonChannel - .referenceListAll(pigeonFirebaseApp, pigeonReference); + InternalListResult pigeonReferenceList = + await MethodChannelFirebaseStorage.pigeonChannel + .referenceListAll(pigeonFirebaseApp, pigeonReference); return convertListReference(pigeonReferenceList); } catch (e, stack) { convertPlatformException(e, stack); @@ -173,9 +173,9 @@ class MethodChannelReference extends ReferencePlatform { handle, storage, fullPath, data, format, metadata); } - /// Convert a [SettableMetadata] to [PigeonSettableMetadata] - PigeonSettableMetadata convertToPigeonMetaData(SettableMetadata data) { - return PigeonSettableMetadata( + /// Convert a [SettableMetadata] to [InternalSettableMetadata] + InternalSettableMetadata convertToPigeonMetaData(SettableMetadata data) { + return InternalSettableMetadata( cacheControl: data.cacheControl, contentDisposition: data.contentDisposition, contentEncoding: data.contentEncoding, @@ -188,7 +188,7 @@ class MethodChannelReference extends ReferencePlatform { @override Future updateMetadata(SettableMetadata metadata) async { try { - PigeonFullMetaData updatedMetaData = await MethodChannelFirebaseStorage + InternalFullMetaData updatedMetaData = await MethodChannelFirebaseStorage .pigeonChannel .referenceUpdateMetadata(pigeonFirebaseApp, pigeonReference, convertToPigeonMetaData(metadata)); diff --git a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_task.dart b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_task.dart index cb10a718cc6b..71524a2c441e 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_task.dart +++ b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/method_channel/method_channel_task.dart @@ -126,27 +126,27 @@ abstract class MethodChannelTask extends TaskPlatform { bool _userListening = false; /// FirebaseApp pigeon instance - static PigeonStorageFirebaseApp pigeonFirebaseApp( + static InternalStorageFirebaseApp pigeonFirebaseApp( FirebaseStoragePlatform storage) { - return PigeonStorageFirebaseApp( + return InternalStorageFirebaseApp( appName: storage.app.name, bucket: storage.bucket, ); } - /// Convert [TaskState] to [PigeonStorageTaskState] - PigeonStorageTaskState convertToPigeonTaskState(TaskState state) { + /// Convert [TaskState] to [InternalStorageTaskState] + InternalStorageTaskState convertToPigeonTaskState(TaskState state) { switch (state) { case TaskState.canceled: - return PigeonStorageTaskState.canceled; + return InternalStorageTaskState.canceled; case TaskState.error: - return PigeonStorageTaskState.error; + return InternalStorageTaskState.error; case TaskState.paused: - return PigeonStorageTaskState.paused; + return InternalStorageTaskState.paused; case TaskState.running: - return PigeonStorageTaskState.running; + return InternalStorageTaskState.running; case TaskState.success: - return PigeonStorageTaskState.success; + return InternalStorageTaskState.success; } } @@ -263,7 +263,7 @@ class MethodChannelPutFileTask extends MethodChannelTask { static Future _getTask(int handle, FirebaseStoragePlatform storage, String path, File file, SettableMetadata? metadata) { - PigeonSettableMetadata? pigeonSettableMetadata; + InternalSettableMetadata? pigeonSettableMetadata; if (defaultTargetPlatform == TargetPlatform.windows) { // TODO(russellwheatley): sending null to windows throws exception so we pass empty metadata pigeonSettableMetadata = diff --git a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/pigeon/messages.pigeon.dart index d5f1ca5617df..ceb6abb3e6e0 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_storage/firebase_storage_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,19 +1,118 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; +} + +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + +bool _deepEquals(Object? a, Object? b) { + if (identical(a, b)) { + return true; + } + if (a is double && b is double) { + if (a.isNaN && b.isNaN) { + return true; + } + return a == b; + } + if (a is List && b is List) { + return a.length == b.length && + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + } + if (a is Map && b is Map) { + if (a.length != b.length) { + return false; + } + for (final MapEntry entryA in a.entries) { + bool found = false; + for (final MapEntry entryB in b.entries) { + if (_deepEquals(entryA.key, entryB.key)) { + if (_deepEquals(entryA.value, entryB.value)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; + } + return a == b; +} + +int _deepHash(Object? value) { + if (value is List) { + return Object.hashAll(value.map(_deepHash)); + } + if (value is Map) { + int result = 0; + for (final MapEntry entry in value.entries) { + result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value); + } + return result; + } + if (value is double && value.isNaN) { + // Normalize NaN to a consistent hash. + return 0x7FF8000000000000.hashCode; + } + if (value is double && value == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return 0.0.hashCode; + } + return value.hashCode; +} /// The type of operation that generated the action code from calling /// [TaskState]. -enum PigeonStorageTaskState { +enum InternalStorageTaskState { /// Indicates the task has been paused by the user. paused, @@ -30,8 +129,8 @@ enum PigeonStorageTaskState { error, } -class PigeonStorageFirebaseApp { - PigeonStorageFirebaseApp({ +class InternalStorageFirebaseApp { + InternalStorageFirebaseApp({ required this.appName, this.tenantId, required this.bucket, @@ -43,7 +142,7 @@ class PigeonStorageFirebaseApp { String bucket; - Object encode() { + List _toList() { return [ appName, tenantId, @@ -51,18 +150,41 @@ class PigeonStorageFirebaseApp { ]; } - static PigeonStorageFirebaseApp decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalStorageFirebaseApp decode(Object result) { result as List; - return PigeonStorageFirebaseApp( + return InternalStorageFirebaseApp( appName: result[0]! as String, tenantId: result[1] as String?, bucket: result[2]! as String, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalStorageFirebaseApp || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(appName, other.appName) && + _deepEquals(tenantId, other.tenantId) && + _deepEquals(bucket, other.bucket); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonStorageReference { - PigeonStorageReference({ +class InternalStorageReference { + InternalStorageReference({ required this.bucket, required this.fullPath, required this.name, @@ -74,7 +196,7 @@ class PigeonStorageReference { String name; - Object encode() { + List _toList() { return [ bucket, fullPath, @@ -82,39 +204,82 @@ class PigeonStorageReference { ]; } - static PigeonStorageReference decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalStorageReference decode(Object result) { result as List; - return PigeonStorageReference( + return InternalStorageReference( bucket: result[0]! as String, fullPath: result[1]! as String, name: result[2]! as String, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalStorageReference || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(bucket, other.bucket) && + _deepEquals(fullPath, other.fullPath) && + _deepEquals(name, other.name); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonFullMetaData { - PigeonFullMetaData({ +class InternalFullMetaData { + InternalFullMetaData({ this.metadata, }); Map? metadata; - Object encode() { + List _toList() { return [ metadata, ]; } - static PigeonFullMetaData decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalFullMetaData decode(Object result) { result as List; - return PigeonFullMetaData( + return InternalFullMetaData( metadata: (result[0] as Map?)?.cast(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalFullMetaData || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(metadata, other.metadata); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonListOptions { - PigeonListOptions({ +class InternalListOptions { + InternalListOptions({ required this.maxResults, this.pageToken, }); @@ -129,24 +294,45 @@ class PigeonListOptions { /// If provided, listing is resumed from the previous position. String? pageToken; - Object encode() { + List _toList() { return [ maxResults, pageToken, ]; } - static PigeonListOptions decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalListOptions decode(Object result) { result as List; - return PigeonListOptions( + return InternalListOptions( maxResults: result[0]! as int, pageToken: result[1] as String?, ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalListOptions || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(maxResults, other.maxResults) && + _deepEquals(pageToken, other.pageToken); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonSettableMetadata { - PigeonSettableMetadata({ +class InternalSettableMetadata { + InternalSettableMetadata({ this.cacheControl, this.contentDisposition, this.contentEncoding, @@ -183,7 +369,7 @@ class PigeonSettableMetadata { /// Additional user-defined custom metadata. Map? customMetadata; - Object encode() { + List _toList() { return [ cacheControl, contentDisposition, @@ -194,9 +380,13 @@ class PigeonSettableMetadata { ]; } - static PigeonSettableMetadata decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalSettableMetadata decode(Object result) { result as List; - return PigeonSettableMetadata( + return InternalSettableMetadata( cacheControl: result[0] as String?, contentDisposition: result[1] as String?, contentEncoding: result[2] as String?, @@ -206,22 +396,104 @@ class PigeonSettableMetadata { (result[5] as Map?)?.cast(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalSettableMetadata || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(cacheControl, other.cacheControl) && + _deepEquals(contentDisposition, other.contentDisposition) && + _deepEquals(contentEncoding, other.contentEncoding) && + _deepEquals(contentLanguage, other.contentLanguage) && + _deepEquals(contentType, other.contentType) && + _deepEquals(customMetadata, other.customMetadata); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class PigeonListResult { - PigeonListResult({ +class InternalStorageTaskSnapShot { + InternalStorageTaskSnapShot({ + required this.bytesTransferred, + this.metadata, + required this.state, + required this.totalBytes, + }); + + int bytesTransferred; + + InternalFullMetaData? metadata; + + InternalStorageTaskState state; + + int totalBytes; + + List _toList() { + return [ + bytesTransferred, + metadata, + state, + totalBytes, + ]; + } + + Object encode() { + return _toList(); + } + + static InternalStorageTaskSnapShot decode(Object result) { + result as List; + return InternalStorageTaskSnapShot( + bytesTransferred: result[0]! as int, + metadata: result[1] as InternalFullMetaData?, + state: result[2]! as InternalStorageTaskState, + totalBytes: result[3]! as int, + ); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalStorageTaskSnapShot || + other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(bytesTransferred, other.bytesTransferred) && + _deepEquals(metadata, other.metadata) && + _deepEquals(state, other.state) && + _deepEquals(totalBytes, other.totalBytes); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); +} + +class InternalListResult { + InternalListResult({ required this.items, this.pageToken, required this.prefixs, }); - List items; + List items; String? pageToken; - List prefixs; + List prefixs; - Object encode() { + List _toList() { return [ items, pageToken, @@ -229,38 +501,69 @@ class PigeonListResult { ]; } - static PigeonListResult decode(Object result) { + Object encode() { + return _toList(); + } + + static InternalListResult decode(Object result) { result as List; - return PigeonListResult( - items: (result[0] as List?)!.cast(), + return InternalListResult( + items: (result[0]! as List).cast(), pageToken: result[1] as String?, - prefixs: (result[2] as List?)!.cast(), + prefixs: (result[2]! as List).cast(), ); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! InternalListResult || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; + } + return _deepEquals(items, other.items) && + _deepEquals(pageToken, other.pageToken) && + _deepEquals(prefixs, other.prefixs); + } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => _deepHash([runtimeType, ..._toList()]); } -class _FirebaseStorageHostApiCodec extends StandardMessageCodec { - const _FirebaseStorageHostApiCodec(); +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonFullMetaData) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonListOptions) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is InternalStorageTaskState) { buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonListResult) { + writeValue(buffer, value.index); + } else if (value is InternalStorageFirebaseApp) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is PigeonSettableMetadata) { + } else if (value is InternalStorageReference) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is PigeonStorageFirebaseApp) { + } else if (value is InternalFullMetaData) { buffer.putUint8(132); writeValue(buffer, value.encode()); - } else if (value is PigeonStorageReference) { + } else if (value is InternalListOptions) { buffer.putUint8(133); writeValue(buffer, value.encode()); + } else if (value is InternalSettableMetadata) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is InternalStorageTaskSnapShot) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is InternalListResult) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -269,18 +572,23 @@ class _FirebaseStorageHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: - return PigeonFullMetaData.decode(readValue(buffer)!); case 129: - return PigeonListOptions.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : InternalStorageTaskState.values[value]; case 130: - return PigeonListResult.decode(readValue(buffer)!); + return InternalStorageFirebaseApp.decode(readValue(buffer)!); case 131: - return PigeonSettableMetadata.decode(readValue(buffer)!); + return InternalStorageReference.decode(readValue(buffer)!); case 132: - return PigeonStorageFirebaseApp.decode(readValue(buffer)!); + return InternalFullMetaData.decode(readValue(buffer)!); case 133: - return PigeonStorageReference.decode(readValue(buffer)!); + return InternalListOptions.decode(readValue(buffer)!); + case 134: + return InternalSettableMetadata.decode(readValue(buffer)!); + case 135: + return InternalStorageTaskSnapShot.decode(readValue(buffer)!); + case 136: + return InternalListResult.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -291,571 +599,427 @@ class FirebaseStorageHostApi { /// Constructor for [FirebaseStorageHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - FirebaseStorageHostApi({BinaryMessenger? binaryMessenger}) - : _binaryMessenger = binaryMessenger; - final BinaryMessenger? _binaryMessenger; - - static const MessageCodec codec = _FirebaseStorageHostApiCodec(); - - Future getReferencebyPath( - PigeonStorageFirebaseApp arg_app, - String arg_path, - String? arg_bucket) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel - .send([arg_app, arg_path, arg_bucket]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonStorageReference?)!; - } + FirebaseStorageHostApi( + {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future getReferencebyPath( + InternalStorageFirebaseApp app, String path, String? bucket) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, path, bucket]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalStorageReference; } Future setMaxOperationRetryTime( - PigeonStorageFirebaseApp arg_app, int arg_time) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_time]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + InternalStorageFirebaseApp app, int time) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, time]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setMaxUploadRetryTime( - PigeonStorageFirebaseApp arg_app, int arg_time) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_time]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + InternalStorageFirebaseApp app, int time) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, time]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future setMaxDownloadRetryTime( - PigeonStorageFirebaseApp arg_app, int arg_time) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_time]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + InternalStorageFirebaseApp app, int time) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, time]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future useStorageEmulator( - PigeonStorageFirebaseApp arg_app, String arg_host, int arg_port) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel - .send([arg_app, arg_host, arg_port]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + InternalStorageFirebaseApp app, String host, int port) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, host, port]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future referenceDelete(PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_reference]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return; - } + Future referenceDelete(InternalStorageFirebaseApp app, + InternalStorageReference reference) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } - Future referenceGetDownloadURL(PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_reference]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + Future referenceGetDownloadURL(InternalStorageFirebaseApp app, + InternalStorageReference reference) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } - Future referenceGetMetaData( - PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_reference]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonFullMetaData?)!; - } + Future referenceGetMetaData( + InternalStorageFirebaseApp app, + InternalStorageReference reference) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalFullMetaData; } - Future referenceList( - PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference, - PigeonListOptions arg_options) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel - .send([arg_app, arg_reference, arg_options]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonListResult?)!; - } + Future referenceList(InternalStorageFirebaseApp app, + InternalStorageReference reference, InternalListOptions options) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference, options]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalListResult; } - Future referenceListAll(PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_reference]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonListResult?)!; - } + Future referenceListAll(InternalStorageFirebaseApp app, + InternalStorageReference reference) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalListResult; } - Future referenceGetData(PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference, int arg_maxSize) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel - .send([arg_app, arg_reference, arg_maxSize]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else { - return (replyList[0] as Uint8List?); - } + Future referenceGetData(InternalStorageFirebaseApp app, + InternalStorageReference reference, int maxSize) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference, maxSize]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); + return pigeonVar_replyValue as Uint8List?; } Future referencePutData( - PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference, - Uint8List arg_data, - PigeonSettableMetadata arg_settableMetaData, - int arg_handle) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send([ - arg_app, - arg_reference, - arg_data, - arg_settableMetaData, - arg_handle - ]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + InternalStorageFirebaseApp app, + InternalStorageReference reference, + Uint8List data, + InternalSettableMetadata settableMetaData, + int handle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([app, reference, data, settableMetaData, handle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future referencePutString( - PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference, - String arg_data, - int arg_format, - PigeonSettableMetadata arg_settableMetaData, - int arg_handle) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send([ - arg_app, - arg_reference, - arg_data, - arg_format, - arg_settableMetaData, - arg_handle - ]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + InternalStorageFirebaseApp app, + InternalStorageReference reference, + String data, + int format, + InternalSettableMetadata settableMetaData, + int handle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [app, reference, data, format, settableMetaData, handle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future referencePutFile( - PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference, - String arg_filePath, - PigeonSettableMetadata? arg_settableMetaData, - int arg_handle) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel.send([ - arg_app, - arg_reference, - arg_filePath, - arg_settableMetaData, - arg_handle - ]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + InternalStorageFirebaseApp app, + InternalStorageReference reference, + String filePath, + InternalSettableMetadata? settableMetaData, + int handle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([app, reference, filePath, settableMetaData, handle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } - Future referenceDownloadFile( - PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference, - String arg_filePath, - int arg_handle) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = await channel - .send([arg_app, arg_reference, arg_filePath, arg_handle]) - as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as String?)!; - } + Future referenceDownloadFile(InternalStorageFirebaseApp app, + InternalStorageReference reference, String filePath, int handle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference, filePath, handle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } - Future referenceUpdateMetadata( - PigeonStorageFirebaseApp arg_app, - PigeonStorageReference arg_reference, - PigeonSettableMetadata arg_metadata) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_reference, arg_metadata]) - as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as PigeonFullMetaData?)!; - } + Future referenceUpdateMetadata( + InternalStorageFirebaseApp app, + InternalStorageReference reference, + InternalSettableMetadata metadata) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, reference, metadata]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as InternalFullMetaData; } - Future> taskPause( - PigeonStorageFirebaseApp arg_app, int arg_handle) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_handle]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Map?)!.cast(); - } + Future> taskPause( + InternalStorageFirebaseApp app, int handle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, handle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } - Future> taskResume( - PigeonStorageFirebaseApp arg_app, int arg_handle) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_handle]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Map?)!.cast(); - } + Future> taskResume( + InternalStorageFirebaseApp app, int handle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, handle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } - Future> taskCancel( - PigeonStorageFirebaseApp arg_app, int arg_handle) async { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel', - codec, - binaryMessenger: _binaryMessenger); - final List? replyList = - await channel.send([arg_app, arg_handle]) as List?; - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel.', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (replyList[0] as Map?)!.cast(); - } + Future> taskCancel( + InternalStorageFirebaseApp app, int handle) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([app, handle]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return (pigeonVar_replyValue! as Map) + .cast(); } } diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pigeons/messages.dart b/packages/firebase_storage/firebase_storage_platform_interface/pigeons/messages.dart index bd36f3a6b57d..2cade8ddbef5 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pigeons/messages.dart +++ b/packages/firebase_storage/firebase_storage_platform_interface/pigeons/messages.dart @@ -24,8 +24,8 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) -class PigeonStorageFirebaseApp { - const PigeonStorageFirebaseApp({ +class InternalStorageFirebaseApp { + const InternalStorageFirebaseApp({ required this.appName, required this.tenantId, required this.bucket, @@ -38,7 +38,7 @@ class PigeonStorageFirebaseApp { /// The type of operation that generated the action code from calling /// [TaskState]. -enum PigeonStorageTaskState { +enum InternalStorageTaskState { /// Indicates the task has been paused by the user. paused, @@ -55,8 +55,8 @@ enum PigeonStorageTaskState { error, } -class PigeonStorageReference { - const PigeonStorageReference({ +class InternalStorageReference { + const InternalStorageReference({ required this.bucket, required this.fullPath, required this.name, @@ -67,15 +67,15 @@ class PigeonStorageReference { final String name; } -class PigeonFullMetaData { - const PigeonFullMetaData({ +class InternalFullMetaData { + const InternalFullMetaData({ required this.metadata, }); final Map? metadata; } -class PigeonListOptions { - const PigeonListOptions({ +class InternalListOptions { + const InternalListOptions({ required this.maxResults, this.pageToken, }); @@ -91,9 +91,9 @@ class PigeonListOptions { final String? pageToken; } -class PigeonSettableMetadata { - /// Creates a new [PigeonSettableMetadata] instance. - PigeonSettableMetadata({ +class InternalSettableMetadata { + /// Creates a new [InternalSettableMetadata] instance. + InternalSettableMetadata({ this.cacheControl, this.contentDisposition, this.contentEncoding, @@ -131,8 +131,8 @@ class PigeonSettableMetadata { final Map? customMetadata; } -class PigeonStorageTaskSnapShot { - const PigeonStorageTaskSnapShot({ +class InternalStorageTaskSnapShot { + const InternalStorageTaskSnapShot({ required this.bytesTransferred, required this.metadata, required this.state, @@ -140,50 +140,50 @@ class PigeonStorageTaskSnapShot { }); final int bytesTransferred; - final PigeonFullMetaData? metadata; - final PigeonStorageTaskState state; + final InternalFullMetaData? metadata; + final InternalStorageTaskState state; final int totalBytes; } -class PigeonListResult { - const PigeonListResult({ +class InternalListResult { + const InternalListResult({ required this.items, required this.pageToken, required this.prefixs, }); - final List items; + final List items; final String? pageToken; - final List prefixs; + final List prefixs; } @HostApi(dartHostTestHandler: 'TestFirebaseStorageHostApi') abstract class FirebaseStorageHostApi { @async - PigeonStorageReference getReferencebyPath( - PigeonStorageFirebaseApp app, + InternalStorageReference getReferencebyPath( + InternalStorageFirebaseApp app, String path, String? bucket, ); @async void setMaxOperationRetryTime( - PigeonStorageFirebaseApp app, + InternalStorageFirebaseApp app, int time, ); @async void setMaxUploadRetryTime( - PigeonStorageFirebaseApp app, + InternalStorageFirebaseApp app, int time, ); @async void setMaxDownloadRetryTime( - PigeonStorageFirebaseApp app, + InternalStorageFirebaseApp app, int time, ); @async void useStorageEmulator( - PigeonStorageFirebaseApp app, + InternalStorageFirebaseApp app, String host, int port, ); @@ -192,101 +192,101 @@ abstract class FirebaseStorageHostApi { @async void referenceDelete( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, ); @async String referenceGetDownloadURL( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, ); @async - PigeonFullMetaData referenceGetMetaData( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalFullMetaData referenceGetMetaData( + InternalStorageFirebaseApp app, + InternalStorageReference reference, ); @async - PigeonListResult referenceList( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, - PigeonListOptions options, + InternalListResult referenceList( + InternalStorageFirebaseApp app, + InternalStorageReference reference, + InternalListOptions options, ); @async - PigeonListResult referenceListAll( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalListResult referenceListAll( + InternalStorageFirebaseApp app, + InternalStorageReference reference, ); @async Uint8List? referenceGetData( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, int maxSize, ); @async String referencePutData( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, Uint8List data, - PigeonSettableMetadata settableMetaData, + InternalSettableMetadata settableMetaData, int handle, ); @async String referencePutString( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, String data, int format, - PigeonSettableMetadata settableMetaData, + InternalSettableMetadata settableMetaData, int handle, ); @async String referencePutFile( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, String filePath, - PigeonSettableMetadata? settableMetaData, + InternalSettableMetadata? settableMetaData, int handle, ); @async String referenceDownloadFile( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, String filePath, int handle, ); @async - PigeonFullMetaData referenceUpdateMetadata( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, - PigeonSettableMetadata metadata, + InternalFullMetaData referenceUpdateMetadata( + InternalStorageFirebaseApp app, + InternalStorageReference reference, + InternalSettableMetadata metadata, ); // APIs for Task class @async Map taskPause( - PigeonStorageFirebaseApp app, + InternalStorageFirebaseApp app, int handle, ); @async Map taskResume( - PigeonStorageFirebaseApp app, + InternalStorageFirebaseApp app, int handle, ); @async Map taskCancel( - PigeonStorageFirebaseApp app, + InternalStorageFirebaseApp app, int handle, ); } diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml index 50456ad4f18a..6cbd4094710a 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml @@ -22,4 +22,4 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 - pigeon: 11.0.1 + pigeon: 26.3.4 diff --git a/packages/firebase_storage/firebase_storage_platform_interface/test/pigeon/test_api.dart b/packages/firebase_storage/firebase_storage_platform_interface/test/pigeon/test_api.dart index d11d0f21236b..13214ad904ab 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/test/pigeon/test_api.dart +++ b/packages/firebase_storage/firebase_storage_platform_interface/test/pigeon/test_api.dart @@ -1,39 +1,49 @@ // Copyright 2023, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v11.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, unnecessary_import, no_leading_underscores_for_local_identifiers, omit_obvious_local_variable_types // ignore_for_file: avoid_relative_lib_imports import 'dart:async'; -import 'dart:typed_data' show Uint8List; -import 'package:firebase_storage_platform_interface/src/pigeon/messages.pigeon.dart'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -class _TestFirebaseStorageHostApiCodec extends StandardMessageCodec { - const _TestFirebaseStorageHostApiCodec(); +import 'package:firebase_storage_platform_interface/src/pigeon/messages.pigeon.dart'; + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); @override void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonFullMetaData) { - buffer.putUint8(128); - writeValue(buffer, value.encode()); - } else if (value is PigeonListOptions) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else if (value is InternalStorageTaskState) { buffer.putUint8(129); - writeValue(buffer, value.encode()); - } else if (value is PigeonListResult) { + writeValue(buffer, value.index); + } else if (value is InternalStorageFirebaseApp) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is PigeonSettableMetadata) { + } else if (value is InternalStorageReference) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is PigeonStorageFirebaseApp) { + } else if (value is InternalFullMetaData) { buffer.putUint8(132); writeValue(buffer, value.encode()); - } else if (value is PigeonStorageReference) { + } else if (value is InternalListOptions) { buffer.putUint8(133); writeValue(buffer, value.encode()); + } else if (value is InternalSettableMetadata) { + buffer.putUint8(134); + writeValue(buffer, value.encode()); + } else if (value is InternalStorageTaskSnapShot) { + buffer.putUint8(135); + writeValue(buffer, value.encode()); + } else if (value is InternalListResult) { + buffer.putUint8(136); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -42,18 +52,23 @@ class _TestFirebaseStorageHostApiCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: - return PigeonFullMetaData.decode(readValue(buffer)!); case 129: - return PigeonListOptions.decode(readValue(buffer)!); + final value = readValue(buffer) as int?; + return value == null ? null : InternalStorageTaskState.values[value]; case 130: - return PigeonListResult.decode(readValue(buffer)!); + return InternalStorageFirebaseApp.decode(readValue(buffer)!); case 131: - return PigeonSettableMetadata.decode(readValue(buffer)!); + return InternalStorageReference.decode(readValue(buffer)!); case 132: - return PigeonStorageFirebaseApp.decode(readValue(buffer)!); + return InternalFullMetaData.decode(readValue(buffer)!); case 133: - return PigeonStorageReference.decode(readValue(buffer)!); + return InternalListOptions.decode(readValue(buffer)!); + case 134: + return InternalSettableMetadata.decode(readValue(buffer)!); + case 135: + return InternalStorageTaskSnapShot.decode(readValue(buffer)!); + case 136: + return InternalListResult.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -63,671 +78,667 @@ class _TestFirebaseStorageHostApiCodec extends StandardMessageCodec { abstract class TestFirebaseStorageHostApi { static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding => TestDefaultBinaryMessengerBinding.instance; - static const MessageCodec codec = _TestFirebaseStorageHostApiCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - Future getReferencebyPath( - PigeonStorageFirebaseApp app, String path, String? bucket); + Future getReferencebyPath( + InternalStorageFirebaseApp app, String path, String? bucket); - Future setMaxOperationRetryTime(PigeonStorageFirebaseApp app, int time); + Future setMaxOperationRetryTime( + InternalStorageFirebaseApp app, int time); - Future setMaxUploadRetryTime(PigeonStorageFirebaseApp app, int time); + Future setMaxUploadRetryTime(InternalStorageFirebaseApp app, int time); - Future setMaxDownloadRetryTime(PigeonStorageFirebaseApp app, int time); + Future setMaxDownloadRetryTime( + InternalStorageFirebaseApp app, int time); Future useStorageEmulator( - PigeonStorageFirebaseApp app, String host, int port); + InternalStorageFirebaseApp app, String host, int port); Future referenceDelete( - PigeonStorageFirebaseApp app, PigeonStorageReference reference); + InternalStorageFirebaseApp app, InternalStorageReference reference); Future referenceGetDownloadURL( - PigeonStorageFirebaseApp app, PigeonStorageReference reference); + InternalStorageFirebaseApp app, InternalStorageReference reference); - Future referenceGetMetaData( - PigeonStorageFirebaseApp app, PigeonStorageReference reference); + Future referenceGetMetaData( + InternalStorageFirebaseApp app, InternalStorageReference reference); - Future referenceList(PigeonStorageFirebaseApp app, - PigeonStorageReference reference, PigeonListOptions options); + Future referenceList(InternalStorageFirebaseApp app, + InternalStorageReference reference, InternalListOptions options); - Future referenceListAll( - PigeonStorageFirebaseApp app, PigeonStorageReference reference); + Future referenceListAll( + InternalStorageFirebaseApp app, InternalStorageReference reference); - Future referenceGetData(PigeonStorageFirebaseApp app, - PigeonStorageReference reference, int maxSize); + Future referenceGetData(InternalStorageFirebaseApp app, + InternalStorageReference reference, int maxSize); Future referencePutData( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, Uint8List data, - PigeonSettableMetadata settableMetaData, + InternalSettableMetadata settableMetaData, int handle); Future referencePutString( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, String data, int format, - PigeonSettableMetadata settableMetaData, + InternalSettableMetadata settableMetaData, int handle); Future referencePutFile( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, + InternalStorageFirebaseApp app, + InternalStorageReference reference, String filePath, - PigeonSettableMetadata? settableMetaData, + InternalSettableMetadata? settableMetaData, int handle); - Future referenceDownloadFile(PigeonStorageFirebaseApp app, - PigeonStorageReference reference, String filePath, int handle); + Future referenceDownloadFile(InternalStorageFirebaseApp app, + InternalStorageReference reference, String filePath, int handle); - Future referenceUpdateMetadata( - PigeonStorageFirebaseApp app, - PigeonStorageReference reference, - PigeonSettableMetadata metadata); + Future referenceUpdateMetadata( + InternalStorageFirebaseApp app, + InternalStorageReference reference, + InternalSettableMetadata metadata); - Future> taskPause( - PigeonStorageFirebaseApp app, int handle); + Future> taskPause( + InternalStorageFirebaseApp app, int handle); - Future> taskResume( - PigeonStorageFirebaseApp app, int handle); + Future> taskResume( + InternalStorageFirebaseApp app, int handle); - Future> taskCancel( - PigeonStorageFirebaseApp app, int handle); + Future> taskCancel( + InternalStorageFirebaseApp app, int handle); - static void setup(TestFirebaseStorageHostApi? api, - {BinaryMessenger? binaryMessenger}) { + static void setUp( + TestFirebaseStorageHostApi? api, { + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) { + messageChannelSuffix = + messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath was null, expected non-null PigeonStorageFirebaseApp.'); - final String? arg_path = (args[1] as String?); - assert(arg_path != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath was null, expected non-null String.'); - final String? arg_bucket = (args[2] as String?); - final PigeonStorageReference output = - await api.getReferencebyPath(arg_app!, arg_path!, arg_bucket); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final String arg_path = args[1]! as String; + final String? arg_bucket = args[2] as String?; + try { + final InternalStorageReference output = + await api.getReferencebyPath(arg_app, arg_path, arg_bucket); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime was null, expected non-null PigeonStorageFirebaseApp.'); - final int? arg_time = (args[1] as int?); - assert(arg_time != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime was null, expected non-null int.'); - await api.setMaxOperationRetryTime(arg_app!, arg_time!); - return []; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final int arg_time = args[1]! as int; + try { + await api.setMaxOperationRetryTime(arg_app, arg_time); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime was null, expected non-null PigeonStorageFirebaseApp.'); - final int? arg_time = (args[1] as int?); - assert(arg_time != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime was null, expected non-null int.'); - await api.setMaxUploadRetryTime(arg_app!, arg_time!); - return []; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final int arg_time = args[1]! as int; + try { + await api.setMaxUploadRetryTime(arg_app, arg_time); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime was null, expected non-null PigeonStorageFirebaseApp.'); - final int? arg_time = (args[1] as int?); - assert(arg_time != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime was null, expected non-null int.'); - await api.setMaxDownloadRetryTime(arg_app!, arg_time!); - return []; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final int arg_time = args[1]! as int; + try { + await api.setMaxDownloadRetryTime(arg_app, arg_time); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator was null, expected non-null PigeonStorageFirebaseApp.'); - final String? arg_host = (args[1] as String?); - assert(arg_host != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator was null, expected non-null String.'); - final int? arg_port = (args[2] as int?); - assert(arg_port != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator was null, expected non-null int.'); - await api.useStorageEmulator(arg_app!, arg_host!, arg_port!); - return []; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final String arg_host = args[1]! as String; + final int arg_port = args[2]! as int; + try { + await api.useStorageEmulator(arg_app, arg_host, arg_port); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete was null, expected non-null PigeonStorageReference.'); - await api.referenceDelete(arg_app!, arg_reference!); - return []; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + try { + await api.referenceDelete(arg_app, arg_reference); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL was null, expected non-null PigeonStorageReference.'); - final String output = - await api.referenceGetDownloadURL(arg_app!, arg_reference!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + try { + final String output = + await api.referenceGetDownloadURL(arg_app, arg_reference); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData was null, expected non-null PigeonStorageReference.'); - final PigeonFullMetaData output = - await api.referenceGetMetaData(arg_app!, arg_reference!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + try { + final InternalFullMetaData output = + await api.referenceGetMetaData(arg_app, arg_reference); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList was null, expected non-null PigeonStorageReference.'); - final PigeonListOptions? arg_options = - (args[2] as PigeonListOptions?); - assert(arg_options != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList was null, expected non-null PigeonListOptions.'); - final PigeonListResult output = - await api.referenceList(arg_app!, arg_reference!, arg_options!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + final InternalListOptions arg_options = + args[2]! as InternalListOptions; + try { + final InternalListResult output = + await api.referenceList(arg_app, arg_reference, arg_options); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll was null, expected non-null PigeonStorageReference.'); - final PigeonListResult output = - await api.referenceListAll(arg_app!, arg_reference!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + try { + final InternalListResult output = + await api.referenceListAll(arg_app, arg_reference); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData was null, expected non-null PigeonStorageReference.'); - final int? arg_maxSize = (args[2] as int?); - assert(arg_maxSize != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData was null, expected non-null int.'); - final Uint8List? output = await api.referenceGetData( - arg_app!, arg_reference!, arg_maxSize!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + final int arg_maxSize = args[2]! as int; + try { + final Uint8List? output = + await api.referenceGetData(arg_app, arg_reference, arg_maxSize); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData was null, expected non-null PigeonStorageReference.'); - final Uint8List? arg_data = (args[2] as Uint8List?); - assert(arg_data != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData was null, expected non-null Uint8List.'); - final PigeonSettableMetadata? arg_settableMetaData = - (args[3] as PigeonSettableMetadata?); - assert(arg_settableMetaData != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData was null, expected non-null PigeonSettableMetadata.'); - final int? arg_handle = (args[4] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData was null, expected non-null int.'); - final String output = await api.referencePutData(arg_app!, - arg_reference!, arg_data!, arg_settableMetaData!, arg_handle!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + final Uint8List arg_data = args[2]! as Uint8List; + final InternalSettableMetadata arg_settableMetaData = + args[3]! as InternalSettableMetadata; + final int arg_handle = args[4]! as int; + try { + final String output = await api.referencePutData(arg_app, + arg_reference, arg_data, arg_settableMetaData, arg_handle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString was null, expected non-null PigeonStorageReference.'); - final String? arg_data = (args[2] as String?); - assert(arg_data != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString was null, expected non-null String.'); - final int? arg_format = (args[3] as int?); - assert(arg_format != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString was null, expected non-null int.'); - final PigeonSettableMetadata? arg_settableMetaData = - (args[4] as PigeonSettableMetadata?); - assert(arg_settableMetaData != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString was null, expected non-null PigeonSettableMetadata.'); - final int? arg_handle = (args[5] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString was null, expected non-null int.'); - final String output = await api.referencePutString( - arg_app!, - arg_reference!, - arg_data!, - arg_format!, - arg_settableMetaData!, - arg_handle!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + final String arg_data = args[2]! as String; + final int arg_format = args[3]! as int; + final InternalSettableMetadata arg_settableMetaData = + args[4]! as InternalSettableMetadata; + final int arg_handle = args[5]! as int; + try { + final String output = await api.referencePutString( + arg_app, + arg_reference, + arg_data, + arg_format, + arg_settableMetaData, + arg_handle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile was null, expected non-null PigeonStorageReference.'); - final String? arg_filePath = (args[2] as String?); - assert(arg_filePath != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile was null, expected non-null String.'); - final PigeonSettableMetadata? arg_settableMetaData = - (args[3] as PigeonSettableMetadata?); - final int? arg_handle = (args[4] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile was null, expected non-null int.'); - final String output = await api.referencePutFile(arg_app!, - arg_reference!, arg_filePath!, arg_settableMetaData, arg_handle!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + final String arg_filePath = args[2]! as String; + final InternalSettableMetadata? arg_settableMetaData = + args[3] as InternalSettableMetadata?; + final int arg_handle = args[4]! as int; + try { + final String output = await api.referencePutFile(arg_app, + arg_reference, arg_filePath, arg_settableMetaData, arg_handle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile was null, expected non-null PigeonStorageReference.'); - final String? arg_filePath = (args[2] as String?); - assert(arg_filePath != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile was null, expected non-null String.'); - final int? arg_handle = (args[3] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile was null, expected non-null int.'); - final String output = await api.referenceDownloadFile( - arg_app!, arg_reference!, arg_filePath!, arg_handle!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + final String arg_filePath = args[2]! as String; + final int arg_handle = args[3]! as int; + try { + final String output = await api.referenceDownloadFile( + arg_app, arg_reference, arg_filePath, arg_handle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata was null, expected non-null PigeonStorageFirebaseApp.'); - final PigeonStorageReference? arg_reference = - (args[1] as PigeonStorageReference?); - assert(arg_reference != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata was null, expected non-null PigeonStorageReference.'); - final PigeonSettableMetadata? arg_metadata = - (args[2] as PigeonSettableMetadata?); - assert(arg_metadata != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata was null, expected non-null PigeonSettableMetadata.'); - final PigeonFullMetaData output = await api.referenceUpdateMetadata( - arg_app!, arg_reference!, arg_metadata!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final InternalStorageReference arg_reference = + args[1]! as InternalStorageReference; + final InternalSettableMetadata arg_metadata = + args[2]! as InternalSettableMetadata; + try { + final InternalFullMetaData output = await api + .referenceUpdateMetadata(arg_app, arg_reference, arg_metadata); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause was null, expected non-null PigeonStorageFirebaseApp.'); - final int? arg_handle = (args[1] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause was null, expected non-null int.'); - final Map output = - await api.taskPause(arg_app!, arg_handle!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final int arg_handle = args[1]! as int; + try { + final Map output = + await api.taskPause(arg_app, arg_handle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume was null, expected non-null PigeonStorageFirebaseApp.'); - final int? arg_handle = (args[1] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume was null, expected non-null int.'); - final Map output = - await api.taskResume(arg_app!, arg_handle!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final int arg_handle = args[1]! as int; + try { + final Map output = + await api.taskResume(arg_app, arg_handle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel', - codec, + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel$messageChannelSuffix', + pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, null); + .setMockDecodedMessageHandler(pigeonVar_channel, null); } else { _testBinaryMessengerBinding!.defaultBinaryMessenger - .setMockDecodedMessageHandler(channel, + .setMockDecodedMessageHandler(pigeonVar_channel, (Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel was null.'); - final List args = (message as List?)!; - final PigeonStorageFirebaseApp? arg_app = - (args[0] as PigeonStorageFirebaseApp?); - assert(arg_app != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel was null, expected non-null PigeonStorageFirebaseApp.'); - final int? arg_handle = (args[1] as int?); - assert(arg_handle != null, - 'Argument for dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel was null, expected non-null int.'); - final Map output = - await api.taskCancel(arg_app!, arg_handle!); - return [output]; + final List args = message! as List; + final InternalStorageFirebaseApp arg_app = + args[0]! as InternalStorageFirebaseApp; + final int arg_handle = args[1]! as int; + try { + final Map output = + await api.taskCancel(arg_app, arg_handle); + return [output]; + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } From 15eb457726381d80b25e34d9f5ddee7e29d4bfa4 Mon Sep 17 00:00:00 2001 From: Engels Immanuel <40745212+Daeon97@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:02:07 +0100 Subject: [PATCH 036/137] docs(auth): add Android access token revocation guide (#18215) --- docs/auth/federated-auth.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/auth/federated-auth.md b/docs/auth/federated-auth.md index 3811c94f348a..b4d73a36b633 100644 --- a/docs/auth/federated-auth.md +++ b/docs/auth/federated-auth.md @@ -284,6 +284,16 @@ Future signInWithApple() async { } ``` +On Android platforms, obtain the access token then revoke the token using the +`revokeAccessToken()` API. + +```dart +// Keep the access token returned from Android platforms +String? accessToken = userCredential.credential?.accessToken; +// Revoke the access token +await FirebaseAuth.instance.revokeAccessToken(accessToken!); +``` + ## Apple Game Center (Apple only) {:#games} Ensure the "Game Center" sign-in provider is enabled on the [Firebase Console](https://console.firebase.google.com/project/_/authentication/providers). From 6cdfcb103da7be46ccb190d7e107d8c537aa1ff8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 21 Apr 2026 06:54:33 -0700 Subject: [PATCH 037/137] refactor: move all packages to workspace (#18182) * Refactor: move all packages to workspace * Add some workspace validation logic! --------- Co-authored-by: Guillaume Bernos --- .github/workflows/all_plugins.yaml | 11 +- packages/_flutterfire_internals/pubspec.yaml | 6 +- .../cloud_firestore/example/pubspec.yaml | 4 +- .../pipeline_example/lib/main.dart | 2 +- .../pipeline_example/pubspec.yaml | 19 +- .../cloud_firestore/pubspec.yaml | 5 +- .../pubspec.yaml | 7 +- .../cloud_firestore_web/pubspec.yaml | 3 +- .../cloud_functions/example/pubspec.yaml | 5 +- .../cloud_functions/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../cloud_functions_web/pubspec.yaml | 3 +- .../firebase_ai/example/pubspec.yaml | 4 +- packages/firebase_ai/firebase_ai/pubspec.yaml | 3 +- .../firebase_analytics/example/pubspec.yaml | 5 +- .../firebase_analytics/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_analytics_web/pubspec.yaml | 3 +- .../firebase_app_check/example/pubspec.yaml | 4 +- .../firebase_app_check/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_app_check_web/pubspec.yaml | 3 +- .../example/pubspec.yaml | 4 +- .../firebase_app_installations/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../pubspec.yaml | 3 +- .../firebase_auth/example/pubspec.yaml | 4 +- .../firebase_auth/firebase_auth/pubspec.yaml | 3 +- .../pubspec.yaml | 5 +- .../firebase_auth_web/pubspec.yaml | 3 +- .../firebase_core/example/pubspec.yaml | 4 +- .../firebase_core/firebase_core/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_core_web/pubspec.yaml | 3 +- .../firebase_crashlytics/example/pubspec.yaml | 5 +- .../firebase_crashlytics/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../example/pubspec.yaml | 6 +- .../firebase_data_connect/pubspec.yaml | 7 +- .../firebase_database/example/pubspec.yaml | 5 +- .../firebase_database/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_database_web/pubspec.yaml | 3 +- .../example/pubspec.yaml | 4 +- .../firebase_in_app_messaging/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_messaging/example/pubspec.yaml | 5 +- .../firebase_messaging/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_messaging_web/pubspec.yaml | 3 +- .../example/pubspec.yaml | 4 +- .../firebase_ml_model_downloader/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_performance/example/pubspec.yaml | 4 +- .../firebase_performance/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_performance_web/pubspec.yaml | 3 +- .../example/pubspec.yaml | 5 +- .../firebase_remote_config/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_remote_config_web/pubspec.yaml | 3 +- .../firebase_storage/example/pubspec.yaml | 4 +- .../firebase_storage/pubspec.yaml | 5 +- .../pubspec.yaml | 5 +- .../firebase_storage_web/pubspec.yaml | 3 +- pubspec.yaml | 429 +++++++++++++++++- scripts/generate_bom.dart | 2 +- scripts/generate_versions_spm.dart | 5 +- scripts/validate_workspace.dart | 125 +++++ tests/pubspec.yaml | 3 +- 70 files changed, 740 insertions(+), 134 deletions(-) create mode 100644 scripts/validate_workspace.dart diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 7e00a292bc5c..a4a2e1ba8819 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -35,6 +35,9 @@ jobs: melos-version: '5.3.0' - name: 'Run Analyze' run: melos analyze-ci + - name: 'Validate Workspace' + if: always() + run: melos run validate:workspace # Separated from "analyse" action as pubspec_override file is not being taken into account when running `flutter pub publish --dry-run` # This will fail on CI until this is fixed: https://github.com/invertase/melos/issues/467 @@ -192,8 +195,12 @@ jobs: # Go is used by addlicense command (addlicense is used in melos run # check-license-header) - run: go install github.com/google/addlicense@latest - - name: Install Dart - uses: dart-lang/setup-dart@65eb853c7ba17dde3be364c3d2858773e7144260 + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + cache: true + cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" + pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - name: Install Melos uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: diff --git a/packages/_flutterfire_internals/pubspec.yaml b/packages/_flutterfire_internals/pubspec.yaml index c12377176ca4..ae21b2daef21 100755 --- a/packages/_flutterfire_internals/pubspec.yaml +++ b/packages/_flutterfire_internals/pubspec.yaml @@ -3,10 +3,11 @@ description: A package hosting Dart code shared between FlutterFire plugins. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/_flutterfire_internals version: 1.3.69 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: collection: ^1.0.0 @@ -20,4 +21,3 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 - test: any diff --git a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml index 01c8bde1efa1..dc72745bc3ec 100755 --- a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml @@ -1,8 +1,10 @@ name: cloud_firestore_example description: Demonstrates how to use the firestore plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: cloud_firestore: ^6.3.0 diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart index 1875e5da6ece..db42d904e7ff 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/lib/main.dart @@ -543,7 +543,7 @@ class _PipelineExamplePageState extends State { .limit(1) .addFields( // VectorValue - Constant(VectorValue([1.0, 2.0, 3.0])).as('c_vector'), + Constant(const VectorValue([1.0, 2.0, 3.0])).as('c_vector'), Constant(null).as('c_null'), // String diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml index 6186b0a60e8a..3a5b9b2acb1a 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -17,6 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. version: 1.0.0+1 +resolution: workspace environment: sdk: ^3.10.0-290.4.beta @@ -39,22 +40,6 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 -dependency_overrides: - _flutterfire_internals: - path: ../../../_flutterfire_internals - cloud_firestore: - path: .. - cloud_firestore_platform_interface: - path: ../../cloud_firestore_platform_interface - cloud_firestore_web: - path: ../../cloud_firestore_web - firebase_core: - path: ../../../firebase_core/firebase_core - firebase_core_platform_interface: - path: ../../../firebase_core/firebase_core_platform_interface - firebase_core_web: - path: ../../../firebase_core/firebase_core_web - dev_dependencies: flutter_test: sdk: flutter @@ -66,7 +51,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^6.0.0 + flutter_lints: ^4.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/packages/cloud_firestore/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pubspec.yaml index 544142206d52..5cb0b32117e4 100755 --- a/packages/cloud_firestore/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pubspec.yaml @@ -5,6 +5,7 @@ description: homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore version: 6.3.0 +resolution: workspace topics: - firebase - firestore @@ -16,8 +17,8 @@ false_secrets: - dartpad/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: cloud_firestore_platform_interface: ^7.2.0 diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml index c73118f38741..8b8fd425392e 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml @@ -1,12 +1,13 @@ name: cloud_firestore_platform_interface description: A common platform interface for the cloud_firestore plugin. version: 7.2.0 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 @@ -25,5 +26,3 @@ dev_dependencies: pigeon: 26.3.4 watcher: ^1.1.0 -dependency_overrides: - watcher: ^1.1.0 diff --git a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml index 81b1ddbee093..76c108c59d6a 100644 --- a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml @@ -4,9 +4,10 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_fires repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web version: 5.3.0 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/cloud_functions/cloud_functions/example/pubspec.yaml b/packages/cloud_functions/cloud_functions/example/pubspec.yaml index ee17ae3cb745..532101999cb4 100644 --- a/packages/cloud_functions/cloud_functions/example/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/example/pubspec.yaml @@ -1,9 +1,10 @@ name: cloud_functions_example description: Demonstrates how to use the cloud_functions plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: cloud_functions: ^6.2.0 diff --git a/packages/cloud_functions/cloud_functions/pubspec.yaml b/packages/cloud_functions/cloud_functions/pubspec.yaml index 07d85d0a5545..c6ff74fdaf16 100644 --- a/packages/cloud_functions/cloud_functions/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/pubspec.yaml @@ -1,6 +1,7 @@ name: cloud_functions description: A Flutter plugin allowing you to use Firebase Cloud Functions. version: 6.2.0 +resolution: workspace homepage: https://firebase.google.com/docs/functions repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions topics: @@ -13,8 +14,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: cloud_functions_platform_interface: ^5.8.12 diff --git a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml index 4be0404452de..71bf2d59d6c7 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml @@ -6,10 +6,11 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_fun # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes version: 5.8.12 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/cloud_functions/cloud_functions_web/pubspec.yaml b/packages/cloud_functions/cloud_functions_web/pubspec.yaml index 0a7050898e88..867a01d1a684 100644 --- a/packages/cloud_functions/cloud_functions_web/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_web/pubspec.yaml @@ -4,9 +4,10 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_funct repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web version: 5.1.5 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index babc6bf4fb8a..4de1694ae5bf 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -5,9 +5,11 @@ description: "Example project to show how to use the Firebase AI SDK." publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index 4ef4c122d330..6857ad0b0fcd 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,7 @@ name: firebase_ai description: Firebase AI Logic SDK. version: 3.11.0 +resolution: workspace homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: - firebase @@ -16,7 +17,7 @@ platforms: web: environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' flutter: ">=3.16.0" dependencies: diff --git a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml index 41c49ded48dd..17d8e0ad4fab 100755 --- a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml @@ -1,9 +1,10 @@ name: firebase_analytics_example description: Demonstrates how to use the firebase_analytics plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_analytics: ^12.3.0 diff --git a/packages/firebase_analytics/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/pubspec.yaml index f9adf7091b80..f8e82e9412f7 100755 --- a/packages/firebase_analytics/firebase_analytics/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/pubspec.yaml @@ -5,6 +5,7 @@ description: homepage: https://firebase.google.com/docs/analytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics version: 12.3.0 +resolution: workspace topics: - firebase - analytics @@ -15,8 +16,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_analytics_platform_interface: ^5.1.1 diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml index d21a75f0cb4e..3b5c1d1eb8d8 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml @@ -3,10 +3,11 @@ description: A common platform interface for the firebase_analytics plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface version: 5.1.1 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml index 721b85e0d42e..ecbcfb8cecb5 100644 --- a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml @@ -3,9 +3,10 @@ description: The web implementation of firebase_analytics homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web version: 0.6.1+5 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml index a4c69a5c1fdc..2822ab2aefc2 100644 --- a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml @@ -4,9 +4,11 @@ description: Firebase App Check example application. publish_to: 'none' version: 1.0.0+1 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: cloud_firestore: ^6.3.0 diff --git a/packages/firebase_app_check/firebase_app_check/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/pubspec.yaml index 2d87f6170235..660c9464cfb1 100644 --- a/packages/firebase_app_check/firebase_app_check/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/pubspec.yaml @@ -3,6 +3,7 @@ description: App Check works alongside other Firebase services to help protect y homepage: https://firebase.google.com/docs/app-check repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check version: 0.4.3 +resolution: workspace topics: - firebase - app-check @@ -13,8 +14,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_app_check_platform_interface: ^0.3.0 diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 3d90b2b238c5..7db42d4f9647 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -2,10 +2,11 @@ name: firebase_app_check_platform_interface description: A common platform interface for the firebase_app_check plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_platform_interface version: 0.3.0 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml index 7963fb3eb080..07cfdcb236f1 100644 --- a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml @@ -2,9 +2,10 @@ name: firebase_app_check_web description: The web implementation of firebase_app_check homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_web version: 0.2.4 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml index ab7dc8c62514..72a88b7373c6 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml @@ -4,9 +4,11 @@ description: A new Flutter project. publish_to: 'none' version: 1.0.0+1 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml index afcdd587f055..50818e54f8a4 100644 --- a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml @@ -1,6 +1,7 @@ name: firebase_app_installations description: A Flutter plugin allowing you to use Firebase Installations. version: 0.4.2 +resolution: workspace homepage: https://firebase.google.com/docs/projects/manage-installations#flutter repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations topics: @@ -13,8 +14,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_app_installations_platform_interface: ^0.1.4+68 diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 572203d2940e..64857f9f4346 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -1,12 +1,13 @@ name: firebase_app_installations_platform_interface description: A common platform interface for the firebase_app_installations plugin. version: 0.1.4+68 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml index 6fc659fa4222..6ff04ba25b05 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml @@ -1,11 +1,12 @@ name: firebase_app_installations_web description: The web implementation of firebase_app_installations. version: 0.1.7+5 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_auth/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/firebase_auth/example/pubspec.yaml index 14d7328ef781..9b96f37ac33f 100644 --- a/packages/firebase_auth/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/example/pubspec.yaml @@ -1,8 +1,10 @@ name: firebase_auth_example description: Demonstrates how to use the firebase_auth plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: barcode_widget: ^2.0.4 diff --git a/packages/firebase_auth/firebase_auth/pubspec.yaml b/packages/firebase_auth/firebase_auth/pubspec.yaml index 9fffbe7119c3..2a028b15185c 100755 --- a/packages/firebase_auth/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/pubspec.yaml @@ -5,6 +5,7 @@ description: Flutter plugin for Firebase Auth, enabling homepage: https://firebase.google.com/docs/auth repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth version: 6.4.0 +resolution: workspace topics: - firebase - authentication @@ -16,7 +17,7 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.16.0' dependencies: diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml index 41c73626e13c..89ee85d9e9a6 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml @@ -5,9 +5,10 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes version: 8.1.9 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.16.0' dependencies: @@ -30,5 +31,3 @@ dev_dependencies: # NOTE: This is a temporary workaround for Flutter 3.13 watcher: ^1.1.0 -dependency_overrides: - watcher: ^1.1.0 diff --git a/packages/firebase_auth/firebase_auth_web/pubspec.yaml b/packages/firebase_auth/firebase_auth_web/pubspec.yaml index a8813adafe3c..818e8d972fa5 100644 --- a/packages/firebase_auth/firebase_auth_web/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_web/pubspec.yaml @@ -3,9 +3,10 @@ description: The web implementation of firebase_auth homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web version: 6.1.5 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_core/firebase_core/example/pubspec.yaml b/packages/firebase_core/firebase_core/example/pubspec.yaml index 4cb77afda207..eacdf60d8740 100644 --- a/packages/firebase_core/firebase_core/example/pubspec.yaml +++ b/packages/firebase_core/firebase_core/example/pubspec.yaml @@ -1,8 +1,10 @@ name: firebase_core_example description: Demonstrates how to use the firebase_core plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index aef91256e870..5ce012dcdc86 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -4,6 +4,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple homepage: https://firebase.google.com/docs/flutter/setup repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core version: 4.7.0 +resolution: workspace topics: - firebase - core @@ -12,8 +13,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core_platform_interface: ^6.0.3 diff --git a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml index e299ccf9d279..292ad6f194f5 100644 --- a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml +++ b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml @@ -5,10 +5,11 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes version: 6.0.3 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: collection: ^1.0.0 diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index e7cb2ce4055d..f29799d692c1 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -3,9 +3,10 @@ description: The web implementation of firebase_core homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web version: 3.6.0 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml index 4f415aee5233..073a53e57f9d 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml @@ -1,9 +1,10 @@ name: firebase_crashlytics_example description: Demonstrates how to use the firebase_crashlytics plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_analytics: ^12.3.0 diff --git a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml index ef3f5f07c9ea..9031b6f30d16 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml @@ -3,6 +3,7 @@ description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. version: 5.2.0 +resolution: workspace homepage: https://firebase.google.com/docs/crashlytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics topics: @@ -15,8 +16,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml index c252b78a788b..e26aa35cd09d 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml @@ -1,12 +1,13 @@ name: firebase_crashlytics_platform_interface description: A common platform interface for the firebase_crashlytics plugin. version: 3.8.20 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index 7b66b85ecd5d..fa457d5cd9ba 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -4,9 +4,11 @@ description: 'Firebase Data Connect example app' publish_to: 'none' version: 1.0.0+1 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: flutter: @@ -28,7 +30,7 @@ dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^3.0.0 + flutter_lints: ^4.0.0 integration_test: sdk: flutter diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index 35acc8c3f8f0..cf0d70d2d13d 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -1,14 +1,15 @@ name: firebase_data_connect description: 'Flutter plugin for Firebase Data Connect, a relational database service that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL.' version: 0.3.0 +resolution: workspace homepage: https://firebase.google.com/docs/data-connect/quickstart?platform=flutter false_secrets: - example/** - dartpad/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: crypto: ^3.0.6 @@ -19,7 +20,7 @@ dependencies: fixnum: ^1.1.1 flutter: sdk: flutter - grpc: ^3.2.4 + grpc: ^4.0.1 http: ^1.2.1 intl: ^0.20.2 path: ^1.9.0 diff --git a/packages/firebase_database/firebase_database/example/pubspec.yaml b/packages/firebase_database/firebase_database/example/pubspec.yaml index 01b2b05e1abc..f1e233566414 100755 --- a/packages/firebase_database/firebase_database/example/pubspec.yaml +++ b/packages/firebase_database/firebase_database/example/pubspec.yaml @@ -1,9 +1,10 @@ name: firebase_database_example description: Demonstrates how to use the firebase_database plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index 1245083700f8..65f61de369ff 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -4,6 +4,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database homepage: https://firebase.google.com/docs/database repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database version: 12.3.0 +resolution: workspace topics: - firebase - database @@ -13,8 +14,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml index fc60b133c334..135d34bdb10c 100755 --- a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml +++ b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml @@ -1,11 +1,12 @@ name: firebase_database_platform_interface description: A common platform interface for the firebase_database plugin. version: 0.3.1+1 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_platform_interface environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index ba45c603be55..0b054ee4949f 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -1,10 +1,11 @@ name: firebase_database_web description: The web implementation of firebase_database version: 0.2.7+6 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_web environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml index 155716d97266..b3e13e564026 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml @@ -1,9 +1,11 @@ name: firebase_in_app_messaging_example description: Demonstrates how to use the firebase_in_app_messaging plugin. +resolution: workspace publish_to: 'none' environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_analytics: ^12.3.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml index ca1df6800a4d..cf2c15013ecd 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml @@ -1,6 +1,7 @@ name: firebase_in_app_messaging description: Flutter plugin for Firebase In-App Messaging. version: 0.9.2 +resolution: workspace homepage: https://firebase.google.com/docs/in-app-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging topics: @@ -13,8 +14,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml index 812273735d34..1c4bd1db6d64 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml @@ -4,10 +4,11 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface version: 0.2.5+20 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index 49a37810302b..886e72a31853 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -1,9 +1,10 @@ name: firebase_messaging_example description: Demonstrates how to use the firebase_messaging plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_messaging/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/pubspec.yaml index cbe5bbf4efa5..bb4dde6df918 100644 --- a/packages/firebase_messaging/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/pubspec.yaml @@ -4,6 +4,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform homepage: https://firebase.google.com/docs/cloud-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging version: 16.2.0 +resolution: workspace topics: - firebase - messaging @@ -13,8 +14,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml index e5502bac2a5c..521baf09d46f 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml @@ -1,12 +1,13 @@ name: firebase_messaging_platform_interface description: A common platform interface for the firebase_messaging plugin. version: 4.7.9 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml index fc9f670c1864..6eccf69632b1 100644 --- a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml @@ -3,9 +3,10 @@ description: The web implementation of firebase_messaging homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web version: 4.1.5 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml index 47eeb1d1fbfb..97be28d2f7f4 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml @@ -1,10 +1,12 @@ name: firebase_ml_model_downloader_example description: Demonstrates how to use the firebase_ml_model_downloader plugin. +resolution: workspace publish_to: 'none' environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: flutter: diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml index 55c02c635b8d..a7b6a5179b6a 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml @@ -1,6 +1,7 @@ name: firebase_ml_model_downloader description: A Flutter plugin allowing you to use Firebase Ml Model Downloader. version: 0.4.2 +resolution: workspace homepage: https://firebase.google.com/docs/ml/flutter/use-custom-models repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader topics: @@ -13,8 +14,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml index 008d6f1e45a5..5432ad28b54f 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml @@ -1,12 +1,13 @@ name: firebase_ml_model_downloader_platform_interface description: A common platform interface for the firebase_ml_model_downloader plugin. version: 0.1.5+20 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_performance/firebase_performance/example/pubspec.yaml b/packages/firebase_performance/firebase_performance/example/pubspec.yaml index 5ef4bd4bbccc..7a6a39df8464 100644 --- a/packages/firebase_performance/firebase_performance/example/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/example/pubspec.yaml @@ -1,10 +1,12 @@ name: firebase_performance_example description: Demonstrates how to use the firebase_performance plugin. version: 0.0.1 +resolution: workspace publish_to: none environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_performance/firebase_performance/pubspec.yaml b/packages/firebase_performance/firebase_performance/pubspec.yaml index f3164191af76..38235f916862 100644 --- a/packages/firebase_performance/firebase_performance/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/pubspec.yaml @@ -6,6 +6,7 @@ description: homepage: https://firebase.google.com/docs/perf-mon repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance version: 0.11.3 +resolution: workspace topics: - firebase - performance @@ -16,8 +17,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml index 5470c22a2612..1c05ce9f9922 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml @@ -1,11 +1,12 @@ name: firebase_performance_platform_interface description: A common platform interface for the firebase_performance plugin. version: 0.1.6+7 +resolution: workspace homepage: https://firebase.google.com/docs/perf-mon/flutter/get-started environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_performance/firebase_performance_web/pubspec.yaml b/packages/firebase_performance/firebase_performance_web/pubspec.yaml index da98413ffd0b..5f05047fb955 100644 --- a/packages/firebase_performance/firebase_performance_web/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_web/pubspec.yaml @@ -2,9 +2,10 @@ name: firebase_performance_web description: Web implementation of Firebase Performance monitoring. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance_web version: 0.1.8+5 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml index ad7b5d0cec8b..dd7142cae56d 100644 --- a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml @@ -1,9 +1,10 @@ name: firebase_remote_config_example description: Demonstrates how to use the firebase_remote_config plugin. +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: # The following adds the Cupertino Icons font to your application. diff --git a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml index 244af393050e..03fde1effae9 100644 --- a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml @@ -5,6 +5,7 @@ description: homepage: https://firebase.google.com/docs/remote-config repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config version: 6.4.0 +resolution: workspace topics: - firebase - remote @@ -15,8 +16,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml index 57ffffc5c647..bdfc92477bcb 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml @@ -5,10 +5,11 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes version: 2.1.2 +resolution: workspace environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml index ce73959f5b8b..2dd930886ada 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml @@ -4,9 +4,10 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_re repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web version: 1.10.6 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/packages/firebase_storage/firebase_storage/example/pubspec.yaml b/packages/firebase_storage/firebase_storage/example/pubspec.yaml index e0ee56516730..4ea05ff58543 100755 --- a/packages/firebase_storage/firebase_storage/example/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/example/pubspec.yaml @@ -1,8 +1,10 @@ name: firebase_storage_example description: Demonstrates how to use the firebase_storage plugin. +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_storage/firebase_storage/pubspec.yaml b/packages/firebase_storage/firebase_storage/pubspec.yaml index a61addff139d..d5dd4d27365b 100755 --- a/packages/firebase_storage/firebase_storage/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/pubspec.yaml @@ -4,6 +4,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and homepage: https://firebase.google.com/docs/storage/flutter/start repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage version: 13.3.0 +resolution: workspace topics: - firebase - storage @@ -15,8 +16,8 @@ false_secrets: - example/** environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: firebase_core: ^4.7.0 diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml index 6cbd4094710a..54ef0c506483 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml @@ -1,12 +1,13 @@ name: firebase_storage_platform_interface description: A common platform interface for the firebase_storage plugin. version: 5.2.20 +resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface environment: - sdk: '>=3.2.0 <4.0.0' - flutter: '>=3.3.0' + sdk: '^3.6.0' + flutter: '>=3.27.0' dependencies: _flutterfire_internals: ^1.3.69 diff --git a/packages/firebase_storage/firebase_storage_web/pubspec.yaml b/packages/firebase_storage/firebase_storage_web/pubspec.yaml index f98df35478f0..8b1421809455 100644 --- a/packages/firebase_storage/firebase_storage_web/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_web/pubspec.yaml @@ -3,9 +3,10 @@ description: The web implementation of firebase_storage homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web version: 3.11.5 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: diff --git a/pubspec.yaml b/pubspec.yaml index c7021d5c7077..7be36ca5bd83 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,14 +1,435 @@ name: flutterfire_workspace environment: - sdk: '>=3.2.0 <4.0.0' + sdk: '^3.6.0' + +workspace: + - packages/_flutterfire_internals + - packages/cloud_firestore/cloud_firestore + - packages/cloud_firestore/cloud_firestore/example + - packages/cloud_firestore/cloud_firestore/pipeline_example + - packages/cloud_firestore/cloud_firestore_platform_interface + - packages/cloud_firestore/cloud_firestore_web + - packages/cloud_functions/cloud_functions + - packages/cloud_functions/cloud_functions/example + - packages/cloud_functions/cloud_functions_platform_interface + - packages/cloud_functions/cloud_functions_web + - packages/firebase_ai/firebase_ai + - packages/firebase_ai/firebase_ai/example + - packages/firebase_analytics/firebase_analytics + - packages/firebase_analytics/firebase_analytics/example + - packages/firebase_analytics/firebase_analytics_platform_interface + - packages/firebase_analytics/firebase_analytics_web + - packages/firebase_app_check/firebase_app_check + - packages/firebase_app_check/firebase_app_check/example + - packages/firebase_app_check/firebase_app_check_platform_interface + - packages/firebase_app_check/firebase_app_check_web + - packages/firebase_app_installations/firebase_app_installations + - packages/firebase_app_installations/firebase_app_installations/example + - packages/firebase_app_installations/firebase_app_installations_platform_interface + - packages/firebase_app_installations/firebase_app_installations_web + - packages/firebase_auth/firebase_auth + - packages/firebase_auth/firebase_auth/example + - packages/firebase_auth/firebase_auth_platform_interface + - packages/firebase_auth/firebase_auth_web + - packages/firebase_core/firebase_core + - packages/firebase_core/firebase_core/example + - packages/firebase_core/firebase_core_platform_interface + - packages/firebase_core/firebase_core_web + - packages/firebase_crashlytics/firebase_crashlytics + - packages/firebase_crashlytics/firebase_crashlytics/example + - packages/firebase_crashlytics/firebase_crashlytics_platform_interface + - packages/firebase_data_connect/firebase_data_connect + - packages/firebase_data_connect/firebase_data_connect/example + - packages/firebase_database/firebase_database + - packages/firebase_database/firebase_database/example + - packages/firebase_database/firebase_database_platform_interface + - packages/firebase_database/firebase_database_web + - packages/firebase_in_app_messaging/firebase_in_app_messaging + - packages/firebase_in_app_messaging/firebase_in_app_messaging/example + - packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface + - packages/firebase_messaging/firebase_messaging + - packages/firebase_messaging/firebase_messaging/example + - packages/firebase_messaging/firebase_messaging_platform_interface + - packages/firebase_messaging/firebase_messaging_web + - packages/firebase_ml_model_downloader/firebase_ml_model_downloader + - packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example + - packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface + - packages/firebase_performance/firebase_performance + - packages/firebase_performance/firebase_performance/example + - packages/firebase_performance/firebase_performance_platform_interface + - packages/firebase_performance/firebase_performance_web + - packages/firebase_remote_config/firebase_remote_config + - packages/firebase_remote_config/firebase_remote_config/example + - packages/firebase_remote_config/firebase_remote_config_platform_interface + - packages/firebase_remote_config/firebase_remote_config_web + - packages/firebase_storage/firebase_storage + - packages/firebase_storage/firebase_storage/example + - packages/firebase_storage/firebase_storage_platform_interface + - packages/firebase_storage/firebase_storage_web + - tests dev_dependencies: cli_util: ^0.4.1 glob: ^2.1.2 - intl: ^0.19.0 - melos: ^5.3.0 + intl: ^0.20.2 + melos: ^7.5.1 path: ^1.9.0 pub_semver: ^2.1.4 yaml: ^3.1.2 - + +melos: + repository: https://github.com/firebase/flutterfire + resolution: workspace + + command: + version: + # Generate commit links in package changelogs. + linkToCommits: true + # # Only allow versioning to happen on main branch. + # branch: main + # Additionally build a changelog at the root of the workspace. + workspaceChangelog: true + hooks: + preCommit: | + dart run scripts/generate_firebaseai_version.dart && \ + dart run scripts/generate_dataconnect_version.dart && \ + dart run scripts/generate_versions_web.dart && \ + dart run scripts/generate_versions_spm.dart && \ + git add packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart && git add packages/*/*_web/lib/src/*_version.dart && git add packages/*/*/ios/*/Package.swift packages/*/*/macos/*/Package.swift && git add packages/*/*/ios/*/Sources/*/Constants.swift + post: | + dart run scripts/generate_tag_spm_firebase_core.dart + + bootstrap: + # It seems so that running "pub get" in parallel has some issues (like + # https://github.com/dart-lang/pub/issues/3404). Disabling this feature + # makes the CI much more stable. + runPubGetInParallel: false + usePubspecOverrides: true + + scripts: + lint:all: + run: melos run analyze-ci && melos run format-ci + description: Run all static analysis checks. + + validate:workspace: + run: dart scripts/validate_workspace.dart + description: Validate that all packages are listed in the workspace. + + analyze-ci: + # We are setting the concurrency to 1 because a higher concurrency can crash + # the analysis server on low performance machines (like GitHub Actions). + run: | + melos exec -c 1 -- \ + dart analyze . --fatal-infos + description: | + Run `dart analyze` in all packages. + - Note: you can also rely on your IDEs Dart Analysis / Issues window. + + firebase:emulator: + run: | + cd .github/workflows/scripts && ./start-firebase-emulator.sh + description: | + Start the Firebase emulator suite. Used by Functions, Firestore, Auth and Storage + integration testing. + - Requires Node.js and NPM installed. + + format-ci: + run: | + dart pub global run flutter_plugin_tools format && \ + swiftformat . + description: | + Formats the code of all packages (Java, Objective-C, and Dart). + - Requires `flutter_plugin_tools` (`pub global activate flutter_plugin_tools`). + - Requires `git`. + - Requires `clang-format` (can be installed via Brew on MacOS). + - Requires `swiftformat` (can be installed via Brew on macOS). + + build:all: + run: | + melos run build:example_ios_pub --no-select && \ + melos run build:example_android_pub --no-select && \ + melos run build:example_macos --no-select + description: Build all example apps. + + build:example_android: + run: | + melos exec -c 6 --fail-fast -- \ + "flutter build apk" + description: Build a specific example app for Android. + packageFilters: + dirExists: + - android + scope: '*example*' + + build:example_android_pub: + run: | + melos exec -c 6 --fail-fast -- \ + "flutter build apk" + description: Build a specific example app for Android. + packageFilters: + dirExists: + - android + scope: '*example*' + + build:example_ios: + run: | + melos exec -c 6 --fail-fast -- \ + "flutter build ios --no-codesign" + description: Build a specific example app for iOS. + packageFilters: + dirExists: + - ios + scope: '*example*' + + build:example_ios_pub: + run: | + melos exec -c 6 --fail-fast -- \ + "flutter build ios --no-codesign" + description: Build a specific example app for iOS. + packageFilters: + dirExists: + - ios + scope: '*example*' + + build:example_macos: + run: | + melos exec -c 6 --fail-fast -- \ + "flutter build macos" + description: | + Build a specific example app for macOS. + packageFilters: + dirExists: + - macos + scope: '*example*' + + test:all: + run: | + melos run test --no-select && \ + melos run test:web --no-select && \ + melos run test:e2e --no-select + description: | + Run all tests available. + + test: + run: | + melos exec -c 6 --fail-fast -- \ + "flutter test" + description: Run `flutter test` for a specific package. + packageFilters: + dirExists: + - test + ignore: + - '*web*' + - '*example*' + + test:web: + run: | + melos exec -c 1 --fail-fast -- \ + "flutter test --platform=chrome" + description: Run `flutter test --platform=chrome` for a specific '*web' package. + packageFilters: + dirExists: + - test + scope: '*web*' + + test:e2e: + run: | + melos exec -c 1 --fail-fast -- \ + "flutter test integration_test/e2e_test.dart" + description: | + Run all e2e tests. + packageFilters: + dirExists: + - integration_test + scope: '*tests*' + + test:e2e:cloud_firestore: + run: | + cd packages/cloud_firestore/cloud_firestore/example + flutter test integration_test/e2e_test.dart + description: | + Run all e2e tests for cloud_firestore. + + test:e2e:firebase_performance: + run: | + cd packages/firebase_performance/firebase_performance/example + flutter test integration_test/firebase_performance_e2e_test.dart + description: | + Run all e2e tests for firebase_performance. + + test:e2e:web: + run: | + melos exec -c 1 --fail-fast -- \ + "flutter drive --target=./integration_test/e2e_test.dart --driver=./test_driver/integration_test.dart -d chrome --dart-define=LOCAL_WEB_E2E=true" + description: | + Run all e2e tests on web platform. Please ensure you have "chromedriver" installed and running. + packageFilters: + dirExists: + - test_driver + scope: '*tests*' + + test:e2e:web:cloud_firestore: + run: | + cd packages/cloud_firestore/cloud_firestore/example + flutter drive --target=./integration_test/e2e_test.dart --driver=./test_driver/integration_test.dart -d chrome + description: | + Run all e2e tests for cloud_firestore on web platform. Please ensure you have "chromedriver" installed and running. + + test:e2e:web:firebase_performance: + run: | + cd packages/firebase_performance/firebase_performance/example + flutter drive --target=./integration_test/firebase_performance_e2e_test.dart --driver=./test_driver/integration_test.dart --release -d chrome + description: | + Run all e2e tests for firebase_performance on web platform. Please ensure you have "chromedriver" installed and running. + + clean:deep: + run: git clean -x -d -f -q + description: Clean things very deeply, can be used to establish "pristine checkout" status. + + test:e2e:windows: + run: | + melos exec -c 1 --fail-fast -- \ + "flutter test integration_test/e2e_test.dart -d windows" + description: | + Run all e2e tests. + packageFilters: + dirExists: + - integration_test + scope: '*tests*' + + qualitycheck: + run: | + melos run clean:deep && \ + melos clean && \ + melos bootstrap && \ + melos run lint:all && \ + melos run build:all && \ + melos run test:all + description: Run all targets generally expected in CI for a full local quality check. + + generate:pigeon: + run: | + melos exec -- "flutter pub run pigeon --input ./pigeons/messages.dart" && \ + melos run generate:pigeon:macos --no-select && \ + melos run generate:pigeon:android --no-select && \ + melos run format-ci --no-select + packageFilters: + fileExists: 'pigeons/messages.dart' + description: Generate the pigeon messages for all the supported packages. + + generate:pigeon:macos: + run: | + melos exec -- "sed -i '' 's;#import ;#if TARGET_OS_OSX\n#import \n#else\n#import \n#endif;g' ios/Classes/messages.g.m" + packageFilters: + fileExists: 'ios/Classes/messages.g.m' + description: Pigeon does not add the condition to import Flutter or FlutterMacOs. Add the condition + + generate:pigeon:android: + run: | + melos exec -- "find ./android -type f -name '*Generated*' | xargs sed -i '.bak' 's/ArrayList toList() {/public ArrayList toList() {/g'" && \ + melos exec -- "find ./android -type f -name '*.bak' -delete" + packageFilters: + dirExists: 'android' + description: Transform the method toList() into a public one to be used in EventChannel + + # Additional cleanup lifecycle script, executed when `melos clean` is run. + postclean: > + melos exec -c 6 -- "flutter clean" + + add-license-header: + # If you add here another --ignore flag, add it also to + # "check-license-header". + run: | + addlicense -f header_template.txt \ + --ignore "**/.dart_tool/**" \ + --ignore "**/*.cmake" \ + --ignore "**/*.g.dart" \ + --ignore "**/*.g.h" \ + --ignore "**/*.g.m" \ + --ignore "**/*.gradle" \ + --ignore "**/*.html" \ + --ignore "**/*.js" \ + --ignore "**/*.rb" \ + --ignore "**/*.sh" \ + --ignore "**/*.ts" \ + --ignore "**/*.txt" \ + --ignore "**/*.xml" \ + --ignore "**/*.yaml" \ + --ignore "**/*.yml" \ + --ignore "**/android/app/build.gradle.kts" \ + --ignore "**/android/build.gradle.kts" \ + --ignore "**/android/settings.gradle.kts" \ + --ignore "**/build/**" \ + --ignore "**/ephemeral/**" \ + --ignore "**/flutter/generated_plugin_registrant.cc" \ + --ignore "**/flutter/generated_plugin_registrant.h" \ + --ignore "**/FlutterMultiDexApplication.java" \ + --ignore "**/generated/**" \ + --ignore "**/GeneratedPluginRegistrant.h" \ + --ignore "**/GeneratedPluginRegistrant.java" \ + --ignore "**/GeneratedPluginRegistrant.m" \ + --ignore "**/GeneratedPluginRegistrant.swift" \ + --ignore "**/MainActivity.java" \ + --ignore "**/MainActivity.kt" \ + --ignore "**/Pods/**" \ + --ignore "**/Runner/AppDelegate.h" \ + --ignore "**/Runner/AppDelegate.m" \ + --ignore "**/Runner/AppDelegate.swift" \ + --ignore "**/Runner/main.m" \ + --ignore "**/Runner/MainFlutterWindow.swift" \ + --ignore "**/Runner/Runner-Bridging-Header.h" \ + --ignore "**/RunnerTests/RunnerTests.swift" \ + . + description: Add a license header to all necessary files. + + check-license-header: + # If you add here another --ignore flag, add it also to + # "add-license-header". + run: | + addlicense -f header_template.txt \ + --check \ + --ignore "**/.dart_tool/**" \ + --ignore "**/*.cmake" \ + --ignore "**/*.g.dart" \ + --ignore "**/*.g.h" \ + --ignore "**/*.g.m" \ + --ignore "**/*.gradle" \ + --ignore "**/*.html" \ + --ignore "**/*.js" \ + --ignore "**/*.rb" \ + --ignore "**/*.sh" \ + --ignore "**/*.ts" \ + --ignore "**/*.txt" \ + --ignore "**/*.xml" \ + --ignore "**/*.yaml" \ + --ignore "**/*.yml" \ + --ignore "**/android/app/build.gradle.kts" \ + --ignore "**/android/build.gradle.kts" \ + --ignore "**/android/settings.gradle.kts" \ + --ignore "**/build/**" \ + --ignore "**/ephemeral/**" \ + --ignore "**/flutter/generated_plugin_registrant.cc" \ + --ignore "**/flutter/generated_plugin_registrant.h" \ + --ignore "**/FlutterMultiDexApplication.java" \ + --ignore "**/generated/**" \ + --ignore "**/GeneratedPluginRegistrant.h" \ + --ignore "**/GeneratedPluginRegistrant.java" \ + --ignore "**/GeneratedPluginRegistrant.m" \ + --ignore "**/GeneratedPluginRegistrant.swift" \ + --ignore "**/MainActivity.java" \ + --ignore "**/MainActivity.kt" \ + --ignore "**/Pods/**" \ + --ignore "**/Runner/AppDelegate.h" \ + --ignore "**/Runner/AppDelegate.m" \ + --ignore "**/Runner/AppDelegate.swift" \ + --ignore "**/Runner/main.m" \ + --ignore "**/Runner/MainFlutterWindow.swift" \ + --ignore "**/Runner/Runner-Bridging-Header.h" \ + --ignore "**/RunnerTests/RunnerTests.swift" \ + . + description: Add a license header to all necessary files. + + bom: + run: dart scripts/generate_bom.dart + description: Generate a Bill of Materials (BOM) file for all packages. diff --git a/scripts/generate_bom.dart b/scripts/generate_bom.dart index a3f269127686..716b6677a3dd 100644 --- a/scripts/generate_bom.dart +++ b/scripts/generate_bom.dart @@ -203,7 +203,7 @@ Future appendStaticText( // Adding rows for each package for (final package in packages.entries) { sink.writeln( - '| [${package.key}](https://pub.dev/packages/${package.key}/versions/${package.value.version}) | ${package.value.version} | ${package.value.pubSpec.environment?.sdkConstraint.toString() ?? ''} | ${package.value.pubSpec.environment?.toJson()['flutter'] ?? ''} |', + '| [${package.key}](https://pub.dev/packages/${package.key}/versions/${package.value.version}) | ${package.value.version} | ${package.value.pubspec.environment['sdk']?.toString() ?? ''} | ${package.value.pubspec.environment['flutter']?.toString() ?? ''} |', ); } diff --git a/scripts/generate_versions_spm.dart b/scripts/generate_versions_spm.dart index 27485fd76e32..369efb4f07a0 100644 --- a/scripts/generate_versions_spm.dart +++ b/scripts/generate_versions_spm.dart @@ -26,8 +26,8 @@ void main(List args) async { // Update hard-coded versions in all plugin Package.swift files final firebaseCoreVersion = loadYaml( - File('${firebaseCorePackage.path}/pubspec.yaml') - .readAsStringSync())['version'] + File('${firebaseCorePackage.path}/pubspec.yaml').readAsStringSync(), + )['version'] .toString(); updatePluginPackageSwiftVersions( workspace, @@ -52,7 +52,6 @@ Future getMelosWorkspace() async { logger: melos.MelosLogger(logging.Logger.standard()), packageFilters: packageFilters, ); - return workspace; } diff --git a/scripts/validate_workspace.dart b/scripts/validate_workspace.dart new file mode 100644 index 000000000000..db5ebe2531d4 --- /dev/null +++ b/scripts/validate_workspace.dart @@ -0,0 +1,125 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// ignore_for_file: avoid_print + +/// Validates that all packages in the repository are listed in the root +/// pubspec.yaml workspace. +library; + +import 'dart:io'; +import 'package:yaml/yaml.dart'; +import 'package:path/path.dart' as p; + +void main() { + // Ensure running at the root of the git repo + final gitResult = Process.runSync('git', ['rev-parse', '--show-cdup']); + if (gitResult.exitCode != 0 || + gitResult.stdout.toString().trim().isNotEmpty) { + print( + 'Error: This script must be run from the root of the git repository.', + ); + exitCode = 1; + return; + } + + final rootDir = Directory.current.path; + final pubspecFile = File(p.join(rootDir, 'pubspec.yaml')); + + if (!pubspecFile.existsSync()) { + print('Error: pubspec.yaml not found at root.'); + exitCode = 1; + return; + } + + final pubspecContent = pubspecFile.readAsStringSync(); + final yaml = loadYaml(pubspecContent); + + final workspace = yaml['workspace']; + if (workspace == null || workspace is! YamlList) { + print('Error: No workspace list found in pubspec.yaml.'); + exitCode = 1; + return; + } + + final workspacePaths = workspace.map((e) => e.toString()).toSet(); + print('Workspace paths in pubspec.yaml: ${workspacePaths.length}'); + + final foundPackages = []; + + final packagesDir = Directory(p.join(rootDir, 'packages')); + if (packagesDir.existsSync()) { + foundPackages.addAll(_findPackages(packagesDir, rootDir)); + } + + final testsDir = Directory(p.join(rootDir, 'tests')); + if (testsDir.existsSync()) { + foundPackages.addAll(_findPackages(testsDir, rootDir)); + } + + print('Found pubspec.yaml files: ${foundPackages.length}'); + + final missingFromWorkspace = + foundPackages.where((p) => !workspacePaths.contains(p)).toList(); + + final listedButMissingFromDisk = + workspacePaths.where((p) => !foundPackages.contains(p)).toList(); + + var hasError = false; + + if (missingFromWorkspace.isNotEmpty) { + print('\nMissing from workspace:'); + for (final p in missingFromWorkspace) { + print(' - $p'); + } + hasError = true; + } + + if (listedButMissingFromDisk.isNotEmpty) { + print('\nListed in workspace but missing from disk:'); + for (final p in listedButMissingFromDisk) { + print(' - $p'); + } + hasError = true; + } + + if (hasError) { + exitCode = 1; + } else { + print('\nWorkspace is valid! All packages are listed.'); + } +} + +Iterable _findPackages(Directory dir, String rootDir) sync* { + for (final entity in dir.listSync(recursive: true)) { + if (entity is File && p.basename(entity.path) == 'pubspec.yaml') { + final path = entity.path; + final components = p.split(path); + if (components.any(_ignoredDirectories.contains)) { + continue; + } + final relPath = p.relative(p.dirname(path), from: rootDir); + if (relPath != '.') { + yield relPath; + } + } + } +} + +const _ignoredDirectories = { + '.dart_tool', + '.plugin_symlinks', + 'ephemeral', + 'build', +}; diff --git a/tests/pubspec.yaml b/tests/pubspec.yaml index 99f7a1cf3cc1..a5d91e69def6 100644 --- a/tests/pubspec.yaml +++ b/tests/pubspec.yaml @@ -3,9 +3,10 @@ name: tests description: A an app for FlutterFire testing (e2e). publish_to: 'none' version: 1.0.0+1 +resolution: workspace environment: - sdk: '>=3.4.0 <4.0.0' + sdk: '^3.6.0' flutter: '>=3.22.0' dependencies: From 865f03ba46ff198da68a6c229a1f545f311995e0 Mon Sep 17 00:00:00 2001 From: Aashish <112133849+aashishpatil-g@users.noreply.github.com> Date: Wed, 22 Apr 2026 04:48:27 -0700 Subject: [PATCH 038/137] chore(fdc): Integration Tests for Websockets (#18216) * Integration Tests for Websockets * Test to check for websocket closure when no subscriptions are active. * Revert the spm required false change. --- .../firebase_data_connect/example/.gitignore | 2 + .../.dataconnect/schema/main/implicit.gql | 34 + .../.dataconnect/schema/main/input.gql | 1049 +++++++ .../.dataconnect/schema/main/mutation.gql | 552 ++++ .../.dataconnect/schema/main/query.gql | 262 ++ .../.dataconnect/schema/main/relation.gql | 417 +++ .../.dataconnect/schema/prelude.gql | 2419 +++++++++++++++++ .../example/integration_test/e2e_test.dart | 6 +- .../integration_test/websocket_e2e.dart | 223 ++ .../example/lib/generated/.guides/config.json | 9 + .../example/lib/generated/.guides/setup.md | 15 + .../example/lib/generated/.guides/usage.md | 32 + .../lib/generated/add_date_and_timestamp.dart | 58 +- .../lib/generated/add_director_to_movie.dart | 80 +- .../example/lib/generated/add_person.dart | 54 +- .../example/lib/generated/add_timestamp.dart | 55 +- .../example/lib/generated/create_movie.dart | 72 +- .../example/lib/generated/delete_movie.dart | 54 +- .../example/lib/generated/get_movie.dart | 74 +- .../example/lib/generated/list_movies.dart | 65 +- .../list_movies_by_partial_title.dart | 67 +- .../example/lib/generated/list_persons.dart | 38 +- .../example/lib/generated/list_thing.dart | 54 +- .../lib/generated/list_timestamps.dart | 39 +- .../example/lib/generated/movies.dart | 1 + .../example/lib/generated/seed_data.dart | 36 +- .../example/lib/generated/seed_movies.dart | 58 +- .../example/lib/generated/thing.dart | 74 +- .../example/macos/Podfile | 2 +- .../macos/Runner.xcodeproj/project.pbxproj | 120 +- .../xcshareddata/xcschemes/Runner.xcscheme | 1 + .../contents.xcworkspacedata | 3 + .../example/macos/Runner/AppDelegate.swift | 6 +- 33 files changed, 5961 insertions(+), 70 deletions(-) create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/implicit.gql create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/input.gql create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/mutation.gql create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/query.gql create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/relation.gql create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/prelude.gql create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/config.json create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/setup.md create mode 100644 packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/usage.md diff --git a/packages/firebase_data_connect/firebase_data_connect/example/.gitignore b/packages/firebase_data_connect/firebase_data_connect/example/.gitignore index fa1ffd5b7c5d..e101d9f0a871 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/.gitignore +++ b/packages/firebase_data_connect/firebase_data_connect/example/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/implicit.gql b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/implicit.gql new file mode 100644 index 000000000000..f3cc340c8b71 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/implicit.gql @@ -0,0 +1,34 @@ +extend type DirectedBy { + """ + ✨ Implicit foreign key field based on `DirectedBy`.`movie`. It must match the value of `Movie`.`id`. See `@ref` for how to customize it. + """ + movieId: UUID! @fdc_generated(from: "DirectedBy.movie", purpose: IMPLICIT_REF_FIELD) + """ + ✨ Implicit foreign key field based on `DirectedBy`.`directedby`. It must match the value of `Person`.`id`. See `@ref` for how to customize it. + """ + directedbyId: UUID! @fdc_generated(from: "DirectedBy.directedby", purpose: IMPLICIT_REF_FIELD) +} +extend type Movie { + """ + ✨ Implicit primary key field. It's a UUID column default to a generated new value. See `@table` for how to customize it. + """ + id: UUID! @default(expr: "uuidV4()") @fdc_generated(from: "Movie", purpose: IMPLICIT_KEY_FIELD) +} +extend type Person { + """ + ✨ Implicit primary key field. It's a UUID column default to a generated new value. See `@table` for how to customize it. + """ + id: UUID! @default(expr: "uuidV4()") @fdc_generated(from: "Person", purpose: IMPLICIT_KEY_FIELD) +} +extend type Thing { + """ + ✨ Implicit primary key field. It's a UUID column default to a generated new value. See `@table` for how to customize it. + """ + id: UUID! @default(expr: "uuidV4()") @fdc_generated(from: "Thing", purpose: IMPLICIT_KEY_FIELD) +} +extend type TimestampHolder { + """ + ✨ Implicit primary key field. It's a UUID column default to a generated new value. See `@table` for how to customize it. + """ + id: UUID! @default(expr: "uuidV4()") @fdc_generated(from: "TimestampHolder", purpose: IMPLICIT_KEY_FIELD) +} diff --git a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/input.gql b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/input.gql new file mode 100644 index 000000000000..bb9b46b78467 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/input.gql @@ -0,0 +1,1049 @@ +""" +✨ `DirectedBy_KeyOutput` returns the primary key fields of table type `DirectedBy`. + +It has the same format as `DirectedBy_Key`, but is only used as mutation return value. +""" +scalar DirectedBy_KeyOutput +""" +✨ `Movie_KeyOutput` returns the primary key fields of table type `Movie`. + +It has the same format as `Movie_Key`, but is only used as mutation return value. +""" +scalar Movie_KeyOutput +""" +✨ `Person_KeyOutput` returns the primary key fields of table type `Person`. + +It has the same format as `Person_Key`, but is only used as mutation return value. +""" +scalar Person_KeyOutput +""" +✨ `Thing_KeyOutput` returns the primary key fields of table type `Thing`. + +It has the same format as `Thing_Key`, but is only used as mutation return value. +""" +scalar Thing_KeyOutput +""" +✨ `TimestampHolder_KeyOutput` returns the primary key fields of table type `TimestampHolder`. + +It has the same format as `TimestampHolder_Key`, but is only used as mutation return value. +""" +scalar TimestampHolder_KeyOutput +""" +✨ Generated data input type for table 'DirectedBy'. It includes all necessary fields for creating or upserting rows into table. +""" +input DirectedBy_Data { + """ + ✨ Generated from Field `DirectedBy`.`movieId` of type `UUID!` + """ + movieId: UUID + """ + ✨ `_expr` server value variant of `movieId` (✨ Generated from Field `DirectedBy`.`movieId` of type `UUID!`) + """ + movieId_expr: UUID_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `DirectedBy`.`directedbyId` of type `UUID!` + """ + directedbyId: UUID + """ + ✨ `_expr` server value variant of `directedbyId` (✨ Generated from Field `DirectedBy`.`directedbyId` of type `UUID!`) + """ + directedbyId_expr: UUID_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `DirectedBy`.`directedby` of type `Person!` + """ + directedby: Person_Key @fdc_forbiddenInVariables + """ + ✨ Generated from Field `DirectedBy`.`movie` of type `Movie!` + """ + movie: Movie_Key @fdc_forbiddenInVariables +} +""" +✨ Generated filter input type for table 'DirectedBy'. This input allows filtering objects using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input DirectedBy_Filter { + """ + Apply multiple filter conditions using `AND` logic. + """ + _and: [DirectedBy_Filter!] + """ + Negate the result of the provided filter condition. + """ + _not: DirectedBy_Filter + """ + Apply multiple filter conditions using `OR` logic. + """ + _or: [DirectedBy_Filter!] + """ + ✨ Generated from Field `DirectedBy`.`movieId` of type `UUID!` + """ + movieId: UUID_Filter + """ + ✨ Generated from Field `DirectedBy`.`directedbyId` of type `UUID!` + """ + directedbyId: UUID_Filter + """ + ✨ Generated from Field `DirectedBy`.`directedby` of type `Person!` + """ + directedby: Person_Filter + """ + ✨ Generated from Field `DirectedBy`.`movie` of type `Movie!` + """ + movie: Movie_Filter +} +""" +✨ Generated first-row input type for table 'DirectedBy'. This input selects the first row matching the filter criteria, ordered according to the specified conditions. +""" +input DirectedBy_FirstRow { + """ + Order the result by the specified fields. + """ + orderBy: [DirectedBy_Order!] + """ + Filters rows based on the specified conditions. + """ + where: DirectedBy_Filter +} +""" +✨ Generated having input type for table 'DirectedBy'. This input allows you to filter groups during aggregate queries using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input DirectedBy_Having { + """ + Apply multiple Having conditions using `AND` logic. + """ + _and: [DirectedBy_Having!] + """ + Whether to apply DISTINCT to the aggregate function. + """ + _distinct: Boolean + """ + Negate the result of the provided Having condition. + """ + _not: DirectedBy_Having + """ + Apply multiple Having conditions using `OR` logic. + """ + _or: [DirectedBy_Having!] + """ + ✨ Generated from Field `DirectedBy`.`_count` of type `Int!` + """ + _count: Int_Filter + """ + ✨ Generated from Field `DirectedBy`.`directedbyId_count` of type `Int!` + """ + directedbyId_count: Int_Filter + """ + ✨ Generated from Field `DirectedBy`.`movieId_count` of type `Int!` + """ + movieId_count: Int_Filter +} +""" +✨ Generated key input type for table 'DirectedBy'. It represents the primary key fields used to uniquely identify a row in the table. +""" +input DirectedBy_Key { + """ + ✨ Generated from Field `DirectedBy`.`movieId` of type `UUID!` + """ + movieId: UUID + """ + ✨ `_expr` server value variant of `movieId` (✨ Generated from Field `DirectedBy`.`movieId` of type `UUID!`) + """ + movieId_expr: UUID_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `DirectedBy`.`directedbyId` of type `UUID!` + """ + directedbyId: UUID + """ + ✨ `_expr` server value variant of `directedbyId` (✨ Generated from Field `DirectedBy`.`directedbyId` of type `UUID!`) + """ + directedbyId_expr: UUID_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated list filter input type for table 'DirectedBy'. This input applies filtering logic based on the count or existence of related objects that matches certain criteria. +""" +input DirectedBy_ListFilter { + """ + The desired number of objects that match the condition (defaults to at least one). + """ + count: Int_Filter = {gt:0} + """ + Condition of the related objects to filter for. + """ + exist: DirectedBy_Filter +} +""" +✨ Generated order input type for table 'DirectedBy'. This input defines the sorting order of rows in query results based on one or more fields. +""" +input DirectedBy_Order { + """ + ✨ Generated from Field `DirectedBy`.`movieId` of type `UUID!` + """ + movieId: OrderDirection + """ + ✨ Generated from Field `DirectedBy`.`directedbyId` of type `UUID!` + """ + directedbyId: OrderDirection + """ + ✨ Generated from Field `DirectedBy`.`directedby` of type `Person!` + """ + directedby: Person_Order + """ + ✨ Generated from Field `DirectedBy`.`movie` of type `Movie!` + """ + movie: Movie_Order + """ + ✨ Generated from Field `DirectedBy`.`_count` of type `Int!` + """ + _count: OrderDirection + """ + ✨ Generated from Field `DirectedBy`.`directedbyId_count` of type `Int!` + """ + directedbyId_count: OrderDirection + """ + ✨ Generated from Field `DirectedBy`.`movieId_count` of type `Int!` + """ + movieId_count: OrderDirection +} +""" +✨ Generated data input type for table 'Movie'. It includes all necessary fields for creating or upserting rows into table. +""" +input Movie_Data { + """ + ✨ Generated from Field `Movie`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `Movie`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `Movie`.`description` of type `String` + """ + description: String + """ + ✨ `_expr` server value variant of `description` (✨ Generated from Field `Movie`.`description` of type `String`) + """ + description_expr: String_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `Movie`.`genre` of type `String!` + """ + genre: String + """ + ✨ `_expr` server value variant of `genre` (✨ Generated from Field `Movie`.`genre` of type `String!`) + """ + genre_expr: String_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `Movie`.`rating` of type `Float` + """ + rating: Float + """ + ✨ `_expr` server value variant of `rating` (✨ Generated from Field `Movie`.`rating` of type `Float`) + """ + rating_expr: Float_Expr @fdc_forbiddenInVariables + """ + ✨ `_update` server value variant of `rating` (✨ Generated from Field `Movie`.`rating` of type `Float`) + """ + rating_update: [Float_Update!] @fdc_forbiddenInVariables + """ + ✨ Generated from Field `Movie`.`releaseYear` of type `Int` + """ + releaseYear: Int + """ + ✨ `_expr` server value variant of `releaseYear` (✨ Generated from Field `Movie`.`releaseYear` of type `Int`) + """ + releaseYear_expr: Int_Expr @fdc_forbiddenInVariables + """ + ✨ `_update` server value variant of `releaseYear` (✨ Generated from Field `Movie`.`releaseYear` of type `Int`) + """ + releaseYear_update: [Int_Update!] @fdc_forbiddenInVariables + """ + ✨ Generated from Field `Movie`.`title` of type `String!` + """ + title: String + """ + ✨ `_expr` server value variant of `title` (✨ Generated from Field `Movie`.`title` of type `String!`) + """ + title_expr: String_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated filter input type for table 'Movie'. This input allows filtering objects using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input Movie_Filter { + """ + Apply multiple filter conditions using `AND` logic. + """ + _and: [Movie_Filter!] + """ + Negate the result of the provided filter condition. + """ + _not: Movie_Filter + """ + Apply multiple filter conditions using `OR` logic. + """ + _or: [Movie_Filter!] + """ + ✨ Generated from Field `Movie`.`id` of type `UUID!` + """ + id: UUID_Filter + """ + ✨ Generated from Field `Movie`.`description` of type `String` + """ + description: String_Filter + """ + ✨ Generated from Field `Movie`.`genre` of type `String!` + """ + genre: String_Filter + """ + ✨ Generated from Field `Movie`.`rating` of type `Float` + """ + rating: Float_Filter + """ + ✨ Generated from Field `Movie`.`releaseYear` of type `Int` + """ + releaseYear: Int_Filter + """ + ✨ Generated from Field `Movie`.`title` of type `String!` + """ + title: String_Filter + """ + ✨ Generated from Field `Movie`.`directedBies_on_movie` of type `[DirectedBy!]!` + """ + directedBies_on_movie: DirectedBy_ListFilter + """ + ✨ Generated from Field `Movie`.`people_via_DirectedBy` of type `[Person!]!` + """ + people_via_DirectedBy: Person_ListFilter +} +""" +✨ Generated first-row input type for table 'Movie'. This input selects the first row matching the filter criteria, ordered according to the specified conditions. +""" +input Movie_FirstRow { + """ + Order the result by the specified fields. + """ + orderBy: [Movie_Order!] + """ + Filters rows based on the specified conditions. + """ + where: Movie_Filter +} +""" +✨ Generated having input type for table 'Movie'. This input allows you to filter groups during aggregate queries using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input Movie_Having { + """ + Apply multiple Having conditions using `AND` logic. + """ + _and: [Movie_Having!] + """ + Whether to apply DISTINCT to the aggregate function. + """ + _distinct: Boolean + """ + Negate the result of the provided Having condition. + """ + _not: Movie_Having + """ + Apply multiple Having conditions using `OR` logic. + """ + _or: [Movie_Having!] + """ + ✨ Generated from Field `Movie`.`_count` of type `Int!` + """ + _count: Int_Filter + """ + ✨ Generated from Field `Movie`.`description_count` of type `Int!` + """ + description_count: Int_Filter + """ + ✨ Generated from Field `Movie`.`genre_count` of type `Int!` + """ + genre_count: Int_Filter + """ + ✨ Generated from Field `Movie`.`id_count` of type `Int!` + """ + id_count: Int_Filter + """ + ✨ Generated from Field `Movie`.`rating_count` of type `Int!` + """ + rating_count: Int_Filter + """ + ✨ Generated from Field `Movie`.`releaseYear_count` of type `Int!` + """ + releaseYear_count: Int_Filter + """ + ✨ Generated from Field `Movie`.`title_count` of type `Int!` + """ + title_count: Int_Filter + """ + ✨ Generated from Field `Movie`.`rating_sum` of type `Float` + """ + rating_sum: Float_Filter + """ + ✨ Generated from Field `Movie`.`releaseYear_sum` of type `Int` + """ + releaseYear_sum: Int_Filter + """ + ✨ Generated from Field `Movie`.`rating_avg` of type `Float` + """ + rating_avg: Float_Filter + """ + ✨ Generated from Field `Movie`.`releaseYear_avg` of type `Float` + """ + releaseYear_avg: Float_Filter + """ + ✨ Generated from Field `Movie`.`rating_min` of type `Float` + """ + rating_min: Float_Filter + """ + ✨ Generated from Field `Movie`.`releaseYear_min` of type `Int` + """ + releaseYear_min: Int_Filter + """ + ✨ Generated from Field `Movie`.`rating_max` of type `Float` + """ + rating_max: Float_Filter + """ + ✨ Generated from Field `Movie`.`releaseYear_max` of type `Int` + """ + releaseYear_max: Int_Filter +} +""" +✨ Generated key input type for table 'Movie'. It represents the primary key fields used to uniquely identify a row in the table. +""" +input Movie_Key { + """ + ✨ Generated from Field `Movie`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `Movie`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated list filter input type for table 'Movie'. This input applies filtering logic based on the count or existence of related objects that matches certain criteria. +""" +input Movie_ListFilter { + """ + The desired number of objects that match the condition (defaults to at least one). + """ + count: Int_Filter = {gt:0} + """ + Condition of the related objects to filter for. + """ + exist: Movie_Filter +} +""" +✨ Generated order input type for table 'Movie'. This input defines the sorting order of rows in query results based on one or more fields. +""" +input Movie_Order { + """ + ✨ Generated from Field `Movie`.`id` of type `UUID!` + """ + id: OrderDirection + """ + ✨ Generated from Field `Movie`.`description` of type `String` + """ + description: OrderDirection + """ + ✨ Generated from Field `Movie`.`genre` of type `String!` + """ + genre: OrderDirection + """ + ✨ Generated from Field `Movie`.`rating` of type `Float` + """ + rating: OrderDirection + """ + ✨ Generated from Field `Movie`.`releaseYear` of type `Int` + """ + releaseYear: OrderDirection + """ + ✨ Generated from Field `Movie`.`title` of type `String!` + """ + title: OrderDirection + """ + ✨ Generated from Field `Movie`.`_count` of type `Int!` + """ + _count: OrderDirection + """ + ✨ Generated from Field `Movie`.`description_count` of type `Int!` + """ + description_count: OrderDirection + """ + ✨ Generated from Field `Movie`.`genre_count` of type `Int!` + """ + genre_count: OrderDirection + """ + ✨ Generated from Field `Movie`.`id_count` of type `Int!` + """ + id_count: OrderDirection + """ + ✨ Generated from Field `Movie`.`rating_count` of type `Int!` + """ + rating_count: OrderDirection + """ + ✨ Generated from Field `Movie`.`releaseYear_count` of type `Int!` + """ + releaseYear_count: OrderDirection + """ + ✨ Generated from Field `Movie`.`title_count` of type `Int!` + """ + title_count: OrderDirection + """ + ✨ Generated from Field `Movie`.`rating_sum` of type `Float` + """ + rating_sum: OrderDirection + """ + ✨ Generated from Field `Movie`.`releaseYear_sum` of type `Int` + """ + releaseYear_sum: OrderDirection + """ + ✨ Generated from Field `Movie`.`rating_avg` of type `Float` + """ + rating_avg: OrderDirection + """ + ✨ Generated from Field `Movie`.`releaseYear_avg` of type `Float` + """ + releaseYear_avg: OrderDirection + """ + ✨ Generated from Field `Movie`.`rating_min` of type `Float` + """ + rating_min: OrderDirection + """ + ✨ Generated from Field `Movie`.`releaseYear_min` of type `Int` + """ + releaseYear_min: OrderDirection + """ + ✨ Generated from Field `Movie`.`rating_max` of type `Float` + """ + rating_max: OrderDirection + """ + ✨ Generated from Field `Movie`.`releaseYear_max` of type `Int` + """ + releaseYear_max: OrderDirection +} +""" +✨ Generated data input type for table 'Person'. It includes all necessary fields for creating or upserting rows into table. +""" +input Person_Data { + """ + ✨ Generated from Field `Person`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `Person`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `Person`.`name` of type `String!` + """ + name: String + """ + ✨ `_expr` server value variant of `name` (✨ Generated from Field `Person`.`name` of type `String!`) + """ + name_expr: String_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated filter input type for table 'Person'. This input allows filtering objects using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input Person_Filter { + """ + Apply multiple filter conditions using `AND` logic. + """ + _and: [Person_Filter!] + """ + Negate the result of the provided filter condition. + """ + _not: Person_Filter + """ + Apply multiple filter conditions using `OR` logic. + """ + _or: [Person_Filter!] + """ + ✨ Generated from Field `Person`.`id` of type `UUID!` + """ + id: UUID_Filter + """ + ✨ Generated from Field `Person`.`name` of type `String!` + """ + name: String_Filter + """ + ✨ Generated from Field `Person`.`directedBies_on_directedby` of type `[DirectedBy!]!` + """ + directedBies_on_directedby: DirectedBy_ListFilter + """ + ✨ Generated from Field `Person`.`movies_via_DirectedBy` of type `[Movie!]!` + """ + movies_via_DirectedBy: Movie_ListFilter +} +""" +✨ Generated first-row input type for table 'Person'. This input selects the first row matching the filter criteria, ordered according to the specified conditions. +""" +input Person_FirstRow { + """ + Order the result by the specified fields. + """ + orderBy: [Person_Order!] + """ + Filters rows based on the specified conditions. + """ + where: Person_Filter +} +""" +✨ Generated having input type for table 'Person'. This input allows you to filter groups during aggregate queries using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input Person_Having { + """ + Apply multiple Having conditions using `AND` logic. + """ + _and: [Person_Having!] + """ + Whether to apply DISTINCT to the aggregate function. + """ + _distinct: Boolean + """ + Negate the result of the provided Having condition. + """ + _not: Person_Having + """ + Apply multiple Having conditions using `OR` logic. + """ + _or: [Person_Having!] + """ + ✨ Generated from Field `Person`.`_count` of type `Int!` + """ + _count: Int_Filter + """ + ✨ Generated from Field `Person`.`id_count` of type `Int!` + """ + id_count: Int_Filter + """ + ✨ Generated from Field `Person`.`name_count` of type `Int!` + """ + name_count: Int_Filter +} +""" +✨ Generated key input type for table 'Person'. It represents the primary key fields used to uniquely identify a row in the table. +""" +input Person_Key { + """ + ✨ Generated from Field `Person`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `Person`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated list filter input type for table 'Person'. This input applies filtering logic based on the count or existence of related objects that matches certain criteria. +""" +input Person_ListFilter { + """ + The desired number of objects that match the condition (defaults to at least one). + """ + count: Int_Filter = {gt:0} + """ + Condition of the related objects to filter for. + """ + exist: Person_Filter +} +""" +✨ Generated order input type for table 'Person'. This input defines the sorting order of rows in query results based on one or more fields. +""" +input Person_Order { + """ + ✨ Generated from Field `Person`.`id` of type `UUID!` + """ + id: OrderDirection + """ + ✨ Generated from Field `Person`.`name` of type `String!` + """ + name: OrderDirection + """ + ✨ Generated from Field `Person`.`_count` of type `Int!` + """ + _count: OrderDirection + """ + ✨ Generated from Field `Person`.`id_count` of type `Int!` + """ + id_count: OrderDirection + """ + ✨ Generated from Field `Person`.`name_count` of type `Int!` + """ + name_count: OrderDirection +} +""" +✨ Generated data input type for table 'Thing'. It includes all necessary fields for creating or upserting rows into table. +""" +input Thing_Data { + """ + ✨ Generated from Field `Thing`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `Thing`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `Thing`.`title` of type `Any!` + """ + title: Any + """ + ✨ `_expr` server value variant of `title` (✨ Generated from Field `Thing`.`title` of type `Any!`) + """ + title_expr: Any_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated filter input type for table 'Thing'. This input allows filtering objects using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input Thing_Filter { + """ + Apply multiple filter conditions using `AND` logic. + """ + _and: [Thing_Filter!] + """ + Negate the result of the provided filter condition. + """ + _not: Thing_Filter + """ + Apply multiple filter conditions using `OR` logic. + """ + _or: [Thing_Filter!] + """ + ✨ Generated from Field `Thing`.`id` of type `UUID!` + """ + id: UUID_Filter + """ + ✨ Generated from Field `Thing`.`title` of type `Any!` + """ + title: Any_Filter +} +""" +✨ Generated first-row input type for table 'Thing'. This input selects the first row matching the filter criteria, ordered according to the specified conditions. +""" +input Thing_FirstRow { + """ + Order the result by the specified fields. + """ + orderBy: [Thing_Order!] + """ + Filters rows based on the specified conditions. + """ + where: Thing_Filter +} +""" +✨ Generated having input type for table 'Thing'. This input allows you to filter groups during aggregate queries using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input Thing_Having { + """ + Apply multiple Having conditions using `AND` logic. + """ + _and: [Thing_Having!] + """ + Whether to apply DISTINCT to the aggregate function. + """ + _distinct: Boolean + """ + Negate the result of the provided Having condition. + """ + _not: Thing_Having + """ + Apply multiple Having conditions using `OR` logic. + """ + _or: [Thing_Having!] + """ + ✨ Generated from Field `Thing`.`_count` of type `Int!` + """ + _count: Int_Filter + """ + ✨ Generated from Field `Thing`.`id_count` of type `Int!` + """ + id_count: Int_Filter + """ + ✨ Generated from Field `Thing`.`title_count` of type `Int!` + """ + title_count: Int_Filter + """ + ✨ Generated from Field `Thing`.`title_min` of type `Any` + """ + title_min: Any_Filter + """ + ✨ Generated from Field `Thing`.`title_max` of type `Any` + """ + title_max: Any_Filter +} +""" +✨ Generated key input type for table 'Thing'. It represents the primary key fields used to uniquely identify a row in the table. +""" +input Thing_Key { + """ + ✨ Generated from Field `Thing`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `Thing`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated list filter input type for table 'Thing'. This input applies filtering logic based on the count or existence of related objects that matches certain criteria. +""" +input Thing_ListFilter { + """ + The desired number of objects that match the condition (defaults to at least one). + """ + count: Int_Filter = {gt:0} + """ + Condition of the related objects to filter for. + """ + exist: Thing_Filter +} +""" +✨ Generated order input type for table 'Thing'. This input defines the sorting order of rows in query results based on one or more fields. +""" +input Thing_Order { + """ + ✨ Generated from Field `Thing`.`id` of type `UUID!` + """ + id: OrderDirection + """ + ✨ Generated from Field `Thing`.`title` of type `Any!` + """ + title: OrderDirection + """ + ✨ Generated from Field `Thing`.`_count` of type `Int!` + """ + _count: OrderDirection + """ + ✨ Generated from Field `Thing`.`id_count` of type `Int!` + """ + id_count: OrderDirection + """ + ✨ Generated from Field `Thing`.`title_count` of type `Int!` + """ + title_count: OrderDirection + """ + ✨ Generated from Field `Thing`.`title_min` of type `Any` + """ + title_min: OrderDirection + """ + ✨ Generated from Field `Thing`.`title_max` of type `Any` + """ + title_max: OrderDirection +} +""" +✨ Generated data input type for table 'TimestampHolder'. It includes all necessary fields for creating or upserting rows into table. +""" +input TimestampHolder_Data { + """ + ✨ Generated from Field `TimestampHolder`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `TimestampHolder`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables + """ + ✨ Generated from Field `TimestampHolder`.`date` of type `Date` + """ + date: Date + """ + ✨ `_date` server value variant of `date` (✨ Generated from Field `TimestampHolder`.`date` of type `Date`) + """ + date_date: Date_Relative @fdc_forbiddenInVariables + """ + ✨ `_expr` server value variant of `date` (✨ Generated from Field `TimestampHolder`.`date` of type `Date`) + """ + date_expr: Date_Expr @fdc_forbiddenInVariables + """ + ✨ `_update` server value variant of `date` (✨ Generated from Field `TimestampHolder`.`date` of type `Date`) + """ + date_update: [Date_Update!] @fdc_forbiddenInVariables + """ + ✨ Generated from Field `TimestampHolder`.`timestamp` of type `Timestamp!` + """ + timestamp: Timestamp + """ + ✨ `_expr` server value variant of `timestamp` (✨ Generated from Field `TimestampHolder`.`timestamp` of type `Timestamp!`) + """ + timestamp_expr: Timestamp_Expr @fdc_forbiddenInVariables + """ + ✨ `_time` server value variant of `timestamp` (✨ Generated from Field `TimestampHolder`.`timestamp` of type `Timestamp!`) + """ + timestamp_time: Timestamp_Relative @fdc_forbiddenInVariables + """ + ✨ `_update` server value variant of `timestamp` (✨ Generated from Field `TimestampHolder`.`timestamp` of type `Timestamp!`) + """ + timestamp_update: [Timestamp_Update!] @fdc_forbiddenInVariables +} +""" +✨ Generated filter input type for table 'TimestampHolder'. This input allows filtering objects using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input TimestampHolder_Filter { + """ + Apply multiple filter conditions using `AND` logic. + """ + _and: [TimestampHolder_Filter!] + """ + Negate the result of the provided filter condition. + """ + _not: TimestampHolder_Filter + """ + Apply multiple filter conditions using `OR` logic. + """ + _or: [TimestampHolder_Filter!] + """ + ✨ Generated from Field `TimestampHolder`.`id` of type `UUID!` + """ + id: UUID_Filter + """ + ✨ Generated from Field `TimestampHolder`.`date` of type `Date` + """ + date: Date_Filter + """ + ✨ Generated from Field `TimestampHolder`.`timestamp` of type `Timestamp!` + """ + timestamp: Timestamp_Filter +} +""" +✨ Generated first-row input type for table 'TimestampHolder'. This input selects the first row matching the filter criteria, ordered according to the specified conditions. +""" +input TimestampHolder_FirstRow { + """ + Order the result by the specified fields. + """ + orderBy: [TimestampHolder_Order!] + """ + Filters rows based on the specified conditions. + """ + where: TimestampHolder_Filter +} +""" +✨ Generated having input type for table 'TimestampHolder'. This input allows you to filter groups during aggregate queries using various conditions. Use `_or`, `_and`, and `_not` to compose complex filters. +""" +input TimestampHolder_Having { + """ + Apply multiple Having conditions using `AND` logic. + """ + _and: [TimestampHolder_Having!] + """ + Whether to apply DISTINCT to the aggregate function. + """ + _distinct: Boolean + """ + Negate the result of the provided Having condition. + """ + _not: TimestampHolder_Having + """ + Apply multiple Having conditions using `OR` logic. + """ + _or: [TimestampHolder_Having!] + """ + ✨ Generated from Field `TimestampHolder`.`_count` of type `Int!` + """ + _count: Int_Filter + """ + ✨ Generated from Field `TimestampHolder`.`date_count` of type `Int!` + """ + date_count: Int_Filter + """ + ✨ Generated from Field `TimestampHolder`.`id_count` of type `Int!` + """ + id_count: Int_Filter + """ + ✨ Generated from Field `TimestampHolder`.`timestamp_count` of type `Int!` + """ + timestamp_count: Int_Filter + """ + ✨ Generated from Field `TimestampHolder`.`date_min` of type `Date` + """ + date_min: Date_Filter + """ + ✨ Generated from Field `TimestampHolder`.`timestamp_min` of type `Timestamp` + """ + timestamp_min: Timestamp_Filter + """ + ✨ Generated from Field `TimestampHolder`.`date_max` of type `Date` + """ + date_max: Date_Filter + """ + ✨ Generated from Field `TimestampHolder`.`timestamp_max` of type `Timestamp` + """ + timestamp_max: Timestamp_Filter +} +""" +✨ Generated key input type for table 'TimestampHolder'. It represents the primary key fields used to uniquely identify a row in the table. +""" +input TimestampHolder_Key { + """ + ✨ Generated from Field `TimestampHolder`.`id` of type `UUID!` + """ + id: UUID + """ + ✨ `_expr` server value variant of `id` (✨ Generated from Field `TimestampHolder`.`id` of type `UUID!`) + """ + id_expr: UUID_Expr @fdc_forbiddenInVariables +} +""" +✨ Generated list filter input type for table 'TimestampHolder'. This input applies filtering logic based on the count or existence of related objects that matches certain criteria. +""" +input TimestampHolder_ListFilter { + """ + The desired number of objects that match the condition (defaults to at least one). + """ + count: Int_Filter = {gt:0} + """ + Condition of the related objects to filter for. + """ + exist: TimestampHolder_Filter +} +""" +✨ Generated order input type for table 'TimestampHolder'. This input defines the sorting order of rows in query results based on one or more fields. +""" +input TimestampHolder_Order { + """ + ✨ Generated from Field `TimestampHolder`.`id` of type `UUID!` + """ + id: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`date` of type `Date` + """ + date: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`timestamp` of type `Timestamp!` + """ + timestamp: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`_count` of type `Int!` + """ + _count: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`date_count` of type `Int!` + """ + date_count: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`id_count` of type `Int!` + """ + id_count: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`timestamp_count` of type `Int!` + """ + timestamp_count: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`date_min` of type `Date` + """ + date_min: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`timestamp_min` of type `Timestamp` + """ + timestamp_min: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`date_max` of type `Date` + """ + date_max: OrderDirection + """ + ✨ Generated from Field `TimestampHolder`.`timestamp_max` of type `Timestamp` + """ + timestamp_max: OrderDirection +} diff --git a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/mutation.gql b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/mutation.gql new file mode 100644 index 000000000000..419cc0062903 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/mutation.gql @@ -0,0 +1,552 @@ +extend type Mutation { + """ + ✨ Insert a single `DirectedBy` into the table and return its key. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + directedBy_insert( + """ + Data object to insert into the table. + """ + data: DirectedBy_Data! + ): DirectedBy_KeyOutput! @fdc_generated(from: "DirectedBy", purpose: INSERT_SINGLE) + """ + ✨ Insert a single `Movie` into the table and return its key. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + movie_insert( + """ + Data object to insert into the table. + """ + data: Movie_Data! + ): Movie_KeyOutput! @fdc_generated(from: "Movie", purpose: INSERT_SINGLE) + """ + ✨ Insert a single `Person` into the table and return its key. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + person_insert( + """ + Data object to insert into the table. + """ + data: Person_Data! + ): Person_KeyOutput! @fdc_generated(from: "Person", purpose: INSERT_SINGLE) + """ + ✨ Insert a single `Thing` into the table and return its key. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + thing_insert( + """ + Data object to insert into the table. + """ + data: Thing_Data! + ): Thing_KeyOutput! @fdc_generated(from: "Thing", purpose: INSERT_SINGLE) + """ + ✨ Insert a single `TimestampHolder` into the table and return its key. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + timestampHolder_insert( + """ + Data object to insert into the table. + """ + data: TimestampHolder_Data! + ): TimestampHolder_KeyOutput! @fdc_generated(from: "TimestampHolder", purpose: INSERT_SINGLE) + """ + ✨ Insert `DirectedBy` objects into the table and return their keys. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + directedBy_insertMany( + """ + List of data objects to insert into the table. + """ + data: [DirectedBy_Data!]! + ): [DirectedBy_KeyOutput!]! @fdc_generated(from: "DirectedBy", purpose: INSERT_MULTIPLE) + """ + ✨ Insert `Movie` objects into the table and return their keys. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + movie_insertMany( + """ + List of data objects to insert into the table. + """ + data: [Movie_Data!]! + ): [Movie_KeyOutput!]! @fdc_generated(from: "Movie", purpose: INSERT_MULTIPLE) + """ + ✨ Insert `Person` objects into the table and return their keys. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + person_insertMany( + """ + List of data objects to insert into the table. + """ + data: [Person_Data!]! + ): [Person_KeyOutput!]! @fdc_generated(from: "Person", purpose: INSERT_MULTIPLE) + """ + ✨ Insert `Thing` objects into the table and return their keys. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + thing_insertMany( + """ + List of data objects to insert into the table. + """ + data: [Thing_Data!]! + ): [Thing_KeyOutput!]! @fdc_generated(from: "Thing", purpose: INSERT_MULTIPLE) + """ + ✨ Insert `TimestampHolder` objects into the table and return their keys. Columns not specified in `data` will receive defaults (e.g. `null`). + """ + timestampHolder_insertMany( + """ + List of data objects to insert into the table. + """ + data: [TimestampHolder_Data!]! + ): [TimestampHolder_KeyOutput!]! @fdc_generated(from: "TimestampHolder", purpose: INSERT_MULTIPLE) + """ + ✨ Insert or update a single `DirectedBy` into the table, based on the primary key. Returns the key of the newly inserted or existing updated `DirectedBy`. + """ + directedBy_upsert( + """ + Data object to insert or update if it already exists. + """ + data: DirectedBy_Data! + ): DirectedBy_KeyOutput! @fdc_generated(from: "DirectedBy", purpose: UPSERT_SINGLE) + """ + ✨ Insert or update a single `Movie` into the table, based on the primary key. Returns the key of the newly inserted or existing updated `Movie`. + """ + movie_upsert( + """ + Data object to insert or update if it already exists. + """ + data: Movie_Data! + ): Movie_KeyOutput! @fdc_generated(from: "Movie", purpose: UPSERT_SINGLE) + """ + ✨ Insert or update a single `Person` into the table, based on the primary key. Returns the key of the newly inserted or existing updated `Person`. + """ + person_upsert( + """ + Data object to insert or update if it already exists. + """ + data: Person_Data! + ): Person_KeyOutput! @fdc_generated(from: "Person", purpose: UPSERT_SINGLE) + """ + ✨ Insert or update a single `Thing` into the table, based on the primary key. Returns the key of the newly inserted or existing updated `Thing`. + """ + thing_upsert( + """ + Data object to insert or update if it already exists. + """ + data: Thing_Data! + ): Thing_KeyOutput! @fdc_generated(from: "Thing", purpose: UPSERT_SINGLE) + """ + ✨ Insert or update a single `TimestampHolder` into the table, based on the primary key. Returns the key of the newly inserted or existing updated `TimestampHolder`. + """ + timestampHolder_upsert( + """ + Data object to insert or update if it already exists. + """ + data: TimestampHolder_Data! + ): TimestampHolder_KeyOutput! @fdc_generated(from: "TimestampHolder", purpose: UPSERT_SINGLE) + """ + ✨ Insert or update `DirectedBy` objects into the table, based on the primary key. Returns the key of the newly inserted or existing updated `DirectedBy`. + """ + directedBy_upsertMany( + """ + List of data objects to insert or update if it already exists. + """ + data: [DirectedBy_Data!]! + ): [DirectedBy_KeyOutput!]! @fdc_generated(from: "DirectedBy", purpose: UPSERT_MULTIPLE) + """ + ✨ Insert or update `Movie` objects into the table, based on the primary key. Returns the key of the newly inserted or existing updated `Movie`. + """ + movie_upsertMany( + """ + List of data objects to insert or update if it already exists. + """ + data: [Movie_Data!]! + ): [Movie_KeyOutput!]! @fdc_generated(from: "Movie", purpose: UPSERT_MULTIPLE) + """ + ✨ Insert or update `Person` objects into the table, based on the primary key. Returns the key of the newly inserted or existing updated `Person`. + """ + person_upsertMany( + """ + List of data objects to insert or update if it already exists. + """ + data: [Person_Data!]! + ): [Person_KeyOutput!]! @fdc_generated(from: "Person", purpose: UPSERT_MULTIPLE) + """ + ✨ Insert or update `Thing` objects into the table, based on the primary key. Returns the key of the newly inserted or existing updated `Thing`. + """ + thing_upsertMany( + """ + List of data objects to insert or update if it already exists. + """ + data: [Thing_Data!]! + ): [Thing_KeyOutput!]! @fdc_generated(from: "Thing", purpose: UPSERT_MULTIPLE) + """ + ✨ Insert or update `TimestampHolder` objects into the table, based on the primary key. Returns the key of the newly inserted or existing updated `TimestampHolder`. + """ + timestampHolder_upsertMany( + """ + List of data objects to insert or update if it already exists. + """ + data: [TimestampHolder_Data!]! + ): [TimestampHolder_KeyOutput!]! @fdc_generated(from: "TimestampHolder", purpose: UPSERT_MULTIPLE) + """ + ✨ Update a single `DirectedBy` based on `id`, `key` or `first`, setting columns specified in `data`. Returns the key of the updated `DirectedBy` or `null` if not found. + """ + directedBy_update( + """ + The key used to identify the object. + """ + key: DirectedBy_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: DirectedBy_FirstRow + + """ + Data object containing fields to be updated. + """ + data: DirectedBy_Data! + ): DirectedBy_KeyOutput @fdc_generated(from: "DirectedBy", purpose: UPDATE_SINGLE) + """ + ✨ Update a single `Movie` based on `id`, `key` or `first`, setting columns specified in `data`. Returns the key of the updated `Movie` or `null` if not found. + """ + movie_update( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Movie_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Movie_FirstRow + + """ + Data object containing fields to be updated. + """ + data: Movie_Data! + ): Movie_KeyOutput @fdc_generated(from: "Movie", purpose: UPDATE_SINGLE) + """ + ✨ Update a single `Person` based on `id`, `key` or `first`, setting columns specified in `data`. Returns the key of the updated `Person` or `null` if not found. + """ + person_update( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Person_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Person_FirstRow + + """ + Data object containing fields to be updated. + """ + data: Person_Data! + ): Person_KeyOutput @fdc_generated(from: "Person", purpose: UPDATE_SINGLE) + """ + ✨ Update a single `Thing` based on `id`, `key` or `first`, setting columns specified in `data`. Returns the key of the updated `Thing` or `null` if not found. + """ + thing_update( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Thing_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Thing_FirstRow + + """ + Data object containing fields to be updated. + """ + data: Thing_Data! + ): Thing_KeyOutput @fdc_generated(from: "Thing", purpose: UPDATE_SINGLE) + """ + ✨ Update a single `TimestampHolder` based on `id`, `key` or `first`, setting columns specified in `data`. Returns the key of the updated `TimestampHolder` or `null` if not found. + """ + timestampHolder_update( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: TimestampHolder_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: TimestampHolder_FirstRow + + """ + Data object containing fields to be updated. + """ + data: TimestampHolder_Data! + ): TimestampHolder_KeyOutput @fdc_generated(from: "TimestampHolder", purpose: UPDATE_SINGLE) + """ + ✨ Update `DirectedBy` objects matching `where` conditions (or `all`, if true) according to `data`. Returns the number of rows updated. + """ + directedBy_updateMany( + """ + Filter condition to specify which rows to update. + """ + where: DirectedBy_Filter + + """ + Set to true to update all rows. + """ + all: Boolean = false + + """ + Data object containing fields to update. + """ + data: DirectedBy_Data! + ): Int! @fdc_generated(from: "DirectedBy", purpose: UPDATE_MULTIPLE) + """ + ✨ Update `Movie` objects matching `where` conditions (or `all`, if true) according to `data`. Returns the number of rows updated. + """ + movie_updateMany( + """ + Filter condition to specify which rows to update. + """ + where: Movie_Filter + + """ + Set to true to update all rows. + """ + all: Boolean = false + + """ + Data object containing fields to update. + """ + data: Movie_Data! + ): Int! @fdc_generated(from: "Movie", purpose: UPDATE_MULTIPLE) + """ + ✨ Update `Person` objects matching `where` conditions (or `all`, if true) according to `data`. Returns the number of rows updated. + """ + person_updateMany( + """ + Filter condition to specify which rows to update. + """ + where: Person_Filter + + """ + Set to true to update all rows. + """ + all: Boolean = false + + """ + Data object containing fields to update. + """ + data: Person_Data! + ): Int! @fdc_generated(from: "Person", purpose: UPDATE_MULTIPLE) + """ + ✨ Update `Thing` objects matching `where` conditions (or `all`, if true) according to `data`. Returns the number of rows updated. + """ + thing_updateMany( + """ + Filter condition to specify which rows to update. + """ + where: Thing_Filter + + """ + Set to true to update all rows. + """ + all: Boolean = false + + """ + Data object containing fields to update. + """ + data: Thing_Data! + ): Int! @fdc_generated(from: "Thing", purpose: UPDATE_MULTIPLE) + """ + ✨ Update `TimestampHolder` objects matching `where` conditions (or `all`, if true) according to `data`. Returns the number of rows updated. + """ + timestampHolder_updateMany( + """ + Filter condition to specify which rows to update. + """ + where: TimestampHolder_Filter + + """ + Set to true to update all rows. + """ + all: Boolean = false + + """ + Data object containing fields to update. + """ + data: TimestampHolder_Data! + ): Int! @fdc_generated(from: "TimestampHolder", purpose: UPDATE_MULTIPLE) + """ + ✨ Delete a single `DirectedBy` based on `id`, `key` or `first` and return its key (or `null` if not found). + """ + directedBy_delete( + """ + The key used to identify the object. + """ + key: DirectedBy_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: DirectedBy_FirstRow + ): DirectedBy_KeyOutput @fdc_generated(from: "DirectedBy", purpose: DELETE_SINGLE) + """ + ✨ Delete a single `Movie` based on `id`, `key` or `first` and return its key (or `null` if not found). + """ + movie_delete( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Movie_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Movie_FirstRow + ): Movie_KeyOutput @fdc_generated(from: "Movie", purpose: DELETE_SINGLE) + """ + ✨ Delete a single `Person` based on `id`, `key` or `first` and return its key (or `null` if not found). + """ + person_delete( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Person_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Person_FirstRow + ): Person_KeyOutput @fdc_generated(from: "Person", purpose: DELETE_SINGLE) + """ + ✨ Delete a single `Thing` based on `id`, `key` or `first` and return its key (or `null` if not found). + """ + thing_delete( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Thing_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Thing_FirstRow + ): Thing_KeyOutput @fdc_generated(from: "Thing", purpose: DELETE_SINGLE) + """ + ✨ Delete a single `TimestampHolder` based on `id`, `key` or `first` and return its key (or `null` if not found). + """ + timestampHolder_delete( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: TimestampHolder_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: TimestampHolder_FirstRow + ): TimestampHolder_KeyOutput @fdc_generated(from: "TimestampHolder", purpose: DELETE_SINGLE) + """ + ✨ Delete `DirectedBy` objects matching `where` conditions (or `all`, if true). Returns the number of rows deleted. + """ + directedBy_deleteMany( + """ + Filter condition to specify which rows to delete. + """ + where: DirectedBy_Filter + + """ + Set to true to delete all rows. + """ + all: Boolean = false + ): Int! @fdc_generated(from: "DirectedBy", purpose: DELETE_MULTIPLE) + """ + ✨ Delete `Movie` objects matching `where` conditions (or `all`, if true). Returns the number of rows deleted. + """ + movie_deleteMany( + """ + Filter condition to specify which rows to delete. + """ + where: Movie_Filter + + """ + Set to true to delete all rows. + """ + all: Boolean = false + ): Int! @fdc_generated(from: "Movie", purpose: DELETE_MULTIPLE) + """ + ✨ Delete `Person` objects matching `where` conditions (or `all`, if true). Returns the number of rows deleted. + """ + person_deleteMany( + """ + Filter condition to specify which rows to delete. + """ + where: Person_Filter + + """ + Set to true to delete all rows. + """ + all: Boolean = false + ): Int! @fdc_generated(from: "Person", purpose: DELETE_MULTIPLE) + """ + ✨ Delete `Thing` objects matching `where` conditions (or `all`, if true). Returns the number of rows deleted. + """ + thing_deleteMany( + """ + Filter condition to specify which rows to delete. + """ + where: Thing_Filter + + """ + Set to true to delete all rows. + """ + all: Boolean = false + ): Int! @fdc_generated(from: "Thing", purpose: DELETE_MULTIPLE) + """ + ✨ Delete `TimestampHolder` objects matching `where` conditions (or `all`, if true). Returns the number of rows deleted. + """ + timestampHolder_deleteMany( + """ + Filter condition to specify which rows to delete. + """ + where: TimestampHolder_Filter + + """ + Set to true to delete all rows. + """ + all: Boolean = false + ): Int! @fdc_generated(from: "TimestampHolder", purpose: DELETE_MULTIPLE) +} diff --git a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/query.gql b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/query.gql new file mode 100644 index 000000000000..f7fd3c460647 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/query.gql @@ -0,0 +1,262 @@ +extend type Query { + """ + ✨ Look up a single `DirectedBy` based on `id`, `key` or `first` and return selected fields (or `null` if not found). + """ + directedBy( + """ + The key used to identify the object. + """ + key: DirectedBy_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: DirectedBy_FirstRow + ): DirectedBy @fdc_generated(from: "DirectedBy", purpose: QUERY_SINGLE) + """ + ✨ Look up a single `Movie` based on `id`, `key` or `first` and return selected fields (or `null` if not found). + """ + movie( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Movie_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Movie_FirstRow + ): Movie @fdc_generated(from: "Movie", purpose: QUERY_SINGLE) + """ + ✨ Look up a single `Person` based on `id`, `key` or `first` and return selected fields (or `null` if not found). + """ + person( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Person_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Person_FirstRow + ): Person @fdc_generated(from: "Person", purpose: QUERY_SINGLE) + """ + ✨ Look up a single `Thing` based on `id`, `key` or `first` and return selected fields (or `null` if not found). + """ + thing( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: Thing_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: Thing_FirstRow + ): Thing @fdc_generated(from: "Thing", purpose: QUERY_SINGLE) + """ + ✨ Look up a single `TimestampHolder` based on `id`, `key` or `first` and return selected fields (or `null` if not found). + """ + timestampHolder( + """ + The unique ID of the object. + """ + id: UUID + + """ + The key used to identify the object. + """ + key: TimestampHolder_Key + + """ + Fetch the first row based on the filters and ordering. + """ + first: TimestampHolder_FirstRow + ): TimestampHolder @fdc_generated(from: "TimestampHolder", purpose: QUERY_SINGLE) + """ + ✨ List `DirectedBy` objects in the table and return selected fields, optionally filtered by `where` conditions + """ + directedBies( + """ + Filter condition to narrow down the query results. + """ + where: DirectedBy_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [DirectedBy_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: DirectedBy_Having + ): [DirectedBy!]! @fdc_generated(from: "DirectedBy", purpose: QUERY_MULTIPLE) + """ + ✨ List `Movie` objects in the table and return selected fields, optionally filtered by `where` conditions + """ + movies( + """ + Filter condition to narrow down the query results. + """ + where: Movie_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [Movie_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: Movie_Having + ): [Movie!]! @fdc_generated(from: "Movie", purpose: QUERY_MULTIPLE) + """ + ✨ List `Person` objects in the table and return selected fields, optionally filtered by `where` conditions + """ + people( + """ + Filter condition to narrow down the query results. + """ + where: Person_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [Person_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: Person_Having + ): [Person!]! @fdc_generated(from: "Person", purpose: QUERY_MULTIPLE) + """ + ✨ List `Thing` objects in the table and return selected fields, optionally filtered by `where` conditions + """ + things( + """ + Filter condition to narrow down the query results. + """ + where: Thing_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [Thing_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: Thing_Having + ): [Thing!]! @fdc_generated(from: "Thing", purpose: QUERY_MULTIPLE) + """ + ✨ List `TimestampHolder` objects in the table and return selected fields, optionally filtered by `where` conditions + """ + timestampHolders( + """ + Filter condition to narrow down the query results. + """ + where: TimestampHolder_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [TimestampHolder_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: TimestampHolder_Having + ): [TimestampHolder!]! @fdc_generated(from: "TimestampHolder", purpose: QUERY_MULTIPLE) +} diff --git a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/relation.gql b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/relation.gql new file mode 100644 index 000000000000..97e64bd39091 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/main/relation.gql @@ -0,0 +1,417 @@ +extend type DirectedBy { + """ + Implicit metadata field that cannot be written. It provides extra information about query results. + """ + _metadata: _Metadata @fdc_generated(from: "DirectedBy", purpose: METADATA_FIELD) + """ + ✨ Count the number of rows in the `DirectedBy` table. + """ + _count: Int! @fdc_generated(from: "DirectedBy.", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `DirectedBy` table where the `directedbyId` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + directedbyId_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "DirectedBy.directedbyId", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `DirectedBy` table where the `movieId` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + movieId_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "DirectedBy.movieId", purpose: QUERY_COUNT) + """ + A generated field that is used for caching results in SDKs. + """ + _id: ID! @fdc_generated(from: "DirectedBy.movieId,directedbyId", purpose: ENTITY_ID) +} +extend type Movie { + """ + ✨ List `DirectedBy` objects in a one-to-many relationship (where `DirectedBy`.`movie` is this object). + """ + directedBies_on_movie( + """ + Filter condition to narrow down the query results. + """ + where: DirectedBy_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [DirectedBy_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: DirectedBy_Having + ): [DirectedBy!]! @fdc_generated(from: "DirectedBy.movie", purpose: QUERY_MULTIPLE_ONE_TO_MANY) + """ + ✨ List `Person` objects using `DirectedBy` as the join table (a `DirectedBy` object exists where its `movie` is this and its `directedby` is that). + """ + people_via_DirectedBy( + """ + Filter condition to narrow down the query results. + """ + where: DirectedBy_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [DirectedBy_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: DirectedBy_Having + ): [Person!]! @fdc_generated(from: "DirectedBy", purpose: QUERY_MULTIPLE_MANY_TO_MANY) + """ + Implicit metadata field that cannot be written. It provides extra information about query results. + """ + _metadata: _Metadata @fdc_generated(from: "Movie", purpose: METADATA_FIELD) + """ + ✨ Count the number of rows in the `Movie` table. + """ + _count: Int! @fdc_generated(from: "Movie.", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Movie` table where the `description` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + description_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Movie.description", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Movie` table where the `genre` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + genre_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Movie.genre", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Movie` table where the `id` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + id_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Movie.id", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Movie` table where the `rating` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + rating_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Movie.rating", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Movie` table where the `releaseYear` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + releaseYear_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Movie.releaseYear", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Movie` table where the `title` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + title_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Movie.title", purpose: QUERY_COUNT) + """ + ✨ Sum the `rating` field in the `Movie` table. + """ + rating_sum( + """ + Set to true to sum the distinct values. + """ + distinct: Boolean = false + ): Float @fdc_generated(from: "Movie.rating", purpose: QUERY_SUM) + """ + ✨ Sum the `releaseYear` field in the `Movie` table. + """ + releaseYear_sum( + """ + Set to true to sum the distinct values. + """ + distinct: Boolean = false + ): Int @fdc_generated(from: "Movie.releaseYear", purpose: QUERY_SUM) + """ + ✨ Average the `rating` field in the `Movie` table. + """ + rating_avg( + """ + Set to true to average the distinct values. + """ + distinct: Boolean = false + ): Float @fdc_generated(from: "Movie.rating", purpose: QUERY_AVG) + """ + ✨ Average the `releaseYear` field in the `Movie` table. + """ + releaseYear_avg( + """ + Set to true to average the distinct values. + """ + distinct: Boolean = false + ): Float @fdc_generated(from: "Movie.releaseYear", purpose: QUERY_AVG) + """ + ✨ Minimum of the `rating` field in the `Movie` table. + """ + rating_min: Float @fdc_generated(from: "Movie.rating", purpose: QUERY_MIN) + """ + ✨ Minimum of the `releaseYear` field in the `Movie` table. + """ + releaseYear_min: Int @fdc_generated(from: "Movie.releaseYear", purpose: QUERY_MIN) + """ + ✨ Maximum of the `rating` field in the `Movie` table. + """ + rating_max: Float @fdc_generated(from: "Movie.rating", purpose: QUERY_MAX) + """ + ✨ Maximum of the `releaseYear` field in the `Movie` table. + """ + releaseYear_max: Int @fdc_generated(from: "Movie.releaseYear", purpose: QUERY_MAX) + """ + A generated field that is used for caching results in SDKs. + """ + _id: ID! @fdc_generated(from: "Movie.id", purpose: ENTITY_ID) +} +extend type Person { + """ + ✨ List `DirectedBy` objects in a one-to-many relationship (where `DirectedBy`.`directedby` is this object). + """ + directedBies_on_directedby( + """ + Filter condition to narrow down the query results. + """ + where: DirectedBy_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [DirectedBy_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: DirectedBy_Having + ): [DirectedBy!]! @fdc_generated(from: "DirectedBy.directedby", purpose: QUERY_MULTIPLE_ONE_TO_MANY) + """ + ✨ List `Movie` objects using `DirectedBy` as the join table (a `DirectedBy` object exists where its `directedby` is this and its `movie` is that). + """ + movies_via_DirectedBy( + """ + Filter condition to narrow down the query results. + """ + where: DirectedBy_Filter + + """ + Order the query results by specific fields. + """ + orderBy: [DirectedBy_Order!] + + """ + Number of rows to skip before starting to return the results. + """ + offset: Int + + """ + Maximum number of rows to return (defaults to 100 rows). + """ + limit: Int = 100 + + """ + Set to true to return distinct results. + """ + distinct: Boolean = false + + """ + Filter condition to apply to the groups of aggregate queries. + """ + having: DirectedBy_Having + ): [Movie!]! @fdc_generated(from: "DirectedBy", purpose: QUERY_MULTIPLE_MANY_TO_MANY) + """ + Implicit metadata field that cannot be written. It provides extra information about query results. + """ + _metadata: _Metadata @fdc_generated(from: "Person", purpose: METADATA_FIELD) + """ + ✨ Count the number of rows in the `Person` table. + """ + _count: Int! @fdc_generated(from: "Person.", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Person` table where the `id` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + id_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Person.id", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Person` table where the `name` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + name_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Person.name", purpose: QUERY_COUNT) + """ + A generated field that is used for caching results in SDKs. + """ + _id: ID! @fdc_generated(from: "Person.id", purpose: ENTITY_ID) +} +extend type Thing { + """ + Implicit metadata field that cannot be written. It provides extra information about query results. + """ + _metadata: _Metadata @fdc_generated(from: "Thing", purpose: METADATA_FIELD) + """ + ✨ Count the number of rows in the `Thing` table. + """ + _count: Int! @fdc_generated(from: "Thing.", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Thing` table where the `id` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + id_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Thing.id", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `Thing` table where the `title` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + title_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "Thing.title", purpose: QUERY_COUNT) + """ + ✨ Minimum of the `title` field in the `Thing` table. + """ + title_min: Any @fdc_generated(from: "Thing.title", purpose: QUERY_MIN) + """ + ✨ Maximum of the `title` field in the `Thing` table. + """ + title_max: Any @fdc_generated(from: "Thing.title", purpose: QUERY_MAX) + """ + A generated field that is used for caching results in SDKs. + """ + _id: ID! @fdc_generated(from: "Thing.id", purpose: ENTITY_ID) +} +extend type TimestampHolder { + """ + Implicit metadata field that cannot be written. It provides extra information about query results. + """ + _metadata: _Metadata @fdc_generated(from: "TimestampHolder", purpose: METADATA_FIELD) + """ + ✨ Count the number of rows in the `TimestampHolder` table. + """ + _count: Int! @fdc_generated(from: "TimestampHolder.", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `TimestampHolder` table where the `date` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + date_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "TimestampHolder.date", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `TimestampHolder` table where the `id` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + id_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "TimestampHolder.id", purpose: QUERY_COUNT) + """ + ✨ Count the number of rows in the `TimestampHolder` table where the `timestamp` field is non-null. Pass the `distinct` argument to instead count the number of distinct values. + """ + timestamp_count( + """ + Set to true to count the number of distinct values. + """ + distinct: Boolean = false + ): Int! @fdc_generated(from: "TimestampHolder.timestamp", purpose: QUERY_COUNT) + """ + ✨ Minimum of the `date` field in the `TimestampHolder` table. + """ + date_min: Date @fdc_generated(from: "TimestampHolder.date", purpose: QUERY_MIN) + """ + ✨ Minimum of the `timestamp` field in the `TimestampHolder` table. + """ + timestamp_min: Timestamp @fdc_generated(from: "TimestampHolder.timestamp", purpose: QUERY_MIN) + """ + ✨ Maximum of the `date` field in the `TimestampHolder` table. + """ + date_max: Date @fdc_generated(from: "TimestampHolder.date", purpose: QUERY_MAX) + """ + ✨ Maximum of the `timestamp` field in the `TimestampHolder` table. + """ + timestamp_max: Timestamp @fdc_generated(from: "TimestampHolder.timestamp", purpose: QUERY_MAX) + """ + A generated field that is used for caching results in SDKs. + """ + _id: ID! @fdc_generated(from: "TimestampHolder.id", purpose: ENTITY_ID) +} diff --git a/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/prelude.gql b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/prelude.gql new file mode 100644 index 000000000000..ebd062ea55f7 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/dataconnect/.dataconnect/schema/prelude.gql @@ -0,0 +1,2419 @@ +"AccessLevel specifies coarse access policies for common situations." +enum AccessLevel @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + """ + This operation is accessible to anyone, with or without authentication. + Equivalent to: `@auth(expr: "true")` + """ + PUBLIC + + """ + This operation can be executed only with a valid Firebase Auth ID token. + **Note:** This access level allows anonymous and unverified accounts, + which may present security and abuse risks. + Equivalent to: `@auth(expr: "auth.uid != nil")` + """ + USER_ANON + + """ + This operation is restricted to non-anonymous Firebase Auth accounts. + Equivalent to: `@auth(expr: "auth.uid != nil && auth.token.firebase.sign_in_provider != 'anonymous'")` + """ + USER + + """ + This operation is restricted to Firebase Auth accounts with verified email addresses. + Equivalent to: `@auth(expr: "auth.uid != nil && auth.token.email_verified")` + """ + USER_EMAIL_VERIFIED + + """ + This operation cannot be executed by anyone. The operation can only be performed + by using the Admin SDK from a privileged environment. + Equivalent to: `@auth(expr: "false")` + """ + NO_ACCESS +} + +""" +The `@auth` directive defines the authentication policy for a query or mutation. + +It must be added to any operation that you wish to be accessible from a client +application. If not specified, the operation defaults to `@auth(level: NO_ACCESS)`. + +Refer to [Data Connect Auth Guide](https://firebase.google.com/docs/data-connect/authorization-and-security) for the best practices. +""" +directive @auth( + """ + The minimal level of access required to perform this operation. + Exactly one of `level` and `expr` should be specified. + """ + level: AccessLevel @fdc_oneOf(required: true) + """ + A CEL expression that grants access to this operation if the expression + evaluates to `true`. + Exactly one of `level` and `expr` should be specified. + """ + expr: Boolean_Expr @fdc_oneOf(required: true) + """ + If the `@auth` on this operation is considered insecure, then developer + acknowledgement is required to deploy this operation, for new operations. + `@auth` is considered insecure if `level: PUBLIC`, or if + `level: USER/USER_ANON/USER_EMAIL_VERIFIED` and `auth.uid` is not referenced + in the operation. + If `insecureReason` is set, no further developer acknowledgement is needed. + """ + insecureReason: String +) on QUERY | MUTATION + +""" +Require that this mutation always run in a DB transaction. + +Mutations with `@transaction` are guaranteed to either fully succeed or fully +fail. Upon the first error in a transaction (either an execution error or failed +`@check`), the transaction will be rolled back. In the GraphQL response, all +fields within the transaction will be `null`, each with an error raised. + +- Fields that have been already evaluated will be nullified due to the rollback + and a "(rolled back)" error will be reported on each of them. +- The execution error or failed `@check` will be reported on the current field. +- Subsequent fields will not be executed. An `(aborted)` error will be reported + on each subsequent field. + +Mutations without `@transaction` would execute each root field one after +another in sequence. They surface any errors as partial +[field errors](https://spec.graphql.org/October2021/#sec-Errors.Field-errors), +but does not impact the execution of subsequent fields. However, failed +`@check`s still terminate the entire operation. + +The `@transaction` directive cannot be added to queries for now. +Currently, queries cannot fail partially, the response data is not guaranteed +to be a consistent snapshot. +""" +directive @transaction on MUTATION + +""" +Redact a part of the response from the client. + +Redacted fields are still evaluated for side effects (including data changes and +`@check`) and the results are still available to later steps in CEL expressions +(via `response.fieldName`). +""" +directive @redact on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT + +""" +Ensure this field is present and is not null or `[]`, or abort the request / transaction. + +A CEL expression, `expr` is used to test the field value. It defaults to +rejecting null and `[]` but a custom expression can be provided instead. + +If the field occurs multiple times (i.e. directly or indirectly nested under a +list), `expr` will be executed once for each occurrence and `@check` succeeds if +all values succeed. `@check` fails when the field is not present at all (i.e. +all ancestor paths contain `null` or `[]`), unless `optional` is true. + +If a `@check` fails in a mutation, the top-level field containing it will be +replaced with a partial error, whose message can be customzied via the `message` +argument. Each subsequent top-level fields will return an aborted error (i.e. +not executed). To rollback previous steps, see `@transaction`. +""" +directive @check( + """ + The CEL expression to test the field value (or values if nested under a list). + + Within the CEL expression, a special value `this` evaluates to the field that + this directive is attached to. If this field occurs multiple times because + any ancestor is a list, each occurrence is tested with `this` bound to each + value. When the field itself is a list or object, `this` follows the same + structure (including all descendants selected in case of objects). + + For any given path, if an ancestor is `null` or `[]`, the field will not be + reached and the CEL evaluation will be skipped for that path. In other words, + evaluation only takes place when `this` is `null` or non-null, but never + undefined. (See also the `optional` argument.) + """ + expr: Boolean_Expr! = "!(this in [null, []])" + """ + The error message to return to the client if the check fails. + + Defaults to "permission denied" if not specified. + """ + message: String! = "permission denied" + """ + Whether the check should pass or fail (default) when the field is not present. + + A field will not be reached at a given path if its parent or any ancestor is + `[]` or `null`. When this happens to all paths, the field will not be present + anywhere in the response tree. In other words, `expr` is evaluated 0 times. + By default, @check will automatically fail in this case. Set this argument to + `true` to make it pass even if no tests are run (a.k.a. "vacuously true"). + """ + optional: Boolean = false +) repeatable on QUERY | MUTATION | FIELD | FRAGMENT_DEFINITION | FRAGMENT_SPREAD | INLINE_FRAGMENT + +""" +Marks an element of a GraphQL operation as no longer supported for client use. +The Firebase Data Connect backend will continue supporting this element, +but it will no longer be visible in the generated SDKs. +""" +directive @retired( + "Provides the reason for retirement." + reason: String +) on QUERY | MUTATION | FIELD | VARIABLE_DEFINITION + +"Query filter criteria for `String` scalar fields." +input String_Filter { + "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." + isNull: Boolean + "Match if field is exactly equal to provided value." + eq: String @fdc_oneOf(group: "eq") + """ + Match if field is exactly equal to the result of the provided server value + expression. Currently only `auth.uid` is supported as an expression. + """ + eq_expr: String_Expr @fdc_oneOf(group: "eq") + "Match if field is not equal to provided value." + ne: String @fdc_oneOf(group: "ne") + """ + Match if field is not equal to the result of the provided server value + expression. Currently only `auth.uid` is supported as an expression. + """ + ne_expr: String_Expr @fdc_oneOf(group: "ne") + "Match if field value is among the provided list of values." + in: [String!] + "Match if field value is not among the provided list of values." + nin: [String!] + "Match if field value is greater than the provided value." + gt: String + "Match if field value is greater than or equal to the provided value." + ge: String + "Match if field value is less than the provided value." + lt: String + "Match if field value is less than or equal to the provided value." + le: String + """ + Match if field value contains the provided value as a substring. Equivalent + to `LIKE '%value%'` + """ + contains: String + """ + Match if field value starts with the provided value. Equivalent to + `LIKE 'value%'` + """ + startsWith: String + """ + Match if field value ends with the provided value. Equivalent to + `LIKE '%value'` + """ + endsWith: String + """ + Match based on the provided pattern. + """ + pattern: String_Pattern +} + +input String_Pattern { + """ + Match using LIKE semantics (https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE) + """ + like: String @fdc_oneOf + """ + Match against a POSIX regular expression. + """ + regex: String @fdc_oneOf + """ + If true, match patterns case-insensitively. + """ + ignoreCase: Boolean +} + +"Query filter criteris for `[String!]` scalar fields." +input String_ListFilter { + "Match if list field contains the provided value as a member." + includes: String + "Match if list field does not contain the provided value as a member." + excludes: String + "Match if list field contains all of the provided values as members." + includesAll: [String!] + "Match if list field does not contain any of the provided values as members." + excludesAll: [String!] +} + +"Query filter criteria for `UUID` scalar fields." +input UUID_Filter { + "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." + isNull: Boolean + "Match if field is exactly equal to provided value." + eq: UUID @fdc_oneOf(group: "eq") + """ + Match if field is exactly equal to the result of the provided server value + expression. + """ + eq_expr: UUID_Expr @fdc_oneOf(group: "eq") + "Match if field is not equal to provided value." + ne: UUID @fdc_oneOf(group: "ne") + """ + Match if field is not equal to the result of the provided server value + expression. + """ + ne_expr: UUID_Expr @fdc_oneOf(group: "ne") + "Match if field value is among the provided list of values." + in: [UUID!] + "Match if field value is not among the provided list of values." + nin: [UUID!] +} + +"Query filter criteris for `[UUID!]` scalar fields." +input UUID_ListFilter { + "Match if list field contains the provided value as a member." + includes: UUID + "Match if list field does not contain the provided value as a member." + excludes: UUID + "Match if list field contains all of the provided values as members." + includesAll: [UUID!] + "Match if list field does not contain any of the provided values as members." + excludesAll: [UUID!] +} + +"Query filter criteria for `Int` scalar fields." +input Int_Filter { + "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." + isNull: Boolean + "Match if field is exactly equal to provided value." + eq: Int @fdc_oneOf(group: "eq") + """ + Match if field is exactly equal to the result of the provided server value + expression. + """ + eq_expr: Int_Expr @fdc_oneOf(group: "eq") + "Match if field is not equal to provided value." + ne: Int @fdc_oneOf(group: "ne") + """ + Match if field is not equal to the result of the provided server value + expression. + """ + ne_expr: Int_Expr @fdc_oneOf(group: "ne") + "Match if field value is among the provided list of values." + in: [Int!] + "Match if field value is not among the provided list of values." + nin: [Int!] + "Match if field value is greater than the provided value." + gt: Int @fdc_oneOf(group: "gt") + """ + Match if field value is greater than the result of the provided server value + expression. + """ + gt_expr: Int_Expr @fdc_oneOf(group: "gt") + "Match if field value is greater than or equal to the provided value." + ge: Int @fdc_oneOf(group: "ge") + """ + Match if field value is greater than or equal to the result of the provided + server value expression. + """ + ge_expr: Int_Expr @fdc_oneOf(group: "ge") + "Match if field value is less than the provided value." + lt: Int @fdc_oneOf(group: "lt") + """ + Match if field value is less than the result of the provided server value + expression. + """ + lt_expr: Int_Expr @fdc_oneOf(group: "lt") + "Match if field value is less than or equal to the provided value." + le: Int @fdc_oneOf(group: "le") + """ + Match if field value is less than or equal to the result of the provided + server value expression. + """ + le_expr: Int_Expr @fdc_oneOf(group: "le") +} + +"Query filter criteris for `[Int!]` scalar fields." +input Int_ListFilter { + "Match if list field contains the provided value as a member." + includes: Int + "Match if list field does not contain the provided value as a member." + excludes: Int + "Match if list field contains all of the provided values as members." + includesAll: [Int!] + "Match if list field does not contain any of the provided values as members." + excludesAll: [Int!] +} + +"Query filter criteria for `Int64` scalar fields." +input Int64_Filter { + "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." + isNull: Boolean + "Match if field is exactly equal to provided value." + eq: Int64 @fdc_oneOf(group: "eq") + """ + Match if field is exactly equal to the result of the provided server value + expression. + """ + eq_expr: Int64_Expr @fdc_oneOf(group: "eq") + "Match if field is not equal to provided value." + ne: Int64 @fdc_oneOf(group: "ne") + """ + Match if field is not equal to the result of the provided server value + expression. + """ + ne_expr: Int64_Expr @fdc_oneOf(group: "ne") + "Match if field value is among the provided list of values." + in: [Int64!] + "Match if field value is not among the provided list of values." + nin: [Int64!] + "Match if field value is greater than the provided value." + gt: Int64 @fdc_oneOf(group: "gt") + """ + Match if field value is greater than the result of the provided server value + expression. + """ + gt_expr: Int64_Expr @fdc_oneOf(group: "gt") + "Match if field value is greater than or equal to the provided value." + ge: Int64 @fdc_oneOf(group: "ge") + """ + Match if field value is greater than or equal to the result of the provided + server value expression. + """ + ge_expr: Int64_Expr @fdc_oneOf(group: "ge") + "Match if field value is less than the provided value." + lt: Int64 @fdc_oneOf(group: "lt") + """ + Match if field value is less than the result of the provided server value + expression. + """ + lt_expr: Int64_Expr @fdc_oneOf(group: "lt") + "Match if field value is less than or equal to the provided value." + le: Int64 @fdc_oneOf(group: "le") + """ + Match if field value is less than or equal to the result of the provided + server value expression. + """ + le_expr: Int64_Expr @fdc_oneOf(group: "le") +} + +"Query filter criteria for `[Int64!]` scalar fields." +input Int64_ListFilter { + "Match if list field contains the provided value as a member." + includes: Int64 + "Match if list field does not contain the provided value as a member." + excludes: Int64 + "Match if list field contains all of the provided values as members." + includesAll: [Int64!] + "Match if list field does not contain any of the provided values as members." + excludesAll: [Int64!] +} + +"Query filter criteria for `Float` scalar fields." +input Float_Filter { + "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." + isNull: Boolean + "Match if field is exactly equal to provided value." + eq: Float @fdc_oneOf(group: "eq") + """ + Match if field is exactly equal to the result of the provided server value + expression. + """ + eq_expr: Float_Expr @fdc_oneOf(group: "eq") + "Match if field is not equal to provided value." + ne: Float @fdc_oneOf(group: "ne") + """ + Match if field is not equal to the result of the provided server value + expression. + """ + ne_expr: Float_Expr @fdc_oneOf(group: "ne") + "Match if field value is among the provided list of values." + in: [Float!] + "Match if field value is not among the provided list of values." + nin: [Float!] + "Match if field value is greater than the provided value." + gt: Float @fdc_oneOf(group: "gt") + """ + Match if field value is greater than the result of the provided server value + expression. + """ + gt_expr: Float_Expr @fdc_oneOf(group: "gt") + "Match if field value is greater than or equal to the provided value." + ge: Float @fdc_oneOf(group: "ge") + """ + Match if field value is greater than or equal to the result of the provided + server value expression. + """ + ge_expr: Float_Expr @fdc_oneOf(group: "ge") + "Match if field value is less than the provided value." + lt: Float @fdc_oneOf(group: "lt") + """ + Match if field value is less than the result of the provided server value + expression. + """ + lt_expr: Float_Expr @fdc_oneOf(group: "lt") + "Match if field value is less than or equal to the provided value." + le: Float @fdc_oneOf(group: "le") + """ + Match if field value is less than or equal to the result of the provided + server value expression. + """ + le_expr: Float_Expr @fdc_oneOf(group: "le") +} + +"Query filter criteria for `[Float!]` scalar fields." +input Float_ListFilter { + "Match if list field contains the provided value as a member." + includes: Float + "Match if list field does not contain the provided value as a member." + excludes: Float + "Match if list field contains all of the provided values as members." + includesAll: [Float!] + "Match if list field does not contain any of the provided values as members." + excludesAll: [Float!] +} + +"Query filter criteria for `Boolean` scalar fields." +input Boolean_Filter { + "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." + isNull: Boolean + "Match if field is exactly equal to provided value." + eq: Boolean @fdc_oneOf(group: "eq") + "Match if field is equal to the result of the provided expression." + eq_expr: Boolean_Expr @fdc_oneOf(group: "eq") + "Match if field is not equal to provided value." + ne: Boolean @fdc_oneOf(group: "ne") + """ + Match if field does not match the result of the provided expression. + """ + ne_expr: Boolean_Expr @fdc_oneOf(group: "ne") + "Match if field value is among the provided list of values." + in: [Boolean!] + "Match if field value is not among the provided list of values." + nin: [Boolean!] +} + +"Query filter criteria for `[Boolean!]` scalar fields." +input Boolean_ListFilter { + "Match if list field contains the provided value as a member." + includes: Boolean + "Match if list field does not contain the provided value as a member." + excludes: Boolean + "Match if list field contains all of the provided values as members." + includesAll: [Boolean!] + "Match if list field does not contain any of the provided values as members." + excludesAll: [Boolean!] +} + +"Query filter criteria for `Any` scalar fields." +input Any_Filter { + "When true, match if field `IS NULL`. When false, match if field is `NOT NULL`." + isNull: Boolean + "Match if field is exactly equal to provided value." + eq: Any @fdc_oneOf(group: "eq") + """ + Match if field is exactly equal to the result of the provided server value + expression. + """ + eq_expr: Any_Expr @fdc_oneOf(group: "eq") + "Match if field is not equal to provided value." + ne: Any @fdc_oneOf(group: "ne") + """ + Match if field is not equal to the result of the provided server value + expression. + """ + ne_expr: Any_Expr @fdc_oneOf(group: "ne") + "Match if field value is among the provided list of values." + in: [Any!] + "Match if field value is not among the provided list of values." + nin: [Any!] +} + +"Query filter criteria for `[Any!]` scalar fields." +input Any_ListFilter { + "Match if list field contains the provided value as a member." + includes: Any + "Match if list field does not contain the provided value as a member." + excludes: Any + "Match if list field contains all of the provided values as members." + includesAll: [Any!] + "Match if list field does not contain any of the provided values as members." + excludesAll: [Any!] +} + +"Conditions on a `Date` value." +input Date_Filter { + "Match if the field `IS NULL`." + isNull: Boolean + "Match if the field is exactly equal to the provided value." + eq: Date @fdc_oneOf(group: "eq") + "Match if the field equals the provided CEL expression." + eq_expr: Date_Expr @fdc_oneOf(group: "eq") + "Match if the field equals the provided relative date." + eq_date: Date_Relative @fdc_oneOf(group: "eq") + "Match if the field is not equal to the provided value." + ne: Date @fdc_oneOf(group: "ne") + "Match if the field is not equal to the provided CEL expression." + ne_expr: Date_Expr @fdc_oneOf(group: "ne") + "Match if the field is not equal to the provided relative date." + ne_date: Date_Relative @fdc_oneOf(group: "ne") + "Match if the field value is among the provided list of values." + in: [Date!] + "Match if the field value is not among the provided list of values." + nin: [Date!] + "Match if the field value is greater than the provided value." + gt: Date @fdc_oneOf(group: "gt") + "Match if the field value is greater than the provided CEL expression." + gt_expr: Date_Expr @fdc_oneOf(group: "gt") + "Match if the field value is greater than the provided relative date." + gt_date: Date_Relative @fdc_oneOf(group: "gt") + "Match if the field value is greater than or equal to the provided value." + ge: Date @fdc_oneOf(group: "ge") + "Match if the field value is greater than or equal to the provided CEL expression." + ge_expr: Date_Expr @fdc_oneOf(group: "ge") + "Match if the field value is greater than or equal to the provided relative date." + ge_date: Date_Relative @fdc_oneOf(group: "ge") + "Match if the field value is less than the provided value." + lt: Date @fdc_oneOf(group: "lt") + "Match if the field value is less than the provided CEL expression." + lt_expr: Date_Expr @fdc_oneOf(group: "lt") + "Match if the field value is less than the provided relative date." + lt_date: Date_Relative @fdc_oneOf(group: "lt") + "Match if the field value is less than or equal to the provided value." + le: Date @fdc_oneOf(group: "le") + "Match if the field value is less than or equal to the provided CEL expression." + le_expr: Date_Expr @fdc_oneOf(group: "le") + "Match if the field value is less than or equal to the provided relative date." + le_date: Date_Relative @fdc_oneOf(group: "le") +} + +"Conditions on a`Date` list." +input Date_ListFilter { + "Match if the list contains the provided date." + includes: Date @fdc_oneOf(group: "includes") + "Match if the list contains the provided date CEL expression." + includes_expr: Date_Expr @fdc_oneOf(group: "includes") + "Match if the list contains the provided relative date." + includes_date: Date_Relative @fdc_oneOf(group: "includes") + "Match if the list does not contain the provided date." + excludes: Date @fdc_oneOf(group: "excludes") + "Match if the list does not contain the provided date CEL expression." + excludes_expr: Date_Expr @fdc_oneOf(group: "excludes") + "Match if the list does not contain the provided relative date." + excludes_date: Date_Relative @fdc_oneOf(group: "excludes") + "Match if the list contains all the provided dates." + includesAll: [Date!] + "Match if the list contains none of the provided dates." + excludesAll: [Date!] +} + +"Conditions on a `Timestamp` value." +input Timestamp_Filter { + "Match if the field `IS NULL`." + isNull: Boolean + "Match if the field is exactly equal to the provided value." + eq: Timestamp @fdc_oneOf(group: "eq") + "Match if the field equals the provided CEL expression." + eq_expr: Timestamp_Expr @fdc_oneOf(group: "eq") + "Match if the field equals the provided relative time." + eq_time: Timestamp_Relative @fdc_oneOf(group: "eq") + "Match if the field is not equal to the provided value." + ne: Timestamp @fdc_oneOf(group: "ne") + "Match if the field is not equal to the provided CEL expression." + ne_expr: Timestamp_Expr @fdc_oneOf(group: "ne") + "Match if the field is not equal to the provided relative time." + ne_time: Timestamp_Relative @fdc_oneOf(group: "ne") + "Match if the field value is among the provided list of values." + in: [Timestamp!] + "Match if the field value is not among the provided list of values." + nin: [Timestamp!] + "Match if the field value is greater than the provided value." + gt: Timestamp @fdc_oneOf(group: "gt") + "Match if the field value is greater than the provided CEL expression." + gt_expr: Timestamp_Expr @fdc_oneOf(group: "gt") + "Match if the field value is greater than the provided relative time." + gt_time: Timestamp_Relative @fdc_oneOf(group: "gt") + "Match if the field value is greater than or equal to the provided value." + ge: Timestamp @fdc_oneOf(group: "ge") + "Match if the field value is greater than or equal to the provided CEL expression." + ge_expr: Timestamp_Expr @fdc_oneOf(group: "ge") + "Match if the field value is greater than or equal to the provided relative time." + ge_time: Timestamp_Relative @fdc_oneOf(group: "ge") + "Match if the field value is less than the provided value." + lt: Timestamp @fdc_oneOf(group: "lt") + "Match if the field value is less than the provided CEL expression." + lt_expr: Timestamp_Expr @fdc_oneOf(group: "lt") + "Match if the field value is less than the provided relative time." + lt_time: Timestamp_Relative @fdc_oneOf(group: "lt") + "Match if the field value is less than or equal to the provided value." + le: Timestamp @fdc_oneOf(group: "le") + "Match if the field value is less than or equal to the provided CEL expression." + le_expr: Timestamp_Expr @fdc_oneOf(group: "le") + "Match if the field value is less than or equal to the provided relative time." + le_time: Timestamp_Relative @fdc_oneOf(group: "le") +} + +"Conditions on a `Timestamp` list." +input Timestamp_ListFilter { + "Match if the list contains the provided timestamp." + includes: Timestamp @fdc_oneOf(group: "includes") + "Match if the list contains the provided timestamp CEL expression." + includes_expr: Timestamp_Expr @fdc_oneOf(group: "includes") + "Match if the list contains the provided relative timestamp." + includes_time: Timestamp_Relative @fdc_oneOf(group: "includes") + "Match if the list does not contain the provided timestamp." + excludes: Timestamp @fdc_oneOf(group: "excludes") + "Match if the list does not contain the provided timestamp CEL expression." + excludes_expr: Timestamp_Expr @fdc_oneOf(group: "excludes") + "Match if the list does not contain the provided relative timestamp." + excludes_time: Timestamp_Relative @fdc_oneOf(group: "excludes") + "Match if the list contains all the provided timestamps." + includesAll: [Timestamp!] + "Match if the list contains none of the provided timestamps." + excludesAll: [Timestamp!] +} + +""" +Put on a `String` field to include it in the full-text search index. + +###### Example + +```graphql +type Post @table { + title: String @searchable + body: String @searchable +} +``` + +```graphql +query SearchPosts($query: String!) @auth(level: PUBLIC) { + posts_search(query: $query) { + id title body + } +} +``` + +""" +directive @searchable( + """ + Language of the string column to be indexed for full-text search. + (e.g. "french", "spanish", etc.) + Defaults to "english" if not specified. + """ + language: String = "english") on FIELD_DEFINITION + +extend type _Metadata { + """ + Only set for entities returned from a full text search. + The `ts_rank` relevance score of the row compared to the search query. + + You can use it to tune `relevanceThreshold`. + """ + relevance: Float +} + + +enum Search_QueryFormat @fdc_forbiddenAsFieldType { + """ + Allows search engine style semantics (e.g. quoted strings, AND and OR). + """ + QUERY, + """ + Splits the query into words and does ANDs between them. + """ + PLAIN, + """ + Matches an exact phrase. Requires the words to be in the same order (i.e. "brown + dog" will not match "brown and red dog"). + """ + PHRASE, + """ + Create complex queries using the full set of tsquery operators. + """ + ADVANCED, +} + +""" +(Internal) A string that uniquely identifies a type, field, and so on. + +The most common usage in FDC is `SomeType` or `SomeType.someField`. See the +linked page in the @specifiedBy directive for the GraphQL RFC with more details. +""" +scalar SchemaCoordinate + @specifiedBy(url: "https://github.com/graphql/graphql-wg/blob/6d02705dea034fb65ebc6799632adb7bd550d0aa/rfcs/SchemaCoordinates.md") + @fdc_forbiddenAsFieldType + @fdc_forbiddenAsVariableType + +"(Internal) The purpose of a generated type or field." +enum GeneratedPurpose @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + # Implicit fields added to the table types as columns. + IMPLICIT_KEY_FIELD + IMPLICIT_REF_FIELD + + # Generated static fields extended to table types. + METADATA_FIELD + + # Relational non-column fields extended to table types. + QUERY_MULTIPLE_ONE_TO_MANY + QUERY_MULTIPLE_MANY_TO_MANY + + # Generated fields for aggregates + QUERY_COUNT + QUERY_SUM + QUERY_AVG + QUERY_MIN + QUERY_MAX + + # Generated field for full text search + QUERY_MULTIPLE_BY_FULL_TEXT_SEARCH + + # Top-level Query fields. + QUERY_SINGLE + QUERY_MULTIPLE + QUERY_MULTIPLE_BY_SIMILARITY + + # Top-level Mutation fields. + INSERT_SINGLE + INSERT_MULTIPLE + UPSERT_SINGLE + UPSERT_MULTIPLE + UPDATE_SINGLE + UPDATE_MULTIPLE + DELETE_SINGLE + DELETE_MULTIPLE +} + +"(Internal) Added to definitions generated by FDC." +directive @fdc_generated( + "The source type or field that causes this definition to be generated." + from: SchemaCoordinate + "The reason why this definition is generated, such as the intended use case." + purpose: GeneratedPurpose! +) on + | SCALAR + | OBJECT + | FIELD_DEFINITION + | ARGUMENT_DEFINITION + | INTERFACE + | UNION + | ENUM + | ENUM_VALUE + | INPUT_OBJECT + | INPUT_FIELD_DEFINITION + +type _Service { + "Full Service Definition Language of the Frebase Data Connect Schema, including normalized schema, predefined and generated types." + sdl( + """ + Whether or not to omit Data Connect builtin GraphQL preludes. + They are static GraphQL publically available in the docsite. + """ + omitBuiltin: Boolean = false + """ + Whether or not to omit GQL description in the SDL. + We generate description to document generated schema. + It may bloat the size of SDL. + """ + omitDescription: Boolean = false + ): String! + "All GraphQL Schema Sources in the service." + schema: String! + "GraphQL Schema Sources in the service for each schema_id." + schemas: [_Schema!]! + "Generated documentation from the schema of the Firebase Data Connect Service." + docs: [_Doc!]! +} + +type _Schema { + """ + The schema id of the schema. + The `main` schema can define SQL `@table` and `@view` based by Cloud SQL PostgreSQL. + Other schemas are secondary schemas backed by GraphQL services in Cloud Run. + """ + id: String! + "The GraphQL Schema in this particular schema." + source: String! +} + +type _Doc { + "Name of the Doc Page." + page: String! + "The markdown content of the doc page." + markdown: String! +} + +"(Internal) Added to scalars representing quoted CEL expressions." +directive @fdc_celExpression( + "The expected CEL type that the expression should evaluate to." + returnType: String +) on SCALAR + +"(Internal) Added to scalars representing quoted SQL expressions." +directive @fdc_sqlExpression( + "The expected SQL type that the expression should evaluate to." + dataType: String +) on SCALAR + +"(Internal) Added to types that may not be used as variables." +directive @fdc_forbiddenAsVariableType on SCALAR | OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT + +"(Internal) Added to input field definitions that may not be present when used as variables." +directive @fdc_forbiddenInVariables on INPUT_FIELD_DEFINITION + +"(Internal) Added to types that may not be used as fields in schema." +directive @fdc_forbiddenAsFieldType on SCALAR | OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT + +"Provides a frequently used example for this type / field / argument." +directive @fdc_example( + "A GraphQL literal value (verbatim) whose type matches the target." + value: Any + "A human-readable text description of what `value` means in this context." + description: String +) repeatable on SCALAR | OBJECT | FIELD_DEFINITION | ARGUMENT_DEFINITION | INTERFACE | UNION | ENUM | INPUT_OBJECT | INPUT_FIELD_DEFINITION + +"(Internal) Marks this field / argument as conflicting with others in the same group." +directive @fdc_oneOf( + "The group name where fields / arguments conflict with each other." + group: String! = "" + "If true, exactly one field / argument in the group must be specified." + required: Boolean! = false +) repeatable on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION + +""" +The `_Metadata` type is used to return metadata about a field in a response. +""" +type _Metadata { + # During vector similarity search, the distance between the query vector and + # this row's vector. In other cases, this field is not set. + distance: Float +} + +""" +**SQL_Query**: A scalar representing a PostgreSQL SQL Data Query Language (DQL) statement. + +To guard against SQL injection, the SQL statement must be a **string literal** embedded directly within the GraphQL operation. It **cannot** be provided as a GraphQL variable. + +**Constraints:** + +* Only Data Query Language (DQL) statements (e.g., `SELECT`, `TABLE`) are permitted. +* Data Definition Language (DDL) statements (e.g., `CREATE`, `ALTER`, `DROP`) are **not** allowed. +* Data Manipulation Language (DML) statements (e.g., `INSERT`, `UPDATE`, `DELETE`) are **not** allowed. +""" +scalar SQL_Query + @fdc_sqlExpression + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "SELECT id, content FROM items WHERE id = $1", description: "Select items by ID.") + @fdc_example(value: "TABLE items", description: "Select all from items.") + +""" +**SQL_Mutation**: A scalar representing a PostgreSQL SQL Data Manipulation Language (DML) statement. + +To guard against SQL injection, the SQL statement must be a **string literal** embedded directly within the GraphQL operation. It **cannot** be provided as a GraphQL variable. + +**Constraints:** + +* Only Data Manipulation Language (DML) statements (e.g., `INSERT`, `UPDATE`, `DELETE`) are permitted. +* Data Definition Language (DDL) statements (e.g., `CREATE`, `ALTER`, `DROP`) are **not** allowed. +""" +scalar SQL_Mutation + @fdc_sqlExpression + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "UPDATE my_table SET status = $1 WHERE id = $2", description: "Update status by ID.") + @fdc_example(value: "INSERT INTO new_table (col1, col2) VALUES ($1, $2) RETURNING *", description: "Insert and return all columns.") + +""" +A list of values to bind to the `$1`, `$2`, etc. placeholders in the SQL statement, in order. +""" +scalar SQL_Params + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: ["user123", "active"], description: "List of values for $1, $2, etc.") + +extend type Query { + """ + Executes a SQL statement expected to return zero or more rows. + Intended for read-only operations (e.g., SELECT, TABLE). + Deploy-time checks will warn against DML statements in this field. + + **Usage:** + + ```graphql + query GetRestaurantStats { + _select( + sql: "SELECT id, column from my_table WHERE user_id = $1 AND status = $2", + params: [{_expr: "auth.uid"}, "active"] + ) + } + ``` + + **Returns:** A JSON array of objects. The structure is derived from the `SELECT` statement's columns. + """ + _select( + """ + The SQL DQL statement to execute. This must be a **string literal** defined directly in the GraphQL operation. Use `$1`, `$2`, etc. as placeholders for values provided in the `params` argument. + """ + sql: SQL_Query!, + """ + A list of values to bind to the `$1`, `$2`, etc. placeholders in the `sql`, in order. Values can also be expressions using `_expr` (e.g., `{_expr: "auth.uid"}`) to inject dynamic values. + """ + params: SQL_Params + ): [Any] + + """ + Executes a SQL statement expected to return exactly one row. + Returns null if no row is returned. + Intended for read-only operations. + Deploy-time checks will warn against DML statements in this field. + + **Usage:** + + ```graphql + query MyCustomSelect { + _selectFirst( + sql: "SELECT id, column from my_table WHERE user_id = $1 LIMIT 1", + params: [{_expr: "auth.uid"}] + ) + } + ``` + + **Returns:** A single JSON object or `null`. The structure is derived from the `SELECT` statement's columns. + """ + _selectFirst( + """ + The SQL DQL statement to execute. This must be a **string literal** defined directly in the GraphQL operation. Use `$1`, `$2`, etc. as placeholders for values provided in the `params` argument. + """ + sql: SQL_Query!, + """ + A list of values to bind to the `$1`, `$2`, etc. placeholders in the `sql`, in order. Values can also be expressions using `_expr` (e.g., `{_expr: "auth.uid"}`) to inject dynamic values. + """ + params: SQL_Params + ): Any +} + +extend type Mutation { + """ + Executes a SQL statement, potentially with side effects, expected to return zero or more rows. + Useful for DML statements with a RETURNING clause (e.g., INSERT/UPDATE/DELETE ... RETURNING *). + + **Usage:** + + ```graphql + mutation MyCustomInsert { + _executeReturning( + sql: "INSERT INTO new_table (col1, col2) VALUES ($1, $2) RETURNING *", + params: ["value1", 456] + ) + } + ``` + + **Returns:** A JSON array of objects, where each object represents a row from the `RETURNING` clause. + """ + _executeReturning( + """ + The SQL statement to execute. This must be a **string literal** defined directly in the GraphQL operation. Use `$1`, `$2`, etc. as placeholders for values provided in the `params` argument. + """ + sql: SQL_Mutation!, + """ + A list of values to bind to the `$1`, `$2`, etc. placeholders in the `sql`, in order. Values can also be expressions using `_expr` (e.g., `{_expr: "auth.uid"}`) to inject dynamic values. + """ + params: SQL_Params + ): [Any] + + """ + Executes a SQL statement, potentially with side effects, expected to return exactly one row. + Useful for DML statements on a single row with a RETURNING clause. + Returns null if no row is returned. + + **Usage:** + + ```graphql + mutation MyCustomUpdate { + _executeReturningFirst( + sql: "UPDATE my_table SET status = $1 WHERE id = $2 AND user_id = $3 RETURNING *", + params: ["inactive", 123, {_expr: "auth.uid"}] + ) + } + ``` + + **Returns:** A single JSON object or `null`, representing a row from the `RETURNING` clause. + """ + _executeReturningFirst( + """ + The SQL DML statement with a `RETURNING *` clause. This must be a **string literal** defined directly in the GraphQL operation. Use `$1`, `$2`, etc. as placeholders for values provided in the `params` argument. + """ + sql: SQL_Mutation!, + """ + A list of values to bind to the `$1`, `$2`, etc. placeholders in the `sql`, in order. Values can also be expressions using `_expr` (e.g., `{_expr: "auth.uid"}`) to inject dynamic values. + """ + params: SQL_Params + ): Any + + """ + Executes a SQL DML statement (e.g., INSERT, UPDATE, DELETE) where the primary result is the number of affected rows. + RETURNING clauses in the SQL will be ignored in the output of this field. + + **Usage:** + + ```graphql + mutation MyCustomExecute { + _execute( + sql: "DELETE FROM my_table WHERE id = $1", + params: [123] + ) + } + ``` + + **Returns:** The number of rows affected. + """ + _execute( + """ + The SQL statement to execute. This must be a **string literal** defined directly in the GraphQL operation. Use `$1`, `$2`, etc. as placeholders for values provided in the `params` argument. + """ + sql: SQL_Mutation!, + """ + A list of values to bind to the `$1`, `$2`, etc. placeholders in the `sql`, in order. Values can also be expressions using `_expr` (e.g., `{_expr: "auth.uid"}`) to inject dynamic values. + """ + params: SQL_Params + ): Int +} + +type Mutation { + """ + Run a query during the mutation and add fields into the response. + + Example: foo: query { users { id } } will add a field foo: {users: [{id: "..."}, …]} into the response JSON. + + Note: Data fetched this way can be handy for permission checks. See @check. + """ + query: Query +} + +""" +`UUID` is a string of hexadecimal digits representing an RFC4122-compliant UUID. + +UUIDs are always output as 32 lowercase hexadecimal digits without delimiters or +curly braces. +Inputs in the following formats are also accepted (case insensitive): + +- `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` +- `urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` +- `{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}` + +In the PostgreSQL table, it's stored as [`uuid`](https://www.postgresql.org/docs/current/datatype-uuid.html). +""" +scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122") + +""" +`Int64` is a scalar that represents a 64-bit signed integer. + +In the PostgreSQL table, it's stored as [`bigint`](https://www.postgresql.org/docs/current/datatype-numeric.html). + +On the wire, it's encoded as string because 64-bit integer exceeds the range of JSON number. +""" +scalar Int64 + +""" +The `Any` scalar type accommodates any valid [JSON value](https://www.json.org/json-en.html) +(e.g., numbers, strings, booleans, arrays, objects). PostgreSQL efficiently +stores this data as jsonb, providing flexibility for schemas with evolving structures. + +Caution: JSON doesn't distinguish Int and Float. + +##### Example: + +#### Schema + +```graphql +type Movie @table { + name: String! + metadata: Any! +} +``` + +#### Mutation + +Insert a movie with name and metadata from JSON literal. + +```graphql +mutation InsertMovie { + movie_insert( + data: { + name: "The Dark Knight" + metadata: { + release_year: 2008 + genre: ["Action", "Adventure", "Superhero"] + cast: [ + { name: "Christopher Bale", age: 31 } + { name: "Heath Ledger", age: 28 } + ] + director: "Christopher Nolan" + } + } + ) +} +``` + +Insert a movie with name and metadata that's constructed from a few GQL variables. + +```graphql +mutation InsertMovie($name: String!, $releaseDate: Date!, $genre: [String], $cast: [Any], $director: String!, $boxOfficeInUSD: Int) { + movie_insert(data: { + name: $name, + release_date: $releaseDate, + genre: $genre, + cast: $cast, + director: $director, + box_office: $boxOfficeInUSD + }) +} +``` +**Note**: + + - A mix of non-null and nullable variables can be provided. + + - `Date!` can be passed into scalar `Any` as well! It's stored as string. + + - `$cast` is a nested array. `[Any]` can represent an array of arbitrary types, but it won't enforce the input shape. + +#### Query + +Since `metadata` field has scalar `Any` type, it would return the full JSON in the response. + +**Note**: You can't define selection set to scalar based on [GraphQL spec](https://spec.graphql.org/October2021/#sec-Field-Selections). + +```graphql +query GetAllMovies { + movies { + name + metadata + } +} +``` + +""" +scalar Any @specifiedBy(url: "https://www.json.org/json-en.html") + +""" +The `Void` scalar type represents the absence of any value. It is typically used +in operations where no value is expected in return. +""" +scalar Void @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType + +""" +The `True` scalar type only accepts the boolean value `true`. + +An optional field/argument typed as `True` may either be set +to `true` or omitted (not provided at all). The values `false` or `null` are not +accepted. +""" +scalar True + @fdc_forbiddenAsFieldType + @fdc_forbiddenAsVariableType + @fdc_example(value: true, description: "The only allowed value.") + +""" +Date is a string in the YYYY-MM-DD format representing a local-only date. + +See the description for Timestamp for range and limitations. + +As a FDC-specific extension, inputs that includes time portions (as specified by +the Timestamp scalar) are accepted but only the date portion is used. In other +words, only the part before "T" is used and the rest discarded. This effectively +truncates it to the local date in the specified time-zone. + +Outputs will always be in the canonical YYYY-MM-DD format. + +In the PostgreSQL table, it's stored as [`date`](https://www.postgresql.org/docs/current/datatype-datetime.html). +""" +scalar Date @specifiedBy(url: "https://scalars.graphql.org/andimarek/local-date.html") + +""" +Timestamp is a RFC 3339 string that represents an exact point in time. + +The serialization format follows https://scalars.graphql.org/andimarek/date-time +except the "Non-optional exact milliseconds" Section. As a FDC-specific +extension, inputs and outputs may contain 0, 3, 6, or 9 fractional digits. + +Specifically, output precision varies by server-side factors such as data source +support and clients must not rely on an exact number of digits. Clients may +truncate extra digits as fit, with the caveat that there may be information loss +if the truncated value is subsequently sent back to the server. + +FDC only supports year 1583 to 9999 (inclusive) and uses the ISO-8601 calendar +system for all date-time calculations. Notably, the expanded year representation +(+/-YYYYY) is rejected and Year 1582 and before may either be rejected or cause +undefined behavior. + +In the PostgreSQL table, it's stored as [`timestamptz`](https://www.postgresql.org/docs/current/datatype-datetime.html). +""" +scalar Timestamp @specifiedBy(url: "https://scalars.graphql.org/andimarek/date-time") + + +""" +A Common Expression Language (CEL) expression that returns a boolean at runtime. + +This expression can reference the `auth` variable, which is null when Firebase +Auth is not used. When Firebase Auth is used, the following fields are available: + + - `auth.uid`: The current user ID. + - `auth.token`: A map containing all token fields (e.g., claims). + +""" +scalar Boolean_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "bool") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "auth != null", description: "Allow only if a Firebase Auth user is present.") + +""" +A Common Expression Language (CEL) expression that returns a string at runtime. + +**Limitation**: Currently, only a limited set of expressions are supported. +""" +scalar String_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "string") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "auth.uid", description: "The ID of the currently logged in user in Firebase Auth. (Errors if not logged in.)") + @fdc_example(value: "uuidV4()", description: "Generates a new random UUID (version 4) string, formatted as 32 lower-case hex digits without delimiters.") + +""" +A Common Expression Language (CEL) expression that returns a UUID string at runtime. + +**Limitation**: Currently, only a limited set of expressions are supported. +""" +scalar UUID_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "string") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "uuidV4()", description: "Generates a new random UUID (version 4) every time.") + +""" +A Common Expression Language (CEL) expression that returns a Int at runtime. +""" +scalar Int_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "int") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "2 * 4", description: "Evaluates to 8.") + @fdc_example(value: "vars.foo.size()", description: "Assuming `vars.foo` is a string, it will evaluate to the length of the string.") + + +""" +A Common Expression Language (CEL) expression that returns a Int64 at runtime. +""" +scalar Int64_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "int64") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "5000*1000*1000", description: "Evaluates to 5e9.") + +""" +A Common Expression Language (CEL) expression that returns a Float at runtime. +""" +scalar Float_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "float") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "2.0 * 4.0", description: "Evaluates to 8.0.") + +""" +A Common Expression Language (CEL) expression whose return type is valid JSON. + +Examples: + - `{'A' : 'B'}` (Evaluates to a JSON object.) + - `['A', 'B']` (Evaluates to a JSON array.) + - `{'A' 1, 'B': [1, 2, {'foo': 'bar'}]}` (Nested JSON objects and arrays.) +""" +scalar Any_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + +""" +A PostgreSQL value expression whose return type is unspecified. +""" +scalar Any_SQL + @specifiedBy(url: "https://www.postgresql.org/docs/current/sql-expressions.html") + @fdc_sqlExpression + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + +""" +A Common Expression Language (CEL) expression that returns a Timestamp at runtime. + +Limitation: Right now, only a few expressions are supported. +""" +scalar Timestamp_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "google.protobuf.Timestamp") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "request.time", description: "The timestamp when the request is received (with microseconds precision).") + +""" +A Common Expression Language (CEL) expression that returns a Timestamp at runtime, +which is then truncated to UTC date only. The time-of-day parts are discarded. + +Limitation: Right now, only a few expressions are supported. +""" +scalar Date_Expr + @specifiedBy(url: "https://github.com/google/cel-spec") + @fdc_celExpression(returnType: "google.protobuf.Timestamp") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "request.time", description: "The UTC date on which the request is received.") + + +""" +Defines a relational database table. + +In this example, we defined one table with a field named `myField`. + +```graphql +type TableName @table { + myField: String +} +``` +Data Connect adds an implicit `id` primary key column. So the above schema is equivalent to: + +```graphql +type TableName @table(key: "id") { + id: String @default(expr: "uuidV4()") + myField: String +} +``` + +Data Connect generates the following SQL table and CRUD operations to use it. + +```sql +CREATE TABLE "public"."table_name" ( + "id" uuid NOT NULL DEFAULT uuid_generate_v4(), + "my_field" text NULL, + PRIMARY KEY ("id") +) +``` + + * You can lookup a row: `query ($id: UUID!) { tableName(id: $id) { myField } } ` + * You can find rows using: `query tableNames(limit: 20) { myField }` + * You can insert a row: `mutation { tableName_insert(data: {myField: "foo"}) }` + * You can update a row: `mutation ($id: UUID!) { tableName_update(id: $id, data: {myField: "bar"}) }` + * You can delete a row: `mutation ($id: UUID!) { tableName_delete(id: $id) }` + +##### Customizations + +- `@table(singular)` and `@table(plural)` can customize the singular and plural name. +- `@table(name)` can customize the Postgres table name. +- `@table(key)` can customize the primary key field name and type. + +For example, the `User` table often has a `uid` as its primary key. + +```graphql +type User @table(key: "uid") { + uid: String! + name: String +} +``` + + * You can securely lookup a row: `query { user(key: {uid_expr: "auth.uid"}) { name } } ` + * You can securely insert a row: `mutation { user_insert(data: {uid_expr: "auth.uid" name: "Fred"}) }` + * You can securely update a row: `mutation { user_update(key: {uid_expr: "auth.uid"}, data: {name: "New Name"}) }` + * You can securely delete a row: `mutation { user_delete(key: {uid_expr: "auth.uid"}) }` + +`@table` type can be configured further with: + + - Custom SQL data types for columns. See `@col`. + - Add SQL indexes. See `@index`. + - Add SQL unique constraints. See `@unique`. + - Add foreign key constraints to define relations. See `@ref`. + +""" +directive @table( + """ + Configures the SQL database table name. Defaults to snake_case like `table_name`. + """ + name: String + """ + Configures the singular name. Defaults to the camelCase like `tableName`. + """ + singular: String + """ + Configures the plural name. Defaults to infer based on English plural pattern like `tableNames`. + """ + plural: String + """ + Defines the primary key of the table. Defaults to a single field named `id`. + If not present already, Data Connect adds an implicit field `id: UUID! @default(expr: "uuidV4()")`. + """ + key: [String!] +) on OBJECT + +""" +Defines a relational database SQL view. + +Data Connect generates GraphQL queries with WHERE and ORDER BY clauses. +However, not all SQL features have a native GraphQL equivalent. + +With `@view`, you can write **arbitrary SQL SELECT statements** and Data Connect +maps GraphQL fields on `@view` type to columns in your SELECT statement. + +* Scalar GQL fields (camelCase) should match SQL columns (snake_case) + in the SQL SELECT statement. +* Reference GQL field can point to another `@table` type. Similar to foreign key + defined with `@ref` on a `@table` type, a `@view` type establishes a relation + when `@ref(fields)` match `@ref(references)` on the target table. + +In this example, you can use `@view(sql)` to define an aggregation view on existing +table. + +```graphql +type User @table { + name: String + score: Int +} +type UserAggregation @view(sql: ''' + SELECT + COUNT(*) as count, + SUM(score) as sum, + AVG(score) as average, + PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY score) AS median, + (SELECT id FROM "user" LIMIT 1) as example_id + FROM "user" +''') { + count: Int + sum: Int + average: Float + median: Float + example: User + exampleId: UUID +} +``` + +###### Example: Query SQL View + +```graphql +query { + userAggregations { + count sum average median + exampleId example { id } + } +} +``` + +##### One-to-One View + +An one-to-one companion `@view` can be handy if you want to argument a `@table` +with additional implied content. + +```graphql +type Restaurant @table { + name: String! +} +type Review @table { + restaurant: Restaurant! + rating: Int! +} +type RestaurantStats @view(sql: ''' + SELECT + restaurant_id, + COUNT(*) AS review_count, + AVG(rating) AS average_rating + FROM review + GROUP BY restaurant_id +''') { + restaurant: Restaurant @unique + reviewCount: Int + averageRating: Float +} +``` + +In this example, `@unique` convey the assumption that each `Restaurant` should +have only one `RestaurantStats` object. + +###### Example: Query One-to-One View + +```graphql +query ListRestaurants { + restaurants { + name + stats: restaurantStats_on_restaurant { + reviewCount + averageRating + } + } +} +``` + +###### Example: Filter based on One-to-One View + +```graphql +query BestRestaurants($minAvgRating: Float, $minReviewCount: Int) { + restaurants(where: { + restaurantStats_on_restaurant: { + averageRating: {ge: $minAvgRating} + reviewCount: {ge: $minReviewCount} + } + }) { name } +} +``` + +##### Customizations + +- One of `@view(sql)` or `@view(name)` should be defined. + `@view(name)` can refer to a persisted SQL view in the Postgres schema. +- `@view(singular)` and `@view(plural)` can customize the singular and plural name. + +`@view` type can be configured further: + + - `@unique` lets you define one-to-one relation. + - `@col` lets you customize SQL column mapping. For example, `@col(name: "column_in_select")`. + +##### Limitations + +SQL views doesn't have a primary key, so they don't support lookup. Other +`@table` or `@view` cannot have `@ref` to a view either. + +A view cannot be mutated. You can perform CRUD operations on the underlying +table to alter its content. + +**Important: Data Connect doesn't parse and validate SQL** + +- If the SQL view is invalid or undefined, related requests may fail. +- If the SQL view return incompatible types. Firebase Data Connect may surface + errors. +- If a field doesn't have a corresponding column in the SQL SELECT statement, + it will always be `null`. +- There is no way to ensure VIEW to TABLE `@ref` constraint. +- All fields must be nullable in case they aren't found in the SELECT statement + or in the referenced table. + +**Important: You should always test `@view`!** + +""" +directive @view( + """ + The SQL view name. If neither `name` nor `sql` are provided, defaults to the + snake_case of the singular type name. + `name` and `sql` cannot be specified at the same time. + """ + name: String @fdc_oneOf + """ + SQL `SELECT` statement used as the basis for this type. + SQL SELECT columns should use snake_case. GraphQL fields should use camelCase. + `name` and `sql` cannot be specified at the same time. + """ + sql: String @fdc_oneOf + """ + Configures the singular name. Defaults to the camelCase like `viewName`. + """ + singular: String + """ + Configures the plural name. Defaults to infer based on English plural pattern like `viewNames`. + """ + plural: String +) on OBJECT + +""" +Customizes a field that represents a SQL database table column. + +Data Connect maps scalar Fields on `@table` type to a SQL column of +corresponding data type. + +- scalar `UUID` maps to [`uuid`](https://www.postgresql.org/docs/current/datatype-uuid.html). +- scalar `String` maps to [`text`](https://www.postgresql.org/docs/current/datatype-character.html). +- scalar `Int` maps to [`int`](https://www.postgresql.org/docs/current/datatype-numeric.html). +- scalar `Int64` maps to [`bigint`](https://www.postgresql.org/docs/current/datatype-numeric.html). +- scalar `Float` maps to [`double precision`](https://www.postgresql.org/docs/current/datatype-numeric.html). +- scalar `Boolean` maps to [`boolean`](https://www.postgresql.org/docs/current/datatype-boolean.html). +- scalar `Date` maps to [`date`](https://www.postgresql.org/docs/current/datatype-datetime.html). +- scalar `Timestamp` maps to [`timestamptz`](https://www.postgresql.org/docs/current/datatype-datetime.html). +- scalar `Any` maps to [`jsonb`](https://www.postgresql.org/docs/current/datatype-json.html). +- scalar `Vector` maps to [`pgvector`](https://github.com/pgvector/pgvector). + +Array scalar fields are mapped to [Postgres arrays](https://www.postgresql.org/docs/current/arrays.html). + +###### Example: Serial Primary Key + +For example, you can define auto-increment primary key. + +```graphql +type Post @table { + id: Int! @col(name: "post_id", dataType: "serial") +} +``` + +Data Connect converts it to the following SQL table schema. + +```sql +CREATE TABLE "public"."post" ( + "post_id" serial NOT NULL, + PRIMARY KEY ("id") +) +``` + +###### Example: Vector + +```graphql +type Post @table { + content: String! @col(name: "post_content") + contentEmbedding: Vector! @col(size:768) +} +``` + +""" +directive @col( + """ + The SQL database column name. Defaults to snake_case of the field name. + """ + name: String + """ + Configures the custom SQL data type. + + Each GraphQL type can map to multiple SQL data types. + Refer to [Postgres supported data types](https://www.postgresql.org/docs/current/datatype.html). + + Incompatible SQL data type will lead to undefined behavior. + """ + dataType: String + """ + Required on `Vector` columns. It specifies the length of the Vector. + `textembedding-gecko@003` model generates `Vector` of `@col(size:768)`. + """ + size: Int +) on FIELD_DEFINITION + + +""" +Defines a foreign key reference to another table. + +For example, we can define a many-to-one relation. + +```graphql +type ManyTable @table { + refField: OneTable! +} +type OneTable @table { + someField: String! +} +``` +Data Connect adds implicit foreign key column and relation query field. So the +above schema is equivalent to the following schema. + +```graphql +type ManyTable @table { + id: UUID! @default(expr: "uuidV4()") + refField: OneTable! @ref(fields: "refFieldId", references: "id") + refFieldId: UUID! +} +type OneTable @table { + id: UUID! @default(expr: "uuidV4()") + someField: UUID! + # Generated Fields: + # manyTables_on_refField: [ManyTable!]! +} +``` +Data Connect generates the necessary foreign key constraint. + +```sql +CREATE TABLE "public"."many_table" ( + "id" uuid NOT NULL DEFAULT uuid_generate_v4(), + "ref_field_id" uuid NOT NULL, + PRIMARY KEY ("id"), + CONSTRAINT "many_table_ref_field_id_fkey" FOREIGN KEY ("ref_field_id") REFERENCES "public"."one_table" ("id") ON DELETE CASCADE +) +``` + +###### Example: Traverse the Reference Field + +```graphql +query ($id: UUID!) { + manyTable(id: $id) { + refField { id } + } +} +``` + +###### Example: Reverse Traverse the Reference field + +```graphql +query ($id: UUID!) { + oneTable(id: $id) { + manyTables_on_refField { id } + } +} +``` + +##### Optional Many-to-One Relation + +An optional foreign key reference will be set to null if the referenced row is deleted. + +In this example, if a `User` is deleted, the `assignee` and `reporter` +references will be set to null. + +```graphql +type Bug @table { + title: String! + assignee: User + reproter: User +} + +type User @table { name: String! } +``` + +##### Required Many-to-One Relation + +A required foreign key reference will cascade delete if the referenced row is +deleted. + +In this example, if a `Post` is deleted, associated comments will also be +deleted. + +```graphql +type Comment @table { + post: Post! + content: String! +} + +type Post @table { title: String! } +``` + +##### Many To Many Relation + +You can define a many-to-many relation with a join table. + +```graphql +type Membership @table(key: ["group", "user"]) { + group: Group! + user: User! + role: String! @default(value: "member") +} + +type Group @table { name: String! } +type User @table { name: String! } +``` + +When Data Connect sees a table with two reference field as its primary key, it +knows this is a join table, so expands the many-to-many query field. + +```graphql +type Group @table { + name: String! + # Generated Fields: + # users_via_Membership: [User!]! + # memberships_on_group: [Membership!]! +} +type User @table { + name: String! + # Generated Fields: + # groups_via_Membership: [Group!]! + # memberships_on_user: [Membership!]! +} +``` + +###### Example: Traverse the Many-To-Many Relation + +```graphql +query ($id: UUID!) { + group(id: $id) { + users: users_via_Membership { + name + } + } +} +``` + +###### Example: Traverse to the Join Table + +```graphql +query ($id: UUID!) { + group(id: $id) { + memberships: memberships_on_group { + user { name } + role + } + } +} +``` + +##### One To One Relation + +You can even define a one-to-one relation with the help of `@unique` or `@table(key)`. + +```graphql +type User @table { + name: String +} +type Account @table { + user: User! @unique +} +# Alternatively, use primary key constraint. +# type Account @table(key: "user") { +# user: User! +# } +``` + +###### Example: Transerse the Reference Field + +```graphql +query ($id: UUID!) { + account(id: $id) { + user { id } + } +} +``` + +###### Example: Reverse Traverse the Reference field + +```graphql +query ($id: UUID!) { + user(id: $id) { + account_on_user { id } + } +} +``` + +##### Customizations + +- `@ref(constraintName)` can customize the SQL foreign key constraint name (`table_name_ref_field_fkey` above). +- `@ref(fields)` can customize the foreign key field names. +- `@ref(references)` can customize the constraint to reference other columns. + By default, `@ref(references)` is the primary key of the `@ref` table. + Other fields with `@unique` may also be referred in the foreign key constraint. + +""" +directive @ref( + "The SQL database foreign key constraint name. Defaults to snake_case `{table_name}_{field_name}_fkey`." + constraintName: String + """ + Foreign key fields. Defaults to `{tableName}{PrimaryIdName}`. + """ + fields: [String!] + "The fields that the foreign key references in the other table. Defaults to its primary key." + references: [String!] +) on FIELD_DEFINITION + +"Defines the orderBy direction in a query." +enum OrderDirection @fdc_forbiddenAsFieldType { +"Results are ordered in ascending order." + ASC +"Results are ordered in descending order." + DESC +} + +""" +Specifies the default value for a column field. + +For example: + +```graphql +type User @table(key: "uid") { + uid: String! @default(expr: "auth.uid") + number: Int! @col(dataType: "serial") + createdAt: Date! @default(expr: "request.time") + role: String! @default(value: "Member") + credit: Int! @default(value: 100) +} +``` + +The supported arguments vary based on the field type. +""" +directive @default( + "A constant value validated against the field's GraphQL type during compilation." + value: Any @fdc_oneOf(required: true) + "A CEL expression whose return value must match the field's data type." + expr: Any_Expr @fdc_oneOf(required: true) + """ + An SQL expression, whose SQL data type must match the underlying column. + + The value is any variable-free expression (in particular, cross-references to + other columns in the current table are not allowed). Subqueries are not allowed either. + See [PostgreSQL defaults](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-PARMS-DEFAULT) + for more details. + """ + sql: Any_SQL @fdc_oneOf(required: true) +) on FIELD_DEFINITION + +""" +Defines a database index to optimize query performance. + +```graphql +type User @table @index(fields: ["name", "phoneNumber"], order: [ASC, DESC]) { + name: String @index + phoneNumber: Int64 @index + tags: [String] @index # GIN Index +} +``` + +##### Single Field Index + +You can put `@index` on a `@col` field to create a SQL index. + +`@index(order)` matters little for single field indexes, as they can be scanned +in both directions. + +##### Composite Index + +You can put `@index(fields: [...])` on `@table` type to define composite indexes. + +`@index(order: [...])` can customize the index order to satisfy particular +filter and order requirement. + +""" +directive @index( + """ + Configure the SQL database index id. + + If not overridden, Data Connect generates the index name: + - `{table_name}_{first_field}_{second_field}_aa_idx` + - `{table_name}_{field_name}_idx` + """ + name: String + """ + Only allowed and required when used on a `@table` type. + Specifies the fields to create the index on. + """ + fields: [String!] + """ + Only allowed for `BTREE` `@index` on `@table` type. + Specifies the order for each indexed column. Defaults to all `ASC`. + """ + order: [IndexFieldOrder!] + """ + Customize the index type. + + For most index, it defaults to `BTREE`. + For array fields, only allowed `IndexType` is `GIN`. + For `Vector` fields, defaults to `HNSW`, may configure to `IVFFLAT`. + """ + type: IndexType + """ + Only allowed when used on vector field. + Defines the vector similarity method. Defaults to `INNER_PRODUCT`. + """ + vector_method: VectorSimilarityMethod +) repeatable on FIELD_DEFINITION | OBJECT + +"Specifies the sorting order for database indexes." +enum IndexFieldOrder @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + "Sorts the field in ascending order (from lowest to highest)." + ASC + "Sorts the field in descending order (from highest to lowest)." + DESC +} + +"Defines the type of index to be used in the database." +enum IndexType @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + "A general-purpose index type commonly used for sorting and searching." + BTREE + "Generalized Inverted Index, optimized for indexing composite values such as arrays." + GIN + "Hierarchical Navigable Small World graph, used for nearest-neighbor searches on vector fields." + HNSW + "Inverted File Index, optimized for approximate nearest-neighbor searches in vector databases." + IVFFLAT +} + +""" +Defines unique constraints on `@table`. + +For example, + +```graphql +type User @table { + phoneNumber: Int64 @unique +} +type UserProfile @table { + user: User! @unique + address: String @unique +} +``` + +- `@unique` on a `@col` field adds a single-column unique constraint. +- `@unique` on a `@table` type adds a composite unique constraint. +- `@unique` on a `@ref` defines a one-to-one relation. It adds unique constraint + on `@ref(fields)`. + +`@unique` ensures those fields can uniquely identify a row, so other `@table` +type may define `@ref(references)` to refer to fields that has a unique constraint. + +""" +directive @unique( + """ + Configures the SQL database unique constraint name. + + If not overridden, Data Connect generates the unique constraint name: + - `table_name_first_field_second_field_uidx` + - `table_name_only_field_name_uidx` + """ + indexName: String + """ + Only allowed and required when used on OBJECT, + this specifies the fields to create a unique constraint on. + """ + fields: [String!] +) repeatable on FIELD_DEFINITION | OBJECT + +"A runtime-calculated `Timestamp` value relative to `now` or `at`." +input Timestamp_Relative @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + "Match for the current time." + now: True @fdc_oneOf(group: "from", required: true) + "A specific timestamp for matching." + at: Timestamp @fdc_oneOf(group: "from", required: true) + "Add the provided duration to the base timestamp." + add: Timestamp_Duration + "Subtract the provided duration from the base timestamp." + sub: Timestamp_Duration + "Truncate the timestamp to the provided interval." + truncateTo: Timestamp_Interval +} + +input Timestamp_Duration @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + "The number of milliseconds for the duration." + milliseconds: Int! = 0 + "The number of seconds for the duration." + seconds: Int! = 0 + "The number of minutes for the duration." + minutes: Int! = 0 + "The number of hours for the duration." + hours: Int! = 0 + "The number of days for the duration." + days: Int! = 0 + "The number of weeks for the duration." + weeks: Int! = 0 + "The number of months for the duration." + months: Int! = 0 + "The number of years for the duration." + years: Int! = 0 +} + +enum Timestamp_Interval @fdc_forbiddenAsFieldType { + "Represents a time interval of one second." + SECOND + "Represents a time interval of one minute." + MINUTE + "Represents a time interval of one hour." + HOUR + "Represents a time interval of one day." + DAY + "Represents a time interval of one week." + WEEK + "Represents a time interval of one month." + MONTH + "Represents a time interval of one year." + YEAR +} + +"A runtime-calculated Date value relative to `today` or `on`." +input Date_Relative @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + "Match for today’s date." + today: True @fdc_oneOf(group: "from", required: true) + "A specific date for matching." + on: Date @fdc_oneOf(group: "from", required: true) + "Add the provided duration to the base date." + add: Date_Duration + "Subtract the provided duration from the base date." + sub: Date_Duration + "Truncate the date to the provided interval." + truncateTo: Date_Interval +} + +input Date_Duration @fdc_forbiddenAsVariableType @fdc_forbiddenAsFieldType { + "The number of days for the duration." + days: Int! = 0 + "The number of weeks for the duration." + weeks: Int! = 0 + "The number of months for the duration." + months: Int! = 0 + "The number of years for the duration." + years: Int! = 0 +} + +enum Date_Interval @fdc_forbiddenAsFieldType { + "Represents a time interval of one week." + WEEK + "Represents a time interval of one month." + MONTH + "Represents a time interval of one year." + YEAR +} + +"Update input of a `String` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input String_ListUpdate { + "Append the provided values to the existing list." + append: [String!] @fdc_oneOf + "Prepend the provided values to the existing list." + prepend: [String!] @fdc_oneOf + "Append values that do not already exist to the list." + add: [String!] @fdc_oneOf + "Remove all occurrences of each value from the list." + remove: [String!] @fdc_oneOf +} + +"Update input of an `ID` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input UUID_ListUpdate { + "Append the provided UUIDs to the existing list." + append: [UUID!] @fdc_oneOf + "Prepend the provided UUIDs to the existing list." + prepend: [UUID!] @fdc_oneOf + "Append values that do not already exist to the list." + add: [UUID!] @fdc_oneOf + "Remove all occurrences of each value from the list." + remove: [UUID!] @fdc_oneOf +} + +"Update input of an `Int` value. Only one of `inc` or `dec` may be specified." +input Int_Update { + "Increment the field by a provided value." + inc: Int @fdc_oneOf + "Decrement the field by a provided value." + dec: Int @fdc_oneOf +} + +"Update input of an `Int` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input Int_ListUpdate { + "Append the provided list of values to the existing list." + append: [Int!] @fdc_oneOf + "Prepend the provided list of values to the existing list." + prepend: [Int!] @fdc_oneOf + "Append values that do not already exist to the list." + add: [Int!] @fdc_oneOf + "Remove all occurrences of each value from the list." + remove: [Int!] @fdc_oneOf +} + +"Update input of an `Int64` value. Only one of `inc` or `dec` may be specified." +input Int64_Update { + "Increment the field by a provided value." + inc: Int64 @fdc_oneOf + "Decrement the field by a provided value." + dec: Int64 @fdc_oneOf +} + +"Update input of an `Int64` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input Int64_ListUpdate { + "Append the provided list of values to the existing list." + append: [Int64!] @fdc_oneOf + "Prepend the provided list of values to the existing list." + prepend: [Int64!] @fdc_oneOf + "Append values that do not already exist to the list." + add: [Int64!] @fdc_oneOf + "Remove all occurrences of each value from the list." + remove: [Int64!] @fdc_oneOf +} + +"Update input of a `Float` value. Only one of `inc` or `dec` may be specified." +input Float_Update { + "Increment the field by a provided value." + inc: Float @fdc_oneOf + "Decrement the field by a provided value." + dec: Float @fdc_oneOf +} + +"Update input of a `Float` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input Float_ListUpdate { + "Append the provided list of values to the existing list." + append: [Float!] @fdc_oneOf + "Prepend the provided list of values to the existing list." + prepend: [Float!] @fdc_oneOf + "Append values that do not already exist to the list." + add: [Float!] @fdc_oneOf + "Remove all occurrences of each value from the list." + remove: [Float!] @fdc_oneOf +} + +"Update input of a `Boolean` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input Boolean_ListUpdate { + "Append the provided list of values to the existing list." + append: [Boolean!] @fdc_oneOf + "Prepend the provided list of values to the existing list." + prepend: [Boolean!] @fdc_oneOf + "Append values that do not already exist to the list." + add: [Boolean!] @fdc_oneOf + "Remove all occurrences of each value from the list." + remove: [Boolean!] @fdc_oneOf +} + +"Update input of an `Any` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input Any_ListUpdate { + "Append the provided list of values to the existing list." + append: [Any!] @fdc_oneOf + "Prepend the provided list of values to the existing list." + prepend: [Any!] @fdc_oneOf + "Append values that do not already exist to the list." + add: [Any!] @fdc_oneOf + "Remove all occurrences of each value from the list." + remove: [Any!] @fdc_oneOf +} + +"Update input of a `Date` value. Only one of `inc` or `dec` may be specified." +input Date_Update { + "Increment the field by a provided duration." + inc: Date_Duration @fdc_oneOf + "Decrement the field by a provided duration." + dec: Date_Duration @fdc_oneOf +} + +"Update input of a `Date` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input Date_ListUpdate { + "Append the provided `Date` values to the existing list." + append: [Date!] @fdc_oneOf + "Prepend the provided `Date` values to the existing list." + prepend: [Date!] @fdc_oneOf + "Append any `Date` values that do not already exist to the list." + add: [Date!] @fdc_oneOf + "Remove all occurrences of each `Date` from the list." + remove: [Date!] @fdc_oneOf +} + +"Update input of a `Timestamp` value. Only one of `inc` or `dec` may be specified." +input Timestamp_Update { + "Increment the field by a provided duration." + inc: Timestamp_Duration @fdc_oneOf + "Decrement the field by a provided duration." + dec: Timestamp_Duration @fdc_oneOf +} + +"Update input of an `Timestamp` list value. Only one of `append`, `prepend`, `add`, or `remove` may be specified." +input Timestamp_ListUpdate { + "Append the provided `Timestamp` values to the existing list." + append: [Timestamp!] @fdc_oneOf + "Prepend the provided `Timestamp` values to the existing list." + prepend: [Timestamp!] @fdc_oneOf + "Append any `Timestamp` values that do not already exist to the list." + add: [Timestamp!] @fdc_oneOf + "Remove all occurrences of each `Timestamp` from the list." + remove: [Timestamp!] @fdc_oneOf +} + +type Query { + """ + _service provides customized introspection on Firebase Data Connect Sevice. + """ + _service: _Service! +} + +""" +Vector is an array of single-precision floating-point numbers, serialized +as a JSON array. All elements must be finite (no NaN, Infinity or -Infinity). + +Example: [1.1, 2, 3.3] + +In the PostgreSQL table, it's stored as [`pgvector`](https://github.com/pgvector/pgvector). + +See `Vector_Embed` for how to generate text embeddings in query and mutations. +""" +scalar Vector + +""" +Defines the similarity function to use when comparing vectors in queries. + +Defaults to `INNER_PRODUCT`. + +View [all vector functions](https://github.com/pgvector/pgvector?tab=readme-ov-file#vector-functions). +""" +enum VectorSimilarityMethod @fdc_forbiddenAsFieldType { + "Measures the Euclidean (L2) distance between two vectors." + L2 + "Measures the cosine similarity between two vectors." + COSINE + "Measures the inner product(dot product) between two vectors." + INNER_PRODUCT +} + +"Conditions on a Vector value." +input Vector_Filter { + "Match if the field is exactly equal to the provided vector." + eq: Vector + "Match if the field is not equal to the provided vector." + ne: Vector + "Match if the field value is among the provided list of vectors." + in: [Vector!] + "Match if the field value is not among the provided list of vectors." + nin: [Vector!] + "Match if the field is `NULL`." + isNull: Boolean +} + +input Vector_ListFilter { + "Match if the list includes the supplied vector." + includes: Vector + "Match if the list does not include the supplied vector." + excludes: Vector + "Match if the list contains all the provided vectors." + includesAll: [Vector!] + "Match if the list contains none of the provided vectors." + excludesAll: [Vector!] +} + +""" +Create a vector embedding of text using the given model on Vertex AI. + +Cloud SQL for Postgresql natively integrates with [Vertex AI Text embeddings API](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text-embeddings-api) +to effectively generate text embeddings. + +If you uses [`Vector`](scalar.md#Vector) in your schema, Firebase Data Connect automatically installs +[`pgvector`](https://github.com/pgvector/pgvector) and [`google_ml_integration`](https://cloud.google.com/sql/docs/postgres/integrate-cloud-sql-with-vertex-ai) +Postgres extensions in your Cloud SQL database. + +Given a Post table with a `Vector` embedding field. + +```graphql +type Post @table { + content: String! + contentEmbedding: Vector @col(size:768) +} +``` + +NOTE: All natively supported `Vector_Embed_Model` generates vector of length `768`. + +###### Example: Insert embedding + +```graphql +mutation CreatePost($content: String!) { + post_insert(data: { + content: $content, + contentEmbedding_embed: {model: "textembedding-gecko@003", text: $content}, + }) +} +``` + +###### Example: Vector similarity Search + +```graphql +query SearchPost($query: String!) { + posts_contentEmbedding_similarity(compare_embed: {model: "textembedding-gecko@003", text: $query}) { + id + content + } +} +``` +""" +input Vector_Embed @fdc_forbiddenAsVariableType { + """ + The model to use for vector embedding. + Recommend the latest stable model: `textembedding-gecko@003`. + """ + model: Vector_Embed_Model! + "The text to generate the vector embedding from." + text: String! +} + +""" +The Vertex AI model version that is required in input `Vector_Embed`. + +It is recommended to use the latest stable model version: `textembedding-gecko@003`. + +View all supported [Vertex AI Text embeddings APIs](https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/text-embeddings-api). +""" +scalar Vector_Embed_Model + @specifiedBy(url: "https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versioning") + @fdc_forbiddenAsVariableType + @fdc_forbiddenAsFieldType + @fdc_example(value: "textembedding-gecko@003", description: "A stable version of the textembedding-gecko model") + @fdc_example(value: "textembedding-gecko@001", description: "An older version of the textembedding-gecko model") + @fdc_example(value: "text-embedding-004", description: "Another text embedding model") + +# Intentionally left blank. + diff --git a/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart index 1ea81e9e0aa3..bae5432a6b96 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart @@ -14,6 +14,7 @@ import 'generation_e2e.dart'; import 'instance_e2e.dart'; import 'listen_e2e.dart'; import 'query_e2e.dart'; +import 'websocket_e2e.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -27,8 +28,8 @@ void main() { final connector = MoviesConnector.connectorConfig; FirebaseDataConnect.instanceFor(connectorConfig: connector) - .useDataConnectEmulator('localhost', 9399); - await FirebaseAuth.instance.useAuthEmulator('localhost', 9099); + .useDataConnectEmulator('127.0.0.1', 9399); + await FirebaseAuth.instance.useAuthEmulator('127.0.0.1', 9099); await FirebaseAuth.instance.createUserWithEmailAndPassword( email: 'test@mail.com', password: 'password'); @@ -38,5 +39,6 @@ void main() { runQueryTests(); runGenerationTest(); runListenTests(); + runWebSocketTests(); }); } diff --git a/packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart new file mode 100644 index 000000000000..930c7d4da0c2 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart @@ -0,0 +1,223 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:async'; + +import 'package:firebase_data_connect/firebase_data_connect.dart'; +import 'package:firebase_data_connect_example/generated/movies.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'query_e2e.dart'; // For deleteAllMovies + +void runWebSocketTests() { + group( + '$FirebaseDataConnect WebSocketTransport', + () { + setUp(() async { + await deleteAllMovies(); + }); + + testWidgets('should support multiplexing multiple subscriptions', + (WidgetTester tester) async { + final Completer ready1 = Completer(); + final Completer ready2 = Completer(); + final Completer update1 = Completer(); + final Completer update2 = Completer(); + + int count1 = 0; + int count2 = 0; + + final sub1 = MoviesConnector.instance + .listMoviesByPartialTitle(input: 'Matrix') + .ref() + .subscribe() + .listen((value) { + if (count1 == 0) { + ready1.complete(); + } else { + update1.complete(); + } + count1++; + }); + + final sub2 = MoviesConnector.instance + .listMoviesByPartialTitle(input: 'Titan') + .ref() + .subscribe() + .listen((value) { + if (count2 == 0) { + ready2.complete(); + } else { + update2.complete(); + } + count2++; + }); + + // Wait for both to be ready + await ready1.future; + await ready2.future; + + // Create movies + await MoviesConnector.instance + .createMovie( + genre: 'Action', + title: 'The Matrix', + releaseYear: 1999, + ) + .rating(4.5) + .ref() + .execute(); + + await MoviesConnector.instance + .createMovie( + genre: 'Drama', + title: 'Titanic', + releaseYear: 1997, + ) + .rating(4.8) + .ref() + .execute(); + + // Wait for updates + await update1.future; + await update2.future; + + await sub1.cancel(); + await sub2.cancel(); + }); + + testWidgets( + 'should support unary operations over WebSocket when connected', + (WidgetTester tester) async { + final Completer isReady = Completer(); + int count = 0; + + // Start a subscription to ensure WebSocket is connected + final sub = MoviesConnector.instance + .listMovies() + .ref() + .subscribe() + .listen((value) { + if (count == 0) { + isReady.complete(); + } + count++; + }); + + await isReady.future; + + // Now perform a query, which should go over WebSocket if connected + final result = + await MoviesConnector.instance.listMovies().ref().execute(); + expect(result.data.movies.length, 0); + + // Perform a mutation + await MoviesConnector.instance + .createMovie( + genre: 'Action', + title: 'Inception', + releaseYear: 2010, + ) + .rating(4.9) + .ref() + .execute(); + + // Verify update via query + final result2 = + await MoviesConnector.instance.listMovies().ref().execute(); + expect(result2.data.movies.length, 1); + expect(result2.data.movies[0].title, 'Inception'); + + await sub.cancel(); + }); + + testWidgets('should stop receiving events after cancel', + (WidgetTester tester) async { + final Completer isReady = Completer(); + final Completer receivedUpdate = Completer(); + int count = 0; + + final sub = MoviesConnector.instance + .listMovies() + .ref() + .subscribe() + .listen((value) { + if (count == 0) { + isReady.complete(); + } else { + receivedUpdate.complete(); + } + count++; + }); + + await isReady.future; + + // Cancel the subscription + await sub.cancel(); + + // Create a movie + await MoviesConnector.instance + .createMovie( + genre: 'Action', + title: 'Avatar', + releaseYear: 2009, + ) + .rating(4.7) + .ref() + .execute(); + + // Wait a bit to ensure no event is received + bool received = true; + try { + await receivedUpdate.future.timeout(const Duration(seconds: 2)); + } on TimeoutException { + received = false; + } + expect(received, isFalse, + reason: 'Should not receive events after cancel'); + }); + + testWidgets( + 'should disconnect the websocket channel when all subscriptions are closed', + (WidgetTester tester) async { + final Completer isReady = Completer(); + int count = 0; + + final sub = MoviesConnector.instance + .listMovies() + .ref() + .subscribe() + .listen((value) { + if (count == 0) { + isReady.complete(); + } + count++; + }); + + await isReady.future; + + final dataConnect = MoviesConnector.instance.dataConnect; + final transport = (dataConnect as dynamic).transport; + final ws = (transport as dynamic).websocket; + + expect(ws.isConnected, isTrue); + + // Cancel the subscription + await sub.cancel(); + + expect(ws.isConnected, isFalse); + }); + }, + ); +} diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/config.json b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/config.json new file mode 100644 index 000000000000..e37ed06f8a66 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/config.json @@ -0,0 +1,9 @@ +{ + "description": "A set of guides for interacting with the generated firebase dataconnect sdk", + "mcpServers": { + "firebase": { + "command": "npx", + "args": ["-y", "firebase-tools@latest", "experimental:mcp"] + } + } +} diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/setup.md b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/setup.md new file mode 100644 index 000000000000..4a3737fe81bf --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/setup.md @@ -0,0 +1,15 @@ +# Setup + +This guide will walk you through setting up your environment to use the Firebase Data Connect SDK. Mostly using +documentation listed [here](https://firebase.google.com/docs/flutter/setup?platform=ios#install-cli-tools). + +1. Make sure you have the latest Firebase CLI tools installed. Follow the instructions [here](https://firebase.google.com/docs/cli#setup_update_cli) to install. +2. Log into your Firebase account: +```sh +firebase login +``` +3. Install the FlutterFire CLI by running the following command from any directory: +```sh +dart pub global activate flutterfire_cli +``` +4. Make sure the user has initialized Firebase already based on the instructions [here](https://firebase.google.com/docs/flutter/setup?platform=ios#initialize-firebase). diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/usage.md b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/usage.md new file mode 100644 index 000000000000..9006a3657ea6 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/.guides/usage.md @@ -0,0 +1,32 @@ +# Basic Usage + +```dart +MoviesConnector.instance.addPerson(addPersonVariables).execute(); +MoviesConnector.instance.addDirectorToMovie(addDirectorToMovieVariables).execute(); +MoviesConnector.instance.addTimestamp(addTimestampVariables).execute(); +MoviesConnector.instance.addDateAndTimestamp(addDateAndTimestampVariables).execute(); +MoviesConnector.instance.seedMovies().execute(); +MoviesConnector.instance.createMovie(createMovieVariables).execute(); +MoviesConnector.instance.deleteMovie(deleteMovieVariables).execute(); +MoviesConnector.instance.thing(thingVariables).execute(); +MoviesConnector.instance.seedData().execute(); +MoviesConnector.instance.ListMovies().execute(); + +``` + +## Optional Fields + +Some operations may have optional fields. In these cases, the Flutter SDK exposes a builder method, and will have to be set separately. + +Optional fields can be discovered based on classes that have `Optional` object types. + +This is an example of a mutation with an optional field: + +```dart +await MoviesConnector.instance.ListThing({ ... }) +.data(...) +.execute(); +``` + +Note: the above example is a mutation, but the same logic applies to query operations as well. Additionally, `createMovie` is an example, and may not be available to the user. + diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_date_and_timestamp.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_date_and_timestamp.dart index 8f221792ec16..8f7680ea851e 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_date_and_timestamp.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_date_and_timestamp.dart @@ -29,10 +29,27 @@ class AddDateAndTimestampVariablesBuilder { } } +@immutable class AddDateAndTimestampTimestampHolderInsert { - String id; + final String id; AddDateAndTimestampTimestampHolderInsert.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddDateAndTimestampTimestampHolderInsert otherTyped = + other as AddDateAndTimestampTimestampHolderInsert; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -45,12 +62,28 @@ class AddDateAndTimestampTimestampHolderInsert { }); } +@immutable class AddDateAndTimestampData { - AddDateAndTimestampTimestampHolderInsert timestampHolder_insert; + final AddDateAndTimestampTimestampHolderInsert timestampHolder_insert; AddDateAndTimestampData.fromJson(dynamic json) : timestampHolder_insert = AddDateAndTimestampTimestampHolderInsert.fromJson( json['timestampHolder_insert']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddDateAndTimestampData otherTyped = other as AddDateAndTimestampData; + return timestampHolder_insert == otherTyped.timestampHolder_insert; + } + + @override + int get hashCode => timestampHolder_insert.hashCode; Map toJson() { Map json = {}; @@ -63,14 +96,31 @@ class AddDateAndTimestampData { }); } +@immutable class AddDateAndTimestampVariables { - DateTime date; - Timestamp timestamp; + final DateTime date; + final Timestamp timestamp; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') AddDateAndTimestampVariables.fromJson(Map json) : date = nativeFromJson(json['date']), timestamp = Timestamp.fromJson(json['timestamp']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddDateAndTimestampVariables otherTyped = + other as AddDateAndTimestampVariables; + return date == otherTyped.date && timestamp == otherTyped.timestamp; + } + + @override + int get hashCode => Object.hashAll([date.hashCode, timestamp.hashCode]); Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_director_to_movie.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_director_to_movie.dart index f70b56719550..235d4c31ae78 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_director_to_movie.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_director_to_movie.dart @@ -39,12 +39,30 @@ class AddDirectorToMovieVariablesBuilder { } } +@immutable class AddDirectorToMovieDirectedByInsert { - String directedbyId; - String movieId; + final String directedbyId; + final String movieId; AddDirectorToMovieDirectedByInsert.fromJson(dynamic json) : directedbyId = nativeFromJson(json['directedbyId']), movieId = nativeFromJson(json['movieId']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddDirectorToMovieDirectedByInsert otherTyped = + other as AddDirectorToMovieDirectedByInsert; + return directedbyId == otherTyped.directedbyId && + movieId == otherTyped.movieId; + } + + @override + int get hashCode => Object.hashAll([directedbyId.hashCode, movieId.hashCode]); Map toJson() { Map json = {}; @@ -59,11 +77,27 @@ class AddDirectorToMovieDirectedByInsert { }); } +@immutable class AddDirectorToMovieData { - AddDirectorToMovieDirectedByInsert directedBy_insert; + final AddDirectorToMovieDirectedByInsert directedBy_insert; AddDirectorToMovieData.fromJson(dynamic json) : directedBy_insert = AddDirectorToMovieDirectedByInsert.fromJson( json['directedBy_insert']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddDirectorToMovieData otherTyped = other as AddDirectorToMovieData; + return directedBy_insert == otherTyped.directedBy_insert; + } + + @override + int get hashCode => directedBy_insert.hashCode; Map toJson() { Map json = {}; @@ -76,10 +110,27 @@ class AddDirectorToMovieData { }); } +@immutable class AddDirectorToMovieVariablesPersonId { - String id; + final String id; AddDirectorToMovieVariablesPersonId.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddDirectorToMovieVariablesPersonId otherTyped = + other as AddDirectorToMovieVariablesPersonId; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -92,9 +143,10 @@ class AddDirectorToMovieVariablesPersonId { }); } +@immutable class AddDirectorToMovieVariables { - late Optional personId; - late Optional movieId; + late final Optional personId; + late final Optional movieId; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') AddDirectorToMovieVariables.fromJson(Map json) { @@ -109,6 +161,22 @@ class AddDirectorToMovieVariables { ? null : nativeFromJson(json['movieId']); } + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddDirectorToMovieVariables otherTyped = + other as AddDirectorToMovieVariables; + return personId == otherTyped.personId && movieId == otherTyped.movieId; + } + + @override + int get hashCode => Object.hashAll([personId.hashCode, movieId.hashCode]); Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_person.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_person.dart index ecd924a47ba0..359cfb32768c 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_person.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_person.dart @@ -29,10 +29,26 @@ class AddPersonVariablesBuilder { } } +@immutable class AddPersonPersonInsert { - String id; + final String id; AddPersonPersonInsert.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddPersonPersonInsert otherTyped = other as AddPersonPersonInsert; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -45,10 +61,26 @@ class AddPersonPersonInsert { }); } +@immutable class AddPersonData { - AddPersonPersonInsert person_insert; + final AddPersonPersonInsert person_insert; AddPersonData.fromJson(dynamic json) : person_insert = AddPersonPersonInsert.fromJson(json['person_insert']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddPersonData otherTyped = other as AddPersonData; + return person_insert == otherTyped.person_insert; + } + + @override + int get hashCode => person_insert.hashCode; Map toJson() { Map json = {}; @@ -61,8 +93,9 @@ class AddPersonData { }); } +@immutable class AddPersonVariables { - late Optional name; + late final Optional name; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') AddPersonVariables.fromJson(Map json) { @@ -70,6 +103,21 @@ class AddPersonVariables { name.value = json['name'] == null ? null : nativeFromJson(json['name']); } + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddPersonVariables otherTyped = other as AddPersonVariables; + return name == otherTyped.name; + } + + @override + int get hashCode => name.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_timestamp.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_timestamp.dart index 67d2a26649b4..19ce28607185 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_timestamp.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/add_timestamp.dart @@ -25,10 +25,27 @@ class AddTimestampVariablesBuilder { } } +@immutable class AddTimestampTimestampHolderInsert { - String id; + final String id; AddTimestampTimestampHolderInsert.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddTimestampTimestampHolderInsert otherTyped = + other as AddTimestampTimestampHolderInsert; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -41,11 +58,27 @@ class AddTimestampTimestampHolderInsert { }); } +@immutable class AddTimestampData { - AddTimestampTimestampHolderInsert timestampHolder_insert; + final AddTimestampTimestampHolderInsert timestampHolder_insert; AddTimestampData.fromJson(dynamic json) : timestampHolder_insert = AddTimestampTimestampHolderInsert.fromJson( json['timestampHolder_insert']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddTimestampData otherTyped = other as AddTimestampData; + return timestampHolder_insert == otherTyped.timestampHolder_insert; + } + + @override + int get hashCode => timestampHolder_insert.hashCode; Map toJson() { Map json = {}; @@ -58,12 +91,28 @@ class AddTimestampData { }); } +@immutable class AddTimestampVariables { - Timestamp timestamp; + final Timestamp timestamp; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') AddTimestampVariables.fromJson(Map json) : timestamp = Timestamp.fromJson(json['timestamp']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final AddTimestampVariables otherTyped = other as AddTimestampVariables; + return timestamp == otherTyped.timestamp; + } + + @override + int get hashCode => timestamp.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/create_movie.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/create_movie.dart index 33d6cfcac2bd..14ba5ce8a7a0 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/create_movie.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/create_movie.dart @@ -46,10 +46,26 @@ class CreateMovieVariablesBuilder { } } +@immutable class CreateMovieMovieInsert { - String id; + final String id; CreateMovieMovieInsert.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final CreateMovieMovieInsert otherTyped = other as CreateMovieMovieInsert; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -62,10 +78,26 @@ class CreateMovieMovieInsert { }); } +@immutable class CreateMovieData { - CreateMovieMovieInsert movie_insert; + final CreateMovieMovieInsert movie_insert; CreateMovieData.fromJson(dynamic json) : movie_insert = CreateMovieMovieInsert.fromJson(json['movie_insert']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final CreateMovieData otherTyped = other as CreateMovieData; + return movie_insert == otherTyped.movie_insert; + } + + @override + int get hashCode => movie_insert.hashCode; Map toJson() { Map json = {}; @@ -78,12 +110,13 @@ class CreateMovieData { }); } +@immutable class CreateMovieVariables { - String title; - int releaseYear; - String genre; - late Optional rating; - late Optional description; + final String title; + final int releaseYear; + final String genre; + late final Optional rating; + late final Optional description; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') CreateMovieVariables.fromJson(Map json) @@ -99,6 +132,31 @@ class CreateMovieVariables { ? null : nativeFromJson(json['description']); } + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final CreateMovieVariables otherTyped = other as CreateMovieVariables; + return title == otherTyped.title && + releaseYear == otherTyped.releaseYear && + genre == otherTyped.genre && + rating == otherTyped.rating && + description == otherTyped.description; + } + + @override + int get hashCode => Object.hashAll([ + title.hashCode, + releaseYear.hashCode, + genre.hashCode, + rating.hashCode, + description.hashCode + ]); Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/delete_movie.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/delete_movie.dart index b5cfa8ecd3b1..9050d5c5d707 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/delete_movie.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/delete_movie.dart @@ -25,10 +25,26 @@ class DeleteMovieVariablesBuilder { } } +@immutable class DeleteMovieMovieDelete { - String id; + final String id; DeleteMovieMovieDelete.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final DeleteMovieMovieDelete otherTyped = other as DeleteMovieMovieDelete; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -41,12 +57,28 @@ class DeleteMovieMovieDelete { }); } +@immutable class DeleteMovieData { - DeleteMovieMovieDelete? movie_delete; + final DeleteMovieMovieDelete? movie_delete; DeleteMovieData.fromJson(dynamic json) : movie_delete = json['movie_delete'] == null ? null : DeleteMovieMovieDelete.fromJson(json['movie_delete']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final DeleteMovieData otherTyped = other as DeleteMovieData; + return movie_delete == otherTyped.movie_delete; + } + + @override + int get hashCode => movie_delete.hashCode; Map toJson() { Map json = {}; @@ -61,12 +93,28 @@ class DeleteMovieData { }); } +@immutable class DeleteMovieVariables { - String id; + final String id; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') DeleteMovieVariables.fromJson(Map json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final DeleteMovieVariables otherTyped = other as DeleteMovieVariables; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/get_movie.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/get_movie.dart index 5e09901aef92..4fe64439c88a 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/get_movie.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/get_movie.dart @@ -25,12 +25,28 @@ class GetMovieVariablesBuilder { } } +@immutable class GetMovieMovie { - String id; - String title; + final String id; + final String title; GetMovieMovie.fromJson(dynamic json) : id = nativeFromJson(json['id']), title = nativeFromJson(json['title']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final GetMovieMovie otherTyped = other as GetMovieMovie; + return id == otherTyped.id && title == otherTyped.title; + } + + @override + int get hashCode => Object.hashAll([id.hashCode, title.hashCode]); Map toJson() { Map json = {}; @@ -45,12 +61,28 @@ class GetMovieMovie { }); } +@immutable class GetMovieData { - GetMovieMovie? movie; + final GetMovieMovie? movie; GetMovieData.fromJson(dynamic json) : movie = json['movie'] == null ? null : GetMovieMovie.fromJson(json['movie']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final GetMovieData otherTyped = other as GetMovieData; + return movie == otherTyped.movie; + } + + @override + int get hashCode => movie.hashCode; Map toJson() { Map json = {}; @@ -65,10 +97,26 @@ class GetMovieData { }); } +@immutable class GetMovieVariablesKey { - String id; + final String id; GetMovieVariablesKey.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final GetMovieVariablesKey otherTyped = other as GetMovieVariablesKey; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -81,12 +129,28 @@ class GetMovieVariablesKey { }); } +@immutable class GetMovieVariables { - GetMovieVariablesKey key; + final GetMovieVariablesKey key; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') GetMovieVariables.fromJson(Map json) : key = GetMovieVariablesKey.fromJson(json['key']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final GetMovieVariables otherTyped = other as GetMovieVariables; + return key == otherTyped.key; + } + + @override + int get hashCode => key.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies.dart index 3647007b8328..7b9faaeb08dd 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies.dart @@ -18,11 +18,12 @@ class ListMoviesVariablesBuilder { } } +@immutable class ListMoviesMovies { - String id; - String title; - List directed_by; - double? rating; + final String id; + final String title; + final List directed_by; + final double? rating; ListMoviesMovies.fromJson(dynamic json) : id = nativeFromJson(json['id']), title = nativeFromJson(json['title']), @@ -32,6 +33,25 @@ class ListMoviesMovies { rating = json['rating'] == null ? null : nativeFromJson(json['rating']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListMoviesMovies otherTyped = other as ListMoviesMovies; + return id == otherTyped.id && + title == otherTyped.title && + directed_by == otherTyped.directed_by && + rating == otherTyped.rating; + } + + @override + int get hashCode => Object.hashAll( + [id.hashCode, title.hashCode, directed_by.hashCode, rating.hashCode]); Map toJson() { Map json = {}; @@ -52,10 +72,27 @@ class ListMoviesMovies { }); } +@immutable class ListMoviesMoviesDirectedBy { - String name; + final String name; ListMoviesMoviesDirectedBy.fromJson(dynamic json) : name = nativeFromJson(json['name']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListMoviesMoviesDirectedBy otherTyped = + other as ListMoviesMoviesDirectedBy; + return name == otherTyped.name; + } + + @override + int get hashCode => name.hashCode; Map toJson() { Map json = {}; @@ -68,12 +105,28 @@ class ListMoviesMoviesDirectedBy { }); } +@immutable class ListMoviesData { - List movies; + final List movies; ListMoviesData.fromJson(dynamic json) : movies = (json['movies'] as List) .map((e) => ListMoviesMovies.fromJson(e)) .toList(); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListMoviesData otherTyped = other as ListMoviesData; + return movies == otherTyped.movies; + } + + @override + int get hashCode => movies.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies_by_partial_title.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies_by_partial_title.dart index c4f013c77dc3..bc895bf95238 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies_by_partial_title.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_movies_by_partial_title.dart @@ -28,11 +28,12 @@ class ListMoviesByPartialTitleVariablesBuilder { } } +@immutable class ListMoviesByPartialTitleMovies { - String id; - String title; - String genre; - double? rating; + final String id; + final String title; + final String genre; + final double? rating; ListMoviesByPartialTitleMovies.fromJson(dynamic json) : id = nativeFromJson(json['id']), title = nativeFromJson(json['title']), @@ -40,6 +41,26 @@ class ListMoviesByPartialTitleMovies { rating = json['rating'] == null ? null : nativeFromJson(json['rating']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListMoviesByPartialTitleMovies otherTyped = + other as ListMoviesByPartialTitleMovies; + return id == otherTyped.id && + title == otherTyped.title && + genre == otherTyped.genre && + rating == otherTyped.rating; + } + + @override + int get hashCode => Object.hashAll( + [id.hashCode, title.hashCode, genre.hashCode, rating.hashCode]); Map toJson() { Map json = {}; @@ -60,12 +81,29 @@ class ListMoviesByPartialTitleMovies { }); } +@immutable class ListMoviesByPartialTitleData { - List movies; + final List movies; ListMoviesByPartialTitleData.fromJson(dynamic json) : movies = (json['movies'] as List) .map((e) => ListMoviesByPartialTitleMovies.fromJson(e)) .toList(); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListMoviesByPartialTitleData otherTyped = + other as ListMoviesByPartialTitleData; + return movies == otherTyped.movies; + } + + @override + int get hashCode => movies.hashCode; Map toJson() { Map json = {}; @@ -78,12 +116,29 @@ class ListMoviesByPartialTitleData { }); } +@immutable class ListMoviesByPartialTitleVariables { - String input; + final String input; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') ListMoviesByPartialTitleVariables.fromJson(Map json) : input = nativeFromJson(json['input']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListMoviesByPartialTitleVariables otherTyped = + other as ListMoviesByPartialTitleVariables; + return input == otherTyped.input; + } + + @override + int get hashCode => input.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_persons.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_persons.dart index 5bdb83d6f7f0..a8629c79585a 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_persons.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_persons.dart @@ -18,12 +18,28 @@ class ListPersonsVariablesBuilder { } } +@immutable class ListPersonsPeople { - String id; - String name; + final String id; + final String name; ListPersonsPeople.fromJson(dynamic json) : id = nativeFromJson(json['id']), name = nativeFromJson(json['name']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListPersonsPeople otherTyped = other as ListPersonsPeople; + return id == otherTyped.id && name == otherTyped.name; + } + + @override + int get hashCode => Object.hashAll([id.hashCode, name.hashCode]); Map toJson() { Map json = {}; @@ -38,12 +54,28 @@ class ListPersonsPeople { }); } +@immutable class ListPersonsData { - List people; + final List people; ListPersonsData.fromJson(dynamic json) : people = (json['people'] as List) .map((e) => ListPersonsPeople.fromJson(e)) .toList(); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListPersonsData otherTyped = other as ListPersonsData; + return people == otherTyped.people; + } + + @override + int get hashCode => people.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_thing.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_thing.dart index 4d6c7d6f1d5a..3f63233fae95 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_thing.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_thing.dart @@ -30,10 +30,26 @@ class ListThingVariablesBuilder { } } +@immutable class ListThingThings { - AnyValue title; + final AnyValue title; ListThingThings.fromJson(dynamic json) : title = AnyValue.fromJson(json['title']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListThingThings otherTyped = other as ListThingThings; + return title == otherTyped.title; + } + + @override + int get hashCode => title.hashCode; Map toJson() { Map json = {}; @@ -46,12 +62,28 @@ class ListThingThings { }); } +@immutable class ListThingData { - List things; + final List things; ListThingData.fromJson(dynamic json) : things = (json['things'] as List) .map((e) => ListThingThings.fromJson(e)) .toList(); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListThingData otherTyped = other as ListThingData; + return things == otherTyped.things; + } + + @override + int get hashCode => things.hashCode; Map toJson() { Map json = {}; @@ -64,14 +96,30 @@ class ListThingData { }); } +@immutable class ListThingVariables { - late Optional data; + late final Optional data; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') ListThingVariables.fromJson(Map json) { data = Optional.optional(AnyValue.fromJson, defaultSerializer); data.value = json['data'] == null ? null : AnyValue.fromJson(json['data']); } + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListThingVariables otherTyped = other as ListThingVariables; + return data == otherTyped.data; + } + + @override + int get hashCode => data.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_timestamps.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_timestamps.dart index 70bf3615d06f..f2b6b64ade80 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_timestamps.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/list_timestamps.dart @@ -18,14 +18,31 @@ class ListTimestampsVariablesBuilder { } } +@immutable class ListTimestampsTimestampHolders { - Timestamp timestamp; - DateTime? date; + final Timestamp timestamp; + final DateTime? date; ListTimestampsTimestampHolders.fromJson(dynamic json) : timestamp = Timestamp.fromJson(json['timestamp']), date = json['date'] == null ? null : nativeFromJson(json['date']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListTimestampsTimestampHolders otherTyped = + other as ListTimestampsTimestampHolders; + return timestamp == otherTyped.timestamp && date == otherTyped.date; + } + + @override + int get hashCode => Object.hashAll([timestamp.hashCode, date.hashCode]); Map toJson() { Map json = {}; @@ -42,12 +59,28 @@ class ListTimestampsTimestampHolders { }); } +@immutable class ListTimestampsData { - List timestampHolders; + final List timestampHolders; ListTimestampsData.fromJson(dynamic json) : timestampHolders = (json['timestampHolders'] as List) .map((e) => ListTimestampsTimestampHolders.fromJson(e)) .toList(); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ListTimestampsData otherTyped = other as ListTimestampsData; + return timestampHolders == otherTyped.timestampHolders; + } + + @override + int get hashCode => timestampHolders.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/movies.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/movies.dart index ef27424855d7..7ad7e907c59a 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/movies.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/movies.dart @@ -1,6 +1,7 @@ library movies; import 'package:firebase_data_connect/firebase_data_connect.dart'; +import 'package:flutter/foundation.dart'; import 'dart:convert'; part 'add_person.dart'; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_data.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_data.dart index 8efc6ed7863a..ac4ade4472e2 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_data.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_data.dart @@ -18,10 +18,26 @@ class SeedDataVariablesBuilder { } } +@immutable class SeedDataTheMatrix { - String id; + final String id; SeedDataTheMatrix.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final SeedDataTheMatrix otherTyped = other as SeedDataTheMatrix; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -34,10 +50,26 @@ class SeedDataTheMatrix { }); } +@immutable class SeedDataData { - SeedDataTheMatrix the_matrix; + final SeedDataTheMatrix the_matrix; SeedDataData.fromJson(dynamic json) : the_matrix = SeedDataTheMatrix.fromJson(json['the_matrix']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final SeedDataData otherTyped = other as SeedDataData; + return the_matrix == otherTyped.the_matrix; + } + + @override + int get hashCode => the_matrix.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_movies.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_movies.dart index 370d83681e44..2805c05d308e 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_movies.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/seed_movies.dart @@ -18,10 +18,26 @@ class SeedMoviesVariablesBuilder { } } +@immutable class SeedMoviesTheMatrix { - String id; + final String id; SeedMoviesTheMatrix.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final SeedMoviesTheMatrix otherTyped = other as SeedMoviesTheMatrix; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -34,10 +50,26 @@ class SeedMoviesTheMatrix { }); } +@immutable class SeedMoviesJurassicPark { - String id; + final String id; SeedMoviesJurassicPark.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final SeedMoviesJurassicPark otherTyped = other as SeedMoviesJurassicPark; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -50,12 +82,30 @@ class SeedMoviesJurassicPark { }); } +@immutable class SeedMoviesData { - SeedMoviesTheMatrix the_matrix; - SeedMoviesJurassicPark jurassic_park; + final SeedMoviesTheMatrix the_matrix; + final SeedMoviesJurassicPark jurassic_park; SeedMoviesData.fromJson(dynamic json) : the_matrix = SeedMoviesTheMatrix.fromJson(json['the_matrix']), jurassic_park = SeedMoviesJurassicPark.fromJson(json['jurassic_park']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final SeedMoviesData otherTyped = other as SeedMoviesData; + return the_matrix == otherTyped.the_matrix && + jurassic_park == otherTyped.jurassic_park; + } + + @override + int get hashCode => + Object.hashAll([the_matrix.hashCode, jurassic_park.hashCode]); Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/thing.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/thing.dart index 49230260b438..167d997a25e5 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/thing.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/generated/thing.dart @@ -30,9 +30,25 @@ class ThingVariablesBuilder { } } +@immutable class ThingAbc { - String id; + final String id; ThingAbc.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ThingAbc otherTyped = other as ThingAbc; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -45,9 +61,25 @@ class ThingAbc { }); } +@immutable class ThingDef { - String id; + final String id; ThingDef.fromJson(dynamic json) : id = nativeFromJson(json['id']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ThingDef otherTyped = other as ThingDef; + return id == otherTyped.id; + } + + @override + int get hashCode => id.hashCode; Map toJson() { Map json = {}; @@ -60,12 +92,28 @@ class ThingDef { }); } +@immutable class ThingData { - ThingAbc abc; - ThingDef def; + final ThingAbc abc; + final ThingDef def; ThingData.fromJson(dynamic json) : abc = ThingAbc.fromJson(json['abc']), def = ThingDef.fromJson(json['def']); + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ThingData otherTyped = other as ThingData; + return abc == otherTyped.abc && def == otherTyped.def; + } + + @override + int get hashCode => Object.hashAll([abc.hashCode, def.hashCode]); Map toJson() { Map json = {}; @@ -80,8 +128,9 @@ class ThingData { }); } +@immutable class ThingVariables { - late Optional title; + late final Optional title; @Deprecated( 'fromJson is deprecated for Variable classes as they are no longer required for deserialization.') ThingVariables.fromJson(Map json) { @@ -89,6 +138,21 @@ class ThingVariables { title.value = json['title'] == null ? null : AnyValue.fromJson(json['title']); } + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + if (other.runtimeType != runtimeType) { + return false; + } + + final ThingVariables otherTyped = other as ThingVariables; + return title == otherTyped.title; + } + + @override + int get hashCode => title.hashCode; Map toJson() { Map json = {}; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/macos/Podfile b/packages/firebase_data_connect/firebase_data_connect/example/macos/Podfile index c795730db8ed..b52666a10389 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/macos/Podfile +++ b/packages/firebase_data_connect/firebase_data_connect/example/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.14' +platform :osx, '10.15' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/project.pbxproj index ac658b11a81e..b8abb5878e44 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 5A0EBAC5CA5020E53D9F5FB9 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68259C80087E2CE600CA9E3E /* Pods_RunnerTests.framework */; }; + CDE09EBC5F87EFADA38F8F59 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F81E46173A5FB7C231B32AE1 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -76,8 +78,16 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 367BE93E3B25556D72E19BE6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 57638D81F785C506C897EA30 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 58F3E215A6EE6C70A757F8D4 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 603D07CF30CE7F11FFBF6764 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 68259C80087E2CE600CA9E3E /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 704B294FA8C9834EEDCCF961 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D093DBBD5E141E58AB2CE079 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F81E46173A5FB7C231B32AE1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 5A0EBAC5CA5020E53D9F5FB9 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +103,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CDE09EBC5F87EFADA38F8F59 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -125,6 +137,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + FB0AE6DB54A0C7F6C5B5F8B5 /* Pods */, ); sourceTree = ""; }; @@ -175,10 +188,26 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + F81E46173A5FB7C231B32AE1 /* Pods_Runner.framework */, + 68259C80087E2CE600CA9E3E /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; }; + FB0AE6DB54A0C7F6C5B5F8B5 /* Pods */ = { + isa = PBXGroup; + children = ( + 704B294FA8C9834EEDCCF961 /* Pods-Runner.debug.xcconfig */, + 367BE93E3B25556D72E19BE6 /* Pods-Runner.release.xcconfig */, + 603D07CF30CE7F11FFBF6764 /* Pods-Runner.profile.xcconfig */, + D093DBBD5E141E58AB2CE079 /* Pods-RunnerTests.debug.xcconfig */, + 57638D81F785C506C897EA30 /* Pods-RunnerTests.release.xcconfig */, + 58F3E215A6EE6C70A757F8D4 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -186,6 +215,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 30E7763C8BF85951A4034B2F /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -204,11 +234,14 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 92B2B246524EF31F3D357243 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 9D22A98DF478583AFE4C87D0 /* [CP] Embed Pods Frameworks */, + 7D0A7AE5F7B788418083225F /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -291,6 +324,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 30E7763C8BF85951A4034B2F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -329,6 +384,62 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 7D0A7AE5F7B788418083225F /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 92B2B246524EF31F3D357243 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9D22A98DF478583AFE4C87D0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -380,6 +491,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D093DBBD5E141E58AB2CE079 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -394,6 +506,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 57638D81F785C506C897EA30 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -408,6 +521,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 58F3E215A6EE6C70A757F8D4 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -461,7 +575,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -543,7 +657,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -593,7 +707,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 15368eccb25a..ac78810cdd2c 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -59,6 +59,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..21a3cc14c74e 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner/AppDelegate.swift b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner/AppDelegate.swift index d53ef6437726..b3c176141221 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner/AppDelegate.swift +++ b/packages/firebase_data_connect/firebase_data_connect/example/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } From 2711b616a3aa15ef1a17d4837d020522506c40f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 13:47:04 +0200 Subject: [PATCH 039/137] chore(deps): bump protobufjs in /.github/workflows/scripts/functions (#18217) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.4.0 to 7.5.5. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.5) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.5.5 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../workflows/scripts/functions/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index 8e9a4027cadb..cf5ca86aec07 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -1839,9 +1839,9 @@ } }, "node_modules/protobufjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", - "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz", + "integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -3850,9 +3850,9 @@ } }, "protobufjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", - "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz", + "integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", From 39e5a808f583fe96bb1bc901042c0a07d86e8c08 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Thu, 23 Apr 2026 13:49:21 -0700 Subject: [PATCH 040/137] chore(ci): nightly build and test setup (#18225) --- .github/workflows/nightly.yaml | 226 +++++++++++++++++ .../scripts/nightly_issue_dashboard.dart | 228 ++++++++++++++++++ 2 files changed, 454 insertions(+) create mode 100644 .github/workflows/nightly.yaml create mode 100644 .github/workflows/scripts/nightly_issue_dashboard.dart diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml new file mode 100644 index 000000000000..263cd65b2e39 --- /dev/null +++ b/.github/workflows/nightly.yaml @@ -0,0 +1,226 @@ +name: nightly-ci + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +on: + # schedule: + # - cron: '0 4 * * *' + workflow_dispatch: + +permissions: + contents: read + issues: write + +jobs: + pipeline-e2e-android: + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + AVD_ARCH: x86_64 + AVD_API_LEVEL: 34 + AVD_TARGET: google_apis + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a + name: Install Node.js 20 + with: + node-version: '20' + - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + with: + distribution: 'temurin' + java-version: '21' + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + cache: true + cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" + pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" + - uses: bluefireteam/melos-action@c7dcb921b33cc520cace360b95d02b37bf09cdaa + with: + run-bootstrap: false + melos-version: '5.3.0' + - name: Inject Firebase config for pipeline E2E + env: + FIREBASE_OPTIONS_DART: ${{ secrets.PIPELINE_E2E_FIREBASE_OPTIONS_DART }} + GOOGLE_SERVICES_JSON: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICES_JSON }} + GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICE_INFO_PLIST }} + run: | + echo "$FIREBASE_OPTIONS_DART" > packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart + echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json + echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist + - name: Bootstrap package + run: melos bootstrap --scope "cloud_firestore*" + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - name: Gradle cache + uses: gradle/actions/setup-gradle@v4 + - name: Free Disk Space (Ubuntu) + uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 + with: + remove-dotnet: true + remove-haskell: true + remove-codeql: true + remove-docker-images: true + remove-large-packages: true + - name: AVD cache + uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + continue-on-error: true + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} + - name: Start AVD then run pipeline E2E tests + uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b + with: + api-level: ${{ env.AVD_API_LEVEL }} + target: ${{ env.AVD_TARGET }} + arch: ${{ env.AVD_ARCH }} + emulator-build: 14214601 + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + script: | + flutter test integration_test/pipeline/pipeline_live_test.dart --timeout 10x --dart-define=CI=true -d emulator-5554 + - name: Ensure Appium is shut down + run: | + pgrep -f appium && pkill -f appium || echo "No Appium process found" + - name: Save Android Emulator Cache + if: github.ref == 'refs/heads/main' + uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + continue-on-error: true + with: + key: ${{ steps.avd-cache.outputs.cache-primary-key }} + path: | + ~/.android/avd/* + ~/.android/adb* + + pipeline-e2e-web: + runs-on: macos-latest + timeout-minutes: 25 + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a + name: Install Node.js 20 + with: + node-version: '20' + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + cache: true + cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" + pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" + - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa + with: + run-bootstrap: false + melos-version: '5.3.0' + - name: Inject Firebase config for pipeline E2E + env: + FIREBASE_OPTIONS_DART: ${{ secrets.PIPELINE_E2E_FIREBASE_OPTIONS_DART }} + GOOGLE_SERVICES_JSON: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICES_JSON }} + GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICE_INFO_PLIST }} + run: | + echo "$FIREBASE_OPTIONS_DART" > packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart + echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json + echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist + - name: Bootstrap package + run: melos bootstrap --scope "cloud_firestore*" + - name: Run pipeline E2E tests (Chrome) + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + run: | + chromedriver --port=4444 --trace-buffer-size=100000 & + flutter drive --target=./integration_test/pipeline/pipeline_live_test.dart --driver=./test_driver/integration_test.dart -d chrome --dart-define=CI=true | tee output.log + output=$( packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart + echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json + echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist + - name: Bootstrap package + run: melos bootstrap --scope "cloud_firestore*" + - name: Prepare iOS project for Swift Package Manager + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example/ios + run: | + if [ -f Podfile ]; then pod deintegrate; fi + rm -f Podfile Podfile.lock + rm -rf Pods + - uses: futureware-tech/simulator-action@e89aa8f93d3aec35083ff49d2854d07f7186f7f5 + id: simulator + with: + model: "iPhone 16" + - name: Build iOS (simulator) + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + run: | + flutter build ios --no-codesign --simulator --debug --target=./integration_test/pipeline/pipeline_live_test.dart --dart-define=CI=true + - name: Run pipeline E2E tests (iOS) + working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example + env: + SIMULATOR: ${{ steps.simulator.outputs.udid }} + run: | + perl -e 'alarm 360; exec @ARGV' -- flutter test integration_test/pipeline/pipeline_live_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true || { + echo "First attempt failed or timed out. Rebooting simulator and retrying..." + xcrun simctl shutdown "$SIMULATOR" || true + xcrun simctl boot "$SIMULATOR" + xcrun simctl bootstatus "$SIMULATOR" -b + flutter test integration_test/pipeline/pipeline_live_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true + } + + update-dashboard: + runs-on: ubuntu-latest + if: always() + needs: [pipeline-e2e-android, pipeline-e2e-web, pipeline-e2e-ios] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + - name: Update Dashboard Issue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ANDROID_STATUS: ${{ needs.pipeline-e2e-android.result }} + WEB_STATUS: ${{ needs.pipeline-e2e-web.result }} + IOS_STATUS: ${{ needs.pipeline-e2e-ios.result }} + REPO: ${{ github.repository }} + run: | + dart .github/workflows/scripts/nightly_issue_dashboard.dart diff --git a/.github/workflows/scripts/nightly_issue_dashboard.dart b/.github/workflows/scripts/nightly_issue_dashboard.dart new file mode 100644 index 000000000000..13dbf3cf535a --- /dev/null +++ b/.github/workflows/scripts/nightly_issue_dashboard.dart @@ -0,0 +1,228 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:convert'; +import 'dart:io'; + +void main() async { + final env = Platform.environment; + final token = env['GITHUB_TOKEN']; + final repo = env['REPO']; + final androidStatus = env['ANDROID_STATUS'] ?? 'skipped'; + final webStatus = env['WEB_STATUS'] ?? 'skipped'; + final iosStatus = env['IOS_STATUS'] ?? 'skipped'; + final runId = env['GITHUB_RUN_ID']; + final serverUrl = env['GITHUB_SERVER_URL'] ?? 'https://github.com'; + + if (token == null || repo == null) { + print('Error: GITHUB_TOKEN or REPO environment variables not set.'); + exit(1); + } + + final date = DateTime.now().toUtc().toString().substring(0, 10); + final runUrl = '$serverUrl/$repo/actions/runs/$runId'; + final notes = '[View Run]($runUrl)'; + + final androidIcon = _getIcon(androidStatus); + final webIcon = _getIcon(webStatus); + final iosIcon = _getIcon(iosStatus); + + final newRow = '| $date | $androidIcon | $iosIcon | $webIcon | $notes |'; + + print('New Row: $newRow'); + + final client = HttpClient(); + try { + // 1. Find the issue + final issueNumber = await _findIssue(client, token, repo); + + if (issueNumber == null) { + print('Issue not found. Creating a new one.'); + await _createIssue(client, token, repo, newRow); + } else { + print('Found issue #$issueNumber. Updating.'); + await _updateIssue(client, token, repo, issueNumber, newRow); + } + } finally { + client.close(); + } +} + +String _getIcon(String status) { + switch (status) { + case 'success': + return '✅ Pass'; + case 'failure': + return '❌ Failure'; + case 'cancelled': + return '⚪ Cancelled'; + case 'skipped': + return '➖ Skipped'; + default: + return '❓ Unknown'; + } +} + +Future _findIssue(HttpClient client, String token, String repo) async { + final url = Uri.parse('https://api.github.com/repos/$repo/issues?labels=nightly-testing&state=open'); + final request = await client.getUrl(url); + _addHeaders(request, token); + + final response = await request.close(); + if (response.statusCode != 200) { + print('Failed to search issues: ${response.statusCode}'); + return null; + } + + final body = await response.transform(utf8.decoder).join(); + final json = jsonDecode(body) as List; + + for (final issue in json) { + if (issue['title'] == '[FlutterFire] Nightly Integration Testing Report') { + return issue['number'] as int; + } + } + return null; +} + +Future _createIssue(HttpClient client, String token, String repo, String newRow) async { + final url = Uri.parse('https://api.github.com/repos/$repo/issues'); + final request = await client.postUrl(url); + _addHeaders(request, token); + + final body = { + 'title': '[FlutterFire] Nightly Integration Testing Report', + 'labels': ['nightly-testing'], + 'body': ''' +## Testing History (last 30 days) + +| Date | Android | iOS | Web | Notes | +| :--- | :--- | :--- | :--- | :--- | +$newRow +''' + }; + + request.add(utf8.encode(jsonEncode(body))); + final response = await request.close(); + if (response.statusCode != 201) { + print('Failed to create issue: ${response.statusCode}'); + final respBody = await response.transform(utf8.decoder).join(); + print('Response: $respBody'); + } else { + print('Issue created successfully.'); + } +} + +Future _updateIssue(HttpClient client, String token, String repo, int issueNumber, String newRow) async { + // Fetch current issue body + final getUrl = Uri.parse('https://api.github.com/repos/$repo/issues/$issueNumber'); + final getRequest = await client.getUrl(getUrl); + _addHeaders(getRequest, token); + + final getResponse = await getRequest.close(); + if (getResponse.statusCode != 200) { + print('Failed to fetch issue #$issueNumber: ${getResponse.statusCode}'); + return; + } + + final getBody = await getResponse.transform(utf8.decoder).join(); + final issueJson = jsonDecode(getBody); + String currentBody = issueJson['body'] ?? ''; + + // Parse and update table + final updatedBody = _appendRow(currentBody, newRow); + + // Update issue + final patchUrl = Uri.parse('https://api.github.com/repos/$repo/issues/$issueNumber'); + final patchRequest = await client.patchUrl(patchUrl); + _addHeaders(patchRequest, token); + + final patchBody = {'body': updatedBody}; + patchRequest.add(utf8.encode(jsonEncode(patchBody))); + + final patchResponse = await patchRequest.close(); + if (patchResponse.statusCode != 200) { + print('Failed to update issue #$issueNumber: ${patchResponse.statusCode}'); + final respBody = await patchResponse.transform(utf8.decoder).join(); + print('Response: $respBody'); + } else { + print('Issue #$issueNumber updated successfully.'); + } +} + +String _appendRow(String currentBody, String newRow) { + final lines = currentBody.split('\n'); + final tableRows = []; + var inTable = false; + + for (final line in lines) { + if (line.startsWith('| Date |')) { + inTable = true; + continue; + } + if (inTable && line.startsWith('|')) { + if (line.startsWith('| ---') || line.startsWith('| :---')) { + continue; + } + tableRows.add(line); + } + } + + tableRows.add(newRow); + + // Keep only last 30 rows + if (tableRows.length > 30) { + tableRows.removeRange(0, tableRows.length - 30); + } + + // Rebuild body + final newBodyLines = []; + var processedTable = false; + + for (final line in lines) { + if (line.startsWith('| Date |')) { + if (!processedTable) { + newBodyLines.add('| Date | Android | iOS | Web | Notes |'); + newBodyLines.add('| :--- | :--- | :--- | :--- | :--- |'); + newBodyLines.addAll(tableRows); + processedTable = true; + } + inTable = true; + continue; + } + if (inTable && line.startsWith('|')) { + continue; + } + inTable = false; + newBodyLines.add(line); + } + + if (!processedTable) { + // Table not found, append it + newBodyLines.add('## Testing History (last 30 days)'); + newBodyLines.add(''); + newBodyLines.add('| Date | Android | iOS | Web | Notes |'); + newBodyLines.add('| :--- | :--- | :--- | :--- | :--- |'); + newBodyLines.add(newRow); + } + + return newBodyLines.join('\n'); +} + +void _addHeaders(HttpClientRequest request, String token) { + request.headers.add('Authorization', 'token $token'); + request.headers.add('Accept', 'application/vnd.github.v3+json'); + request.headers.add('User-Agent', 'dart-script'); + request.headers.contentType = ContentType.json; +} From 65d9bb7104f59de82010e3e82fd0ddddbf9a2e23 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Fri, 24 Apr 2026 15:11:35 +0000 Subject: [PATCH 041/137] refactor(database, android): simplify query handling by extracting queryFromModifiers method (#18221) --- .../database/FirebaseDatabasePlugin.kt | 255 +----------------- .../plugins/firebase/database/QueryBuilder.kt | 32 ++- 2 files changed, 29 insertions(+), 258 deletions(-) diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt index 808cf7c0e6b6..80c7ae0bef23 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt @@ -141,10 +141,16 @@ class FirebaseDatabasePlugin : @Suppress("UNCHECKED_CAST") private fun getQuery(arguments: Map): Query { val ref = getReference(arguments) - val modifiers = arguments[Constants.MODIFIERS] as List> - return QueryBuilder(ref, modifiers).build() + val modifiers = arguments[Constants.MODIFIERS] as List> + return queryFromModifiers(ref, modifiers) } + /** Applies [modifiers]. */ + private fun queryFromModifiers( + reference: DatabaseReference, + modifiers: List>, + ): Query = QueryBuilder(reference, modifiers).build() + private fun goOnline(arguments: Map): Task { val taskCompletionSource = TaskCompletionSource() @@ -844,84 +850,7 @@ class FirebaseDatabasePlugin : Log.d("FirebaseDatabase", "🔍 Kotlin: Setting up query observe for path=${request.path}") val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) - - // Apply query modifiers if any - var query: com.google.firebase.database.Query = reference - // Note: no hasOrderModifier needed — Android SDK defaults to PriorityIndex - // when no orderBy is specified, so cursors work without an explicit orderBy. - - for (modifier in request.modifiers) { - when (modifier["type"] as String) { - "orderBy" -> { - when (modifier["name"] as String) { - "orderByChild" -> { - query = query.orderByChild(modifier["path"] as String) - } - "orderByKey" -> { - query = query.orderByKey() - } - "orderByValue" -> { - query = query.orderByValue() - } - "orderByPriority" -> { - query = query.orderByPriority() - } - } - } - "cursor" -> { - when (modifier["name"] as String) { - "startAt" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key) - is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key) - else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key) - } - } - "startAfter" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key) - is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key) - else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key) - } - } - "endAt" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key) - is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key) - else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key) - } - } - "endBefore" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key) - is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key) - else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key) - } - } - } - } - "limit" -> { - when (modifier["name"] as String) { - "limitToFirst" -> { - val value = (modifier["limit"] as Number).toInt() - query = query.limitToFirst(value) - } - "limitToLast" -> { - val value = (modifier["limit"] as Number).toInt() - query = query.limitToLast(value) - } - } - } - } - } + val query = queryFromModifiers(reference, request.modifiers) // Generate a unique channel name val channelName = "firebase_database_query_${System.currentTimeMillis()}_${request.path.hashCode()}" @@ -947,84 +876,7 @@ class FirebaseDatabasePlugin : try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) - - // Apply query modifiers if any - var query: com.google.firebase.database.Query = reference - // Note: no hasOrderModifier needed — Android SDK defaults to PriorityIndex - // when no orderBy is specified, so cursors work without an explicit orderBy. - - for (modifier in request.modifiers) { - when (modifier["type"] as String) { - "orderBy" -> { - when (modifier["name"] as String) { - "orderByChild" -> { - query = query.orderByChild(modifier["path"] as String) - } - "orderByKey" -> { - query = query.orderByKey() - } - "orderByValue" -> { - query = query.orderByValue() - } - "orderByPriority" -> { - query = query.orderByPriority() - } - } - } - "cursor" -> { - when (modifier["name"] as String) { - "startAt" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key) - is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key) - else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key) - } - } - "startAfter" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key) - is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key) - else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key) - } - } - "endAt" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key) - is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key) - else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key) - } - } - "endBefore" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key) - is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key) - else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key) - } - } - } - } - "limit" -> { - when (modifier["name"] as String) { - "limitToFirst" -> { - val value = (modifier["limit"] as Number).toInt() - query = query.limitToFirst(value) - } - "limitToLast" -> { - val value = (modifier["limit"] as Number).toInt() - query = query.limitToLast(value) - } - } - } - } - } + val query = queryFromModifiers(reference, request.modifiers) // Add keepSynced to the query query.keepSynced(request.value ?: false) @@ -1038,92 +890,7 @@ class FirebaseDatabasePlugin : try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) - - // Apply query modifiers if any - var query: com.google.firebase.database.Query = reference - // Note: no hasOrderModifier needed — Android SDK defaults to PriorityIndex - // when no orderBy is specified, so cursors work without an explicit orderBy. - - for (modifier in request.modifiers) { - when (modifier["type"] as String) { - "orderBy" -> { - when (modifier["name"] as String) { - "orderByChild" -> { - query = query.orderByChild(modifier["path"] as String) - } - "orderByKey" -> { - query = query.orderByKey() - } - "orderByValue" -> { - query = query.orderByValue() - } - "orderByPriority" -> { - query = query.orderByPriority() - } - } - } - "cursor" -> { - when (modifier["name"] as String) { - "startAt" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key) - is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key) - else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key) - } - } - "startAfter" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key) - is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key) - else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key) - } - } - "endAt" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key) - is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key) - else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key) - } - } - "endBefore" -> { - val value = modifier["value"] - val key = modifier["key"] as String? - query = when (value) { - is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key) - is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key) - else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key) - } - } - } - } - "limit" -> { - when (modifier["name"] as String) { - "limitToFirst" -> { - val value = when (val limit = modifier["limit"]) { - is Int -> limit - is Number -> limit.toInt() - else -> throw IllegalArgumentException("Invalid limit value: $limit") - } - query = query.limitToFirst(value) - } - "limitToLast" -> { - val value = when (val limit = modifier["limit"]) { - is Int -> limit - is Number -> limit.toInt() - else -> throw IllegalArgumentException("Invalid limit value: $limit") - } - query = query.limitToLast(value) - } - } - } - } - } + val query = queryFromModifiers(reference, request.modifiers) // Get the data query.get().addOnCompleteListener { task -> diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt index 8cadd84e4fe8..ebb84e4edc4b 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt @@ -9,13 +9,12 @@ package io.flutter.plugins.firebase.database import androidx.annotation.NonNull import com.google.firebase.database.DatabaseReference import com.google.firebase.database.Query -import java.util.* class QueryBuilder @JvmOverloads constructor( @NonNull ref: DatabaseReference, - @NonNull private val modifiers: List>, + @NonNull private val modifiers: List>, ) { private var query: Query = ref @@ -35,9 +34,14 @@ class QueryBuilder return query } - private fun limit(modifier: Map) { + private fun limit(modifier: Map) { val name = modifier["name"] as String - val value = modifier["limit"] as Int + val value = + when (val limit = modifier["limit"]) { + is Int -> limit + is Number -> limit.toInt() + else -> throw IllegalArgumentException("Invalid limit value: $limit") + } query = when (name) { @@ -47,7 +51,7 @@ class QueryBuilder } } - private fun orderBy(modifier: Map) { + private fun orderBy(modifier: Map) { val name = modifier["name"] as String query = @@ -63,7 +67,7 @@ class QueryBuilder } } - private fun cursor(modifier: Map) { + private fun cursor(modifier: Map) { val name = modifier["name"] as String when (name) { @@ -74,7 +78,7 @@ class QueryBuilder } } - private fun startAt(modifier: Map) { + private fun startAt(modifier: Map) { val value = modifier["value"] val key = modifier["key"] as String? @@ -82,11 +86,11 @@ class QueryBuilder when (value) { is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key) is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key) - else -> if (key == null) query.startAt(value as String) else query.startAt(value as String, key) + else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key) } } - private fun startAfter(modifier: Map) { + private fun startAfter(modifier: Map) { val value = modifier["value"] val key = modifier["key"] as String? @@ -94,11 +98,11 @@ class QueryBuilder when (value) { is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key) is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key) - else -> if (key == null) query.startAfter(value as String) else query.startAfter(value as String, key) + else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key) } } - private fun endAt(modifier: Map) { + private fun endAt(modifier: Map) { val value = modifier["value"] val key = modifier["key"] as String? @@ -106,11 +110,11 @@ class QueryBuilder when (value) { is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key) is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key) - else -> if (key == null) query.endAt(value as String) else query.endAt(value as String, key) + else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key) } } - private fun endBefore(modifier: Map) { + private fun endBefore(modifier: Map) { val value = modifier["value"] val key = modifier["key"] as String? @@ -118,7 +122,7 @@ class QueryBuilder when (value) { is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key) is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key) - else -> if (key == null) query.endBefore(value as String) else query.endBefore(value as String, key) + else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key) } } } From 918554c668977c161e01d2b14f819c2659c25e02 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Fri, 24 Apr 2026 08:31:25 -0700 Subject: [PATCH 042/137] chore(ci): nightly build, improve the way how workflows are triggered (#18228) * ussing existing workflow * only update the dashboard once preset test is done * change the way how it runs * add timeout for writing issue * comment out concurrency block for testing * update concurrency group --- .github/workflows/android.yaml | 3 +- .github/workflows/e2e_tests_fdc.yaml | 3 +- .github/workflows/e2e_tests_pipeline.yaml | 3 +- .github/workflows/ios.yaml | 3 +- .github/workflows/macos.yaml | 3 +- .github/workflows/nightly.yaml | 237 ++---------------- .../scripts/nightly_issue_dashboard.dart | 121 ++++++--- .github/workflows/update_dashboard.yaml | 31 +++ .github/workflows/web.yaml | 3 +- .github/workflows/windows.yaml | 3 +- 10 files changed, 152 insertions(+), 258 deletions(-) create mode 100644 .github/workflows/update_dashboard.yaml diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index bcd3a290d84e..5e4f6d5f34b9 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -1,7 +1,7 @@ name: e2e-android concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-android cancel-in-progress: true on: @@ -23,6 +23,7 @@ on: - '!**/example/integration_test/**' - '**/flutterfire_ui/**' - '**.md' + workflow_call: jobs: android: diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 09c75e073f17..b260ad033243 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -1,7 +1,7 @@ name: e2e-fdc concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-fdc cancel-in-progress: true on: @@ -20,6 +20,7 @@ on: - 'website/**' - '**/example/**' - '**.md' + workflow_call: permissions: contents: read diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index f13f10f20af6..f8b4732d65e9 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -1,7 +1,7 @@ name: e2e-pipeline concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-pipeline cancel-in-progress: true on: @@ -19,6 +19,7 @@ on: - 'website/**' - '**/example/**' - '**.md' + workflow_call: permissions: contents: read diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 5e8df18080a0..90859a335e76 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -1,7 +1,7 @@ name: e2e-iOS concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-ios cancel-in-progress: true on: @@ -23,6 +23,7 @@ on: - '!**/example/integration_test/**' - '**/flutterfire_ui/**' - '**.md' + workflow_call: jobs: ios: diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index d9c41a6376c9..0ec18a7b9d1c 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -1,7 +1,7 @@ name: e2e-macOS concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-macos cancel-in-progress: true on: @@ -23,6 +23,7 @@ on: - '!**/example/integration_test/**' - '**/flutterfire_ui/**' - '**.md' + workflow_call: jobs: macos: diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 263cd65b2e39..ab82573ec3df 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -1,8 +1,8 @@ name: nightly-ci -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false +# concurrency: +# group: ${{ github.workflow }}-${{ github.ref }} +# cancel-in-progress: false on: # schedule: @@ -14,213 +14,24 @@ permissions: issues: write jobs: - pipeline-e2e-android: - runs-on: ubuntu-latest - timeout-minutes: 45 - env: - AVD_ARCH: x86_64 - AVD_API_LEVEL: 34 - AVD_TARGET: google_apis - steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a - name: Install Node.js 20 - with: - node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b - with: - distribution: 'temurin' - java-version: '21' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff - with: - channel: 'stable' - cache: true - cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" - pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b33cc520cace360b95d02b37bf09cdaa - with: - run-bootstrap: false - melos-version: '5.3.0' - - name: Inject Firebase config for pipeline E2E - env: - FIREBASE_OPTIONS_DART: ${{ secrets.PIPELINE_E2E_FIREBASE_OPTIONS_DART }} - GOOGLE_SERVICES_JSON: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICES_JSON }} - GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICE_INFO_PLIST }} - run: | - echo "$FIREBASE_OPTIONS_DART" > packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart - echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json - echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist - - name: Bootstrap package - run: melos bootstrap --scope "cloud_firestore*" - - name: Enable KVM - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - - name: Gradle cache - uses: gradle/actions/setup-gradle@v4 - - name: Free Disk Space (Ubuntu) - uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 - with: - remove-dotnet: true - remove-haskell: true - remove-codeql: true - remove-docker-images: true - remove-large-packages: true - - name: AVD cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 - continue-on-error: true - id: avd-cache - with: - path: | - ~/.android/avd/* - ~/.android/adb* - key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} - - name: Start AVD then run pipeline E2E tests - uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b - with: - api-level: ${{ env.AVD_API_LEVEL }} - target: ${{ env.AVD_TARGET }} - arch: ${{ env.AVD_ARCH }} - emulator-build: 14214601 - working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example - script: | - flutter test integration_test/pipeline/pipeline_live_test.dart --timeout 10x --dart-define=CI=true -d emulator-5554 - - name: Ensure Appium is shut down - run: | - pgrep -f appium && pkill -f appium || echo "No Appium process found" - - name: Save Android Emulator Cache - if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 - continue-on-error: true - with: - key: ${{ steps.avd-cache.outputs.cache-primary-key }} - path: | - ~/.android/avd/* - ~/.android/adb* - - pipeline-e2e-web: - runs-on: macos-latest - timeout-minutes: 25 - steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a - name: Install Node.js 20 - with: - node-version: '20' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff - with: - channel: 'stable' - cache: true - cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" - pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - - uses: bluefireteam/melos-action@c7dcb921b23cc520cace360b95d02b37bf09cdaa - with: - run-bootstrap: false - melos-version: '5.3.0' - - name: Inject Firebase config for pipeline E2E - env: - FIREBASE_OPTIONS_DART: ${{ secrets.PIPELINE_E2E_FIREBASE_OPTIONS_DART }} - GOOGLE_SERVICES_JSON: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICES_JSON }} - GOOGLE_SERVICE_INFO_PLIST: ${{ secrets.PIPELINE_E2E_GOOGLE_SERVICE_INFO_PLIST }} - run: | - echo "$FIREBASE_OPTIONS_DART" > packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart - echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json - echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist - - name: Bootstrap package - run: melos bootstrap --scope "cloud_firestore*" - - name: Run pipeline E2E tests (Chrome) - working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example - run: | - chromedriver --port=4444 --trace-buffer-size=100000 & - flutter drive --target=./integration_test/pipeline/pipeline_live_test.dart --driver=./test_driver/integration_test.dart -d chrome --dart-define=CI=true | tee output.log - output=$( packages/cloud_firestore/cloud_firestore/pipeline_example/lib/firebase_options.dart - echo "$GOOGLE_SERVICES_JSON" > packages/cloud_firestore/cloud_firestore/pipeline_example/android/app/google-services.json - echo "$GOOGLE_SERVICE_INFO_PLIST" > packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/GoogleService-Info.plist - - name: Bootstrap package - run: melos bootstrap --scope "cloud_firestore*" - - name: Prepare iOS project for Swift Package Manager - working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example/ios - run: | - if [ -f Podfile ]; then pod deintegrate; fi - rm -f Podfile Podfile.lock - rm -rf Pods - - uses: futureware-tech/simulator-action@e89aa8f93d3aec35083ff49d2854d07f7186f7f5 - id: simulator - with: - model: "iPhone 16" - - name: Build iOS (simulator) - working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example - run: | - flutter build ios --no-codesign --simulator --debug --target=./integration_test/pipeline/pipeline_live_test.dart --dart-define=CI=true - - name: Run pipeline E2E tests (iOS) - working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example - env: - SIMULATOR: ${{ steps.simulator.outputs.udid }} - run: | - perl -e 'alarm 360; exec @ARGV' -- flutter test integration_test/pipeline/pipeline_live_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true || { - echo "First attempt failed or timed out. Rebooting simulator and retrying..." - xcrun simctl shutdown "$SIMULATOR" || true - xcrun simctl boot "$SIMULATOR" - xcrun simctl bootstatus "$SIMULATOR" -b - flutter test integration_test/pipeline/pipeline_live_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true - } - - update-dashboard: - runs-on: ubuntu-latest - if: always() - needs: [pipeline-e2e-android, pipeline-e2e-web, pipeline-e2e-ios] - steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff - with: - channel: 'stable' - - name: Update Dashboard Issue - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ANDROID_STATUS: ${{ needs.pipeline-e2e-android.result }} - WEB_STATUS: ${{ needs.pipeline-e2e-web.result }} - IOS_STATUS: ${{ needs.pipeline-e2e-ios.result }} - REPO: ${{ github.repository }} - run: | - dart .github/workflows/scripts/nightly_issue_dashboard.dart + e2e-android: + uses: ./.github/workflows/android.yaml + secrets: inherit + e2e-ios: + uses: ./.github/workflows/ios.yaml + secrets: inherit + e2e-macos: + uses: ./.github/workflows/macos.yaml + secrets: inherit + e2e-web: + uses: ./.github/workflows/web.yaml + secrets: inherit + e2e-windows: + uses: ./.github/workflows/windows.yaml + secrets: inherit + e2e-fdc: + uses: ./.github/workflows/e2e_tests_fdc.yaml + secrets: inherit + e2e-pipeline: + uses: ./.github/workflows/e2e_tests_pipeline.yaml + secrets: inherit diff --git a/.github/workflows/scripts/nightly_issue_dashboard.dart b/.github/workflows/scripts/nightly_issue_dashboard.dart index 13dbf3cf535a..a2cf278ec744 100644 --- a/.github/workflows/scripts/nightly_issue_dashboard.dart +++ b/.github/workflows/scripts/nightly_issue_dashboard.dart @@ -19,40 +19,30 @@ void main() async { final env = Platform.environment; final token = env['GITHUB_TOKEN']; final repo = env['REPO']; - final androidStatus = env['ANDROID_STATUS'] ?? 'skipped'; - final webStatus = env['WEB_STATUS'] ?? 'skipped'; - final iosStatus = env['IOS_STATUS'] ?? 'skipped'; - final runId = env['GITHUB_RUN_ID']; + final workflowName = env['WORKFLOW_NAME']; + final status = env['STATUS']; + final runId = env['RUN_ID']; final serverUrl = env['GITHUB_SERVER_URL'] ?? 'https://github.com'; - if (token == null || repo == null) { - print('Error: GITHUB_TOKEN or REPO environment variables not set.'); + if (token == null || repo == null || workflowName == null || status == null) { + print('Error: Required environment variables not set.'); exit(1); } final date = DateTime.now().toUtc().toString().substring(0, 10); final runUrl = '$serverUrl/$repo/actions/runs/$runId'; - final notes = '[View Run]($runUrl)'; - - final androidIcon = _getIcon(androidStatus); - final webIcon = _getIcon(webStatus); - final iosIcon = _getIcon(iosStatus); - - final newRow = '| $date | $androidIcon | $iosIcon | $webIcon | $notes |'; - - print('New Row: $newRow'); + final statusIcon = _getIcon(status); final client = HttpClient(); try { - // 1. Find the issue final issueNumber = await _findIssue(client, token, repo); if (issueNumber == null) { print('Issue not found. Creating a new one.'); - await _createIssue(client, token, repo, newRow); + await _createIssue(client, token, repo, date, workflowName, statusIcon, runUrl); } else { print('Found issue #$issueNumber. Updating.'); - await _updateIssue(client, token, repo, issueNumber, newRow); + await _updateIssue(client, token, repo, issueNumber, date, workflowName, statusIcon, runUrl); } } finally { client.close(); @@ -74,6 +64,27 @@ String _getIcon(String status) { } } +int _getColumnIndex(String workflowName) { + switch (workflowName) { + case 'e2e-android': + return 1; + case 'e2e-iOS': + return 2; + case 'e2e-web': + return 3; + case 'e2e-macOS': + return 4; + case 'e2e-windows': + return 5; + case 'e2e-fdc': + return 6; + case 'e2e-pipeline': + return 7; + default: + return -1; + } +} + Future _findIssue(HttpClient client, String token, String repo) async { final url = Uri.parse('https://api.github.com/repos/$repo/issues?labels=nightly-testing&state=open'); final request = await client.getUrl(url); @@ -96,19 +107,29 @@ Future _findIssue(HttpClient client, String token, String repo) async { return null; } -Future _createIssue(HttpClient client, String token, String repo, String newRow) async { +Future _createIssue(HttpClient client, String token, String repo, String date, String workflowName, String statusIcon, String runUrl) async { final url = Uri.parse('https://api.github.com/repos/$repo/issues'); final request = await client.postUrl(url); _addHeaders(request, token); + final colIndex = _getColumnIndex(workflowName); + final rowData = List.filled(9, '➖ Skipped'); + rowData[0] = date; + if (colIndex != -1) { + rowData[colIndex] = statusIcon; + } + rowData[8] = '[View Run]($runUrl)'; + + final newRow = '| ${rowData.join(' | ')} |'; + final body = { 'title': '[FlutterFire] Nightly Integration Testing Report', 'labels': ['nightly-testing'], 'body': ''' ## Testing History (last 30 days) -| Date | Android | iOS | Web | Notes | -| :--- | :--- | :--- | :--- | :--- | +| Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes | +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | $newRow ''' }; @@ -124,8 +145,7 @@ $newRow } } -Future _updateIssue(HttpClient client, String token, String repo, int issueNumber, String newRow) async { - // Fetch current issue body +Future _updateIssue(HttpClient client, String token, String repo, int issueNumber, String date, String workflowName, String statusIcon, String runUrl) async { final getUrl = Uri.parse('https://api.github.com/repos/$repo/issues/$issueNumber'); final getRequest = await client.getUrl(getUrl); _addHeaders(getRequest, token); @@ -140,10 +160,8 @@ Future _updateIssue(HttpClient client, String token, String repo, int issu final issueJson = jsonDecode(getBody); String currentBody = issueJson['body'] ?? ''; - // Parse and update table - final updatedBody = _appendRow(currentBody, newRow); + final updatedBody = _updateTable(currentBody, date, workflowName, statusIcon, runUrl); - // Update issue final patchUrl = Uri.parse('https://api.github.com/repos/$repo/issues/$issueNumber'); final patchRequest = await client.patchUrl(patchUrl); _addHeaders(patchRequest, token); @@ -161,12 +179,15 @@ Future _updateIssue(HttpClient client, String token, String repo, int issu } } -String _appendRow(String currentBody, String newRow) { +String _updateTable(String currentBody, String date, String workflowName, String statusIcon, String runUrl) { final lines = currentBody.split('\n'); final tableRows = []; var inTable = false; + var foundToday = false; + final colIndex = _getColumnIndex(workflowName); - for (final line in lines) { + for (var i = 0; i < lines.length; i++) { + final line = lines[i]; if (line.startsWith('| Date |')) { inTable = true; continue; @@ -175,26 +196,45 @@ String _appendRow(String currentBody, String newRow) { if (line.startsWith('| ---') || line.startsWith('| :---')) { continue; } - tableRows.add(line); + final cells = line.split('|').map((c) => c.trim()).toList(); + if (cells.length >= 10) { + final rowDate = cells[1]; + if (rowDate == date) { + foundToday = true; + if (colIndex != -1) { + cells[colIndex + 1] = statusIcon; + } + cells[9] = '[View Run]($runUrl)'; + tableRows.add('| ${cells.sublist(1, 10).join(' | ')} |'); + } else { + tableRows.add(line); + } + } } } - tableRows.add(newRow); + if (!foundToday) { + final rowData = List.filled(9, '➖ Skipped'); + rowData[0] = date; + if (colIndex != -1) { + rowData[colIndex] = statusIcon; + } + rowData[8] = '[View Run]($runUrl)'; + tableRows.add('| ${rowData.join(' | ')} |'); + } - // Keep only last 30 rows if (tableRows.length > 30) { tableRows.removeRange(0, tableRows.length - 30); } - // Rebuild body final newBodyLines = []; var processedTable = false; for (final line in lines) { if (line.startsWith('| Date |')) { if (!processedTable) { - newBodyLines.add('| Date | Android | iOS | Web | Notes |'); - newBodyLines.add('| :--- | :--- | :--- | :--- | :--- |'); + newBodyLines.add('| Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes |'); + newBodyLines.add('| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |'); newBodyLines.addAll(tableRows); processedTable = true; } @@ -209,12 +249,17 @@ String _appendRow(String currentBody, String newRow) { } if (!processedTable) { - // Table not found, append it newBodyLines.add('## Testing History (last 30 days)'); newBodyLines.add(''); - newBodyLines.add('| Date | Android | iOS | Web | Notes |'); - newBodyLines.add('| :--- | :--- | :--- | :--- | :--- |'); - newBodyLines.add(newRow); + newBodyLines.add('| Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes |'); + newBodyLines.add('| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |'); + final rowData = List.filled(9, '➖ Skipped'); + rowData[0] = date; + if (colIndex != -1) { + rowData[colIndex] = statusIcon; + } + rowData[8] = '[View Run]($runUrl)'; + newBodyLines.add('| ${rowData.join(' | ')} |'); } return newBodyLines.join('\n'); diff --git a/.github/workflows/update_dashboard.yaml b/.github/workflows/update_dashboard.yaml new file mode 100644 index 000000000000..d0c14a4a6ce5 --- /dev/null +++ b/.github/workflows/update_dashboard.yaml @@ -0,0 +1,31 @@ +name: update-dashboard + +on: + workflow_run: + workflows: ["e2e-android", "e2e-iOS", "e2e-web", "e2e-macOS", "e2e-windows", "e2e-fdc", "e2e-pipeline"] + types: + - completed + +permissions: + contents: read + issues: write + +jobs: + update: + runs-on: ubuntu-latest + timeout-minutes: 5 + if: ${{ github.event.workflow_run.event == 'schedule' || github.event.workflow_run.event == 'workflow_dispatch' }} + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + - name: Update Dashboard Issue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_NAME: ${{ github.event.workflow_run.name }} + STATUS: ${{ github.event.workflow_run.conclusion }} + RUN_ID: ${{ github.event.workflow_run.id }} + REPO: ${{ github.repository }} + run: | + dart .github/workflows/scripts/nightly_issue_dashboard.dart diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index 30472fb9d097..d77f622f367f 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -1,7 +1,7 @@ name: e2e-web concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-web cancel-in-progress: true on: @@ -23,6 +23,7 @@ on: - '!**/example/integration_test/**' - '**/flutterfire_ui/**' - '**.md' + workflow_call: jobs: web: diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 2a56eee0ef39..52bae4e486cf 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -1,7 +1,7 @@ name: e2e-windows concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-windows cancel-in-progress: true on: @@ -23,6 +23,7 @@ on: - '!**/example/integration_test/**' - '**/flutterfire_ui/**' - '**.md' + workflow_call: jobs: windows: From c23dbadd3a29774ce4a7cd207da81e7cc8dd531f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 09:48:00 +0200 Subject: [PATCH 043/137] chore(deps): bump fast-xml-parser (#18220) Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 5.5.7 to 5.7.1. - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v5.5.7...v5.7.1) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-version: 5.7.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../scripts/functions/package-lock.json | 80 ++++++++++++------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index cf5ca86aec07..2cf7cfdf1386 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -238,6 +238,18 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/@nodable/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "optional": true + }, "node_modules/@opentelemetry/api": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", @@ -987,9 +999,9 @@ "optional": true }, "node_modules/fast-xml-builder": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz", - "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz", + "integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==", "funding": [ { "type": "github", @@ -1002,9 +1014,9 @@ } }, "node_modules/fast-xml-parser": { - "version": "5.5.7", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.7.tgz", - "integrity": "sha512-LteOsISQ2GEiDHZch6L9hB0+MLoYVLToR7xotrzU0opCICBkxOPgHAy1HxAvtxfJNXDJpgAsQN30mkrfpO2Prg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.1.tgz", + "integrity": "sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA==", "funding": [ { "type": "github", @@ -1013,9 +1025,10 @@ ], "optional": true, "dependencies": { - "fast-xml-builder": "^1.1.4", - "path-expression-matcher": "^1.1.3", - "strnum": "^2.2.0" + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.5", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" @@ -1807,9 +1820,9 @@ } }, "node_modules/path-expression-matcher": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz", - "integrity": "sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", "funding": [ { "type": "github", @@ -2180,9 +2193,9 @@ } }, "node_modules/strnum": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.1.tgz", - "integrity": "sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.3.tgz", + "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==", "funding": [ { "type": "github", @@ -2629,6 +2642,12 @@ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", "optional": true }, + "@nodable/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==", + "optional": true + }, "@opentelemetry/api": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", @@ -3237,23 +3256,24 @@ "optional": true }, "fast-xml-builder": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz", - "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz", + "integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==", "optional": true, "requires": { "path-expression-matcher": "^1.1.3" } }, "fast-xml-parser": { - "version": "5.5.7", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.5.7.tgz", - "integrity": "sha512-LteOsISQ2GEiDHZch6L9hB0+MLoYVLToR7xotrzU0opCICBkxOPgHAy1HxAvtxfJNXDJpgAsQN30mkrfpO2Prg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.1.tgz", + "integrity": "sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA==", "optional": true, "requires": { - "fast-xml-builder": "^1.1.4", - "path-expression-matcher": "^1.1.3", - "strnum": "^2.2.0" + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.5", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" } }, "faye-websocket": { @@ -3830,9 +3850,9 @@ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, "path-expression-matcher": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.1.3.tgz", - "integrity": "sha512-qdVgY8KXmVdJZRSS1JdEPOKPdTiEK/pi0RkcT2sw1RhXxohdujUlJFPuS1TSkevZ9vzd3ZlL7ULl1MHGTApKzQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", "optional": true }, "path-to-regexp": { @@ -4112,9 +4132,9 @@ } }, "strnum": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.1.tgz", - "integrity": "sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.2.3.tgz", + "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==", "optional": true }, "stubs": { From a7eec5af4c8ae51908ad684532b11ea3d7564117 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Mon, 27 Apr 2026 13:35:45 -0700 Subject: [PATCH 044/137] chore(ci): nightly build (#18229) --- .github/workflows/android.yaml | 8 +- .github/workflows/e2e_tests_fdc.yaml | 12 +- .github/workflows/ios.yaml | 8 +- .github/workflows/macos.yaml | 8 +- .github/workflows/nightly.yaml | 56 +++++- .../scripts/nightly_issue_dashboard.dart | 164 +++++++++--------- .github/workflows/update_dashboard.yaml | 31 ---- .github/workflows/web.yaml | 12 +- .github/workflows/windows.yaml | 9 +- 9 files changed, 174 insertions(+), 134 deletions(-) delete mode 100644 .github/workflows/update_dashboard.yaml diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 5e4f6d5f34b9..b881255f6094 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -24,16 +24,22 @@ on: - '**/flutterfire_ui/**' - '**.md' workflow_call: + inputs: + nightly_test_mode: + type: boolean + default: false jobs: android: runs-on: ubuntu-latest - timeout-minutes: 45 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} strategy: fail-fast: false matrix: working_directory: ['tests', 'packages/cloud_firestore/cloud_firestore/example'] + exclude: + - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} env: AVD_ARCH: x86_64 AVD_API_LEVEL: 34 diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index b260ad033243..4810a0304fb1 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -21,6 +21,10 @@ on: - '**/example/**' - '**.md' workflow_call: + inputs: + nightly_test_mode: + type: boolean + default: false permissions: contents: read @@ -28,7 +32,7 @@ permissions: jobs: android: runs-on: ubuntu-latest - timeout-minutes: 45 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} strategy: fail-fast: false env: @@ -140,7 +144,7 @@ jobs: ios: runs-on: macos-15 - timeout-minutes: 45 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} strategy: fail-fast: false steps: @@ -261,7 +265,7 @@ jobs: web: runs-on: macos-latest - timeout-minutes: 15 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 15 }} strategy: fail-fast: false steps: @@ -340,7 +344,7 @@ jobs: web-wasm: runs-on: macos-latest - timeout-minutes: 15 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 15 }} strategy: fail-fast: false steps: diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 90859a335e76..da5a9d0d56fc 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -24,16 +24,22 @@ on: - '**/flutterfire_ui/**' - '**.md' workflow_call: + inputs: + nightly_test_mode: + type: boolean + default: false jobs: ios: runs-on: macos-15 - timeout-minutes: 60 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 60 }} strategy: fail-fast: false matrix: working_directory: ['tests', 'packages/cloud_firestore/cloud_firestore/example'] + exclude: + - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index 0ec18a7b9d1c..f23821f92a39 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -24,16 +24,22 @@ on: - '**/flutterfire_ui/**' - '**.md' workflow_call: + inputs: + nightly_test_mode: + type: boolean + default: false jobs: macos: runs-on: macos-15 - timeout-minutes: 45 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} strategy: fail-fast: false matrix: working_directory: ['tests', 'packages/cloud_firestore/cloud_firestore/example'] + exclude: + - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index ab82573ec3df..6a1b5967233f 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -1,13 +1,20 @@ name: nightly-ci +run-name: ${{ github.event.inputs.test_mode == 'true' && format('[Test Mode] {0}', github.workflow) || github.workflow }} -# concurrency: -# group: ${{ github.workflow }}-${{ github.ref }} -# cancel-in-progress: false +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false on: - # schedule: - # - cron: '0 4 * * *' - workflow_dispatch: + schedule: + - cron: '0 4 * * *' + # The dispatch is only for test purpose + # workflow_dispatch: + # inputs: + # test_mode: + # description: 'Run in test mode' + # type: boolean + # default: false permissions: contents: read @@ -16,22 +23,59 @@ permissions: jobs: e2e-android: uses: ./.github/workflows/android.yaml + with: + nightly_test_mode: ${{ github.event.inputs.test_mode == 'true' }} secrets: inherit e2e-ios: uses: ./.github/workflows/ios.yaml + with: + nightly_test_mode: ${{ github.event.inputs.test_mode == 'true' }} secrets: inherit e2e-macos: uses: ./.github/workflows/macos.yaml + with: + nightly_test_mode: ${{ github.event.inputs.test_mode == 'true' }} secrets: inherit e2e-web: uses: ./.github/workflows/web.yaml + with: + nightly_test_mode: ${{ github.event.inputs.test_mode == 'true' }} secrets: inherit e2e-windows: uses: ./.github/workflows/windows.yaml + with: + nightly_test_mode: ${{ github.event.inputs.test_mode == 'true' }} secrets: inherit e2e-fdc: uses: ./.github/workflows/e2e_tests_fdc.yaml + with: + nightly_test_mode: ${{ github.event.inputs.test_mode == 'true' }} secrets: inherit e2e-pipeline: uses: ./.github/workflows/e2e_tests_pipeline.yaml + if: ${{ github.event.inputs.test_mode != 'true' }} secrets: inherit + + update-dashboard: + runs-on: ubuntu-latest + if: ${{ always() && !cancelled() }} + needs: [e2e-android, e2e-ios, e2e-macos, e2e-web, e2e-windows, e2e-fdc, e2e-pipeline] + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + - name: Update Dashboard Issue + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TEST_MODE: ${{ github.event.inputs.test_mode == 'true' }} + ANDROID_STATUS: ${{ needs.e2e-android.result }} + IOS_STATUS: ${{ needs.e2e-ios.result }} + MACOS_STATUS: ${{ needs.e2e-macos.result }} + WEB_STATUS: ${{ needs.e2e-web.result }} + WINDOWS_STATUS: ${{ needs.e2e-windows.result }} + FDC_STATUS: ${{ needs.e2e-fdc.result }} + PIPELINE_STATUS: ${{ needs.e2e-pipeline.result }} + REPO: ${{ github.repository }} + run: | + dart .github/workflows/scripts/nightly_issue_dashboard.dart diff --git a/.github/workflows/scripts/nightly_issue_dashboard.dart b/.github/workflows/scripts/nightly_issue_dashboard.dart index a2cf278ec744..1b486ed5612a 100644 --- a/.github/workflows/scripts/nightly_issue_dashboard.dart +++ b/.github/workflows/scripts/nightly_issue_dashboard.dart @@ -19,19 +19,46 @@ void main() async { final env = Platform.environment; final token = env['GITHUB_TOKEN']; final repo = env['REPO']; - final workflowName = env['WORKFLOW_NAME']; - final status = env['STATUS']; - final runId = env['RUN_ID']; + final androidStatus = env['ANDROID_STATUS'] ?? 'skipped'; + final webStatus = env['WEB_STATUS'] ?? 'skipped'; + final iosStatus = env['IOS_STATUS'] ?? 'skipped'; + final macosStatus = env['MACOS_STATUS'] ?? 'skipped'; + final windowsStatus = env['WINDOWS_STATUS'] ?? 'skipped'; + final fdcStatus = env['FDC_STATUS'] ?? 'skipped'; + final pipelineStatus = env['PIPELINE_STATUS'] ?? 'skipped'; + final runId = env['GITHUB_RUN_ID']; final serverUrl = env['GITHUB_SERVER_URL'] ?? 'https://github.com'; - if (token == null || repo == null || workflowName == null || status == null) { - print('Error: Required environment variables not set.'); + final testMode = env['TEST_MODE'] == 'true'; + + if (token == null || repo == null) { + print('Error: GITHUB_TOKEN or REPO environment variables not set.'); exit(1); } final date = DateTime.now().toUtc().toString().substring(0, 10); final runUrl = '$serverUrl/$repo/actions/runs/$runId'; - final statusIcon = _getIcon(status); + final notes = '[View Run]($runUrl)'; + + final androidIcon = _getIcon(androidStatus); + final webIcon = _getIcon(webStatus); + final iosIcon = _getIcon(iosStatus); + final macosIcon = _getIcon(macosStatus); + final windowsIcon = _getIcon(windowsStatus); + final fdcIcon = _getIcon(fdcStatus); + final pipelineIcon = _getIcon(pipelineStatus); + + final newRow = + '| $date | $androidIcon | $iosIcon | $webIcon | $macosIcon | $windowsIcon | $fdcIcon | $pipelineIcon | $notes |'; + + print('New Row: $newRow'); + + if (testMode) { + print('Test mode enabled. Skipping dashboard update.'); + print('The following row would be added to the issue:'); + print(newRow); + return; + } final client = HttpClient(); try { @@ -39,10 +66,10 @@ void main() async { if (issueNumber == null) { print('Issue not found. Creating a new one.'); - await _createIssue(client, token, repo, date, workflowName, statusIcon, runUrl); + await _createIssue(client, token, repo, newRow); } else { print('Found issue #$issueNumber. Updating.'); - await _updateIssue(client, token, repo, issueNumber, date, workflowName, statusIcon, runUrl); + await _updateIssue(client, token, repo, issueNumber, newRow); } } finally { client.close(); @@ -64,29 +91,10 @@ String _getIcon(String status) { } } -int _getColumnIndex(String workflowName) { - switch (workflowName) { - case 'e2e-android': - return 1; - case 'e2e-iOS': - return 2; - case 'e2e-web': - return 3; - case 'e2e-macOS': - return 4; - case 'e2e-windows': - return 5; - case 'e2e-fdc': - return 6; - case 'e2e-pipeline': - return 7; - default: - return -1; - } -} - Future _findIssue(HttpClient client, String token, String repo) async { - final url = Uri.parse('https://api.github.com/repos/$repo/issues?labels=nightly-testing&state=open'); + final url = Uri.parse( + 'https://api.github.com/repos/$repo/issues?labels=nightly-testing&state=open', + ); final request = await client.getUrl(url); _addHeaders(request, token); @@ -107,31 +115,27 @@ Future _findIssue(HttpClient client, String token, String repo) async { return null; } -Future _createIssue(HttpClient client, String token, String repo, String date, String workflowName, String statusIcon, String runUrl) async { +Future _createIssue( + HttpClient client, + String token, + String repo, + String newRow, +) async { final url = Uri.parse('https://api.github.com/repos/$repo/issues'); final request = await client.postUrl(url); _addHeaders(request, token); - final colIndex = _getColumnIndex(workflowName); - final rowData = List.filled(9, '➖ Skipped'); - rowData[0] = date; - if (colIndex != -1) { - rowData[colIndex] = statusIcon; - } - rowData[8] = '[View Run]($runUrl)'; - - final newRow = '| ${rowData.join(' | ')} |'; - final body = { 'title': '[FlutterFire] Nightly Integration Testing Report', 'labels': ['nightly-testing'], - 'body': ''' + 'body': + ''' ## Testing History (last 30 days) | Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes | | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | $newRow -''' +''', }; request.add(utf8.encode(jsonEncode(body))); @@ -145,8 +149,16 @@ $newRow } } -Future _updateIssue(HttpClient client, String token, String repo, int issueNumber, String date, String workflowName, String statusIcon, String runUrl) async { - final getUrl = Uri.parse('https://api.github.com/repos/$repo/issues/$issueNumber'); +Future _updateIssue( + HttpClient client, + String token, + String repo, + int issueNumber, + String newRow, +) async { + final getUrl = Uri.parse( + 'https://api.github.com/repos/$repo/issues/$issueNumber', + ); final getRequest = await client.getUrl(getUrl); _addHeaders(getRequest, token); @@ -160,9 +172,11 @@ Future _updateIssue(HttpClient client, String token, String repo, int issu final issueJson = jsonDecode(getBody); String currentBody = issueJson['body'] ?? ''; - final updatedBody = _updateTable(currentBody, date, workflowName, statusIcon, runUrl); + final updatedBody = _appendRow(currentBody, newRow); - final patchUrl = Uri.parse('https://api.github.com/repos/$repo/issues/$issueNumber'); + final patchUrl = Uri.parse( + 'https://api.github.com/repos/$repo/issues/$issueNumber', + ); final patchRequest = await client.patchUrl(patchUrl); _addHeaders(patchRequest, token); @@ -179,15 +193,12 @@ Future _updateIssue(HttpClient client, String token, String repo, int issu } } -String _updateTable(String currentBody, String date, String workflowName, String statusIcon, String runUrl) { +String _appendRow(String currentBody, String newRow) { final lines = currentBody.split('\n'); final tableRows = []; var inTable = false; - var foundToday = false; - final colIndex = _getColumnIndex(workflowName); - for (var i = 0; i < lines.length; i++) { - final line = lines[i]; + for (final line in lines) { if (line.startsWith('| Date |')) { inTable = true; continue; @@ -196,32 +207,11 @@ String _updateTable(String currentBody, String date, String workflowName, String if (line.startsWith('| ---') || line.startsWith('| :---')) { continue; } - final cells = line.split('|').map((c) => c.trim()).toList(); - if (cells.length >= 10) { - final rowDate = cells[1]; - if (rowDate == date) { - foundToday = true; - if (colIndex != -1) { - cells[colIndex + 1] = statusIcon; - } - cells[9] = '[View Run]($runUrl)'; - tableRows.add('| ${cells.sublist(1, 10).join(' | ')} |'); - } else { - tableRows.add(line); - } - } + tableRows.add(line); } } - if (!foundToday) { - final rowData = List.filled(9, '➖ Skipped'); - rowData[0] = date; - if (colIndex != -1) { - rowData[colIndex] = statusIcon; - } - rowData[8] = '[View Run]($runUrl)'; - tableRows.add('| ${rowData.join(' | ')} |'); - } + tableRows.add(newRow); if (tableRows.length > 30) { tableRows.removeRange(0, tableRows.length - 30); @@ -233,8 +223,12 @@ String _updateTable(String currentBody, String date, String workflowName, String for (final line in lines) { if (line.startsWith('| Date |')) { if (!processedTable) { - newBodyLines.add('| Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes |'); - newBodyLines.add('| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |'); + newBodyLines.add( + '| Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes |', + ); + newBodyLines.add( + '| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |', + ); newBodyLines.addAll(tableRows); processedTable = true; } @@ -251,15 +245,13 @@ String _updateTable(String currentBody, String date, String workflowName, String if (!processedTable) { newBodyLines.add('## Testing History (last 30 days)'); newBodyLines.add(''); - newBodyLines.add('| Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes |'); - newBodyLines.add('| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |'); - final rowData = List.filled(9, '➖ Skipped'); - rowData[0] = date; - if (colIndex != -1) { - rowData[colIndex] = statusIcon; - } - rowData[8] = '[View Run]($runUrl)'; - newBodyLines.add('| ${rowData.join(' | ')} |'); + newBodyLines.add( + '| Date | Android | iOS | Web | MacOS | Windows | FDC | Pipeline | Notes |', + ); + newBodyLines.add( + '| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |', + ); + newBodyLines.add(newRow); } return newBodyLines.join('\n'); diff --git a/.github/workflows/update_dashboard.yaml b/.github/workflows/update_dashboard.yaml deleted file mode 100644 index d0c14a4a6ce5..000000000000 --- a/.github/workflows/update_dashboard.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: update-dashboard - -on: - workflow_run: - workflows: ["e2e-android", "e2e-iOS", "e2e-web", "e2e-macOS", "e2e-windows", "e2e-fdc", "e2e-pipeline"] - types: - - completed - -permissions: - contents: read - issues: write - -jobs: - update: - runs-on: ubuntu-latest - timeout-minutes: 5 - if: ${{ github.event.workflow_run.event == 'schedule' || github.event.workflow_run.event == 'workflow_dispatch' }} - steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff - with: - channel: 'stable' - - name: Update Dashboard Issue - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - WORKFLOW_NAME: ${{ github.event.workflow_run.name }} - STATUS: ${{ github.event.workflow_run.conclusion }} - RUN_ID: ${{ github.event.workflow_run.id }} - REPO: ${{ github.repository }} - run: | - dart .github/workflows/scripts/nightly_issue_dashboard.dart diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index d77f622f367f..8602f05ba8a6 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -24,16 +24,22 @@ on: - '**/flutterfire_ui/**' - '**.md' workflow_call: + inputs: + nightly_test_mode: + type: boolean + default: false jobs: web: runs-on: macos-latest - timeout-minutes: 15 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 15 }} strategy: fail-fast: false matrix: working_directory: ['tests', 'packages/cloud_firestore/cloud_firestore/example'] + exclude: + - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a @@ -178,12 +184,14 @@ jobs: web-wasm: runs-on: macos-latest - timeout-minutes: 15 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 15 }} strategy: fail-fast: false matrix: working_directory: ['tests', 'packages/cloud_firestore/cloud_firestore/example'] + exclude: + - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 52bae4e486cf..71b7013d83bb 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -24,11 +24,15 @@ on: - '**/flutterfire_ui/**' - '**.md' workflow_call: + inputs: + nightly_test_mode: + type: boolean + default: false jobs: windows: runs-on: windows-latest - timeout-minutes: 45 + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b @@ -62,7 +66,8 @@ jobs: # We cannot run the tests but we can still try to build the app because of https://github.com/flutter/flutter/issues/79213 windows-firestore: runs-on: windows-latest - timeout-minutes: 45 + if: ${{ !inputs.nightly_test_mode }} + timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b From 4351179d357eeab6b23ec66f45d558c02d3fde69 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:40:25 +0000 Subject: [PATCH 045/137] fix(auth, iOS): update import path for autogenerated messages (#18227) --- .../Sources/firebase_auth/firebase_auth_messages.g.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m index d110643c17fc..82ae8cfcccc7 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/firebase_auth_messages.g.m @@ -4,7 +4,7 @@ // Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import "firebase_auth_messages.g.h" +#import "include/Public/firebase_auth_messages.g.h" #if TARGET_OS_OSX @import FlutterMacOS; From ea5bd20829343c83d2ef3d10f0daae71a33641f5 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 30 Apr 2026 10:43:03 +0100 Subject: [PATCH 046/137] chore: fix melos bs (#18234) --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 7be36ca5bd83..ff846f40a643 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -105,7 +105,7 @@ melos: # https://github.com/dart-lang/pub/issues/3404). Disabling this feature # makes the CI much more stable. runPubGetInParallel: false - usePubspecOverrides: true + usePubspecOverrides: false scripts: lint:all: From b9c8a9e2993187c782c94398136aac9bf5418061 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 30 Apr 2026 10:56:39 +0100 Subject: [PATCH 047/137] fix(firestore,windows): fix CI issue (#18218) * fix(firestore,windows): fix CI issue * fix(firestore,windows): emit Pigeon objects on snapshot event sinks The Pigeon 26 upgrade (#18205) changed the Dart-side EventChannel handlers in `method_channel_document_reference.dart` and `method_channel_query.dart` to expect the generated Pigeon class directly (`snapshot as InternalDocumentSnapshot` / `InternalQuerySnapshot`) and updated the Android stream handlers to emit `PigeonParser.toPigeonQuerySnapshot(...)` / `toPigeonDocumentSnapshot(...)` directly, but the Windows stream handlers in `cloud_firestore_plugin.cpp` were missed and still emitted `Parse...(...).ToEncodableList()`. As a result, on Windows every `DocumentReference.snapshots()`, `Query.snapshots()` and (transitively) `FirebaseFirestore.snapshotsInSync()` call threw `type 'List' is not a subtype of type 'InternalDocumentSnapshot' in type cast` on the first event. Wrap the Pigeon class in `CustomEncodableValue(...)` so the Pigeon-aware codec on the EventChannel serializes it end-to-end, the same way Android does. * test(firestore,windows): skip cache snapshot listener tests on Windows * skip vectorevalues * try that * more fixes * fixes * fix * fix * fixes * format --- .github/workflows/windows.yaml | 12 +- .../document_reference_e2e.dart | 110 +++--- .../example/integration_test/query_e2e.dart | 97 +++-- .../integration_test/transaction_e2e.dart | 163 +++++---- .../integration_test/vector_value_e2e.dart | 12 + .../windows/cloud_firestore_plugin.cpp | 335 +++++++++++++----- .../windows/cloud_firestore_plugin.h | 3 +- .../windows/firestore_codec.cpp | 2 +- 8 files changed, 483 insertions(+), 251 deletions(-) diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 71b7013d83bb..272cf888fbc8 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -63,7 +63,6 @@ jobs: - name: Start Firebase Emulator and run tests run: cd ./.github/workflows/scripts && firebase emulators:exec --project flutterfire-e2e-tests "cd ../../../tests && flutter test .\integration_test\e2e_test.dart -d windows --verbose" -# We cannot run the tests but we can still try to build the app because of https://github.com/flutter/flutter/issues/79213 windows-firestore: runs-on: windows-latest if: ${{ !inputs.nightly_test_mode }} @@ -94,4 +93,13 @@ jobs: run: | npm install -g firebase-tools - name: Start Firebase Emulator and run tests - run: cd ./.github/workflows/scripts && firebase emulators:exec --project flutterfire-e2e-tests "cd ../../../packages/cloud_firestore/cloud_firestore/example && flutter build windows" + run: | + cd ./.github/workflows/scripts + firebase emulators:exec --project flutterfire-e2e-tests "cd ../../../packages/cloud_firestore/cloud_firestore/example && flutter drive --target=.\integration_test\e2e_test.dart --driver=.\test_driver\integration_test.dart -d windows --verbose" 2>&1 | Tee-Object -FilePath output.log + $exitCode = $LASTEXITCODE + $output = Get-Content output.log -Raw + if ($output -match '\[E\]' -or $output -match 'Some tests failed') { + Write-Error "All tests did not pass. Please check the logs for more information." + exit 1 + } + exit $exitCode diff --git a/packages/cloud_firestore/cloud_firestore/example/integration_test/document_reference_e2e.dart b/packages/cloud_firestore/cloud_firestore/example/integration_test/document_reference_e2e.dart index 5e570f983331..9063b00f15b6 100644 --- a/packages/cloud_firestore/cloud_firestore/example/integration_test/document_reference_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/example/integration_test/document_reference_e2e.dart @@ -88,51 +88,62 @@ void runDocumentReferenceTests() { }); }); - test('listens to a single response from cache', () async { - DocumentReference> document = - await initializeTest('document-snapshot'); - Stream>> stream = - document.snapshots(source: ListenSource.cache); - StreamSubscription>>? - subscription; - - subscription = stream.listen( - expectAsync1( - (DocumentSnapshot> snapshot) { - expect(snapshot.exists, isFalse); - }, - reason: 'Stream should only have been called once.', - ), - ); - - addTearDown(() async { - await subscription?.cancel(); - }); - }); + test( + 'listens to a single response from cache', + () async { + DocumentReference> document = + await initializeTest('document-snapshot'); + Stream>> stream = + document.snapshots(source: ListenSource.cache); + StreamSubscription>>? + subscription; + + subscription = stream.listen( + expectAsync1( + (DocumentSnapshot> snapshot) { + expect(snapshot.exists, isFalse); + }, + reason: 'Stream should only have been called once.', + ), + ); - test('listens to a document from cache', () async { - DocumentReference> document = - await initializeTest('document-snapshot-cache'); - await document.set({'foo': 'bar'}); - Stream>> stream = - document.snapshots(source: ListenSource.cache); - StreamSubscription>>? - subscription; + addTearDown(() async { + await subscription?.cancel(); + }); + }, + // Listening from cache is not supported on Windows (see + // DocumentReference.snapshots in cloud_firestore). + skip: defaultTargetPlatform == TargetPlatform.windows, + ); - subscription = stream.listen( - expectAsync1( - (DocumentSnapshot> snapshot) { - expect(snapshot.exists, isTrue); - expect(snapshot.data(), equals({'foo': 'bar'})); - }, - reason: 'Stream should only have been called once.', - ), - ); + test( + 'listens to a document from cache', + () async { + DocumentReference> document = + await initializeTest('document-snapshot-cache'); + await document.set({'foo': 'bar'}); + Stream>> stream = + document.snapshots(source: ListenSource.cache); + StreamSubscription>>? + subscription; + + subscription = stream.listen( + expectAsync1( + (DocumentSnapshot> snapshot) { + expect(snapshot.exists, isTrue); + expect(snapshot.data(), equals({'foo': 'bar'})); + }, + reason: 'Stream should only have been called once.', + ), + ); - addTearDown(() async { - await subscription?.cancel(); - }); - }); + addTearDown(() async { + await subscription?.cancel(); + }); + }, + // Listening from cache is not supported on Windows. + skip: defaultTargetPlatform == TargetPlatform.windows, + ); test('listens to multiple documents', () async { DocumentReference> doc1 = @@ -408,7 +419,8 @@ void runDocumentReferenceTests() { 'null': null, 'timestamp': Timestamp.now(), 'geopoint': const GeoPoint(1, 2), - 'vectorValue': const VectorValue([1, 2, 3]), + if (defaultTargetPlatform != TargetPlatform.windows) + 'vectorValue': const VectorValue([1, 2, 3]), 'reference': firestore.doc('foo/bar'), 'nan': double.nan, 'infinity': double.infinity, @@ -445,11 +457,13 @@ void runDocumentReferenceTests() { expect(data['geopoint'], isA()); expect((data['geopoint'] as GeoPoint).latitude, equals(1)); expect((data['geopoint'] as GeoPoint).longitude, equals(2)); - expect(data['vectorValue'], isA()); - expect( - (data['vectorValue'] as VectorValue).toArray(), - equals([1, 2, 3]), - ); + if (defaultTargetPlatform != TargetPlatform.windows) { + expect(data['vectorValue'], isA()); + expect( + (data['vectorValue'] as VectorValue).toArray(), + equals([1, 2, 3]), + ); + } expect(data['reference'], isA()); expect((data['reference'] as DocumentReference).id, equals('bar')); expect(data['nan'].isNaN, equals(true)); diff --git a/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart b/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart index 49b7bb0c932a..4c2df96bb3fc 100644 --- a/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart @@ -295,8 +295,9 @@ void runQueryTests() { await subscription?.cancel(); }); }, - // Failing on CI but works locally - skip: kIsWeb, + // Failing on CI but works locally. Listening from cache is not + // supported on Windows. + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.windows, ); test('listens to multiple queries', () async { @@ -1052,14 +1053,17 @@ void runQueryTests() { isA().having( (e) => e.message, 'message', - contains( - 'Client specified an invalid argument', + anyOf( + contains('Client specified an invalid argument'), + contains('order by clause cannot contain more fields ' + 'after the key'), ), ), ), ); }, - // firebase-js-sdk does not require an orderBy() field to be set for this to work + // firebase-js-sdk does not require an orderBy() field to be set for + // this to work skip: kIsWeb, ); @@ -1106,8 +1110,10 @@ void runQueryTests() { isA().having( (e) => e.message, 'message', - contains( - 'Client specified an invalid argument', + anyOf( + contains('Client specified an invalid argument'), + contains('order by clause cannot contain more fields ' + 'after the key'), ), ), ), @@ -3798,6 +3804,7 @@ void runQueryTests() { 3, ); }, + skip: defaultTargetPlatform == TargetPlatform.windows, ); test( @@ -3820,6 +3827,7 @@ void runQueryTests() { 1, ); }, + skip: defaultTargetPlatform == TargetPlatform.windows, ); test( @@ -3841,6 +3849,7 @@ void runQueryTests() { 1.5, ); }, + skip: defaultTargetPlatform == TargetPlatform.windows, ); test( @@ -3863,6 +3872,7 @@ void runQueryTests() { 1, ); }, + skip: defaultTargetPlatform == TargetPlatform.windows, ); test( @@ -3894,37 +3904,42 @@ void runQueryTests() { 1.5, ); }, + skip: defaultTargetPlatform == TargetPlatform.windows, ); - test('chaining multiples aggregate queries', () async { - final collection = await initializeTest('chaining'); + test( + 'chaining multiples aggregate queries', + () async { + final collection = await initializeTest('chaining'); - await Future.wait([ - collection.add({'foo': 1}), - collection.add({'foo': 2}), - ]); + await Future.wait([ + collection.add({'foo': 1}), + collection.add({'foo': 2}), + ]); - AggregateQuery query = collection - .where('foo', isEqualTo: 1) - .aggregate(count(), sum('foo'), average('foo')); + AggregateQuery query = collection + .where('foo', isEqualTo: 1) + .aggregate(count(), sum('foo'), average('foo')); - AggregateQuerySnapshot snapshot = await query.get(); + AggregateQuerySnapshot snapshot = await query.get(); - expect( - snapshot.count, - 1, - ); + expect( + snapshot.count, + 1, + ); - expect( - snapshot.getSum('foo'), - 1, - ); + expect( + snapshot.getSum('foo'), + 1, + ); - expect( - snapshot.getAverage('foo'), - 1, - ); - }); + expect( + snapshot.getAverage('foo'), + 1, + ); + }, + skip: defaultTargetPlatform == TargetPlatform.windows, + ); test( 'count() with collectionGroup', @@ -3966,16 +3981,20 @@ void runQueryTests() { }, ); - test('count(), average() & sum() on empty collection', () async { - final collection = await initializeTest('empty-collection'); + test( + 'count(), average() & sum() on empty collection', + () async { + final collection = await initializeTest('empty-collection'); - final snapshot = await collection - .aggregate(count(), sum('foo'), average('foo')) - .get(); - expect(snapshot.count, 0); - expect(snapshot.getSum('foo'), 0); - expect(snapshot.getAverage('foo'), null); - }); + final snapshot = await collection + .aggregate(count(), sum('foo'), average('foo')) + .get(); + expect(snapshot.count, 0); + expect(snapshot.getSum('foo'), 0); + expect(snapshot.getAverage('foo'), null); + }, + skip: defaultTargetPlatform == TargetPlatform.windows, + ); }); group('startAfterDocument', () { diff --git a/packages/cloud_firestore/cloud_firestore/example/integration_test/transaction_e2e.dart b/packages/cloud_firestore/cloud_firestore/example/integration_test/transaction_e2e.dart index 3b5017077dc7..8a55da126ad6 100644 --- a/packages/cloud_firestore/cloud_firestore/example/integration_test/transaction_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/example/integration_test/transaction_e2e.dart @@ -126,39 +126,43 @@ void runTransactionTests() { retry: 2, ); - test('should collide if number of maxAttempts is too low', () async { - DocumentReference> doc1 = - await initializeTest('transaction-maxAttempts-2'); + test( + 'should collide if number of maxAttempts is too low', + () async { + DocumentReference> doc1 = + await initializeTest('transaction-maxAttempts-2'); - await doc1.set({'test': 0}); + await doc1.set({'test': 0}); - await expectLater( - Future.wait([ - firestore.runTransaction( - (Transaction transaction) async { - final value = await transaction.get(doc1); - transaction.set(doc1, { - 'test': value['test'] + 1, - }); - }, - maxAttempts: 1, - ), - firestore.runTransaction( - (Transaction transaction) async { - final value = await transaction.get(doc1); - transaction.set(doc1, { - 'test': value['test'] + 1, - }); - }, - maxAttempts: 1, + await expectLater( + Future.wait([ + firestore.runTransaction( + (Transaction transaction) async { + final value = await transaction.get(doc1); + transaction.set(doc1, { + 'test': value['test'] + 1, + }); + }, + maxAttempts: 1, + ), + firestore.runTransaction( + (Transaction transaction) async { + final value = await transaction.get(doc1); + transaction.set(doc1, { + 'test': value['test'] + 1, + }); + }, + maxAttempts: 1, + ), + ]), + throwsA( + isA() + .having((e) => e.code, 'code', 'failed-precondition'), ), - ]), - throwsA( - isA() - .having((e) => e.code, 'code', 'failed-precondition'), - ), - ); - }); + ); + }, + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.windows, + ); test('runs multiple transactions in parallel', () async { DocumentReference> doc1 = @@ -188,19 +192,23 @@ void runTransactionTests() { expect(snapshot2.data()!['test'], equals('value4')); }); - test('should abort if timeout is exceeded', () async { - await expectLater( - firestore.runTransaction( - (Transaction transaction) => - Future.delayed(const Duration(seconds: 2)), - timeout: const Duration(seconds: 1), - ), - throwsA( - isA() - .having((e) => e.code, 'code', 'deadline-exceeded'), - ), - ); - }); + test( + 'should abort if timeout is exceeded', + () async { + await expectLater( + firestore.runTransaction( + (Transaction transaction) => + Future.delayed(const Duration(seconds: 2)), + timeout: const Duration(seconds: 1), + ), + throwsA( + isA() + .having((e) => e.code, 'code', 'deadline-exceeded'), + ), + ); + }, + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.windows, + ); test('should throw with exception', () async { try { @@ -217,23 +225,26 @@ void runTransactionTests() { } }); - test('should throw a native error, and convert to a [FirebaseException]', - () async { - DocumentReference> documentReference = - firestore.doc('not-allowed/document'); + test( + 'should throw a native error, and convert to a [FirebaseException]', + () async { + DocumentReference> documentReference = + firestore.doc('not-allowed/document'); - try { - await firestore.runTransaction((Transaction transaction) async { - transaction.set(documentReference, {'foo': 'bar'}); - }); - fail('Transaction should not have resolved'); - } on FirebaseException catch (e) { - expect(e.code, equals('permission-denied')); - return; - } catch (e) { - fail('Transaction threw invalid exception'); - } - }); + try { + await firestore.runTransaction((Transaction transaction) async { + transaction.set(documentReference, {'foo': 'bar'}); + }); + fail('Transaction should not have resolved'); + } on FirebaseException catch (e) { + expect(e.code, equals('permission-denied')); + return; + } catch (e) { + fail('Transaction threw invalid exception'); + } + }, + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.windows, + ); group('Transaction.get()', () { test('should throw if get is called after a command', () async { @@ -251,23 +262,25 @@ void runTransactionTests() { }); test( - 'should throw a native error, and convert to a [FirebaseException]', - () async { - DocumentReference> documentReference = - firestore.doc('not-allowed/document'); + 'should throw a native error, and convert to a [FirebaseException]', + () async { + DocumentReference> documentReference = + firestore.doc('not-allowed/document'); - try { - await firestore.runTransaction((Transaction transaction) async { - await transaction.get(documentReference); - }); - fail('Transaction should not have resolved'); - } on FirebaseException catch (e) { - expect(e.code, equals('permission-denied')); - return; - } catch (e) { - fail('Transaction threw invalid exception'); - } - }); + try { + await firestore.runTransaction((Transaction transaction) async { + await transaction.get(documentReference); + }); + fail('Transaction should not have resolved'); + } on FirebaseException catch (e) { + expect(e.code, equals('permission-denied')); + return; + } catch (e) { + fail('Transaction threw invalid exception'); + } + }, + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.windows, + ); // ignore: todo // TODO(Salakar): Test seems to fail sometimes. Will look at in a future PR. diff --git a/packages/cloud_firestore/cloud_firestore/example/integration_test/vector_value_e2e.dart b/packages/cloud_firestore/cloud_firestore/example/integration_test/vector_value_e2e.dart index 3163a65b36a4..e10b4689e642 100644 --- a/packages/cloud_firestore/cloud_firestore/example/integration_test/vector_value_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/example/integration_test/vector_value_e2e.dart @@ -3,9 +3,21 @@ // BSD-style license that can be found in the LICENSE file. import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; void runVectorValueTests() { + if (defaultTargetPlatform == TargetPlatform.windows) { + group('$VectorValue', () { + test( + 'is not supported on Windows', + () {}, + skip: 'The Firebase C++ SDK does not expose Firestore vector values.', + ); + }); + return; + } + group('$VectorValue', () { late FirebaseFirestore firestore; diff --git a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp index 597a60adbae1..46d7f52dd372 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp +++ b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.cpp @@ -15,9 +15,11 @@ #include #include +#include #include #include #include +#include #include #include "cloud_firestore/plugin_version.h" @@ -40,9 +42,160 @@ using flutter::EncodableValue; namespace cloud_firestore_windows { static std::string kLibraryName = "flutter-fire-fst"; + +namespace { + +constexpr wchar_t kTaskRunnerWindowClassName[] = + L"CloudFirestoreWindowsTaskRunnerWindow"; +constexpr UINT kTaskRunnerWindowMessage = WM_APP + 0x4673; + +class PlatformThreadDispatcher { + public: + static PlatformThreadDispatcher& GetInstance() { + static PlatformThreadDispatcher instance; + return instance; + } + + void Initialize() { + std::lock_guard lock(mutex_); + if (window_ != nullptr) { + return; + } + + platform_thread_id_ = GetCurrentThreadId(); + + WNDCLASSW window_class = {}; + window_class.lpfnWndProc = PlatformThreadDispatcher::WindowProc; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.lpszClassName = kTaskRunnerWindowClassName; + + RegisterClassW(&window_class); + window_ = + CreateWindowExW(0, kTaskRunnerWindowClassName, L"", 0, 0, 0, 0, 0, + HWND_MESSAGE, nullptr, window_class.hInstance, this); + } + + void Post(std::function task) { + if (GetCurrentThreadId() == platform_thread_id_) { + task(); + return; + } + + { + std::lock_guard lock(mutex_); + tasks_.push(std::move(task)); + } + PostMessageW(window_, kTaskRunnerWindowMessage, 0, 0); + } + + private: + static LRESULT CALLBACK WindowProc(HWND window, UINT message, WPARAM wparam, + LPARAM lparam) { + if (message == WM_NCCREATE) { + auto create_struct = reinterpret_cast(lparam); + SetWindowLongPtr( + window, GWLP_USERDATA, + reinterpret_cast(create_struct->lpCreateParams)); + return TRUE; + } + + auto dispatcher = reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); + if (dispatcher != nullptr && message == kTaskRunnerWindowMessage) { + dispatcher->ProcessTasks(); + return 0; + } + + return DefWindowProc(window, message, wparam, lparam); + } + + void ProcessTasks() { + std::queue> tasks; + { + std::lock_guard lock(mutex_); + tasks.swap(tasks_); + } + + while (!tasks.empty()) { + tasks.front()(); + tasks.pop(); + } + } + + PlatformThreadDispatcher() = default; + + HWND window_ = nullptr; + DWORD platform_thread_id_ = 0; + std::mutex mutex_; + std::queue> tasks_; +}; + +struct EventSinkState { + std::mutex mutex; + std::unique_ptr> events; + bool active = true; +}; + +void SendSuccessOnPlatformThread(std::shared_ptr state, + flutter::EncodableValue value) { + if (!state) { + return; + } + + PlatformThreadDispatcher::GetInstance().Post( + [state, value = std::move(value)]() mutable { + std::lock_guard lock(state->mutex); + if (state->active && state->events) { + state->events->Success(value); + } + }); +} + +void SendErrorOnPlatformThread(std::shared_ptr state, + const std::string& code, + const std::string& message, + flutter::EncodableValue details, + bool end_stream = false) { + if (!state) { + return; + } + + PlatformThreadDispatcher::GetInstance().Post( + [state, code, message, details = std::move(details), end_stream]() { + std::lock_guard lock(state->mutex); + if (!state->active || !state->events) { + return; + } + + state->events->Error(code, message, details); + if (end_stream) { + state->events->EndOfStream(); + state->active = false; + } + }); +} + +void EndStreamOnPlatformThread(std::shared_ptr state) { + if (!state) { + return; + } + + PlatformThreadDispatcher::GetInstance().Post([state]() { + std::lock_guard lock(state->mutex); + if (state->active && state->events) { + state->events->EndOfStream(); + state->active = false; + } + }); +} + +} // namespace + // static void CloudFirestorePlugin::RegisterWithRegistrar( flutter::PluginRegistrarWindows* registrar) { + PlatformThreadDispatcher::GetInstance().Initialize(); + auto channel = std::make_unique>( registrar->messenger(), "cloud_firestore", @@ -130,8 +283,7 @@ std::map>> stream_handlers_; -std::map>> +std::map*> cloud_firestore_windows::CloudFirestorePlugin::transaction_handlers_; std::map> cloud_firestore_windows::CloudFirestorePlugin::transactions_; @@ -542,10 +694,12 @@ class LoadBundleStreamHandler const flutter::EncodableValue* arguments, std::unique_ptr>&& events) override { - events_ = std::move(events); + events_state_ = std::make_shared(); + events_state_->events = std::move(events); events.reset(); firestore_->LoadBundle( - bundle_, [this](const LoadBundleTaskProgress& progress) { + bundle_, + [events_state = events_state_](const LoadBundleTaskProgress& progress) { flutter::EncodableMap map; map[flutter::EncodableValue("bytesLoaded")] = flutter::EncodableValue(progress.bytes_loaded()); @@ -563,9 +717,9 @@ class LoadBundleStreamHandler details[EncodableValue("message")] = EncodableValue("Error loading the bundle"); - events_->Error("firebase_firestore", "Error loading the bundle", - details); - events_->EndOfStream(); + SendErrorOnPlatformThread(events_state, "firebase_firestore", + "Error loading the bundle", + EncodableValue(details), true); return; } case LoadBundleTaskProgress::State::kInProgress: { @@ -574,7 +728,7 @@ class LoadBundleStreamHandler map[flutter::EncodableValue("taskState")] = flutter::EncodableValue("running"); - events_->Success(map); + SendSuccessOnPlatformThread(events_state, EncodableValue(map)); break; } case LoadBundleTaskProgress::State::kSuccess: { @@ -582,8 +736,8 @@ class LoadBundleStreamHandler map[flutter::EncodableValue("taskState")] = flutter::EncodableValue("success"); - events_->Success(map); - events_->EndOfStream(); + SendSuccessOnPlatformThread(events_state, EncodableValue(map)); + EndStreamOnPlatformThread(events_state); break; } } @@ -593,13 +747,13 @@ class LoadBundleStreamHandler std::unique_ptr> OnCancelInternal(const flutter::EncodableValue* arguments) override { - events_->EndOfStream(); + EndStreamOnPlatformThread(events_state_); return nullptr; } private: Firestore* firestore_; - std::unique_ptr> events_; + std::shared_ptr events_state_; std::string bundle_; }; @@ -762,7 +916,8 @@ class SnapshotInSyncStreamHandler const flutter::EncodableValue* arguments, std::unique_ptr>&& events) override { - events_ = std::move(events); + events_state_ = std::make_shared(); + events_state_->events = std::move(events); events.reset(); // We do this to bind the event to the main channel auto boundSendEvent = @@ -778,7 +933,7 @@ class SnapshotInSyncStreamHandler std::unique_ptr> OnCancelInternal(const flutter::EncodableValue* arguments) override { listener_.Remove(); - events_->EndOfStream(); + EndStreamOnPlatformThread(events_state_); return nullptr; } @@ -786,12 +941,14 @@ class SnapshotInSyncStreamHandler sendEventFunc_ = func; } - void SendEvent() { events_->Success(flutter::EncodableValue()); } + void SendEvent() { + SendSuccessOnPlatformThread(events_state_, flutter::EncodableValue()); + } private: Firestore* firestore_; ListenerRegistration listener_; - std::unique_ptr> events_; + std::shared_ptr events_state_; std::function sendEventFunc_; }; @@ -838,7 +995,8 @@ class TransactionStreamHandler const flutter::EncodableValue* arguments, std::unique_ptr>&& events) override { - events_ = std::move(events); + events_state_ = std::make_shared(); + events_state_->events = std::move(events); events.reset(); TransactionOptions options; options.set_max_attempts(maxAttempts_); @@ -854,17 +1012,22 @@ class TransactionStreamHandler flutter::EncodableMap map; map.emplace("appName", firestore_->app()->name()); - events_->Success(flutter::EncodableValue(map)); + SendSuccessOnPlatformThread(events_state_, + flutter::EncodableValue(map)); std::unique_lock lock(mtx_); if (cv_.wait_for(lock, std::chrono::milliseconds(timeout_)) == std::cv_status::timeout) { - events_->Error("Timeout", "Transaction timed out."); - events_->EndOfStream(); + SendErrorOnPlatformThread(events_state_, "Timeout", + "Transaction timed out.", + flutter::EncodableValue(), true); return Error::kErrorDeadlineExceeded; } std::lock_guard command_lock(commands_mutex_); + if (resultType_ == InternalTransactionResult::kFailure) { + return Error::kErrorAborted; + } if (commands_.empty()) return Error::kErrorOk; for (InternalTransactionCommand& command : commands_) { @@ -924,12 +1087,14 @@ class TransactionStreamHandler if (completed_future.error() == firebase::firestore::kErrorOk) { result.insert(std::make_pair(flutter::EncodableValue("complete"), flutter::EncodableValue(true))); - events_->Success(result); + SendSuccessOnPlatformThread(events_state_, + flutter::EncodableValue(result)); } else { - events_->Error("transaction_error", - completed_future.error_message()); + SendErrorOnPlatformThread(events_state_, "transaction_error", + completed_future.error_message(), + flutter::EncodableValue()); } - events_->EndOfStream(); + EndStreamOnPlatformThread(events_state_); }); return nullptr; @@ -939,7 +1104,7 @@ class TransactionStreamHandler OnCancelInternal(const flutter::EncodableValue* arguments) override { std::unique_lock lock(mtx_); cv_.notify_one(); - events_->EndOfStream(); + EndStreamOnPlatformThread(events_state_); return nullptr; } @@ -949,11 +1114,11 @@ class TransactionStreamHandler int maxAttempts_; std::string transactionId_; std::vector commands_; - InternalTransactionResult resultType_; + InternalTransactionResult resultType_ = InternalTransactionResult::kSuccess; std::mutex mtx_; std::mutex commands_mutex_; std::condition_variable cv_; - std::unique_ptr> events_; + std::shared_ptr events_state_; }; void CloudFirestorePlugin::TransactionCreate( @@ -971,16 +1136,13 @@ void CloudFirestorePlugin::TransactionCreate( auto handler = std::make_unique( firestore, static_cast(timeout), static_cast(max_attempts), transactionId); - - // Temporarily release the ownership. - TransactionStreamHandler* raw_handler = handler.release(); - CloudFirestorePlugin::transaction_handlers_[transactionId] = - std::unique_ptr(raw_handler); + TransactionStreamHandler* raw_handler = handler.get(); + CloudFirestorePlugin::transaction_handlers_[transactionId] = raw_handler; // Register the event channel. std::string channelName = RegisterEventChannelWithUUID( "plugins.flutter.io/firebase_firestore/transaction/", transactionId, - std::unique_ptr(raw_handler)); + std::move(handler)); // Return the result (assumed to be transaction ID in this example). result(transactionId); @@ -993,15 +1155,20 @@ void CloudFirestorePlugin::TransactionStoreResult( const InternalTransactionResult& result_type, const flutter::EncodableList* commands, std::function reply)> result) { - if (CloudFirestorePlugin::transaction_handlers_[transaction_id]) { - TransactionStreamHandler& handler = *static_cast( - CloudFirestorePlugin::transaction_handlers_[transaction_id].get()); + auto handler_it = + CloudFirestorePlugin::transaction_handlers_.find(transaction_id); + if (handler_it != CloudFirestorePlugin::transaction_handlers_.end() && + handler_it->second) { + TransactionStreamHandler& handler = + *static_cast(handler_it->second); std::vector commandVector; - for (const auto& element : *commands) { - const InternalTransactionCommand& command = - std::any_cast( - std::get(element)); - commandVector.push_back(command); + if (commands) { + for (const auto& element : *commands) { + const InternalTransactionCommand& command = + std::any_cast( + std::get(element)); + commandVector.push_back(command); + } } handler.ReceiveTransactionResponse(result_type, commandVector); result(std::nullopt); @@ -1557,49 +1724,41 @@ class QuerySnapshotStreamHandler ? MetadataChanges::kInclude : MetadataChanges::kExclude; - events_ = std::move(events); + events_state_ = std::make_shared(); + events_state_->events = std::move(events); events.reset(); listener_ = query_->AddSnapshotListener( metadataChanges, - [this, serverTimestampBehavior = serverTimestampBehavior_, + [events_state = events_state_, + serverTimestampBehavior = serverTimestampBehavior_, metadataChanges](const firebase::firestore::QuerySnapshot& snapshot, firebase::firestore::Error error, const std::string& errorMessage) mutable { if (error == firebase::firestore::kErrorOk) { - flutter::EncodableList toListResult(3); - std::vector documents; - std::vector documentChanges; - - for (const auto& documentSnapshot : snapshot.documents()) { - documents.push_back(ParseDocumentSnapshot(documentSnapshot, - serverTimestampBehavior) - .ToEncodableList()); - } - - // Assuming querySnapshot.getDocumentChanges() returns an iterable - // collection - for (const auto& documentChange : - snapshot.DocumentChanges(metadataChanges)) { - documentChanges.push_back( - ParseDocumentChange(documentChange, serverTimestampBehavior) - .ToEncodableList()); - } - - toListResult[0] = documents; - toListResult[1] = documentChanges; - toListResult[2] = - ParseSnapshotMetadata(snapshot.metadata()).ToEncodableList(); - - events_->Success(toListResult); + // Emit the Pigeon object directly so the Pigeon-aware codec on + // the EventChannel serializes it end-to-end. Pigeon 26 no longer + // flattens nested types, so sending a raw list here would cause + // the Dart side to receive a List it can no longer + // decode into InternalQuerySnapshot. + SendSuccessOnPlatformThread( + events_state, + CustomEncodableValue(InternalQuerySnapshot( + ParseDocumentSnapshots(snapshot.documents(), + serverTimestampBehavior), + ParseDocumentChanges( + snapshot.DocumentChanges(metadataChanges), + serverTimestampBehavior), + ParseSnapshotMetadata(snapshot.metadata())))); } else { EncodableMap details; details[EncodableValue("code")] = EncodableValue(CloudFirestorePlugin::GetErrorCode(error)); details[EncodableValue("message")] = EncodableValue(errorMessage); - events_->Error("firebase_firestore", errorMessage, details); - events_->EndOfStream(); + SendErrorOnPlatformThread(events_state, "firebase_firestore", + errorMessage, EncodableValue(details), + true); } }); return nullptr; @@ -1608,14 +1767,14 @@ class QuerySnapshotStreamHandler std::unique_ptr> OnCancelInternal(const flutter::EncodableValue* arguments) override { listener_.Remove(); - events_->EndOfStream(); + EndStreamOnPlatformThread(events_state_); return nullptr; } private: ListenerRegistration listener_; std::unique_ptr query_; - std::unique_ptr> events_; + std::shared_ptr events_state_; bool includeMetadataChanges_; firebase::firestore::DocumentSnapshot::ServerTimestampBehavior serverTimestampBehavior_; @@ -1669,27 +1828,35 @@ class DocumentSnapshotStreamHandler ? MetadataChanges::kInclude : MetadataChanges::kExclude; - events_ = std::move(events); + events_state_ = std::make_shared(); + events_state_->events = std::move(events); events.reset(); listener_ = reference_->AddSnapshotListener( metadataChanges, - [this, serverTimestampBehavior = serverTimestampBehavior_, - metadataChanges](const firebase::firestore::DocumentSnapshot& snapshot, - firebase::firestore::Error error, - const std::string& errorMessage) mutable { + [events_state = events_state_, + serverTimestampBehavior = serverTimestampBehavior_]( + const firebase::firestore::DocumentSnapshot& snapshot, + firebase::firestore::Error error, + const std::string& errorMessage) mutable { if (error == firebase::firestore::kErrorOk) { - events_->Success( - ParseDocumentSnapshot(snapshot, serverTimestampBehavior) - .ToEncodableList()); + // Emit the Pigeon object directly so the Pigeon-aware codec on + // the EventChannel serializes it end-to-end. Pigeon 26 no longer + // flattens nested types, so sending a raw list here would cause + // the Dart side to receive a List it can no longer + // decode into InternalDocumentSnapshot. + SendSuccessOnPlatformThread( + events_state, CustomEncodableValue(ParseDocumentSnapshot( + snapshot, serverTimestampBehavior))); } else { EncodableMap details; details[EncodableValue("code")] = EncodableValue(CloudFirestorePlugin::GetErrorCode(error)); details[EncodableValue("message")] = EncodableValue(errorMessage); - events_->Error("firebase_firestore", errorMessage, details); - events_->EndOfStream(); + SendErrorOnPlatformThread(events_state, "firebase_firestore", + errorMessage, EncodableValue(details), + true); } }); return nullptr; @@ -1698,14 +1865,14 @@ class DocumentSnapshotStreamHandler std::unique_ptr> OnCancelInternal(const flutter::EncodableValue* arguments) override { listener_.Remove(); - events_->EndOfStream(); + EndStreamOnPlatformThread(events_state_); return nullptr; } private: firebase::firestore::ListenerRegistration listener_; std::unique_ptr reference_; - std::unique_ptr> events_; + std::shared_ptr events_state_; bool includeMetadataChanges_; firebase::firestore::DocumentSnapshot::ServerTimestampBehavior serverTimestampBehavior_; diff --git a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h index e99dac003c16..84081f5ffd21 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h +++ b/packages/cloud_firestore/cloud_firestore/windows/cloud_firestore_plugin.h @@ -152,8 +152,7 @@ class CloudFirestorePlugin : public flutter::Plugin, event_channels_; static std::map>> stream_handlers_; - static std::map>> - transaction_handlers_; + static std::map*> transaction_handlers_; static std::map> transactions_; diff --git a/packages/cloud_firestore/cloud_firestore/windows/firestore_codec.cpp b/packages/cloud_firestore/cloud_firestore/windows/firestore_codec.cpp index 14be5a1776b0..238479a4776b 100644 --- a/packages/cloud_firestore/cloud_firestore/windows/firestore_codec.cpp +++ b/packages/cloud_firestore/cloud_firestore/windows/firestore_codec.cpp @@ -194,7 +194,7 @@ cloud_firestore_windows::FirestoreCodec::ReadValueOfType( } case DATA_TYPE_INCREMENT_INTEGER: { - int incrementValue = std::get(FirestoreCodec::ReadValue(stream)); + int64_t incrementValue = FirestoreCodec::ReadValue(stream).LongValue(); return CustomEncodableValue(FieldValue::Increment(incrementValue)); } From e8d712defc416e00063677c3f79e433bdd96e627 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 5 May 2026 14:05:05 +0200 Subject: [PATCH 048/137] ci(fdc): improve CI for FDC (#18238) * ci(fdc): improve CI for FDC * try * more debug logs * fix that * improve tests --- .github/workflows/e2e_tests_fdc.yaml | 47 ++---- .../example/integration_test/e2e_test.dart | 33 +++- .../integration_test/websocket_e2e.dart | 159 ++++++++++-------- .../example/start-firebase-emulator.sh | 47 +++++- 4 files changed, 182 insertions(+), 104 deletions(-) diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 4810a0304fb1..3f402dc497db 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -52,18 +52,15 @@ jobs: - name: 'Install Tools' run: | sudo npm i -g firebase-tools - echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV + echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true # Must match the save path exactly path: ~/.cache/firebase/emulators - key: firebase-emulators-v3-${{ env.FIREBASE_TOOLS_VERSION }} - restore-keys: firebase-emulators-v3 + key: firebase-emulators-v4-${{ runner.os }}-${{ env.FIREBASE_TOOLS_VERSION }} - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' @@ -81,6 +78,7 @@ jobs: - name: Start Firebase Emulator run: | cd ./packages/firebase_data_connect/firebase_data_connect/example + pkill -x postgres || true unset PGSERVICEFILE firebase experiments:enable dataconnect ./start-firebase-emulator.sh @@ -136,8 +134,6 @@ jobs: uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} # Must match the restore path exactly path: ~/.cache/firebase/emulators @@ -179,18 +175,15 @@ jobs: - name: 'Install Tools' run: | sudo npm i -g firebase-tools - echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV + echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true # Must match the save path exactly path: ~/.cache/firebase/emulators - key: firebase-emulators-v3-${{ env.FIREBASE_TOOLS_VERSION }} - restore-keys: firebase-emulators-v3 + key: firebase-emulators-v4-${{ runner.os }}-${{ env.FIREBASE_TOOLS_VERSION }} - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' @@ -218,6 +211,7 @@ jobs: run: | sudo chown -R 501:20 "/Users/runner/.npm" cd ./packages/firebase_data_connect/firebase_data_connect/example + pkill -x postgres || true unset PGSERVICEFILE firebase experiments:enable dataconnect ./start-firebase-emulator.sh @@ -232,10 +226,9 @@ jobs: run: | # Uncomment following line to have simulator logs printed out for debugging purposes. # xcrun simctl spawn booted log stream --predicate 'eventMessage contains "flutter"' & - # The iOS simulator sometimes fails to connect the VM Service, hanging for - # 12 minutes before timing out. Use a 6-minute limit and retry once with - # a simulator reboot. Normal connection takes 30s-5min. - perl -e 'alarm 360; exec @ARGV' -- flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --dart-define=CI=true --timeout 10x || { + # The iOS simulator sometimes fails to connect the VM Service. Keep a + # limit around the full test command and retry once with a simulator reboot. + perl -e 'alarm 900; exec @ARGV' -- flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --dart-define=CI=true --timeout 10x || { echo "First attempt failed or timed out. Rebooting simulator and retrying..." xcrun simctl shutdown "$SIMULATOR" || true xcrun simctl boot "$SIMULATOR" @@ -248,8 +241,6 @@ jobs: uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} # Must match the restore path exactly path: ~/.cache/firebase/emulators @@ -295,22 +286,20 @@ jobs: - name: 'Install Tools' run: | sudo npm i -g firebase-tools - echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV + echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true # Must match the save path exactly path: ~/.cache/firebase/emulators - key: firebase-emulators-v3-${{ env.FIREBASE_TOOLS_VERSION }} - restore-keys: firebase-emulators-v3 + key: firebase-emulators-v4-${{ runner.os }}-${{ env.FIREBASE_TOOLS_VERSION }} - name: Start Firebase Emulator run: | sudo chown -R 501:20 "/Users/runner/.npm" cd ./packages/firebase_data_connect/firebase_data_connect/example + pkill -x postgres || true unset PGSERVICEFILE firebase experiments:enable dataconnect ./start-firebase-emulator.sh @@ -336,8 +325,6 @@ jobs: uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} # Must match the restore path exactly path: ~/.cache/firebase/emulators @@ -374,21 +361,19 @@ jobs: - name: 'Install Tools' run: | sudo npm i -g firebase-tools - echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV + echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true # Must match the save path exactly path: ~/.cache/firebase/emulators - key: firebase-emulators-v3-${{ env.FIREBASE_TOOLS_VERSION }} - restore-keys: firebase-emulators-v3 + key: firebase-emulators-v4-${{ runner.os }}-${{ env.FIREBASE_TOOLS_VERSION }} - name: Start Firebase Emulator run: | cd ./packages/firebase_data_connect/firebase_data_connect/example + pkill -x postgres || true unset PGSERVICEFILE firebase experiments:enable dataconnect ./start-firebase-emulator.sh @@ -415,8 +400,6 @@ jobs: uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 continue-on-error: true with: - # The firebase emulators are pure javascript and java, OS-independent - enableCrossOsArchive: true key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} # Must match the restore path exactly path: ~/.cache/firebase/emulators diff --git a/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart index bae5432a6b96..78e604c432cf 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/e2e_test.dart @@ -16,6 +16,36 @@ import 'listen_e2e.dart'; import 'query_e2e.dart'; import 'websocket_e2e.dart'; +Future _signInTestUser() async { + final auth = FirebaseAuth.instance; + const password = 'password'; + final email = 'fdc-test-${DateTime.now().microsecondsSinceEpoch}@mail.com'; + + for (var attempt = 0; attempt < 5; attempt++) { + try { + await auth.createUserWithEmailAndPassword( + email: email, + password: password, + ); + return; + } on FirebaseAuthException catch (e) { + if (e.code == 'email-already-in-use') { + await auth.signInWithEmailAndPassword( + email: email, + password: password, + ); + return; + } + + if (attempt == 4) { + rethrow; + } + } + + await Future.delayed(Duration(seconds: attempt + 1)); + } +} + void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -31,8 +61,7 @@ void main() { .useDataConnectEmulator('127.0.0.1', 9399); await FirebaseAuth.instance.useAuthEmulator('127.0.0.1', 9099); - await FirebaseAuth.instance.createUserWithEmailAndPassword( - email: 'test@mail.com', password: 'password'); + await _signInTestUser(); }); runInstanceTests(); diff --git a/packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart index 930c7d4da0c2..a105b4783184 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/integration_test/websocket_e2e.dart @@ -20,6 +20,18 @@ import 'package:flutter_test/flutter_test.dart'; import 'query_e2e.dart'; // For deleteAllMovies +const _streamTimeout = Duration(seconds: 30); + +Future _waitForStreamEvent(Future future, String description) { + return future.timeout( + _streamTimeout, + onTimeout: () => throw TimeoutException( + 'Timed out waiting for $description', + _streamTimeout, + ), + ); +} + void runWebSocketTests() { group( '$FirebaseDataConnect WebSocketTransport', @@ -44,9 +56,9 @@ void runWebSocketTests() { .subscribe() .listen((value) { if (count1 == 0) { - ready1.complete(); + if (!ready1.isCompleted) ready1.complete(); } else { - update1.complete(); + if (!update1.isCompleted) update1.complete(); } count1++; }); @@ -57,44 +69,57 @@ void runWebSocketTests() { .subscribe() .listen((value) { if (count2 == 0) { - ready2.complete(); + if (!ready2.isCompleted) ready2.complete(); } else { - update2.complete(); + if (!update2.isCompleted) update2.complete(); } count2++; }); - // Wait for both to be ready - await ready1.future; - await ready2.future; - - // Create movies - await MoviesConnector.instance - .createMovie( - genre: 'Action', - title: 'The Matrix', - releaseYear: 1999, - ) - .rating(4.5) - .ref() - .execute(); - - await MoviesConnector.instance - .createMovie( - genre: 'Drama', - title: 'Titanic', - releaseYear: 1997, - ) - .rating(4.8) - .ref() - .execute(); - - // Wait for updates - await update1.future; - await update2.future; - - await sub1.cancel(); - await sub2.cancel(); + try { + // Wait for both to be ready + await _waitForStreamEvent(ready1.future, 'Matrix subscription'); + await _waitForStreamEvent(ready2.future, 'Titan subscription'); + + // Create movies + await MoviesConnector.instance + .createMovie( + genre: 'Action', + title: 'The Matrix', + releaseYear: 1999, + ) + .rating(4.5) + .ref() + .execute(); + + await MoviesConnector.instance + .createMovie( + genre: 'Drama', + title: 'Titanic', + releaseYear: 1997, + ) + .rating(4.8) + .ref() + .execute(); + + // Explicitly resume each active query so this test does not depend on + // emulator-side push timing. + await MoviesConnector.instance + .listMoviesByPartialTitle(input: 'Matrix') + .ref() + .execute(fetchPolicy: QueryFetchPolicy.serverOnly); + await MoviesConnector.instance + .listMoviesByPartialTitle(input: 'Titan') + .ref() + .execute(fetchPolicy: QueryFetchPolicy.serverOnly); + + // Wait for updates + await _waitForStreamEvent(update1.future, 'Matrix update'); + await _waitForStreamEvent(update2.future, 'Titan update'); + } finally { + await sub1.cancel(); + await sub2.cancel(); + } }); testWidgets( @@ -110,36 +135,38 @@ void runWebSocketTests() { .subscribe() .listen((value) { if (count == 0) { - isReady.complete(); + if (!isReady.isCompleted) isReady.complete(); } count++; }); - await isReady.future; - - // Now perform a query, which should go over WebSocket if connected - final result = - await MoviesConnector.instance.listMovies().ref().execute(); - expect(result.data.movies.length, 0); - - // Perform a mutation - await MoviesConnector.instance - .createMovie( - genre: 'Action', - title: 'Inception', - releaseYear: 2010, - ) - .rating(4.9) - .ref() - .execute(); - - // Verify update via query - final result2 = - await MoviesConnector.instance.listMovies().ref().execute(); - expect(result2.data.movies.length, 1); - expect(result2.data.movies[0].title, 'Inception'); - - await sub.cancel(); + try { + await _waitForStreamEvent(isReady.future, 'listMovies subscription'); + + // Now perform a query, which should go over WebSocket if connected + final result = + await MoviesConnector.instance.listMovies().ref().execute(); + expect(result.data.movies.length, 0); + + // Perform a mutation + await MoviesConnector.instance + .createMovie( + genre: 'Action', + title: 'Inception', + releaseYear: 2010, + ) + .rating(4.9) + .ref() + .execute(); + + // Verify update via query + final result2 = + await MoviesConnector.instance.listMovies().ref().execute(); + expect(result2.data.movies.length, 1); + expect(result2.data.movies[0].title, 'Inception'); + } finally { + await sub.cancel(); + } }); testWidgets('should stop receiving events after cancel', @@ -154,14 +181,14 @@ void runWebSocketTests() { .subscribe() .listen((value) { if (count == 0) { - isReady.complete(); + if (!isReady.isCompleted) isReady.complete(); } else { - receivedUpdate.complete(); + if (!receivedUpdate.isCompleted) receivedUpdate.complete(); } count++; }); - await isReady.future; + await _waitForStreamEvent(isReady.future, 'listMovies subscription'); // Cancel the subscription await sub.cancel(); @@ -200,12 +227,12 @@ void runWebSocketTests() { .subscribe() .listen((value) { if (count == 0) { - isReady.complete(); + if (!isReady.isCompleted) isReady.complete(); } count++; }); - await isReady.future; + await _waitForStreamEvent(isReady.future, 'listMovies subscription'); final dataConnect = MoviesConnector.instance.dataConnect; final transport = (dataConnect as dynamic).transport; diff --git a/packages/firebase_data_connect/firebase_data_connect/example/start-firebase-emulator.sh b/packages/firebase_data_connect/firebase_data_connect/example/start-firebase-emulator.sh index 3821f46e402a..ddf9dde87cf0 100755 --- a/packages/firebase_data_connect/firebase_data_connect/example/start-firebase-emulator.sh +++ b/packages/firebase_data_connect/firebase_data_connect/example/start-firebase-emulator.sh @@ -1,5 +1,44 @@ #!/bin/bash -firebase emulators:start --project flutterfire-e2e-tests & -# Added below to fix the e2e tests -# npx "firebase/firebase-tools#mtewani/dart-bugbash" emulators:start --project flutterfire-e2e-tests & -sleep 30 \ No newline at end of file +set -euo pipefail + +LOG_FILE="${TMPDIR:-/tmp}/flutterfire-fdc-emulators.log" +rm -f "$LOG_FILE" + +print_emulator_logs() { + cat "$LOG_FILE" + + if [ -f firebase-debug.log ]; then + echo + echo "firebase-debug.log:" + cat firebase-debug.log + fi + + if [ -f dataconnect-debug.log ]; then + echo + echo "dataconnect-debug.log:" + cat dataconnect-debug.log + fi +} + +firebase emulators:start --project flutterfire-e2e-tests >"$LOG_FILE" 2>&1 & +FIREBASE_PID=$! + +for _ in {1..90}; do + if ! kill -0 "$FIREBASE_PID" 2>/dev/null; then + echo "Firebase emulators exited before becoming ready." + print_emulator_logs + wait "$FIREBASE_PID" + exit 1 + fi + + if grep -q "All emulators ready" "$LOG_FILE"; then + print_emulator_logs + exit 0 + fi + + sleep 1 +done + +echo "Timed out waiting for Firebase emulators to become ready." +print_emulator_logs +exit 1 From 7c2fa5b83201f2f68e031476dc37ad41809215f2 Mon Sep 17 00:00:00 2001 From: Russell Wheatley Date: Tue, 5 May 2026 16:48:42 +0100 Subject: [PATCH 049/137] fix(auth, apple): remove incorrect paths in Package.swift files search paths (#18239) --- .../firebase_auth/ios/firebase_auth/Package.swift | 4 ++-- .../firebase_auth/macos/firebase_auth/Package.swift | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index 2905220b029a..fe4429cf5fc9 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -33,8 +33,8 @@ let package = Package( .process("Resources"), ], cSettings: [ - .headerSearchPath("include/firebase_auth/Private"), - .headerSearchPath("include/firebase_auth/Public"), + .headerSearchPath("include/Private"), + .headerSearchPath("include/Public"), .define("LIBRARY_VERSION", to: "\"\(library_version)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-auth\""), ] diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index 691a98814c6f..c7f29e7ad0e1 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -33,8 +33,8 @@ let package = Package( .process("Resources"), ], cSettings: [ - .headerSearchPath("include/firebase_auth/Private"), - .headerSearchPath("include/firebase_auth/Public"), + .headerSearchPath("include/Private"), + .headerSearchPath("include/Public"), .define("LIBRARY_VERSION", to: "\"\(library_version)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-auth\""), ] From 7ce191cbd598b299cd0ec64b45d1366914367a5d Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Tue, 5 May 2026 10:03:20 -0700 Subject: [PATCH 050/137] feat(core): Add Auth and AppCheck as App's registered service. (#18237) * Add appCheck registration * Add auth registration * update example for the change * clean up registries in app delete * fix analyzer * fix format * restrict the registry only for firebase service * add deprecation message * make sure we still can have valid instance if auth and appCheck initialized after firebaseai init and before api call * format * address review comment * more test added for firebase ai fetch token --- .../firebase_ai/example/lib/main.dart | 5 +- .../example/lib/pages/chat_page.dart | 5 +- .../lib/pages/function_calling_page.dart | 7 +- .../example/lib/pages/grounding_page.dart | 6 +- .../lib/pages/image_generation_page.dart | 7 +- .../firebase_ai/lib/src/base_model.dart | 14 ++- .../firebase_ai/lib/src/firebase_ai.dart | 12 +++ .../firebase_ai/test/base_model_test.dart | 92 +++++++++++++++++++ .../test/firebase_vertexai_test.dart | 17 ++++ .../lib/src/firebase_app_check.dart | 7 +- .../firebase_auth/lib/src/firebase_auth.dart | 6 +- .../firebase_core/lib/src/firebase_app.dart | 17 ++++ .../test/firebase_core_test.dart | 28 ++++++ 13 files changed, 197 insertions(+), 26 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/example/lib/main.dart b/packages/firebase_ai/firebase_ai/example/lib/main.dart index bb42d139229c..b91bbd282276 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/main.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/main.dart @@ -13,6 +13,7 @@ // limitations under the License. import 'package:firebase_ai/firebase_ai.dart'; + import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; @@ -70,10 +71,10 @@ class _GenerativeAISampleState extends State { void _initializeModel(bool useVertexBackend) { if (useVertexBackend) { - final vertexInstance = FirebaseAI.vertexAI(auth: FirebaseAuth.instance); + final vertexInstance = FirebaseAI.vertexAI(); _currentModel = vertexInstance.generativeModel(model: 'gemini-2.5-flash'); } else { - final googleAI = FirebaseAI.googleAI(auth: FirebaseAuth.instance); + final googleAI = FirebaseAI.googleAI(); _currentModel = googleAI.generativeModel(model: 'gemini-2.5-flash'); } } diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart index 8a98241001d4..24a29b59569f 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:firebase_ai/firebase_ai.dart'; import '../widgets/message_widget.dart'; @@ -57,12 +56,12 @@ class _ChatPageState extends State { : null, ); if (widget.useVertexBackend) { - _model = FirebaseAI.vertexAI(auth: FirebaseAuth.instance).generativeModel( + _model = FirebaseAI.vertexAI().generativeModel( model: 'gemini-2.5-flash', generationConfig: generationConfig, ); } else { - _model = FirebaseAI.googleAI(auth: FirebaseAuth.instance).generativeModel( + _model = FirebaseAI.googleAI().generativeModel( model: 'gemini-2.5-flash', generationConfig: generationConfig, ); diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart index ccd09c3e1b34..64c5b39ad9b4 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart @@ -14,7 +14,7 @@ import 'package:flutter/material.dart'; import 'package:firebase_ai/firebase_ai.dart'; -import 'package:firebase_auth/firebase_auth.dart'; + import '../utils/function_call_utils.dart'; import '../widgets/message_widget.dart'; @@ -235,9 +235,8 @@ class _FunctionCallingPageState extends State { : null, ); - final aiClient = widget.useVertexBackend - ? FirebaseAI.vertexAI(auth: FirebaseAuth.instance) - : FirebaseAI.googleAI(auth: FirebaseAuth.instance); + final aiClient = + widget.useVertexBackend ? FirebaseAI.vertexAI() : FirebaseAI.googleAI(); _functionCallModel = aiClient.generativeModel( model: 'gemini-2.5-flash', diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart index 8456be1a9e4c..e895e51c14cd 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:firebase_ai/firebase_ai.dart'; import '../widgets/message_widget.dart'; @@ -74,9 +73,8 @@ class _GroundingPageState extends State { } } - final aiProvider = widget.useVertexBackend - ? FirebaseAI.vertexAI(auth: FirebaseAuth.instance) - : FirebaseAI.googleAI(auth: FirebaseAuth.instance); + final aiProvider = + widget.useVertexBackend ? FirebaseAI.vertexAI() : FirebaseAI.googleAI(); _model = aiProvider.generativeModel( model: 'gemini-2.5-flash', diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart index f4e2f527d3c4..0b66b1e7f6d3 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart @@ -15,7 +15,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:firebase_ai/firebase_ai.dart'; -import 'package:firebase_auth/firebase_auth.dart'; + import '../widgets/message_widget.dart'; class ImageGenerationPage extends StatefulWidget { @@ -47,9 +47,8 @@ class _ImageGenerationPageState extends State { } void _initializeModel() { - final aiClient = widget.useVertexBackend - ? FirebaseAI.vertexAI(auth: FirebaseAuth.instance) - : FirebaseAI.googleAI(auth: FirebaseAuth.instance); + final aiClient = + widget.useVertexBackend ? FirebaseAI.vertexAI() : FirebaseAI.googleAI(); _model = aiClient.generativeModel( model: 'gemini-2.5-flash-image', diff --git a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart index edd5a9a7c7b2..de9e8072d249 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart @@ -282,19 +282,23 @@ abstract class BaseModel { ) { return () async { Map headers = {}; + + final effectiveAppCheck = appCheck ?? app?.getService(); + final effectiveAuth = auth ?? app?.getService(); + // Override the client name in Google AI SDK headers['x-goog-api-client'] = 'gl-dart/$packageVersion fire/$packageVersion'; - if (appCheck != null) { + if (effectiveAppCheck != null) { final appCheckToken = useLimitedUseAppCheckTokens == true - ? await appCheck.getLimitedUseToken() - : await appCheck.getToken(); + ? await effectiveAppCheck.getLimitedUseToken() + : await effectiveAppCheck.getToken(); if (appCheckToken != null) { headers['X-Firebase-AppCheck'] = appCheckToken; } } - if (auth != null) { - final idToken = await auth.currentUser?.getIdToken(); + if (effectiveAuth != null) { + final idToken = await effectiveAuth.currentUser?.getIdToken(); if (idToken != null) { headers['Authorization'] = 'Firebase $idToken'; } diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart index 3d7b22023e15..40971c347362 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart @@ -62,12 +62,18 @@ class FirebaseAI extends FirebasePluginPlatform { /// If pass in [appCheck], request session will get protected from abusing. static FirebaseAI vertexAI({ FirebaseApp? app, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') FirebaseAppCheck? appCheck, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') FirebaseAuth? auth, String? location, bool? useLimitedUseAppCheckTokens, }) { app ??= Firebase.app(); + appCheck ??= app.getService(); + auth ??= app.getService(); var instanceKey = '${app.name}::vertexai::$location'; if (_cachedInstances.containsKey(instanceKey)) { @@ -95,11 +101,17 @@ class FirebaseAI extends FirebasePluginPlatform { /// If pass in [appCheck], request session will get protected from abusing. static FirebaseAI googleAI({ FirebaseApp? app, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') FirebaseAppCheck? appCheck, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') FirebaseAuth? auth, bool? useLimitedUseAppCheckTokens, }) { app ??= Firebase.app(); + appCheck ??= app.getService(); + auth ??= app.getService(); var instanceKey = '${app.name}::googleai'; if (_cachedInstances.containsKey(instanceKey)) { diff --git a/packages/firebase_ai/firebase_ai/test/base_model_test.dart b/packages/firebase_ai/firebase_ai/test/base_model_test.dart index 089ef6fe2382..f4aba609e2dd 100644 --- a/packages/firebase_ai/firebase_ai/test/base_model_test.dart +++ b/packages/firebase_ai/firebase_ai/test/base_model_test.dart @@ -31,6 +31,20 @@ class MockFirebaseApp extends Mock implements FirebaseApp { @override bool get isAutomaticDataCollectionEnabled => true; + + FirebaseAppCheck? mockAppCheck; + FirebaseAuth? mockAuth; + + @override + T? getService() { + if (T == FirebaseAppCheck) { + return mockAppCheck as T?; + } + if (T == FirebaseAuth) { + return mockAuth as T?; + } + return null; + } } // Mock FirebaseOptions @@ -131,6 +145,84 @@ void main() { expect(headers.length, 2); }); + test('firebaseTokens discovers App Check token dynamically at request time', + () async { + final mockApp = MockFirebaseApp(); + final mockAppCheck = MockFirebaseAppCheck(); + when(mockAppCheck.getToken()) + .thenAnswer((_) async => 'dynamic-app-check-token'); + mockApp.mockAppCheck = mockAppCheck; + + final tokenFunction = + BaseModel.firebaseTokens(null, null, mockApp, false); + final headers = await tokenFunction(); + + expect(headers['X-Firebase-AppCheck'], 'dynamic-app-check-token'); + expect(headers['X-Firebase-AppId'], 'test-app-id'); + expect(headers.length, 3); + }); + + test('firebaseTokens discovers Auth ID token dynamically at request time', + () async { + final mockApp = MockFirebaseApp(); + final mockAuth = MockFirebaseAuth(); + final mockUser = MockUser(); + when(mockUser.getIdToken()).thenAnswer((_) async => 'dynamic-id-token'); + when(mockAuth.currentUser).thenReturn(mockUser); + mockApp.mockAuth = mockAuth; + + final tokenFunction = + BaseModel.firebaseTokens(null, null, mockApp, false); + final headers = await tokenFunction(); + + expect(headers['Authorization'], 'Firebase dynamic-id-token'); + expect(headers['X-Firebase-AppId'], 'test-app-id'); + expect(headers.length, 3); + }); + + test('firebaseTokens discovers both tokens dynamically at request time', + () async { + final mockApp = MockFirebaseApp(); + final mockAppCheck = MockFirebaseAppCheck(); + final mockAuth = MockFirebaseAuth(); + final mockUser = MockUser(); + + when(mockAppCheck.getToken()) + .thenAnswer((_) async => 'dynamic-app-check-token'); + when(mockUser.getIdToken()).thenAnswer((_) async => 'dynamic-id-token'); + when(mockAuth.currentUser).thenReturn(mockUser); + + mockApp.mockAppCheck = mockAppCheck; + mockApp.mockAuth = mockAuth; + + final tokenFunction = + BaseModel.firebaseTokens(null, null, mockApp, false); + final headers = await tokenFunction(); + + expect(headers['X-Firebase-AppCheck'], 'dynamic-app-check-token'); + expect(headers['Authorization'], 'Firebase dynamic-id-token'); + expect(headers['X-Firebase-AppId'], 'test-app-id'); + expect(headers.length, 4); + }); + + test( + 'firebaseTokens discovers App Check token dynamically with limited use', + () async { + final mockApp = MockFirebaseApp(); + final mockAppCheck = MockFirebaseAppCheck(); + + when(mockAppCheck.getLimitedUseToken()) + .thenAnswer((_) async => 'dynamic-limited-use-token'); + mockApp.mockAppCheck = mockAppCheck; + + final tokenFunction = BaseModel.firebaseTokens(null, null, mockApp, true); + final headers = await tokenFunction(); + + expect(headers['X-Firebase-AppCheck'], 'dynamic-limited-use-token'); + expect(headers['X-Firebase-AppId'], 'test-app-id'); + expect(headers.length, 3); + }); + test('firebaseTokens includes all tokens if available', () async { final mockAppCheck = MockFirebaseAppCheck(); when(mockAppCheck.getToken()) diff --git a/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart b/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart index 71c347f24333..fe52b397a106 100644 --- a/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart +++ b/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart @@ -14,6 +14,7 @@ import 'package:firebase_ai/firebase_ai.dart'; import 'package:firebase_app_check/firebase_app_check.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -28,6 +29,7 @@ void main() { late FirebaseApp customApp; late FirebaseApp limitTokenApp; late FirebaseAppCheck customAppCheck; + late FirebaseAuth customAuth; late FirebaseAppCheck limitTokenAppCheck; group('FirebaseAI Tests', () { @@ -47,6 +49,7 @@ void main() { appCheck = FirebaseAppCheck.instance; customAppCheck = FirebaseAppCheck.instanceFor(app: customApp); limitTokenAppCheck = FirebaseAppCheck.instanceFor(app: limitTokenApp); + customAuth = FirebaseAuth.instanceFor(app: customApp); }); test('Singleton behavior', () { @@ -96,6 +99,20 @@ void main() { expect(vertexAIAppCheck.useLimitedUseAppCheckTokens, true); }); + test('Instance creation with auto-injected AppCheck', () { + final vertexAI = FirebaseAI.vertexAI(app: customApp); + + expect(vertexAI.app, equals(customApp)); + expect(vertexAI.appCheck, equals(customAppCheck)); + }); + + test('Instance creation with auto-injected Auth', () { + final vertexAI = FirebaseAI.vertexAI(app: customApp); + + expect(vertexAI.app, equals(customApp)); + expect(vertexAI.auth, equals(customAuth)); + }); + test('generativeModel creation with Grounding tools', () { final ai = FirebaseAI.googleAI(); diff --git a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart index 25a1845449e8..ba48413dbddd 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart @@ -5,7 +5,8 @@ part of '../firebase_app_check.dart'; -class FirebaseAppCheck extends FirebasePluginPlatform { +class FirebaseAppCheck extends FirebasePluginPlatform + implements FirebaseService { static Map _firebaseAppCheckInstances = {}; FirebaseAppCheck._({required this.app}) @@ -41,7 +42,9 @@ class FirebaseAppCheck extends FirebasePluginPlatform { /// Returns an instance using a specified [FirebaseApp]. static FirebaseAppCheck instanceFor({required FirebaseApp app}) { return _firebaseAppCheckInstances.putIfAbsent(app.name, () { - return FirebaseAppCheck._(app: app); + final instance = FirebaseAppCheck._(app: app); + app.registerService(instance); + return instance; }); } diff --git a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart index 6906c839d281..f4fec1522d59 100644 --- a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart @@ -6,7 +6,7 @@ part of '../firebase_auth.dart'; /// The entry point of the Firebase Authentication SDK. -class FirebaseAuth extends FirebasePluginPlatform { +class FirebaseAuth extends FirebasePluginPlatform implements FirebaseService { // Cached instances of [FirebaseAuth]. static Map _firebaseAuthInstances = {}; @@ -45,7 +45,9 @@ class FirebaseAuth extends FirebasePluginPlatform { required FirebaseApp app, }) { return _firebaseAuthInstances.putIfAbsent(app.name, () { - return FirebaseAuth._(app: app); + final instance = FirebaseAuth._(app: app); + app.registerService(instance); + return instance; }); } diff --git a/packages/firebase_core/firebase_core/lib/src/firebase_app.dart b/packages/firebase_core/firebase_core/lib/src/firebase_app.dart index 841255c8dd7f..8bf663ffb36b 100644 --- a/packages/firebase_core/firebase_core/lib/src/firebase_app.dart +++ b/packages/firebase_core/firebase_core/lib/src/firebase_app.dart @@ -28,6 +28,7 @@ class FirebaseApp { /// Deleting the default app is not possible and throws an exception. Future delete() async { await _delegate.delete(); + _registries.remove(name); } /// The name of this [FirebaseApp]. @@ -71,4 +72,20 @@ class FirebaseApp { @override String toString() => '$FirebaseApp($name)'; + + static final Map> _registries = {}; + + /// Registers a service instance for this app. + void registerService(T service) { + final registry = _registries.putIfAbsent(name, () => {}); + registry[T] = service; + } + + /// Returns a registered service instance for this app. + T? getService() { + return _registries[name]?[T] as T?; + } } + +/// A marker interface for Firebase services that can be registered in [FirebaseApp]. +abstract class FirebaseService {} diff --git a/packages/firebase_core/firebase_core/test/firebase_core_test.dart b/packages/firebase_core/firebase_core/test/firebase_core_test.dart index 87e4abe4718b..55260d9c9c79 100755 --- a/packages/firebase_core/firebase_core/test/firebase_core_test.dart +++ b/packages/firebase_core/firebase_core/test/firebase_core_test.dart @@ -64,6 +64,30 @@ void main() { mock.app(testAppName), ]); }); + + test('.registerService() and .getService()', () { + FirebaseApp app = Firebase.app(testAppName); + + final testService = TestService(); + app.registerService(testService); + + expect(app.getService(), testService); + }); + + test('.getService() returns null when registry is null', () { + String nullAppName = 'nullApp'; + final FirebaseAppPlatform nullPlatformApp = + FirebaseAppPlatform(nullAppName, testOptions); + when(mock.app(nullAppName)).thenReturn(nullPlatformApp); + + FirebaseApp app = Firebase.app(nullAppName); + expect(app.getService(), isNull); + }); + + test('.getService() returns null when service is not registered', () { + FirebaseApp app = Firebase.app(testAppName); + expect(app.getService(), isNull); + }); }); test('.initializeApp() with demoProjectId', () async { @@ -152,3 +176,7 @@ class MockFirebaseCore extends Mock // ignore: avoid_implementing_value_types class FakeFirebaseAppPlatform extends Fake implements FirebaseAppPlatform {} + +class TestService implements FirebaseService {} + +class AnotherTestService implements FirebaseService {} From ab0b2f98360a0fc557ccdfde691d8e35b303e16b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 6 May 2026 07:51:11 -0700 Subject: [PATCH 051/137] chore: update example dependencies across repo (#18219) * chore: update example dependencies across repo including fixing the latest lints * fix CI bits * fix swift bits in the auth package for desktop --- .../cloud_firestore/pipeline_example/pubspec.yaml | 2 +- .../firebase_ai/example/lib/utils/audio_output.dart | 2 +- .../firebase_ai/firebase_ai/example/pubspec.yaml | 8 ++++---- packages/firebase_ai/firebase_ai/pubspec.yaml | 2 +- .../example/lib/main.dart | 4 ++-- .../firebase_app_installations/example/pubspec.yaml | 2 +- ...rebase_app_installations_platform_interface.dart | 2 -- .../pubspec.yaml | 2 +- .../lib/src/interop/installations_interop.dart | 2 +- .../firebase_app_installations_web/pubspec.yaml | 2 +- .../firebase_data_connect/example/lib/main.dart | 2 +- .../firebase_data_connect/example/pubspec.yaml | 2 +- .../firebase_data_connect/pubspec.yaml | 2 +- .../lib/src/interop/database.dart | 13 +++++++------ .../firebase_database_web/pubspec.yaml | 2 +- .../firebase_messaging/example/lib/main.dart | 8 ++++---- .../firebase_messaging/example/pubspec.yaml | 2 +- .../example/lib/main.dart | 2 +- .../example/pubspec.yaml | 2 +- 19 files changed, 31 insertions(+), 32 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml index 3a5b9b2acb1a..5bff723de6c6 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -51,7 +51,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart index 4e0623eeef97..4ec2a1a4911d 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart @@ -69,7 +69,7 @@ class AudioOutput { return null; } // Play audio stream - handle = await SoLoud.instance.play(myStream); + handle = SoLoud.instance.play(myStream); return stream = myStream; } diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index 4de1694ae5bf..c407f685e649 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -21,7 +21,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - camera: ^0.11.2+1 + camera: ^0.12.0+1 camera_macos: ^0.0.9 cupertino_icons: ^1.0.6 firebase_ai: ^3.11.0 @@ -30,8 +30,8 @@ dependencies: flutter: sdk: flutter flutter_animate: ^4.5.2 - flutter_markdown: ^0.6.20 - flutter_soloud: ^3.1.6 + flutter_markdown: ^0.7.7+1 + flutter_soloud: ^4.0.2 image: ^4.5.4 image_picker: ^1.1.2 path_provider: ^2.1.5 @@ -39,7 +39,7 @@ dependencies: waveform_flutter: ^1.2.0 dev_dependencies: - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter_test: sdk: flutter diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index 6857ad0b0fcd..bdbc9fb8effe 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -32,7 +32,7 @@ dependencies: web_socket_channel: ^3.0.1 dev_dependencies: - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter_test: sdk: flutter matcher: ^0.12.16 diff --git a/packages/firebase_app_installations/firebase_app_installations/example/lib/main.dart b/packages/firebase_app_installations/firebase_app_installations/example/lib/main.dart index 56332b8cbe82..eb64f6a490f1 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/lib/main.dart +++ b/packages/firebase_app_installations/firebase_app_installations/example/lib/main.dart @@ -72,7 +72,7 @@ class _InstallationsCardState extends State { String id = 'None'; String authToken = 'None'; - init() async { + Future init() async { await getId(); await getAuthToken(); } @@ -101,7 +101,7 @@ class _InstallationsCardState extends State { } } - Future getAuthToken([forceRefresh = false]) async { + Future getAuthToken([bool forceRefresh = false]) async { try { final token = await FirebaseInstallations.instance.getToken(forceRefresh); setState(() { diff --git a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml index 72a88b7373c6..2533faea74dd 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: sdk: flutter dev_dependencies: - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter: uses-material-design: true diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/firebase_app_installations_platform_interface.dart b/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/firebase_app_installations_platform_interface.dart index 1c0e99358cfb..2dacec194481 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/firebase_app_installations_platform_interface.dart +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/lib/firebase_app_installations_platform_interface.dart @@ -2,6 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -library firebase_app_installations_platform_interface; - export 'src/platform_interface/firebase_app_installations_platform_interface.dart'; diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 64857f9f4346..9c4c59768c73 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -21,4 +21,4 @@ dev_dependencies: firebase_core_platform_interface: ^6.0.3 flutter_test: sdk: flutter - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 diff --git a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/interop/installations_interop.dart b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/interop/installations_interop.dart index 64a899e4e9fb..00f72ab66cd8 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/interop/installations_interop.dart +++ b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/interop/installations_interop.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. @JS('firebase_installations') -library firebase_interop.installations; +library; import 'dart:js_interop'; diff --git a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml index 6ff04ba25b05..17973ad0ff79 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml @@ -23,7 +23,7 @@ dev_dependencies: firebase_core_platform_interface: ^6.0.3 flutter_test: sdk: flutter - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter: plugin: diff --git a/packages/firebase_data_connect/firebase_data_connect/example/lib/main.dart b/packages/firebase_data_connect/firebase_data_connect/example/lib/main.dart index da63eec3afbd..98f684749ffa 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/lib/main.dart +++ b/packages/firebase_data_connect/firebase_data_connect/example/lib/main.dart @@ -248,7 +248,7 @@ class _DataConnectWidgetState extends State { ])); } - _showError(String message) { + void _showError(String message) { showDialog( context: context, builder: (context) { diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index fa457d5cd9ba..9cfefc6a92bf 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -30,7 +30,7 @@ dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 integration_test: sdk: flutter diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index cf0d70d2d13d..e41d36a699ac 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -34,7 +34,7 @@ dev_dependencies: build_runner: ^2.4.12 firebase_app_check_platform_interface: ^0.3.0 firebase_auth_platform_interface: ^8.1.9 - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart index 66a11d3b8337..e9095b557278 100755 --- a/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/interop/database.dart @@ -125,7 +125,7 @@ class DatabaseReference extends Query { /// /// This method returns [ThenableReference], [DatabaseReference] /// with a [Future] property. - ThenableReference push([value]) => ThenableReference.fromJsObject( + ThenableReference push([Object? value]) => ThenableReference.fromJsObject( database_interop.push(jsObject, value?.jsify())); /// Removes data from actual database location. @@ -148,8 +148,8 @@ class DatabaseReference extends Query { /// Sets a priority for data at actual database location. /// /// The [priority] must be a [String], [num] or `null`, or the error is thrown. - Future setPriority(priority) => - database_interop.setPriority(jsObject, priority).toDart; + Future setPriority(Object? priority) => + database_interop.setPriority(jsObject, priority?.jsify()).toDart; /// Sets data [newVal] at actual database location with provided priority /// [newPriority]. @@ -159,9 +159,10 @@ class DatabaseReference extends Query { /// The [newVal] must be a Dart basic type or the error is thrown. /// The [newPriority] must be a [String], [num] or `null`, or the error /// is thrown. - Future setWithPriority(Object? newVal, newPriority) => database_interop - .setWithPriority(jsObject, newVal?.jsify(), newPriority) - .toDart; + Future setWithPriority(Object? newVal, Object? newPriority) => + database_interop + .setWithPriority(jsObject, newVal?.jsify(), newPriority?.jsify()) + .toDart; /// Atomically updates data at actual database location. /// diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index 0b054ee4949f..addfff88fa07 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -22,7 +22,7 @@ dev_dependencies: firebase_core_platform_interface: ^6.0.3 flutter_test: sdk: flutter - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter: diff --git a/packages/firebase_messaging/firebase_messaging/example/lib/main.dart b/packages/firebase_messaging/firebase_messaging/example/lib/main.dart index 128d68951a0b..6175abd772c4 100644 --- a/packages/firebase_messaging/firebase_messaging/example/lib/main.dart +++ b/packages/firebase_messaging/firebase_messaging/example/lib/main.dart @@ -98,10 +98,10 @@ void showFlutterNotification(RemoteMessage message) { AndroidNotification? android = message.notification?.android; if (notification != null && android != null && !kIsWeb) { flutterLocalNotificationsPlugin.show( - notification.hashCode, - notification.title, - notification.body, - NotificationDetails( + id: notification.hashCode, + title: notification.title, + body: notification.body, + notificationDetails: NotificationDetails( android: AndroidNotificationDetails( channel.id, channel.name, diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index 886e72a31853..9267bfe5b016 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -11,7 +11,7 @@ dependencies: firebase_messaging: ^16.2.0 flutter: sdk: flutter - flutter_local_notifications: ^17.2.1 + flutter_local_notifications: ^21.0.0 http: ^1.0.0 flutter: diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/lib/main.dart b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/lib/main.dart index d8bd1bca91c1..0d996951cb39 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/lib/main.dart +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/lib/main.dart @@ -35,7 +35,7 @@ class _MyAppState extends State { FirebaseCustomModel? model; /// Initially get the lcoal model if found, and asynchronously get the latest one in background. - initWithLocalModel() async { + Future initWithLocalModel() async { final newModel = await FirebaseModelDownloader.instance.getModel( kModelName, FirebaseModelDownloadType.localModelUpdateInBackground); diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml index 97be28d2f7f4..490a03e093b5 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: firebase_ml_model_downloader: ^0.4.2 dev_dependencies: - flutter_lints: ^4.0.0 + flutter_lints: ^6.0.0 flutter: uses-material-design: true From 829fd949bf1644ad9ce73dfb8ed416d89654f989 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 6 May 2026 08:49:27 -0700 Subject: [PATCH 052/137] feat(firebaseai): live session resumption (#18038) * add structure for live session resumption * session resumption config should be session based * init setup * a bit session management fix * some update for session management * refactor live_session connect and resume api * refactor for websocket session open * fix some error while handling the received message * some clean up, and more dev logs * session resume with toggle * some minor updates * fix analyzer * somehow worked resume session * add google search system tool for bidi page * some clean up * format * remove unnecessary logs * minor tweak * fix analyzer * review feedback * fix format * add the sliding window documentation * session resumption api update * address review comments * add more error logs --- .../example/lib/pages/bidi_page.dart | 1059 ++++++++++------- .../example/lib/pages/chat_page.dart | 2 + .../example/lib/utils/audio_input.dart | 2 - .../firebase_ai/lib/firebase_ai.dart | 10 +- .../firebase_ai/lib/src/base_model.dart | 4 - .../firebase_ai/lib/src/live_api.dart | 143 ++- .../firebase_ai/lib/src/live_model.dart | 41 +- .../firebase_ai/lib/src/live_session.dart | 215 +++- .../firebase_ai/test/live_session_test.dart | 99 ++ .../firebase_ai/test/live_test.dart | 8 + 10 files changed, 1068 insertions(+), 515 deletions(-) create mode 100644 packages/firebase_ai/firebase_ai/test/live_session_test.dart diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart index e6c53963bd5f..82286cc60b97 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart @@ -14,9 +14,9 @@ import 'dart:async'; import 'dart:developer' as developer; import 'package:flutter/foundation.dart'; - import 'package:flutter/material.dart'; import 'package:firebase_ai/firebase_ai.dart'; +import 'package:waveform_flutter/waveform_flutter.dart'; import '../utils/audio_input.dart'; import '../utils/audio_output.dart'; @@ -25,466 +25,390 @@ import '../widgets/message_widget.dart'; import '../widgets/audio_visualizer.dart'; import '../widgets/camera_previews.dart'; -class BidiPage extends StatefulWidget { - const BidiPage({ - super.key, - required this.title, +// ============================================================================ +// MEDIA MANAGER +// Isolates Audio and Video hardware stream setup, start, stop, and cleanup. +// ============================================================================ +class BidiMediaManager { + final AudioOutput _audioOutput = AudioOutput(); + final AudioInput _audioInput = AudioInput(); + final VideoInput _videoInput = VideoInput(); + + StreamSubscription? _audioSubscription; + StreamSubscription? _videoSubscription; + + bool videoIsInitialized = false; + + // Expose hardware state/streams to the Controller and UI + Stream? get amplitudeStream => _audioInput.amplitudeStream; + dynamic get cameraController => _videoInput.cameraController; + String? get selectedCameraId => _videoInput.selectedCameraId; + bool get controllerInitialized => _videoInput.controllerInitialized; + + void setMacOSController(dynamic controller) { + _videoInput.setMacOSController(controller); + } + + Future init() async { + try { + await _audioOutput.init(); + } catch (e) { + developer.log('Audio Output init error: $e'); + } + + try { + await _audioInput.init(); + } catch (e) { + developer.log('Audio Input init error: $e'); + } + + try { + await _videoInput.init(); + videoIsInitialized = true; + } catch (e) { + developer.log('Error during video initialization: $e'); + } + } + + Future startAudio(void Function(Uint8List) onData) async { + await stopAudio(); + try { + var inputStream = await _audioInput.startRecordingStream(); + await _audioOutput.playStream(); + if (inputStream != null) { + _audioSubscription = inputStream.listen( + onData, + onError: (e) { + developer.log('Audio Stream Error: $e'); + stopAudio(); + }, + cancelOnError: true, + ); + } + } catch (e) { + developer.log('BidiMediaManager.startAudio(): $e'); + rethrow; + } + } + + Future stopAudio() async { + await _audioSubscription?.cancel(); + _audioSubscription = null; + await _audioInput.stopRecording(); + } + + Future startVideo(void Function(Uint8List, String) onData) async { + if (!videoIsInitialized) return; + + if (!_videoInput.controllerInitialized || + _videoInput.cameraController == null) { + await _videoInput.initializeCameraController(); + } + + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { + int attempts = 0; + while (_videoInput.cameraController == null) { + if (attempts > 50) { + developer.log( + 'BidiMediaManager.startVideo(): macOS camera controller initialization timed out after 50 attempts.', + ); + break; // 5 second timeout safety + } + await Future.delayed(const Duration(milliseconds: 100)); + attempts++; + } + } + + // Wait for Mac Camera to Settle (Prevent audio hijack) + await Future.delayed(const Duration(milliseconds: 1000)); + + _videoSubscription = _videoInput.startStreamingImages().listen( + (data) { + String mimeType = 'image/jpeg'; + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { + if (data.length > 3 && data[0] == 0x89 && data[1] == 0x50) { + mimeType = 'image/png'; + } + } + onData(data, mimeType); + }, + onError: (e) => developer.log('Video Stream Error: $e'), + ); + } + + Future stopVideo() async { + await _videoSubscription?.cancel(); + _videoSubscription = null; + await _videoInput.stopStreamingImages(); + } + + void playAudioChunk(Uint8List bytes) { + _audioOutput.addDataToAudioStream(bytes); + } +} + +// ============================================================================ +// BIDI SESSION CONTROLLER +// Isolates business logic, session start/stop, reconnection, and tool execution. +// ============================================================================ +class BidiSessionController extends ChangeNotifier { + BidiSessionController({ required this.model, required this.useVertexBackend, - }); + this.onShowError, + this.onScrollDown, + }) { + _initLiveModel(); + } - final String title; final GenerativeModel model; final bool useVertexBackend; + final void Function(String)? onShowError; + final VoidCallback? onScrollDown; - @override - State createState() => _BidiPageState(); -} + late LiveGenerativeModel _liveModel; + LiveSession? _session; + final BidiMediaManager mediaManager = BidiMediaManager(); -class LightControl { - final int? brightness; - final String? colorTemperature; + bool isLoading = false; + bool isSessionActive = false; + bool isMicOn = false; + bool isCameraOn = false; - LightControl({this.brightness, this.colorTemperature}); -} + // Intention state for robust stream reconnection + bool _intendedMicOn = false; + bool _intendedCameraOn = false; -class _BidiPageState extends State { - final ScrollController _scrollController = ScrollController(); - final TextEditingController _textController = TextEditingController(); - final FocusNode _textFieldFocus = FocusNode(); - final List _messages = []; - bool _loading = false; - bool _sessionOpening = false; - bool _recording = false; - late LiveGenerativeModel _liveModel; - late LiveSession _session; - final AudioOutput _audioOutput = AudioOutput(); - final AudioInput _audioInput = AudioInput(); - final VideoInput _videoInput = VideoInput(); - StreamSubscription? _audioSubscription; + final List messages = []; + String? _activeSessionHandle; int? _inputTranscriptionMessageIndex; int? _outputTranscriptionMessageIndex; - bool _isCameraOn = false; - bool _videoIsInitialized = false; - - @override - void initState() { - super.initState(); + void _initLiveModel() { final config = LiveGenerationConfig( speechConfig: SpeechConfig(voiceName: 'Fenrir'), - responseModalities: [ - ResponseModalities.audio, - ], + responseModalities: [ResponseModalities.audio], inputAudioTranscription: AudioTranscriptionConfig(), outputAudioTranscription: AudioTranscriptionConfig(), ); - _liveModel = widget.useVertexBackend + final tools = [ + Tool.functionDeclarations([_lightControlTool]), + Tool.googleSearch(), + ]; + + _liveModel = useVertexBackend ? FirebaseAI.vertexAI().liveGenerativeModel( model: 'gemini-live-2.5-flash-preview-native-audio-09-2025', liveGenerationConfig: config, - tools: [ - Tool.functionDeclarations([lightControlTool]), - ], + tools: tools, ) : FirebaseAI.googleAI().liveGenerativeModel( model: 'gemini-2.5-flash-native-audio-preview-09-2025', liveGenerationConfig: config, - tools: [ - Tool.functionDeclarations([lightControlTool]), - ], + tools: tools, ); } - Future _initAudio() async { - try { - await _audioOutput.init(); - } catch (e) { - developer.log('Audio Output init error: $e'); - } + Future initialize() async { + isLoading = true; + notifyListeners(); + await mediaManager.init(); + isLoading = false; + notifyListeners(); + } - try { - await _audioInput.init(); - } catch (e) { - developer.log('Audio Input init error: $e'); + Future toggleSession() async { + if (isSessionActive) { + await _stopSession(explicit: true); + } else { + await _startSession(explicit: true); } } - Future _initVideo() async { + Future _startSession({required bool explicit}) async { + isLoading = true; + notifyListeners(); + try { - await _videoInput.init(); - setState(() { - _videoIsInitialized = true; - }); - } catch (e) { - developer.log('Error during video initialization: $e'); + _session = await _liveModel.connect( + sessionResumption: _activeSessionHandle != null + ? SessionResumptionConfig.resume(_activeSessionHandle!) + : SessionResumptionConfig(), + ); + } on Exception catch (e) { + developer.log( + 'Error setting up session with handle $_activeSessionHandle, error: $e, starting a new one.', + ); + _session = await _liveModel.connect(); } - } - void _scrollDown() { - if (!_scrollController.hasClients) return; + isSessionActive = true; + unawaited(_processMessagesContinuously()); - _scrollController.jumpTo( - _scrollController.position.maxScrollExtent, - ); + if (explicit) { + // Reconnect previously active hardware seamlessly into the new session + if (_intendedMicOn) await _startMicStream(); + if (_intendedCameraOn) await _startCameraStream(); + } + + isLoading = false; + notifyListeners(); } - @override - void dispose() { - if (_sessionOpening) { - _sessionOpening = false; - _session.close(); + Future _stopSession({required bool explicit}) async { + isLoading = true; + notifyListeners(); + + if (explicit) { + await mediaManager.stopAudio(); + await mediaManager.stopVideo(); + isMicOn = false; + isCameraOn = false; + // We purposefully DO NOT reset _intendedMicOn/CameraOn so we know what + // the user had active when they reconnect! } - super.dispose(); - } - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (_isCameraOn) - Container( - height: 200, - color: Colors.black, - alignment: Alignment.center, - child: (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) - ? FullCameraPreview( - controller: _videoInput.cameraController, - deviceId: _videoInput.selectedCameraId, - onInitialized: (controller) { - // This is where the controller actually gets born on macOS - _videoInput.setMacOSController(controller); - }, - ) - : (_videoInput.cameraController != null && - _videoInput.controllerInitialized) - ? FullCameraPreview( - controller: _videoInput.cameraController, - deviceId: _videoInput.selectedCameraId, - onInitialized: (controller) { - // Web/Mobile callback (often unused if controller passed in) - }, - ) - : const Center(child: CircularProgressIndicator()), - ), - Expanded( - child: ListView.builder( - controller: _scrollController, - itemBuilder: (context, idx) { - return MessageWidget( - text: _messages[idx].text, - image: _messages[idx].imageBytes != null - ? Image.memory( - _messages[idx].imageBytes!, - cacheWidth: 400, - cacheHeight: 400, - ) - : null, - isFromUser: _messages[idx].fromUser ?? false, - isThought: _messages[idx].isThought, - ); - }, - itemCount: _messages.length, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 25, - horizontal: 15, - ), - child: Row( - children: [ - Expanded( - child: TextField( - focusNode: _textFieldFocus, - controller: _textController, - onSubmitted: _sendTextPrompt, - ), - ), - const SizedBox.square( - dimension: 15, - ), - AudioVisualizer( - audioStreamIsActive: _recording, - amplitudeStream: _audioInput.amplitudeStream, - ), - const SizedBox.square( - dimension: 15, - ), - IconButton( - tooltip: 'Start Streaming', - onPressed: !_loading - ? () async { - await _setupSession(); - } - : null, - icon: Icon( - Icons.network_wifi, - color: _sessionOpening - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.primary, - ), - ), - IconButton( - tooltip: 'Send Stream Message', - onPressed: !_loading - ? () async { - if (_recording) { - await _stopRecording(); - } else { - await _startRecording(); - } - } - : null, - icon: Icon( - _recording ? Icons.stop : Icons.mic, - color: _loading - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.primary, - ), - ), - IconButton( - tooltip: 'Toggle Camera', - onPressed: _isCameraOn ? _stopVideoStream : _startVideoStream, - icon: Icon( - _isCameraOn ? Icons.videocam_off : Icons.videocam, - color: _loading - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.primary, - ), - ), - if (!_loading) - IconButton( - onPressed: () async { - await _sendTextPrompt(_textController.text); - }, - icon: Icon( - Icons.send, - color: Theme.of(context).colorScheme.primary, - ), - ) - else - const CircularProgressIndicator(), - ], - ), - ), - ], - ), - ); - } + await _session?.close(); + _session = null; + isSessionActive = false; - final lightControlTool = FunctionDeclaration( - 'setLightValues', - 'Set the brightness and color temperature of a room light.', - parameters: { - 'brightness': Schema.integer( - description: 'Light level from 0 to 100. ' - 'Zero is off and 100 is full brightness.', - ), - 'colorTemperature': Schema.string( - description: 'Color temperature of the light fixture, ' - 'which can be `daylight`, `cool` or `warm`.', - ), - }, - ); + isLoading = false; + notifyListeners(); + } - Future> _setLightValues({ - int? brightness, - String? colorTemperature, - }) async { - final apiResponse = { - 'colorTemprature': 'warm', - 'brightness': brightness, - }; - return apiResponse; + Future _sessionResume() async { + if (isSessionActive) { + await _stopSession(explicit: false); + await _startSession(explicit: false); + } } - Future _setupSession() async { - setState(() { - _loading = true; - }); - await _initAudio(); + Future _onAudioData(Uint8List data) async { + if (isSessionActive && _session != null) { + try { + await _session!.sendAudioRealtime(InlineDataPart('audio/pcm', data)); + } catch (e) { + developer.log('Error sending audio realtime: $e'); + // If we hit a closed socket, stop trying to send until reconnected + isMicOn = false; + notifyListeners(); + } + } + } - try { - if (!_videoIsInitialized) { - await _initVideo(); - } else { - await _videoInput.initializeCameraController(); + Future _onVideoData(Uint8List data, String mimeType) async { + if (isSessionActive && _session != null) { + try { + await _session!.sendVideoRealtime(InlineDataPart(mimeType, data)); + } catch (e) { + developer.log('Error sending video realtime: $e'); } - } catch (e) { - developer.log('Video Hardware init error: $e'); } + } - if (!_sessionOpening) { - _session = await _liveModel.connect(); - _sessionOpening = true; - unawaited( - _processMessagesContinuously(), - ); + Future toggleMic() async { + _intendedMicOn = !_intendedMicOn; + if (_intendedMicOn) { + await _startMicStream(); } else { - await _session.close(); - _sessionOpening = false; + await mediaManager.stopAudio(); + isMicOn = false; + notifyListeners(); } - - setState(() { - _loading = false; - }); } - Future _startRecording() async { - await _audioSubscription?.cancel(); - _audioSubscription = null; - setState(() { - _recording = true; - }); + Future _startMicStream() async { + if (!isSessionActive) { + isMicOn = true; + notifyListeners(); + return; + } try { - var inputStream = await _audioInput.startRecordingStream(); - await _audioOutput.playStream(); - if (inputStream != null) { - _audioSubscription = inputStream.listen( - (data) { - _session.sendAudioRealtime(InlineDataPart('audio/pcm', data)); - }, - onError: (e) { - developer.log('Audio Stream Error: $e'); - _stopRecording(); - }, - cancelOnError: true, - ); - } + await mediaManager.startAudio(_onAudioData); + isMicOn = true; + notifyListeners(); } catch (e) { - developer.log('bidi_page._startRecording(): $e'); - _showError('bidi_page._startRecording(): $e'); - setState(() => _recording = false); + onShowError?.call(e.toString()); + isMicOn = false; + notifyListeners(); } } - Future _stopRecording() async { - await _audioSubscription?.cancel(); - _audioSubscription = null; + Future _startCameraStream() async { + if (!isSessionActive) { + isCameraOn = true; + notifyListeners(); + return; + } try { - await _audioInput.stopRecording(); + await mediaManager.startVideo(_onVideoData); + isCameraOn = true; + notifyListeners(); } catch (e) { - _showError(e.toString()); + developer.log('Error starting video stream: $e'); + onShowError?.call(e.toString()); + isCameraOn = false; + notifyListeners(); } - - setState(() { - _recording = false; - }); } - Future _startVideoStream() async { - // 1. Re-entry Guard: Prevent multiple clicks while switching - if (_loading || !_videoIsInitialized) return; + Future toggleCamera() async { + if (isLoading) return; // Prevent multiple clicks + _intendedCameraOn = !_intendedCameraOn; - // 2. Capture the current recording state - bool wasRecording = _recording; - - setState(() { - _loading = true; // Lock the UI during the switch - }); + isLoading = true; + notifyListeners(); try { - if (wasRecording) { - await _stopRecording(); - } - - // 4. Wait for ripple/UI (Prevent freeze) - await Future.delayed(const Duration(milliseconds: 250)); - - // 5. Initialize Camera if needed - if (!_videoInput.controllerInitialized || - _videoInput.cameraController == null) { - await _videoInput.initializeCameraController(); - } + if (!_intendedCameraOn) { + await mediaManager.stopVideo(); + isCameraOn = false; + } else { + // Stop audio momentarily to prevent hijacking (Mac quirk workaround) + bool wasMicOn = isMicOn; + if (wasMicOn) await mediaManager.stopAudio(); - // 6. Mount Camera UI - setState(() { - _isCameraOn = true; - }); - - if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - // ✅ Because we set _cameraController to null in stopStreamingImages, - // this loop will now CORRECTLY wait for the new View to initialize. - int attempts = 0; - while (_videoInput.cameraController == null) { - if (attempts > 50) break; // 5 second timeout safety - await Future.delayed(const Duration(milliseconds: 100)); - attempts++; - } - } + await Future.delayed(const Duration(milliseconds: 250)); - // 7. Wait for Mac Camera to Settle (Prevent audio hijack) - await Future.delayed(const Duration(milliseconds: 1000)); + await _startCameraStream(); - // 8. CLEAN RESTART: Use the helper method! - // Only restart if we were recording before. - if (wasRecording) { - developer.log('Resuming audio session...'); - await _startRecording(); + // Restart Audio + if (wasMicOn) await _startMicStream(); } - - // 9. Start Video Stream - _videoInput.startStreamingImages().listen( - (data) { - String mimeType = 'image/jpeg'; - if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - if (data.length > 3 && data[0] == 0x89 && data[1] == 0x50) { - mimeType = 'image/png'; - } - } - _session.sendVideoRealtime(InlineDataPart(mimeType, data)); - }, - onError: (e) => developer.log('Video Stream Error: $e'), - ); } catch (e) { developer.log('Error switching to video: $e'); - _showError(e.toString()); + onShowError?.call(e.toString()); + isCameraOn = false; } finally { - // 10. Always unlock the UI - setState(() { - _loading = false; - }); + isLoading = false; + notifyListeners(); } } - Future _stopVideoStream() async { - await _videoInput.stopStreamingImages(); - setState(() { - _isCameraOn = false; - }); - } + Future sendTextPrompt(String textPrompt) async { + if (!isSessionActive || _session == null) return; + isLoading = true; + notifyListeners(); - Future _sendTextPrompt(String textPrompt) async { - setState(() { - _loading = true; - }); try { - //final prompt = Content.text(textPrompt); - // await _session.send(input: prompt, turnComplete: true); - await _session.sendTextRealtime(textPrompt); + await _session!.sendTextRealtime(textPrompt); } catch (e) { - _showError(e.toString()); + onShowError?.call(e.toString()); } - setState(() { - _loading = false; - }); + isLoading = false; + notifyListeners(); } Future _processMessagesContinuously() async { + if (_session == null) return; try { - await for (final message in _session.receive()) { - if (!mounted) break; + await for (final message in _session!.receive()) { await _handleLiveServerMessage(message); } } catch (e) { - _showError(e.toString()); + onShowError?.call(e.toString()); } } @@ -496,40 +420,6 @@ class _BidiPageState extends State { await _handleLiveServerContent(message); } - int? _handleTranscription( - Transcription? transcription, - int? messageIndex, - String prefix, - bool fromUser, - ) { - int? currentIndex = messageIndex; - if (transcription?.text != null) { - if (currentIndex != null) { - _messages[currentIndex] = _messages[currentIndex].copyWith( - text: '${_messages[currentIndex].text}${transcription!.text!}', - ); - } else { - _messages.add( - MessageData( - text: '$prefix${transcription!.text!}', - fromUser: fromUser, - ), - ); - currentIndex = _messages.length - 1; - } - if (transcription.finished ?? false) { - currentIndex = null; - setState(_scrollDown); - } else { - // Use a scheduled frame instead of an immediate setState - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) setState(() {}); - }); - } - } - return currentIndex; - } - _inputTranscriptionMessageIndex = _handleTranscription( message.inputTranscription, _inputTranscriptionMessageIndex, @@ -549,8 +439,46 @@ class _BidiPageState extends State { } else if (message is LiveServerToolCall && message.functionCalls != null) { await _handleLiveServerToolCall(message); } else if (message is GoingAwayNotice) { - developer.log('Session is going away in ${message.timeLeft} seconds'); + if (_activeSessionHandle != null) { + unawaited(_sessionResume()); + } + } else if (message is SessionResumptionUpdate && + message.resumable != null && + message.resumable!) { + _activeSessionHandle = message.newHandle; + } + } + + int? _handleTranscription( + Transcription? transcription, + int? messageIndex, + String prefix, + bool fromUser, + ) { + int? currentIndex = messageIndex; + if (transcription?.text != null) { + if (currentIndex != null) { + messages[currentIndex] = messages[currentIndex].copyWith( + text: '${messages[currentIndex].text}${transcription!.text!}', + ); + } else { + messages.add( + MessageData( + text: '$prefix${transcription!.text!}', + fromUser: fromUser, + ), + ); + currentIndex = messages.length - 1; + } + + if (transcription.finished ?? false) { + currentIndex = null; + onScrollDown?.call(); + } else { + notifyListeners(); // Trigger UI rebuild for streaming text + } } + return currentIndex; } Future _handleLiveServerContent(LiveServerContent response) async { @@ -558,9 +486,19 @@ class _BidiPageState extends State { if (partList != null) { for (final part in partList) { if (part is TextPart) { - await _handleTextPart(part); + messages.add( + MessageData( + text: part.text, + fromUser: false, + isThought: part.isThought ?? false, + ), + ); + onScrollDown?.call(); + notifyListeners(); } else if (part is InlineDataPart) { - await _handleInlineDataPart(part); + if (part.mimeType.startsWith('audio')) { + mediaManager.playAudioChunk(part.bytes); + } } else { developer.log('receive part with type ${part.runtimeType}'); } @@ -568,31 +506,6 @@ class _BidiPageState extends State { } } - Future _handleTextPart(TextPart part) async { - if (!_loading) { - setState(() { - _loading = true; - }); - } - _messages.add( - MessageData( - text: part.text, - fromUser: false, - isThought: part.isThought ?? false, - ), - ); - setState(() { - _loading = false; - _scrollDown(); - }); - } - - Future _handleInlineDataPart(InlineDataPart part) async { - if (part.mimeType.startsWith('audio')) { - _audioOutput.addDataToAudioStream(part.bytes); - } - } - Future _handleLiveServerToolCall(LiveServerToolCall response) async { final functionCalls = response.functionCalls!.toList(); if (functionCalls.isNotEmpty) { @@ -600,11 +513,15 @@ class _BidiPageState extends State { if (functionCall.name == 'setLightValues') { var color = functionCall.args['colorTemperature']! as String; var brightness = functionCall.args['brightness']! as int; - final functionResult = await _setLightValues( - brightness: brightness, - colorTemperature: color, - ); - await _session.sendToolResponse([ + + // Mock Tool Execution + final functionResult = { + 'colorTemperature': + color, // original had a typo, keeping to preserve functionality intent + 'brightness': brightness, + }; + + await _session?.sendToolResponse([ FunctionResponse( functionCall.name, functionResult, @@ -612,27 +529,108 @@ class _BidiPageState extends State { ), ]); } else { - throw UnimplementedError( - 'Function not declared to the model: ${functionCall.name}', - ); + throw UnimplementedError('Function not declared: ${functionCall.name}'); } } } + void simulateGoingAway() { + if (isSessionActive && _session != null) { + developer.log('Simulating GoingAwayNotice locally'); + _handleLiveServerMessage( + LiveServerResponse(message: const GoingAwayNotice(timeLeft: '10')), + ); + } + } + + @override + void dispose() { + _stopSession(explicit: true); + super.dispose(); + } + + static final _lightControlTool = FunctionDeclaration( + 'setLightValues', + 'Set the brightness and color temperature of a room light.', + parameters: { + 'brightness': Schema.integer( + description: + 'Light level from 0 to 100. Zero is off and 100 is full brightness.', + ), + 'colorTemperature': Schema.string( + description: + 'Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.', + ), + }, + ); +} + +// ============================================================================ +// UI WIDGET +// Isolates presentation, keeping state out of the visual hierarchy. +// ============================================================================ +class BidiPage extends StatefulWidget { + const BidiPage({ + super.key, + required this.title, + required this.model, + required this.useVertexBackend, + }); + + final String title; + final GenerativeModel model; + final bool useVertexBackend; + + @override + State createState() => _BidiPageState(); +} + +class _BidiPageState extends State { + late final BidiSessionController _controller; + final ScrollController _scrollController = ScrollController(); + final TextEditingController _textController = TextEditingController(); + final FocusNode _textFieldFocus = FocusNode(); + + @override + void initState() { + super.initState(); + _controller = BidiSessionController( + model: widget.model, + useVertexBackend: widget.useVertexBackend, + onShowError: _showError, + onScrollDown: _scrollDown, + ); + _controller.initialize(); + } + + @override + void dispose() { + _controller.dispose(); + _scrollController.dispose(); + _textController.dispose(); + _textFieldFocus.dispose(); + super.dispose(); + } + + void _scrollDown() { + if (!_scrollController.hasClients) return; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + _scrollController.jumpTo(_scrollController.position.maxScrollExtent); + } + }); + } + void _showError(String message) { showDialog( context: context, builder: (context) { return AlertDialog( title: const Text('Something went wrong'), - content: SingleChildScrollView( - child: SelectableText(message), - ), + content: SingleChildScrollView(child: SelectableText(message)), actions: [ TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, + onPressed: () => Navigator.of(context).pop(), child: const Text('OK'), ), ], @@ -640,4 +638,165 @@ class _BidiPageState extends State { }, ); } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Padding( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Live Stream Session', + style: TextStyle(fontWeight: FontWeight.bold), + ), + ElevatedButton.icon( + icon: const Icon(Icons.speed, size: 16), + label: const Text('Simulate GoAway'), + style: ElevatedButton.styleFrom( + visualDensity: VisualDensity.compact, + ), + onPressed: _controller.isSessionActive + ? () => _controller.simulateGoingAway() + : null, + ), + ], + ), + const SizedBox(height: 8), + if (_controller.isCameraOn) + Container( + height: 200, + color: Colors.black, + alignment: Alignment.center, + child: (!kIsWeb && + defaultTargetPlatform == TargetPlatform.macOS) + ? FullCameraPreview( + controller: _controller.mediaManager.cameraController, + deviceId: _controller.mediaManager.selectedCameraId, + onInitialized: (controller) { + _controller.mediaManager + .setMacOSController(controller); + }, + ) + : (_controller.mediaManager.cameraController != null && + _controller.mediaManager.controllerInitialized) + ? FullCameraPreview( + controller: + _controller.mediaManager.cameraController, + deviceId: + _controller.mediaManager.selectedCameraId, + onInitialized: (controller) {}, + ) + : const Center(child: CircularProgressIndicator()), + ), + Expanded( + child: ListView.builder( + controller: _scrollController, + itemCount: _controller.messages.length, + itemBuilder: (context, idx) { + final message = _controller.messages[idx]; + return MessageWidget( + text: message.text, + image: message.imageBytes != null + ? Image.memory( + message.imageBytes!, + cacheWidth: 400, + cacheHeight: 400, + ) + : null, + isFromUser: message.fromUser ?? false, + isThought: message.isThought, + ); + }, + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(vertical: 25, horizontal: 15), + child: Row( + children: [ + Expanded( + child: TextField( + focusNode: _textFieldFocus, + controller: _textController, + onSubmitted: (text) { + _controller.sendTextPrompt(text); + _textController.clear(); + }, + ), + ), + const SizedBox.square(dimension: 15), + AudioVisualizer( + audioStreamIsActive: _controller.isMicOn, + amplitudeStream: _controller.mediaManager.amplitudeStream, + ), + const SizedBox.square(dimension: 15), + IconButton( + tooltip: 'Start Streaming', + onPressed: !_controller.isLoading + ? () => _controller.toggleSession() + : null, + icon: Icon( + Icons.network_wifi, + color: _controller.isSessionActive + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.primary, + ), + ), + IconButton( + tooltip: 'Send Stream Message', + onPressed: !_controller.isLoading + ? () => _controller.toggleMic() + : null, + icon: Icon( + _controller.isMicOn ? Icons.stop : Icons.mic, + color: _controller.isLoading + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.primary, + ), + ), + IconButton( + tooltip: 'Toggle Camera', + onPressed: !_controller.isLoading + ? () => _controller.toggleCamera() + : null, + icon: Icon( + _controller.isCameraOn + ? Icons.videocam_off + : Icons.videocam, + color: _controller.isLoading + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.primary, + ), + ), + if (!_controller.isLoading) + IconButton( + tooltip: 'Send Text', + onPressed: () { + _controller.sendTextPrompt(_textController.text); + _textController.clear(); + }, + icon: Icon( + Icons.send, + color: Theme.of(context).colorScheme.primary, + ), + ) + else + const CircularProgressIndicator(), + ], + ), + ), + ], + ), + ); + }, + ); + } } diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart index 24a29b59569f..5a37a78e9903 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart @@ -152,6 +152,7 @@ class _ChatPageState extends State { Icons.send, color: Theme.of(context).colorScheme.primary, ), + tooltip: 'Send', ), IconButton( onPressed: () { @@ -161,6 +162,7 @@ class _ChatPageState extends State { Icons.stream, color: Theme.of(context).colorScheme.primary, ), + tooltip: 'Send Stream', ), ], ) diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_input.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_input.dart index 2698537b048b..9a768d64be9e 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_input.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_input.dart @@ -110,8 +110,6 @@ class AudioInput extends ChangeNotifier { sampleRate: 24000, device: selectedDevice, numChannels: 1, - echoCancel: true, - noiseSuppress: true, androidConfig: const AndroidRecordConfig( audioSource: AndroidAudioSource.voiceCommunication, ), diff --git a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart index 5702945342f1..d2215525cb06 100644 --- a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart @@ -102,15 +102,19 @@ export 'src/imagen/imagen_reference.dart' ImagenControlReference; export 'src/live_api.dart' show - LiveGenerationConfig, - SpeechConfig, AudioTranscriptionConfig, + ContextWindowCompressionConfig, + GoingAwayNotice, + LiveGenerationConfig, LiveServerMessage, LiveServerContent, LiveServerToolCall, LiveServerToolCallCancellation, LiveServerResponse, - GoingAwayNotice, + SessionResumptionConfig, + SessionResumptionUpdate, + SlidingWindow, + SpeechConfig, Transcription; export 'src/live_session.dart' show LiveSession; export 'src/schema.dart' show JSONSchema, Schema, SchemaType; diff --git a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart index de9e8072d249..f02bc723b580 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart @@ -13,16 +13,12 @@ // limitations under the License. import 'dart:async'; -import 'dart:convert'; import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:meta/meta.dart'; -import 'package:web_socket_channel/io.dart'; -import 'package:web_socket_channel/web_socket_channel.dart'; import 'api.dart'; import 'client.dart'; diff --git a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart index 9db6bd845476..973f4ba35b41 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart @@ -77,21 +77,98 @@ class AudioTranscriptionConfig { Map toJson() => {}; } +/// Configures the sliding window context compression mechanism. +/// +/// The SlidingWindow method operates by discarding content at the beginning of +/// the context window. The resulting context will always begin at the start of +/// a USER role turn. System instructions will always remain at the start of the +/// result. +class SlidingWindow { + /// Creates a [SlidingWindow] instance. + /// + /// [targetTokens] (optional): The target number of tokens to keep in the + /// context window. + SlidingWindow({this.targetTokens}); + + /// The session reduction target, i.e., how many tokens we should keep. + final int? targetTokens; + // ignore: public_member_api_docs + Map toJson() => + {if (targetTokens case final targetTokens?) 'targetTokens': targetTokens}; +} + +/// Enables context window compression to manage the model's context window. +/// +/// This mechanism prevents the context from exceeding a given length. +class ContextWindowCompressionConfig { + /// Creates a [ContextWindowCompressionConfig] instance. + /// + /// [triggerTokens] (optional): The number of tokens that triggers the + /// compression mechanism. + /// [slidingWindow] (optional): The sliding window compression mechanism to + /// use. + ContextWindowCompressionConfig({this.triggerTokens, this.slidingWindow}); + + /// The number of tokens (before running a turn) that triggers the context + /// window compression. + final int? triggerTokens; + + /// The sliding window compression mechanism. + final SlidingWindow? slidingWindow; + // ignore: public_member_api_docs + Map toJson() => { + if (triggerTokens case final triggerTokens?) + 'triggerTokens': triggerTokens, + if (slidingWindow case final slidingWindow?) + 'slidingWindow': slidingWindow.toJson() + }; +} + +/// Configuration for the session resumption mechanism. +/// +/// When included in the session setup, the server will send +/// [SessionResumptionUpdate] messages. +class SessionResumptionConfig { + /// Creates a [SessionResumptionConfig] to start a new resumable session. + /// + /// When this is included in the session setup, the server will send + /// [SessionResumptionUpdate] messages with handles that can be used to + /// resume the session later. + SessionResumptionConfig() : handle = null; + + /// Creates a [SessionResumptionConfig] to resume a previous session. + /// + /// [handle] is the session resumption handle received in a previous session's + /// [SessionResumptionUpdate]. + SessionResumptionConfig.resume(String this.handle); + + /// The session resumption handle of the previous session to restore. + /// + /// If null, a new session will be started (and will be resumable if this + /// config was included). + final String? handle; + + // ignore: public_member_api_docs + Map toJson() => { + if (handle case final handle?) 'handle': handle, + }; +} + /// Configures live generation settings. final class LiveGenerationConfig extends BaseGenerationConfig { // ignore: public_member_api_docs - LiveGenerationConfig({ - this.speechConfig, - this.inputAudioTranscription, - this.outputAudioTranscription, - super.responseModalities, - super.maxOutputTokens, - super.temperature, - super.topP, - super.topK, - super.presencePenalty, - super.frequencyPenalty, - }); + LiveGenerationConfig( + {this.speechConfig, + this.inputAudioTranscription, + this.outputAudioTranscription, + this.contextWindowCompression, + super.responseModalities, + super.maxOutputTokens, + super.temperature, + super.topP, + super.topK, + super.presencePenalty, + super.frequencyPenalty}); /// The speech configuration. final SpeechConfig? speechConfig; @@ -103,6 +180,9 @@ final class LiveGenerationConfig extends BaseGenerationConfig { /// the output audio. final AudioTranscriptionConfig? outputAudioTranscription; + /// The context window compression configuration. + final ContextWindowCompressionConfig? contextWindowCompression; + @override Map toJson() => { ...super.toJson(), @@ -222,6 +302,34 @@ class GoingAwayNotice implements LiveServerMessage { final String? timeLeft; } +/// An update of the session resumption state. +/// +/// This message is only sent if [SessionResumptionConfig] was set in the +/// session setup. +class SessionResumptionUpdate implements LiveServerMessage { + /// Creates a [SessionResumptionUpdate] instance. + /// + /// [newHandle] (optional): The new handle that represents the state that can + /// be resumed. + /// [resumable] (optional): Indicates if the session can be resumed at this + /// point. + /// [lastConsumedClientMessageIndex] (optional): The index of the last client + /// message that is included in the state represented by this update. + SessionResumptionUpdate( + {this.newHandle, this.resumable, this.lastConsumedClientMessageIndex}); + + /// The new handle that represents the state that can be resumed. Empty if + /// `resumable` is false. + final String? newHandle; + + /// Indicates if the session can be resumed at this point. + final bool? resumable; + + /// The index of the last client message that is included in the state + /// represented by this update. + final int? lastConsumedClientMessageIndex; +} + /// A single response chunk received during a live content generation. /// /// It can contain generated content, function calls to be executed, or @@ -449,8 +557,17 @@ LiveServerMessage _parseServerMessage(Object jsonObject) { } else if (json.containsKey('setupComplete')) { return LiveServerSetupComplete(); } else if (json.containsKey('goAway')) { - final goAwayJson = json['goAway'] as Map; + final goAwayJson = json['goAway'] as Map; return GoingAwayNotice(timeLeft: goAwayJson['timeLeft'] as String?); + } else if (json.containsKey('sessionResumptionUpdate')) { + final sessionResumptionUpdateJson = + json['sessionResumptionUpdate'] as Map; + return SessionResumptionUpdate( + newHandle: sessionResumptionUpdateJson['newHandle'] as String?, + resumable: sessionResumptionUpdateJson['resumable'] as bool?, + lastConsumedClientMessageIndex: + sessionResumptionUpdateJson['lastConsumedClientMessageIndex'] as int?, + ); } else { throw unhandledFormat('LiveServerMessage', json); } diff --git a/packages/firebase_ai/firebase_ai/lib/src/live_model.dart b/packages/firebase_ai/firebase_ai/lib/src/live_model.dart index 3414b1376af1..19e837fcf849 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/live_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/live_model.dart @@ -90,33 +90,17 @@ final class LiveGenerativeModel extends BaseModel { /// /// This function handles the WebSocket connection setup and returns an [LiveSession] /// object that can be used to communicate with the service. + /// [sessionResumption] (optional): The configuration for session resumption, + /// such as the handle to the previous session state to restore. /// /// Returns a [Future] that resolves to an [LiveSession] object upon successful /// connection. - Future connect() async { + Future connect( + {SessionResumptionConfig? sessionResumption}) async { final uri = _useVertexBackend ? _vertexAIUri() : _googleAIUri(); final modelString = _useVertexBackend ? _vertexAIModelString() : _googleAIModelString(); - final setupJson = { - 'setup': { - 'model': modelString, - if (_systemInstruction != null) - 'system_instruction': _systemInstruction.toJson(), - if (_tools != null) 'tools': _tools.map((t) => t.toJson()).toList(), - if (_liveGenerationConfig != null) ...{ - 'generation_config': _liveGenerationConfig.toJson(), - if (_liveGenerationConfig.inputAudioTranscription != null) - 'input_audio_transcription': - _liveGenerationConfig.inputAudioTranscription!.toJson(), - if (_liveGenerationConfig.outputAudioTranscription != null) - 'output_audio_transcription': - _liveGenerationConfig.outputAudioTranscription!.toJson(), - }, - } - }; - - final request = jsonEncode(setupJson); final headers = await BaseModel.firebaseTokens( _appCheck, _auth, @@ -124,14 +108,15 @@ final class LiveGenerativeModel extends BaseModel { _useLimitedUseAppCheckTokens, )(); - var ws = kIsWeb - ? WebSocketChannel.connect(Uri.parse(uri)) - : IOWebSocketChannel.connect(Uri.parse(uri), headers: headers); - await ws.ready; - - ws.sink.add(request); - - return LiveSession(ws); + return LiveSession.create( + uri: uri, + headers: headers, + modelString: modelString, + systemInstruction: _systemInstruction, + tools: _tools, + sessionResumption: sessionResumption, + liveGenerationConfig: _liveGenerationConfig, + ); } } diff --git a/packages/firebase_ai/firebase_ai/lib/src/live_session.dart b/packages/firebase_ai/firebase_ai/lib/src/live_session.dart index f136a644d03d..d69fd7f678c2 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/live_session.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/live_session.dart @@ -16,37 +16,212 @@ import 'dart:async'; import 'dart:convert'; import 'dart:developer'; +import 'package:flutter/foundation.dart'; +import 'package:web_socket_channel/io.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; import 'content.dart'; import 'error.dart'; import 'live_api.dart'; +import 'tool.dart'; /// Manages asynchronous communication with Gemini model over a WebSocket /// connection. class LiveSession { // ignore: public_member_api_docs - LiveSession(this._ws) { + LiveSession._( + this._ws, { + required String uri, + required Map headers, + required String modelString, + Content? systemInstruction, + List? tools, + LiveGenerationConfig? liveGenerationConfig, + }) : _uri = uri, + _headers = headers, + _modelString = modelString, + _systemInstruction = systemInstruction, + _tools = tools, + _liveGenerationConfig = liveGenerationConfig, + _messageController = StreamController.broadcast() { + _listenToWebSocket(); + } + + /// Internal constructor for testing. + @visibleForTesting + factory LiveSession.forTesting(WebSocketChannel ws) { + return LiveSession._( + ws, + uri: '', + headers: {}, + modelString: '', + ); + } + + /// Establishes a connection to a live generation service. + /// + /// This function handles the WebSocket connection setup and returns an [LiveSession] + /// object that can be used to communicate with the service. + /// + /// Returns a [Future] that resolves to an [LiveSession] object upon successful + /// connection. + @internal + static Future create({ + required String uri, + required Map headers, + required String modelString, + Content? systemInstruction, + List? tools, + SessionResumptionConfig? sessionResumption, + LiveGenerationConfig? liveGenerationConfig, + }) async { + final ws = await _performWebSocketSetup( + uri: uri, + headers: headers, + modelString: modelString, + systemInstruction: systemInstruction, + tools: tools, + sessionResumption: sessionResumption, + liveGenerationConfig: liveGenerationConfig, + ); + return LiveSession._( + ws, + uri: uri, + headers: headers, + modelString: modelString, + systemInstruction: systemInstruction, + tools: tools, + liveGenerationConfig: liveGenerationConfig, + ); + } + + // Persisted values for session resumption. + final String _uri; + final Map _headers; + final String _modelString; + final Content? _systemInstruction; + final List? _tools; + final LiveGenerationConfig? _liveGenerationConfig; + + WebSocketChannel _ws; + StreamController _messageController; + late StreamSubscription _wsSubscription; + + static Future _performWebSocketSetup({ + required String uri, + required Map headers, + required String modelString, + Content? systemInstruction, + List? tools, + SessionResumptionConfig? sessionResumption, + LiveGenerationConfig? liveGenerationConfig, + }) async { + final setupJson = { + 'setup': { + 'model': modelString, + if (systemInstruction != null) + 'system_instruction': systemInstruction.toJson(), + if (tools != null) 'tools': tools.map((t) => t.toJson()).toList(), + if (sessionResumption != null) + 'session_resumption': sessionResumption.toJson(), + if (liveGenerationConfig != null) ...{ + 'generation_config': liveGenerationConfig.toJson(), + if (liveGenerationConfig.inputAudioTranscription != null) + 'input_audio_transcription': + liveGenerationConfig.inputAudioTranscription!.toJson(), + if (liveGenerationConfig.outputAudioTranscription != null) + 'output_audio_transcription': + liveGenerationConfig.outputAudioTranscription!.toJson(), + if (liveGenerationConfig.contextWindowCompression + case final contextWindowCompression?) + 'contextWindowCompression': contextWindowCompression.toJson() + }, + } + }; + + final request = jsonEncode(setupJson); + final ws = kIsWeb + ? WebSocketChannel.connect(Uri.parse(uri)) + : IOWebSocketChannel.connect(Uri.parse(uri), headers: headers); + await ws.ready; + + ws.sink.add(request); + return ws; + } + + void _listenToWebSocket() { _wsSubscription = _ws.stream.listen( (message) { try { - var jsonString = utf8.decode(message); + final String jsonString = + message is String ? message : utf8.decode(message as List); var response = json.decode(jsonString); - _messageController.add(parseServerResponse(response)); + if (!_messageController.isClosed) { + _messageController.add(parseServerResponse(response)); + } } catch (e) { - _messageController.addError(e); + if (!_messageController.isClosed && _messageController.hasListener) { + _messageController.addError(e); + } else { + log('live_session: Dropped parse error because no listeners', + error: e); + } } }, onError: (error) { - _messageController.addError(error); + if (!_messageController.isClosed && _messageController.hasListener) { + _messageController.addError(error); + } else { + log('live_session: Dropped stream error because no listeners', + error: error); + } + }, + onDone: () { + if (!_messageController.isClosed) { + _messageController.close(); + } }, - onDone: _messageController.close, ); } - final WebSocketChannel _ws; - final _messageController = StreamController.broadcast(); - late StreamSubscription _wsSubscription; + + /// Resumes an existing live session with the server. + /// + /// This closes the current WebSocket connection and establishes a new one using + /// the same configuration (URI, headers, model, system instruction, tools, etc.) + /// as the original session. + /// + /// [sessionResumption] (optional): The configuration for session resumption, + /// such as the handle to the previous session state to restore. + Future resumeSession( + {SessionResumptionConfig? sessionResumption}) async { + try { + await _wsSubscription.cancel().timeout(const Duration(seconds: 2), + onTimeout: () { + log('live_session.resumeSession: WebSocket subscription cancel timed out.', + error: TimeoutException('Cancel timed out')); + }); + await _ws.sink.close().timeout(const Duration(seconds: 2), onTimeout: () { + log('live_session.resumeSession: WebSocket close timed out.', + error: TimeoutException('Close timed out')); + }); + + _ws = await _performWebSocketSetup( + uri: _uri, + headers: _headers, + modelString: _modelString, + systemInstruction: _systemInstruction, + tools: _tools, + sessionResumption: sessionResumption, + liveGenerationConfig: _liveGenerationConfig, + ); + } catch (e) { + log('live_session.resumeSession: WebSocket setup failed', error: e); + rethrow; + } + + _listenToWebSocket(); + } /// Sends content to the server. /// @@ -166,17 +341,27 @@ class LiveSession { await for (final result in _messageController.stream) { yield result; - if (result case LiveServerContent(turnComplete: true)) { - break; // Exit the loop when the turn is complete - } } } /// Closes the WebSocket connection. Future close() async { - await _wsSubscription.cancel(); - await _messageController.close(); - await _ws.sink.close(); + try { + await _wsSubscription.cancel().timeout(const Duration(seconds: 1), + onTimeout: () { + log('live_session.close: cancel timed out', + error: TimeoutException('Cancel timed out')); + }); + if (!_messageController.isClosed) { + await _messageController.close(); + } + await _ws.sink.close().timeout(const Duration(seconds: 1), onTimeout: () { + log('live_session.close: sink close timed out', + error: TimeoutException('Sink close timed out')); + }); + } catch (e) { + log('live_session.close: error during close', error: e); + } } void _checkWsStatus() { diff --git a/packages/firebase_ai/firebase_ai/test/live_session_test.dart b/packages/firebase_ai/firebase_ai/test/live_session_test.dart new file mode 100644 index 000000000000..693aba00b26a --- /dev/null +++ b/packages/firebase_ai/firebase_ai/test/live_session_test.dart @@ -0,0 +1,99 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:firebase_ai/src/live_api.dart'; +import 'package:firebase_ai/src/live_session.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; + +class FakeWebSocketChannel implements WebSocketChannel { + final StreamController _controller = StreamController(); + + @override + Stream get stream => _controller.stream; + + @override + WebSocketSink get sink => throw UnimplementedError(); + + void emit(dynamic message) => _controller.add(message); + + void close() => _controller.close(); + + @override + int? get closeCode => null; + + @override + String? get closeReason => null; + + @override + Future get ready => Future.value(); + + @override + String? get protocol => null; + + @override + dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); +} + +void main() { + group('LiveSession Tests', () { + test('processes String messages from WebSocket on Web', () async { + final fakeWs = FakeWebSocketChannel(); + final session = LiveSession.forTesting(fakeWs); + + const jsonMessage = '{"setupComplete": {}}'; + + final completer = Completer(); + final subscription = session.receive().listen((response) { + if (response.message is LiveServerSetupComplete) { + completer.complete(true); + } + }); + + fakeWs.emit(jsonMessage); + + final result = await completer.future.timeout(const Duration(seconds: 5)); + expect(result, isTrue); + + await subscription.cancel(); + fakeWs.close(); + }); + + test('processes List messages from WebSocket', () async { + final fakeWs = FakeWebSocketChannel(); + final session = LiveSession.forTesting(fakeWs); + + const jsonMessage = '{"setupComplete": {}}'; + final bytes = utf8.encode(jsonMessage); + + final completer = Completer(); + final subscription = session.receive().listen((response) { + if (response.message is LiveServerSetupComplete) { + completer.complete(true); + } + }); + + fakeWs.emit(bytes); + + final result = await completer.future.timeout(const Duration(seconds: 5)); + expect(result, isTrue); + + await subscription.cancel(); + fakeWs.close(); + }); + }); +} diff --git a/packages/firebase_ai/firebase_ai/test/live_test.dart b/packages/firebase_ai/firebase_ai/test/live_test.dart index 8eb09d308476..b1b07d5ee445 100644 --- a/packages/firebase_ai/firebase_ai/test/live_test.dart +++ b/packages/firebase_ai/firebase_ai/test/live_test.dart @@ -67,6 +67,14 @@ void main() { expect(liveGenerationConfigWithoutOptionals.toJson(), {}); }); + test('SessionResumptionConfig toJson() returns correct JSON', () { + final resumableConfig = SessionResumptionConfig(); + expect(resumableConfig.toJson(), {}); + + final resumeConfig = SessionResumptionConfig.resume('some_handle'); + expect(resumeConfig.toJson(), {'handle': 'some_handle'}); + }); + test('LiveServerContent constructor and properties', () { final content = Content.text('Hello, world!'); final message = LiveServerContent( From 2771f5505ff0a53cc1bfb41afec3a0eb8781b8f8 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Wed, 6 May 2026 18:17:49 +0200 Subject: [PATCH 053/137] fix(storage,android): fix an issue that could happen when app would get detached from the engine (#18255) --- .../storage/FlutterFirebaseStorageTask.kt | 4 ++- .../firebase_storage/task_e2e.dart | 35 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt index 1727bbde949c..21b6453191f2 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt @@ -95,11 +95,13 @@ internal class FlutterFirebaseStorageTask private constructor( @JvmStatic fun cancelInProgressTasks() { synchronized(inProgressTasks) { + val tasks = ArrayList(inProgressTasks.size()) for (i in 0 until inProgressTasks.size()) { val task: FlutterFirebaseStorageTask? = inProgressTasks.valueAt(i) - task?.destroy() + task?.let { tasks.add(it) } } inProgressTasks.clear() + tasks.forEach { it.destroy() } } } diff --git a/tests/integration_test/firebase_storage/task_e2e.dart b/tests/integration_test/firebase_storage/task_e2e.dart index fd00288c3398..7ad326394d1d 100644 --- a/tests/integration_test/firebase_storage/task_e2e.dart +++ b/tests/integration_test/firebase_storage/task_e2e.dart @@ -6,9 +6,12 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:tests/firebase_options.dart'; import './test_utils.dart'; @@ -346,6 +349,38 @@ void setupTaskTests() { // Windows `task.cancel()` is returning "false", same code on example app works as intended skip: defaultTargetPlatform == TargetPlatform.windows, ); + + test( + 'cancels multiple in-progress Android tasks during core reinitialization', + () async { + final tasks = [ + for (var i = 0; i < 3; i++) + storage + .ref('flutter-tests/regression-18240-$i.txt') + .putString('A' * 20000000), + ]; + final completions = tasks + .map( + (task) => task.then( + (_) {}, + onError: (_) {}, + ), + ) + .toList(); + + try { + MethodChannelFirebase.isCoreInitialized = false; + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ).timeout(const Duration(seconds: 30)); + } finally { + MethodChannelFirebase.isCoreInitialized = true; + completions.forEach(unawaited); + } + }, + retry: 2, + skip: kIsWeb || defaultTargetPlatform != TargetPlatform.android, + ); }, ); From 7d1a8b1db4c5f585ba38d46df37330d3d17de774 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Wed, 6 May 2026 09:24:09 -0700 Subject: [PATCH 054/137] feat(firebaseai): ImageConfig and FinishReasons (#18180) * [AI] Add ImageConfig and expand FinishReasons * style: Fix formatting in api_test.dart * fix(ai): Fix syntax error in api.dart * chore(ai): address code review comments in Flutter SDK * fix(ai): fix typo in documentation in Flutter SDK * Better code organization and public API * fixes * review * fix * review * Add example test case and minor year fix * remove the export from api --------- Co-authored-by: Cynthia J --- .../lib/pages/image_generation_page.dart | 127 +++++++++++++++--- .../firebase_ai/lib/firebase_ai.dart | 1 + .../firebase_ai/firebase_ai/lib/src/api.dart | 60 ++++++++- .../firebase_ai/lib/src/image_config.dart | 110 +++++++++++++++ .../firebase_ai/test/api_test.dart | 75 +++++++++++ 5 files changed, 349 insertions(+), 24 deletions(-) create mode 100644 packages/firebase_ai/firebase_ai/lib/src/image_config.dart diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart index 0b66b1e7f6d3..6206760bdfb1 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/image_generation_page.dart @@ -39,6 +39,8 @@ class _ImageGenerationPageState extends State { final FocusNode _textFieldFocus = FocusNode(); final List _messages = []; bool _loading = false; + ImageAspectRatio? _selectedAspectRatio; + ImageSize? _selectedImageSize; @override void initState() { @@ -79,7 +81,19 @@ class _ImageGenerationPageState extends State { _scrollDown(); try { - final response = await _model.generateContent([Content.text(prompt)]); + final response = await _model.generateContent( + [Content.text(prompt)], + generationConfig: GenerationConfig( + responseModalities: [ + ResponseModalities.text, + ResponseModalities.image, + ], + imageConfig: ImageConfig( + aspectRatio: _selectedAspectRatio, + imageSize: _selectedImageSize, + ), + ), + ); String? textResponse = response.text; Uint8List? imageBytes; @@ -161,31 +175,100 @@ class _ImageGenerationPageState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 25, horizontal: 15), - child: Row( + padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 15), + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Expanded( - child: TextField( - autofocus: true, - focusNode: _textFieldFocus, - controller: _textController, - decoration: const InputDecoration( - hintText: 'Enter image prompt...', + Row( + children: [ + Expanded( + child: DropdownButtonFormField( + initialValue: _selectedAspectRatio, + decoration: const InputDecoration( + labelText: 'Aspect Ratio', + border: OutlineInputBorder(), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + ), + items: [ + const DropdownMenuItem( + child: Text('Default'), + ), + ...ImageAspectRatio.values.map( + (e) => DropdownMenuItem( + value: e, + child: Text('${e.name} (${e.toJson()})'), + ), + ), + ], + onChanged: (value) { + setState(() { + _selectedAspectRatio = value; + }); + }, + ), ), - onSubmitted: _generateImage, - ), + const SizedBox(width: 15), + Expanded( + child: DropdownButtonFormField( + initialValue: _selectedImageSize, + decoration: const InputDecoration( + labelText: 'Image Size', + border: OutlineInputBorder(), + contentPadding: EdgeInsets.symmetric( + horizontal: 10, + vertical: 10, + ), + ), + items: [ + const DropdownMenuItem( + child: Text('Default'), + ), + ...ImageSize.values.map( + (e) => DropdownMenuItem( + value: e, + child: Text('${e.name} (${e.toJson()})'), + ), + ), + ], + onChanged: (value) { + setState(() { + _selectedImageSize = value; + }); + }, + ), + ), + ], ), - const SizedBox(width: 15), - if (!_loading) - IconButton( - onPressed: () => _generateImage(_textController.text), - icon: Icon( - Icons.send, - color: Theme.of(context).colorScheme.primary, + const SizedBox(height: 15), + Row( + children: [ + Expanded( + child: TextField( + autofocus: true, + focusNode: _textFieldFocus, + controller: _textController, + decoration: const InputDecoration( + hintText: 'Enter image prompt...', + ), + onSubmitted: _generateImage, + ), ), - ) - else - const CircularProgressIndicator(), + const SizedBox(width: 15), + if (!_loading) + IconButton( + onPressed: () => _generateImage(_textController.text), + icon: Icon( + Icons.send, + color: Theme.of(context).colorScheme.primary, + ), + ) + else + const CircularProgressIndicator(), + ], + ), ], ), ), diff --git a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart index d2215525cb06..9e48a0c58686 100644 --- a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart @@ -66,6 +66,7 @@ export 'src/error.dart' QuotaExceeded, UnsupportedUserLocation; export 'src/firebase_ai.dart' show FirebaseAI; +export 'src/image_config.dart' show ImageConfig, ImageAspectRatio, ImageSize; export 'src/imagen/imagen_api.dart' show ImagenSafetySettings, diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 2e8ed26fc1cb..d4e20f9f1232 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -14,6 +14,7 @@ import 'content.dart'; import 'error.dart'; +import 'image_config.dart'; import 'schema.dart'; import 'tool.dart' show Tool, ToolConfig; @@ -808,9 +809,45 @@ enum FinishReason { /// The candidate content was flagged for malformed function call reasons. malformedFunctionCall('MALFORMED_FUNCTION_CALL'), - /// The model produced an unexpected tool call. + /// Token generation was stopped because the response contained forbidden terms. + blocklist('BLOCKLIST'), + + /// Token generation was stopped because the response contained potentially prohibited content. + prohibitedContent('PROHIBITED_CONTENT'), + + /// Token generation was stopped because of Sensitive Personally Identifiable Information (SPII). + spii('SPII'), + + /// Token generation stopped because generated images contain safety violations. + imageSafety('IMAGE_SAFETY'), + + /// Image generation stopped because generated images have other prohibited content. + imageProhibitedContent('IMAGE_PROHIBITED_CONTENT'), + + /// Image generation stopped because of other miscellaneous issues. + imageOther('IMAGE_OTHER'), + + /// The model was expected to generate an image, but none was generated. + noImage('NO_IMAGE'), + + /// Image generation stopped due to recitation. + imageRecitation('IMAGE_RECITATION'), + + /// The response candidate content was flagged for using an unsupported language. + language('LANGUAGE'), + + /// Model generated a tool call but no tools were enabled in the request. unexpectedToolCall('UNEXPECTED_TOOL_CALL'), + /// Model called too many tools consecutively, thus the system exited execution. + tooManyToolCalls('TOO_MANY_TOOL_CALLS'), + + /// Request has at least one thought signature missing. + missingThoughtSignature('MISSING_THOUGHT_SIGNATURE'), + + /// Finished due to malformed response. + malformedResponse('MALFORMED_RESPONSE'), + /// Unknown reason. other('OTHER'); @@ -831,8 +868,21 @@ enum FinishReason { 'RECITATION' => FinishReason.recitation, 'OTHER' => FinishReason.other, 'MALFORMED_FUNCTION_CALL' => FinishReason.malformedFunctionCall, + 'BLOCKLIST' => FinishReason.blocklist, + 'PROHIBITED_CONTENT' => FinishReason.prohibitedContent, + 'SPII' => FinishReason.spii, + 'IMAGE_SAFETY' => FinishReason.imageSafety, + 'IMAGE_PROHIBITED_CONTENT' => FinishReason.imageProhibitedContent, + 'IMAGE_OTHER' => FinishReason.imageOther, + 'NO_IMAGE' => FinishReason.noImage, + 'IMAGE_RECITATION' => FinishReason.imageRecitation, + 'LANGUAGE' => FinishReason.language, 'UNEXPECTED_TOOL_CALL' => FinishReason.unexpectedToolCall, - _ => throw FormatException('Unhandled FinishReason format', jsonObject), + 'TOO_MANY_TOOL_CALLS' => FinishReason.tooManyToolCalls, + 'MISSING_THOUGHT_SIGNATURE' => FinishReason.missingThoughtSignature, + 'MALFORMED_RESPONSE' => FinishReason.malformedResponse, + 'UNKNOWN' => FinishReason.unknown, + _ => FinishReason.unknown, }; } @@ -1238,6 +1288,7 @@ final class GenerationConfig extends BaseGenerationConfig { this.responseSchema, this.responseJsonSchema, this.thinkingConfig, + this.imageConfig, }) : assert(responseSchema == null || responseJsonSchema == null, 'responseSchema and responseJsonSchema cannot both be set.'); @@ -1286,6 +1337,9 @@ final class GenerationConfig extends BaseGenerationConfig { /// support thinking. final ThinkingConfig? thinkingConfig; + /// Configuration options for generating images with Gemini models. + final ImageConfig? imageConfig; + @override Map toJson() => { ...super.toJson(), @@ -1300,6 +1354,8 @@ final class GenerationConfig extends BaseGenerationConfig { 'responseJsonSchema': responseJsonSchema, if (thinkingConfig case final thinkingConfig?) 'thinkingConfig': thinkingConfig.toJson(), + if (imageConfig case final imageConfig?) + 'imageConfig': imageConfig.toJson(), }; } diff --git a/packages/firebase_ai/firebase_ai/lib/src/image_config.dart b/packages/firebase_ai/firebase_ai/lib/src/image_config.dart new file mode 100644 index 000000000000..277272b82c29 --- /dev/null +++ b/packages/firebase_ai/firebase_ai/lib/src/image_config.dart @@ -0,0 +1,110 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/// Configuration options for generating images with Gemini models. +final class ImageConfig { + /// Initializes configuration options for generating images with Gemini. + const ImageConfig({this.aspectRatio, this.imageSize}); + + /// The aspect ratio of generated images. + final ImageAspectRatio? aspectRatio; + + /// The size of the generated images. + final ImageSize? imageSize; + + /// Convert to json format. + Map toJson() => { + if (aspectRatio case final aspectRatio?) + 'aspectRatio': aspectRatio.toJson(), + if (imageSize case final imageSize?) 'imageSize': imageSize.toJson(), + }; +} + +/// An aspect ratio for generated images. +enum ImageAspectRatio { + /// Square (1:1) aspect ratio. + square1x1('1:1'), + + /// Portrait widescreen (9:16) aspect ratio. + portrait9x16('9:16'), + + /// Widescreen (16:9) aspect ratio. + landscape16x9('16:9'), + + /// Portrait full screen (3:4) aspect ratio. + portrait3x4('3:4'), + + /// Fullscreen (4:3) aspect ratio. + landscape4x3('4:3'), + + /// Portrait (2:3) aspect ratio. + portrait2x3('2:3'), + + /// Landscape (3:2) aspect ratio. + landscape3x2('3:2'), + + /// Portrait (4:5) aspect ratio. + portrait4x5('4:5'), + + /// Landscape (5:4) aspect ratio. + landscape5x4('5:4'), + + /// Portrait (1:4) aspect ratio. + portrait1x4('1:4'), + + /// Landscape (4:1) aspect ratio. + landscape4x1('4:1'), + + /// Portrait (1:8) aspect ratio. + portrait1x8('1:8'), + + /// Landscape (8:1) aspect ratio. + landscape8x1('8:1'), + + /// Ultrawide (21:9) aspect ratio. + ultrawide21x9('21:9'); + + const ImageAspectRatio(this._jsonString); + final String _jsonString; + + /// Convert to json format. + String toJson() => _jsonString; + + @override + String toString() => name; +} + +/// The size of images to generate. +enum ImageSize { + /// 512px (0.5K) image size. + size512('512'), + + /// 1K image size. + size1K('1K'), + + /// 2K image size. + size2K('2K'), + + /// 4K image size. + size4K('4K'); + + const ImageSize(this._jsonString); + final String _jsonString; + + /// Convert to json format. + String toJson() => _jsonString; + + @override + String toString() => name; +} diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index bc3352b869cc..fcac82a5ab50 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -18,6 +18,7 @@ import 'dart:convert'; import 'package:firebase_ai/src/api.dart'; import 'package:firebase_ai/src/content.dart'; import 'package:firebase_ai/src/error.dart'; +import 'package:firebase_ai/src/image_config.dart'; import 'package:firebase_ai/src/schema.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -322,10 +323,55 @@ void main() { expect(FinishReason.recitation.toJson(), 'RECITATION'); expect(FinishReason.malformedFunctionCall.toJson(), 'MALFORMED_FUNCTION_CALL'); + expect(FinishReason.blocklist.toJson(), 'BLOCKLIST'); + expect(FinishReason.prohibitedContent.toJson(), 'PROHIBITED_CONTENT'); + expect(FinishReason.spii.toJson(), 'SPII'); + expect(FinishReason.imageSafety.toJson(), 'IMAGE_SAFETY'); + expect(FinishReason.imageProhibitedContent.toJson(), + 'IMAGE_PROHIBITED_CONTENT'); + expect(FinishReason.imageOther.toJson(), 'IMAGE_OTHER'); + expect(FinishReason.noImage.toJson(), 'NO_IMAGE'); + expect(FinishReason.imageRecitation.toJson(), 'IMAGE_RECITATION'); + expect(FinishReason.language.toJson(), 'LANGUAGE'); expect(FinishReason.unexpectedToolCall.toJson(), 'UNEXPECTED_TOOL_CALL'); + expect(FinishReason.tooManyToolCalls.toJson(), 'TOO_MANY_TOOL_CALLS'); + expect(FinishReason.missingThoughtSignature.toJson(), + 'MISSING_THOUGHT_SIGNATURE'); + expect(FinishReason.malformedResponse.toJson(), 'MALFORMED_RESPONSE'); expect(FinishReason.other.toJson(), 'OTHER'); }); + test('FinishReason parseValue', () { + expect(FinishReason.parseValue('STOP'), FinishReason.stop); + expect(FinishReason.parseValue('MAX_TOKENS'), FinishReason.maxTokens); + expect(FinishReason.parseValue('SAFETY'), FinishReason.safety); + expect(FinishReason.parseValue('RECITATION'), FinishReason.recitation); + expect(FinishReason.parseValue('MALFORMED_FUNCTION_CALL'), + FinishReason.malformedFunctionCall); + expect(FinishReason.parseValue('BLOCKLIST'), FinishReason.blocklist); + expect(FinishReason.parseValue('PROHIBITED_CONTENT'), + FinishReason.prohibitedContent); + expect(FinishReason.parseValue('SPII'), FinishReason.spii); + expect(FinishReason.parseValue('IMAGE_SAFETY'), FinishReason.imageSafety); + expect(FinishReason.parseValue('IMAGE_PROHIBITED_CONTENT'), + FinishReason.imageProhibitedContent); + expect(FinishReason.parseValue('IMAGE_OTHER'), FinishReason.imageOther); + expect(FinishReason.parseValue('NO_IMAGE'), FinishReason.noImage); + expect(FinishReason.parseValue('IMAGE_RECITATION'), + FinishReason.imageRecitation); + expect(FinishReason.parseValue('LANGUAGE'), FinishReason.language); + expect(FinishReason.parseValue('UNEXPECTED_TOOL_CALL'), + FinishReason.unexpectedToolCall); + expect(FinishReason.parseValue('TOO_MANY_TOOL_CALLS'), + FinishReason.tooManyToolCalls); + expect(FinishReason.parseValue('MISSING_THOUGHT_SIGNATURE'), + FinishReason.missingThoughtSignature); + expect(FinishReason.parseValue('MALFORMED_RESPONSE'), + FinishReason.malformedResponse); + expect(FinishReason.parseValue('OTHER'), FinishReason.other); + expect(FinishReason.parseValue('UNSPECIFIED'), FinishReason.unknown); + }); + test('ContentModality toJson and toString', () { expect(ContentModality.unspecified.toJson(), 'MODALITY_UNSPECIFIED'); expect(ContentModality.text.toJson(), 'TEXT'); @@ -447,10 +493,34 @@ void main() { }); }); + group('ImageConfig', () { + test('toJson with all fields', () { + const config = ImageConfig( + aspectRatio: ImageAspectRatio.portrait9x16, + imageSize: ImageSize.size2K, + ); + expect(config.toJson(), { + 'aspectRatio': '9:16', + 'imageSize': '2K', + }); + }); + + test('toJson with some fields null', () { + const config = ImageConfig( + aspectRatio: ImageAspectRatio.landscape16x9, + ); + expect(config.toJson(), { + 'aspectRatio': '16:9', + }); + }); + }); + group('GenerationConfig & BaseGenerationConfig', () { test('GenerationConfig toJson with all fields', () { final schema = Schema.object(properties: {}); final thinkingConfig = ThinkingConfig(thinkingBudget: 100); + const imageConfig = ImageConfig( + aspectRatio: ImageAspectRatio.square1x1, imageSize: ImageSize.size1K); final config = GenerationConfig( candidateCount: 1, stopSequences: ['\n', 'stop'], @@ -463,6 +533,7 @@ void main() { responseMimeType: 'application/json', responseSchema: schema, thinkingConfig: thinkingConfig, + imageConfig: imageConfig, ); expect(config.toJson(), { 'candidateCount': 1, @@ -476,6 +547,10 @@ void main() { 'responseMimeType': 'application/json', 'responseSchema': schema.toJson(), 'thinkingConfig': {'thinkingBudget': 100}, + 'imageConfig': { + 'aspectRatio': '1:1', + 'imageSize': '1K', + }, }); }); From 851a1fe2ef6668dd1ac10d4b5bf7790b6c80546e Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 6 May 2026 16:19:13 -0700 Subject: [PATCH 055/137] chore(firebaseai): setup for mock response e2e test (#18029) * setup for mock response e2e test * fix the failing parse * update test to address unary-success-unknown-enum-safety-ratings.json * analyzer * clean up and add ai e2e test coverage * fix analyzer * remove extra import * fix web test failure on CI --- .../firebase_ai/firebase_ai/lib/src/api.dart | 17 +- .../firebase_ai/lib/src/content.dart | 8 +- .../test/response_parsing_test.dart | 144 ++++++++++++ tests/integration_test/e2e_test.dart | 2 + .../firebase_ai/firebase_ai_e2e_test.dart | 102 ++------- .../firebase_ai_headers_e2e_test.dart | 117 ++++++++++ .../firebase_ai/firebase_ai_mock_test.dart | 208 ++++++++++++++++++ ...firebase_ai_response_parsing_e2e_test.dart | 110 +++++++++ 8 files changed, 611 insertions(+), 97 deletions(-) create mode 100644 tests/integration_test/firebase_ai/firebase_ai_headers_e2e_test.dart create mode 100644 tests/integration_test/firebase_ai/firebase_ai_mock_test.dart create mode 100644 tests/integration_test/firebase_ai/firebase_ai_response_parsing_e2e_test.dart diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index d4e20f9f1232..ac0a23209456 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -594,7 +594,7 @@ enum BlockReason { 'BLOCK_REASON_UNSPECIFIED' => BlockReason.unknown, 'SAFETY' => BlockReason.safety, 'OTHER' => BlockReason.other, - _ => throw FormatException('Unhandled BlockReason format', jsonObject), + _ => BlockReason.unknown, }; } @@ -700,8 +700,7 @@ enum HarmProbability { 'LOW' => HarmProbability.low, 'MEDIUM' => HarmProbability.medium, 'HIGH' => HarmProbability.high, - _ => - throw FormatException('Unhandled HarmProbability format', jsonObject), + _ => HarmProbability.unknown, }; } @@ -743,7 +742,7 @@ enum HarmSeverity { 'HARM_SEVERITY_LOW' => HarmSeverity.low, 'HARM_SEVERITY_MEDIUM' => HarmSeverity.medium, 'HARM_SEVERITY_HIGH' => HarmSeverity.high, - _ => throw FormatException('Unhandled HarmSeverity format', jsonObject), + _ => HarmSeverity.unknown, }; } @@ -932,8 +931,7 @@ enum ContentModality { 'VIDEO' => ContentModality.video, 'AUDIO' => ContentModality.audio, 'DOCUMENT' => ContentModality.document, - _ => - throw FormatException('Unhandled ContentModality format', jsonObject), + _ => ContentModality.unspecified, }; } @@ -1038,8 +1036,7 @@ enum HarmBlockMethod { 'SEVERITY' => HarmBlockMethod.severity, 'PROBABILITY' => HarmBlockMethod.probability, 'HARM_BLOCK_METHOD_UNSPECIFIED' => HarmBlockMethod.unspecified, - _ => - throw FormatException('Unhandled HarmBlockMethod format', jsonObject), + _ => HarmBlockMethod.unspecified, }; } @@ -1390,7 +1387,7 @@ enum TaskType { 'SEMANTIC_SIMILARITY' => TaskType.semanticSimilarity, 'CLASSIFICATION' => TaskType.classification, 'CLUSTERING' => TaskType.clustering, - _ => throw FormatException('Unhandled TaskType format', jsonObject), + _ => TaskType.unspecified, }; } @@ -1931,7 +1928,7 @@ enum Outcome { 'OUTCOME_OK' => Outcome.ok, 'OUTCOME_FAILED' => Outcome.failed, 'OUTCOME_DEADLINE_EXCEEDED' => Outcome.deadlineExceeded, - _ => throw FormatException('Unhandled Outcome format', jsonObject), + _ => Outcome.unspecified, }; } } diff --git a/packages/firebase_ai/firebase_ai/lib/src/content.dart b/packages/firebase_ai/firebase_ai/lib/src/content.dart index c9ed7813c4ee..8fa2b7b14ad1 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/content.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/content.dart @@ -103,12 +103,12 @@ Part parsePart(Object? jsonObject) { if (jsonObject.containsKey('functionCall')) { final functionCall = jsonObject['functionCall']; - if (functionCall is Map && - functionCall.containsKey('name') && - functionCall.containsKey('args')) { + if (functionCall is Map && functionCall.containsKey('name')) { return FunctionCall._( functionCall['name'] as String, - functionCall['args'] as Map, + functionCall.containsKey('args') + ? functionCall['args'] as Map + : {}, id: functionCall['id'] as String?, isThought: isThought, thoughtSignature: thoughtSignature, diff --git a/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart b/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart index 3078177f180b..7ad3aebe6572 100644 --- a/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart +++ b/packages/firebase_ai/firebase_ai/test/response_parsing_test.dart @@ -1152,6 +1152,150 @@ void main() { expect(groundingChunk.maps?.placeId, 'ChIJS5dFe_cZzosR26ZvwqWaMAM'); expect(groundingChunk.web, isNull); }); + + test('with unknown safety ratings', () async { + const response = ''' +{ + "candidates": [ + { + "content": { + "parts": [ + { + "text": "Some text" + } + ], + "role": "model" + }, + "finishReason": "STOP", + "index": 0, + "safetyRatings": [ + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "MEDIUM" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "FAKE_NEW_HARM_PROBABILITY" + }, + { + "category": "FAKE_NEW_HARM_CATEGORY", + "probability": "HIGH" + } + ] + } + ], + "promptFeedback": { + "safetyRatings": [ + { + "category": "HARM_CATEGORY_HARASSMENT", + "probability": "MEDIUM" + }, + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "probability": "FAKE_NEW_HARM_PROBABILITY" + }, + { + "category": "FAKE_NEW_HARM_CATEGORY", + "probability": "HIGH" + } + ] + } +} +'''; + final decoded = jsonDecode(response) as Object; + final generateContentResponse = + VertexSerialization().parseGenerateContentResponse(decoded); + expect( + generateContentResponse, + matchesGenerateContentResponse( + GenerateContentResponse( + [ + Candidate( + Content.model([ + const TextPart('Some text'), + ]), + [ + SafetyRating( + HarmCategory.harassment, + HarmProbability.medium, + ), + SafetyRating( + HarmCategory.dangerousContent, + HarmProbability.unknown, + ), + SafetyRating( + HarmCategory.unknown, + HarmProbability.high, + ), + ], + null, + FinishReason.stop, + null, + ), + ], + PromptFeedback(null, null, [ + SafetyRating( + HarmCategory.harassment, + HarmProbability.medium, + ), + SafetyRating( + HarmCategory.dangerousContent, + HarmProbability.unknown, + ), + SafetyRating( + HarmCategory.unknown, + HarmProbability.high, + ), + ]), + ), + ), + ); + }); + + test('with an empty function call', () async { + const response = ''' +{ + "candidates": [ + { + "content": { + "parts": [ + { + "functionCall": { + "name": "current_time" + } + } + ], + "role": "model" + }, + "finishReason": "STOP", + "index": 0 + } + ] +} +'''; + final decoded = jsonDecode(response) as Object; + final generateContentResponse = + VertexSerialization().parseGenerateContentResponse(decoded); + expect( + generateContentResponse, + matchesGenerateContentResponse( + GenerateContentResponse( + [ + Candidate( + Content.model([ + const FunctionCall('current_time', {}), + ]), + null, + null, + FinishReason.stop, + null, + ), + ], + null, + ), + ), + ); + }); }); group('parses and throws error responses', () { diff --git a/tests/integration_test/e2e_test.dart b/tests/integration_test/e2e_test.dart index 12511585363c..7c93be2fa8d6 100644 --- a/tests/integration_test/e2e_test.dart +++ b/tests/integration_test/e2e_test.dart @@ -64,6 +64,7 @@ void main() { firebase_performance.main(); firebase_remote_config.main(); firebase_storage.main(); + firebase_ai.main(); return; } @@ -102,5 +103,6 @@ void runAllTests() { firebase_performance.main(); firebase_remote_config.main(); firebase_storage.main(); + firebase_ai.main(); firebase_app_check.main(); } diff --git a/tests/integration_test/firebase_ai/firebase_ai_e2e_test.dart b/tests/integration_test/firebase_ai/firebase_ai_e2e_test.dart index 75c7d67f7720..8509114ae557 100644 --- a/tests/integration_test/firebase_ai/firebase_ai_e2e_test.dart +++ b/tests/integration_test/firebase_ai/firebase_ai_e2e_test.dart @@ -1,94 +1,30 @@ -// Copyright 2026, the Chromium project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -const _channel = MethodChannel('plugins.flutter.io/firebase_ai'); +import 'firebase_ai_headers_e2e_test.dart' as headers_tests; +import 'firebase_ai_response_parsing_e2e_test.dart' as parsing_tests; +import 'firebase_ai_mock_test.dart' as mock_tests; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); group('firebase_ai', () { - group('platform security headers', () { - testWidgets( - 'returns non-empty headers on mobile platforms', - skip: kIsWeb, - (WidgetTester tester) async { - final headers = await _channel.invokeMapMethod( - 'getPlatformHeaders', - ); - - expect( - headers, - isNotNull, - reason: 'Native plugin should return platform headers', - ); - expect( - headers, - isNotEmpty, - reason: 'Native plugin should return non-empty platform headers', - ); - }, - ); - - testWidgets( - 'returns correct Android headers', - skip: kIsWeb || defaultTargetPlatform != TargetPlatform.android, - (WidgetTester tester) async { - final headers = await _channel.invokeMapMethod( - 'getPlatformHeaders', - ); - - expect(headers, isNotNull); - expect(headers, contains('X-Android-Package')); - expect( - headers!['X-Android-Package'], - isNotEmpty, - reason: 'Package name should not be empty', - ); - // Cert may be empty in some emulator environments, but key must exist. - expect(headers, contains('X-Android-Cert')); - }, - ); - - testWidgets( - 'returns correct iOS/macOS headers', - skip: kIsWeb || - (defaultTargetPlatform != TargetPlatform.iOS && - defaultTargetPlatform != TargetPlatform.macOS), - (WidgetTester tester) async { - final headers = await _channel.invokeMapMethod( - 'getPlatformHeaders', - ); - - expect(headers, isNotNull); - expect(headers, contains('x-ios-bundle-identifier')); - expect( - headers!['x-ios-bundle-identifier'], - isNotEmpty, - reason: 'Bundle identifier should not be empty', - ); - }, - ); - - testWidgets( - 'returns empty headers on web', - skip: !kIsWeb, - (WidgetTester tester) async { - // On web, no native plugin is registered, so the channel call - // should throw a MissingPluginException. - expect( - () => _channel.invokeMapMethod( - 'getPlatformHeaders', - ), - throwsA(isA()), - ); - }, - ); - }); + headers_tests.main(); + parsing_tests.main(); + mock_tests.main(); }); } diff --git a/tests/integration_test/firebase_ai/firebase_ai_headers_e2e_test.dart b/tests/integration_test/firebase_ai/firebase_ai_headers_e2e_test.dart new file mode 100644 index 000000000000..0650556a1997 --- /dev/null +++ b/tests/integration_test/firebase_ai/firebase_ai_headers_e2e_test.dart @@ -0,0 +1,117 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + if (!kIsWeb) { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler( + const MethodChannel('plugins.flutter.io/firebase_ai'), + (MethodCall call) async { + if (call.method == 'getPlatformHeaders') { + return { + 'X-Android-Package': 'com.example.test', + 'X-Android-Cert': '12345', + 'x-ios-bundle-identifier': 'com.example.test', + }; + } + return null; + }); + } + + group('platform security headers', () { + const _channel = MethodChannel('plugins.flutter.io/firebase_ai'); + testWidgets( + 'returns non-empty headers on mobile platforms', + skip: kIsWeb, + (WidgetTester tester) async { + final headers = await _channel.invokeMapMethod( + 'getPlatformHeaders', + ); + + expect( + headers, + isNotNull, + reason: 'Native plugin should return platform headers', + ); + expect( + headers, + isNotEmpty, + reason: 'Native plugin should return non-empty platform headers', + ); + }, + ); + + testWidgets( + 'returns correct Android headers', + skip: kIsWeb || defaultTargetPlatform != TargetPlatform.android, + (WidgetTester tester) async { + final headers = await _channel.invokeMapMethod( + 'getPlatformHeaders', + ); + + expect(headers, isNotNull); + expect(headers, contains('X-Android-Package')); + expect( + headers!['X-Android-Package'], + isNotEmpty, + reason: 'Package name should not be empty', + ); + // Cert may be empty in some emulator environments, but key must exist. + expect(headers, contains('X-Android-Cert')); + }, + ); + + testWidgets( + 'returns correct iOS/macOS headers', + skip: kIsWeb || + (defaultTargetPlatform != TargetPlatform.iOS && + defaultTargetPlatform != TargetPlatform.macOS), + (WidgetTester tester) async { + final headers = await _channel.invokeMapMethod( + 'getPlatformHeaders', + ); + + expect(headers, isNotNull); + expect(headers, contains('x-ios-bundle-identifier')); + expect( + headers!['x-ios-bundle-identifier'], + isNotEmpty, + reason: 'Bundle identifier should not be empty', + ); + }, + ); + + testWidgets( + 'returns empty headers on web', + skip: !kIsWeb, + (WidgetTester tester) async { + // On web, no native plugin is registered, so the channel call + // should throw a MissingPluginException. + expect( + () => _channel.invokeMapMethod( + 'getPlatformHeaders', + ), + throwsA(isA()), + ); + }, + ); + }); +} diff --git a/tests/integration_test/firebase_ai/firebase_ai_mock_test.dart b/tests/integration_test/firebase_ai/firebase_ai_mock_test.dart new file mode 100644 index 000000000000..26ebddba04a8 --- /dev/null +++ b/tests/integration_test/firebase_ai/firebase_ai_mock_test.dart @@ -0,0 +1,208 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:async'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_core_platform_interface/test.dart'; +import 'package:firebase_ai/src/api.dart'; +import 'package:firebase_ai/src/client.dart'; +import 'package:firebase_ai/src/base_model.dart'; +import 'package:firebase_ai/src/content.dart'; +import 'package:firebase_ai/src/chat.dart'; +import 'package:tests/firebase_options.dart'; + +class MockApiClient implements ApiClient { + final List> requests = []; + Map mockResponse = {}; + + @override + Future> makeRequest( + Uri uri, Map body,) async { + requests.add({'uri': uri, 'body': body}); + return mockResponse; + } + + @override + Stream> streamRequest( + Uri uri, Map body,) async* { + requests.add({'uri': uri, 'body': body}); + yield mockResponse; + } +} + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('firebase_ai mock tests', () { + setUpAll(() async { + setupFirebaseCoreMocks(); + // Use a named app to avoid conflict with the default app initialized by mocks + await Firebase.initializeApp( + name: 'mockTestApp', + options: DefaultFirebaseOptions.currentPlatform, + ); + }); + + test('Verify Request Payload for Grounding', () async { + final mockClient = MockApiClient(); + mockClient.mockResponse = { + 'candidates': [ + { + 'content': { + 'parts': [ + {'text': 'Hello!'}, + ], + }, + } + ], + }; + + // Using the package-private test method via src import + final model = createModelWithClient( + app: Firebase.app('mockTestApp'), + location: 'us-central1', + model: 'gemini-pro', + client: mockClient, + useVertexBackend: true, + ); + + // We need to construct a request that uses Grounding. + // Assuming there is a way to set tools or similar. + // Let's just call a simple generateContent first to verify the mock works. + final response = await model.generateContent([Content.text('Hi')]); + + expect(response.text, equals('Hello!')); + expect(mockClient.requests, hasLength(1)); + + final requestBody = + mockClient.requests.first['body']! as Map; + expect(requestBody, contains('contents')); + }); + + test('Verify Request Payload for JSON Schema', () async { + final mockClient = MockApiClient(); + mockClient.mockResponse = { + 'candidates': [ + { + 'content': { + 'parts': [ + {'text': '{"name": "Apple", "price": 1.2}'}, + ], + }, + } + ], + }; + + final model = createModelWithClient( + app: Firebase.app('mockTestApp'), + location: 'us-central1', + model: 'gemini-pro', + client: mockClient, + useVertexBackend: true, + ); + + final schema = { + 'type': 'OBJECT', + 'properties': { + 'name': {'type': 'STRING'}, + 'price': {'type': 'NUMBER'}, + }, + 'required': ['name', 'price'], + }; + + await model.generateContent( + [Content.text('Give me a fruit')], + generationConfig: GenerationConfig( + responseMimeType: 'application/json', + responseJsonSchema: schema, + ), + ); + + expect(mockClient.requests, hasLength(1)); + final requestBody = mockClient.requests.first['body']! as Map; + expect(requestBody, contains('generationConfig')); + + final genConfig = requestBody['generationConfig']! as Map; + expect(genConfig['responseMimeType'], equals('application/json')); + expect(genConfig['responseJsonSchema'], equals(schema)); + }); + + test('Verify Request Payload for Multi-turn Chat', () async { + final mockClient = MockApiClient(); + // Mock response for first turn + mockClient.mockResponse = { + 'candidates': [ + { + 'content': { + 'role': 'model', + 'parts': [ + {'text': 'Hello!'}, + ], + }, + } + ], + }; + + final model = createModelWithClient( + app: Firebase.app('mockTestApp'), + location: 'us-central1', + model: 'gemini-pro', + client: mockClient, + useVertexBackend: true, + ); + + final chat = model.startChat(); + + // First turn + await chat.sendMessage(Content.text('Hi')); + + // Mock response for second turn + mockClient.mockResponse = { + 'candidates': [ + { + 'content': { + 'role': 'model', + 'parts': [ + {'text': 'I am good.'}, + ], + }, + } + ], + }; + + // Second turn + await chat.sendMessage(Content.text('How are you?')); + + // Verify that the second request contains the history + expect(mockClient.requests, hasLength(2)); + + final secondRequest = mockClient.requests[1]['body']! as Map; + expect(secondRequest, contains('contents')); + + final contents = secondRequest['contents']! as List; + expect(contents, hasLength(3)); // User 'Hi', Model 'Hello!', User 'How are you?' + + // Verify roles and text + expect(contents[0]['role'], equals('user')); + expect(contents[1]['role'], equals('model')); + expect(contents[2]['role'], equals('user')); + + expect(contents[0]['parts'][0]['text'], equals('Hi')); + expect(contents[1]['parts'][0]['text'], equals('Hello!')); + expect(contents[2]['parts'][0]['text'], equals('How are you?')); + }); + }); +} diff --git a/tests/integration_test/firebase_ai/firebase_ai_response_parsing_e2e_test.dart b/tests/integration_test/firebase_ai/firebase_ai_response_parsing_e2e_test.dart new file mode 100644 index 000000000000..fe0b91644945 --- /dev/null +++ b/tests/integration_test/firebase_ai/firebase_ai_response_parsing_e2e_test.dart @@ -0,0 +1,110 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:http/http.dart' as http; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_core_platform_interface/test.dart'; +import 'package:firebase_ai/src/api.dart'; +import 'package:firebase_ai/src/developer/api.dart'; +import 'package:tests/firebase_options.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('firebase_ai mock json parsing', () { + setUpAll(() async { + setupFirebaseCoreMocks(); + // Use a named app to avoid conflict with the default app initialized by mocks + await Firebase.initializeApp( + name: 'parsingTestApp', + options: DefaultFirebaseOptions.currentPlatform, + ); + }); + + test('test against all json responses from vertexai-sdk-test-data', + () async { + final treeUrl = Uri.parse( + 'https://api.github.com/repos/FirebaseExtended/vertexai-sdk-test-data/git/trees/main?recursive=1', + ); + final treeResponse = await http.get(treeUrl); + if (treeResponse.statusCode != 200) { + if (treeResponse.statusCode == 403 || treeResponse.statusCode == 429) { + // ignore: avoid_print + print( + 'Skipping test: Failed to fetch tree due to rate limit (status ${treeResponse.statusCode})', + ); + return; + } + fail('Failed to fetch tree: ${treeResponse.statusCode}'); + } + final treeData = jsonDecode(treeResponse.body); + final tree = treeData['tree'] as List; + + final jsonFiles = tree.where((item) { + final path = item['path'] as String; + return path.startsWith('mock-responses/') && path.endsWith('.json'); + }).toList(); + + for (final file in jsonFiles) { + final path = file['path'] as String; + final rawUrl = Uri.parse( + 'https://raw.githubusercontent.com/FirebaseExtended/vertexai-sdk-test-data/main/$path', + ); + final response = await http.get(rawUrl); + if (response.statusCode != 200) { + continue; + } + + final jsonData = jsonDecode(response.body); + + final isVertex = path.contains('vertexai'); + final serializer = + isVertex ? VertexSerialization() : DeveloperSerialization(); + + try { + if (path.contains('total-tokens') || path.contains('token')) { + if (jsonData is Map && + (jsonData.containsKey('totalTokens') || + jsonData.containsKey('error'))) { + serializer.parseCountTokensResponse(jsonData); + } else { + serializer.parseGenerateContentResponse(jsonData); + } + } else { + serializer.parseGenerateContentResponse(jsonData); + } + + if (path.contains('failure') && !path.contains('success')) { + fail('Expected parsing to fail for $path, but it succeeded.'); + } + } catch (e) { + if (path.contains('failure') && !path.contains('success')) { + // Expected to fail + expect( + e, + isA(), + reason: 'Expected an Exception but got $e for $path', + ); + } else { + fail('Failed to parse success file $path: $e'); + } + } + } + }); + }); +} From 40fd2904e4634d9257241c1c2e779aa5bfc61624 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 7 May 2026 16:47:29 +0200 Subject: [PATCH 056/137] fix(database): fix a regression with database localEvents handling (#18257) * fix(database): fix a regression with database localEvents handling * fix iOS --- .../database/FirebaseDatabasePlugin.kt | 2 +- .../FLTFirebaseDatabasePlugin.swift | 6 ++-- .../database_reference_e2e.dart | 35 +++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt index 80c7ae0bef23..6f610991d179 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt @@ -770,7 +770,7 @@ class FirebaseDatabasePlugin : callback(KotlinResult.success(Unit)) } } - }) + }, request.applyLocally) } catch (e: Exception) { // Convert generic exceptions to FlutterFirebaseDatabaseException for proper error handling val flutterException = if (e is FlutterFirebaseDatabaseException) e else FlutterFirebaseDatabaseException.unknown(e.message ?: "Unknown transaction error") diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift index f4f0ac77b8c0..1c617600deb7 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift @@ -251,7 +251,7 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) - reference.runTransactionBlock { currentData in + reference.runTransactionBlock({ currentData in let semaphore = DispatchSemaphore(value: 0) var transactionResult: TransactionHandlerResult? @@ -284,7 +284,7 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug currentData.value = result.value return TransactionResult.success(withValue: currentData) - } andCompletionBlock: { error, committed, snapshot in + }, andCompletionBlock: { error, committed, snapshot in if let error { completion(.failure(self.createFlutterError(error))) return @@ -304,7 +304,7 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug ] completion(.success(())) - } + }, withLocalEvents: request.applyLocally) } func databaseReferenceGetTransactionResult(app: DatabasePigeonFirebaseApp, transactionKey: Int64, diff --git a/tests/integration_test/firebase_database/database_reference_e2e.dart b/tests/integration_test/firebase_database/database_reference_e2e.dart index 78fc9616ffe9..0c59b4af6ccb 100644 --- a/tests/integration_test/firebase_database/database_reference_e2e.dart +++ b/tests/integration_test/firebase_database/database_reference_e2e.dart @@ -126,6 +126,41 @@ void setupDatabaseReferenceTests() { expect(result.snapshot.value, 5); }); + test('does not emit local transaction events when disabled', () async { + final ref = database.ref('tests/transaction-apply-locally-false'); + await ref.set({'count': 0}); + + final initialEvent = Completer(); + final events = []; + final subscription = ref.onValue.listen((event) { + if (!initialEvent.isCompleted) { + initialEvent.complete(); + return; + } + + events.add(event.snapshot.value); + }); + + try { + await initialEvent.future.timeout(const Duration(seconds: 5)); + + await ref.runTransaction( + (value) => Transaction.success({ + 'count': ((value as Map?)?['count'] as int? ?? 0) + 1, + 'timestamp': ServerValue.timestamp, + }), + applyLocally: false, + ); + + await Future.delayed(const Duration(seconds: 1)); + + expect(events, hasLength(1)); + } finally { + await database.goOnline(); + await subscription.cancel(); + } + }); + test('executes transaction', () async { final ref = database.ref('tests/transaction-exec'); await ref.set(0); From 2db3166ec20a752514bdc861de335ad2105c714c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 18:25:06 +0100 Subject: [PATCH 057/137] chore(deps): bump actions/setup-java from 4.5.0 to 5.2.0 (#18245) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/android.yaml | 2 +- .github/workflows/e2e_tests_fdc.yaml | 8 ++++---- .github/workflows/e2e_tests_pipeline.yaml | 4 ++-- .github/workflows/ios.yaml | 2 +- .github/workflows/macos.yaml | 2 +- .github/workflows/web.yaml | 6 +++--- .github/workflows/windows.yaml | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index b881255f6094..e963fa3683d6 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -50,7 +50,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 3f402dc497db..493fd36b67a7 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -45,7 +45,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' @@ -151,7 +151,7 @@ jobs: node-version: '20' - name: Xcode run: sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' @@ -265,7 +265,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' @@ -340,7 +340,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index f8b4732d65e9..ee1361e3e41f 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -38,7 +38,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' @@ -166,7 +166,7 @@ jobs: node-version: '20' - name: Xcode run: sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index da5a9d0d56fc..3815aad572de 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -48,7 +48,7 @@ jobs: node-version: '20' - name: Xcode run: sudo xcode-select -s /Applications/Xcode_16.4.app/Contents/Developer - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index f23821f92a39..a96f972ef77b 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -46,7 +46,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index 8602f05ba8a6..27621f4d58e5 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -46,7 +46,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' @@ -116,7 +116,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' @@ -198,7 +198,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 272cf888fbc8..bb89b1d52f70 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -35,7 +35,7 @@ jobs: timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' @@ -69,7 +69,7 @@ jobs: timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' java-version: '21' From 57d4c3d050c6a9252390de6cac91a0ca1d5461e3 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 7 May 2026 19:27:59 +0200 Subject: [PATCH 058/137] fix(messaging,android): fix call race that could happen when using requestPermission (#18256) --- .../FlutterFirebasePermissionManager.java | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebasePermissionManager.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebasePermissionManager.java index 9087ef26e847..ad1202bd0b59 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebasePermissionManager.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebasePermissionManager.java @@ -17,7 +17,11 @@ import java.util.ArrayList; class FlutterFirebasePermissionManager implements PluginRegistry.RequestPermissionsResultListener { + private static final String REQUEST_IN_PROGRESS_ERROR = + "A request for permissions is already running, please wait for it to finish before doing " + + "another request."; + private final Object requestLock = new Object(); private final int permissionCode = 240; @Nullable private RequestPermissionsSuccessCallback successCallback; private boolean requestInProgress = false; @@ -30,15 +34,32 @@ interface RequestPermissionsSuccessCallback { @Override public boolean onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - if (requestInProgress && requestCode == permissionCode && this.successCallback != null) { + final RequestPermissionsSuccessCallback callback; + synchronized (requestLock) { + if (!requestInProgress || requestCode != permissionCode || this.successCallback == null) { + return false; + } + + callback = this.successCallback; + this.successCallback = null; requestInProgress = false; - boolean granted = - grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; + } + + boolean granted = + grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; + callback.onSuccess(granted ? 1 : 0); + return true; + } + + private boolean setRequestInProgress(RequestPermissionsSuccessCallback successCallback) { + synchronized (requestLock) { + if (requestInProgress) { + return false; + } - this.successCallback.onSuccess(granted ? 1 : 0); + requestInProgress = true; + this.successCallback = successCallback; return true; - } else { - return false; } } @@ -47,25 +68,20 @@ public void requestPermissions( Activity activity, RequestPermissionsSuccessCallback successCallback, ErrorCallback errorCallback) { - if (requestInProgress) { - errorCallback.onError( - "A request for permissions is already running, please wait for it to finish before doing another request."); + if (activity == null) { + errorCallback.onError("Unable to detect current Android Activity."); return; } - if (activity == null) { - errorCallback.onError("Unable to detect current Android Activity."); + if (!setRequestInProgress(successCallback)) { + errorCallback.onError(REQUEST_IN_PROGRESS_ERROR); return; } - this.successCallback = successCallback; final ArrayList permissions = new ArrayList(); permissions.add(Manifest.permission.POST_NOTIFICATIONS); final String[] requestNotificationPermission = permissions.toArray(new String[0]); - if (!requestInProgress) { - ActivityCompat.requestPermissions(activity, requestNotificationPermission, permissionCode); - requestInProgress = true; - } + ActivityCompat.requestPermissions(activity, requestNotificationPermission, permissionCode); } } From b0bc6e8f0e92aed2f3da99725eff85b3cf358282 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 7 May 2026 19:28:53 +0200 Subject: [PATCH 059/137] fix(app_check): fix an issue with debug token that would sometime not be passed properly (#18258) --- .../method_channel_firebase_app_check.dart | 43 +++++++---- ...ethod_channel_firebase_app_check_test.dart | 77 +++++++++++++++++++ .../firebase_app_check_e2e_test.dart | 57 ++++++++++++++ 3 files changed, 164 insertions(+), 13 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart index 96afb6f2c999..963c354aca4e 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart @@ -92,18 +92,6 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { WindowsAppCheckProvider? providerWindows, }) async { try { - String? debugToken; - if (providerAndroid is AndroidDebugProvider && - providerAndroid.debugToken != null) { - debugToken = providerAndroid.debugToken; - } else if (providerApple is AppleDebugProvider && - providerApple.debugToken != null) { - debugToken = providerApple.debugToken; - } else if (providerWindows is WindowsDebugProvider && - providerWindows.debugToken != null) { - debugToken = providerWindows.debugToken; - } - await _pigeonApi.activate( app.name, defaultTargetPlatform == TargetPlatform.android || kDebugMode @@ -120,7 +108,11 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { newProvider: providerApple, ) : null, - debugToken, + _getDebugToken( + providerAndroid: providerAndroid, + providerApple: providerApple, + providerWindows: providerWindows, + ), ); } on PlatformException catch (e, s) { convertPlatformException(e, s); @@ -164,3 +156,28 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { } } } + +String? _getDebugToken({ + AndroidAppCheckProvider? providerAndroid, + AppleAppCheckProvider? providerApple, + WindowsAppCheckProvider? providerWindows, +}) { + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return providerAndroid is AndroidDebugProvider + ? providerAndroid.debugToken + : null; + case TargetPlatform.iOS: + case TargetPlatform.macOS: + return providerApple is AppleDebugProvider + ? providerApple.debugToken + : null; + case TargetPlatform.windows: + return providerWindows is WindowsDebugProvider + ? providerWindows.debugToken + : null; + case TargetPlatform.fuchsia: + case TargetPlatform.linux: + return null; + } +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart index 5f215cec19fc..0839886ba264 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart @@ -3,7 +3,9 @@ // found in the LICENSE file. import 'package:firebase_app_check_platform_interface/firebase_app_check_platform_interface.dart'; +import 'package:firebase_app_check_platform_interface/src/pigeon/messages.pigeon.dart'; import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import '../mock.dart'; @@ -26,6 +28,15 @@ void main() { ); }); + tearDown(() { + debugDefaultTargetPlatformOverride = null; + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', + null, + ); + }); + group('delegateFor()', () { test('returns a [FirebaseAppCheckPlatform]', () { final appCheck = FirebaseAppCheckPlatform.instance; @@ -44,5 +55,71 @@ void main() { expect(appCheck.setInitialValues(), appCheck); }); }); + + group('activate()', () { + test('passes the Apple debug token on Apple platforms', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + final calls = >[]; + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', + (ByteData? message) async { + calls.add( + FirebaseAppCheckHostApi.pigeonChannelCodec.decodeMessage(message)! + as List, + ); + return FirebaseAppCheckHostApi.pigeonChannelCodec.encodeMessage( + [], + ); + }, + ); + + final appCheck = MethodChannelFirebaseAppCheck(app: secondaryApp); + + await appCheck.activate( + providerAndroid: const AndroidDebugProvider( + debugToken: 'android-debug-token', + ), + providerApple: const AppleDebugProvider( + debugToken: 'apple-debug-token', + ), + ); + + expect(calls, hasLength(1)); + expect(calls.single[3], 'apple-debug-token'); + }); + + test('passes the Android debug token on Android', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.android; + final calls = >[]; + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', + (ByteData? message) async { + calls.add( + FirebaseAppCheckHostApi.pigeonChannelCodec.decodeMessage(message)! + as List, + ); + return FirebaseAppCheckHostApi.pigeonChannelCodec.encodeMessage( + [], + ); + }, + ); + + final appCheck = MethodChannelFirebaseAppCheck(app: secondaryApp); + + await appCheck.activate( + providerAndroid: const AndroidDebugProvider( + debugToken: 'android-debug-token', + ), + providerApple: const AppleDebugProvider( + debugToken: 'apple-debug-token', + ), + ); + + expect(calls, hasLength(1)); + expect(calls.single[3], 'android-debug-token'); + }); + }); }); } diff --git a/tests/integration_test/firebase_app_check/firebase_app_check_e2e_test.dart b/tests/integration_test/firebase_app_check/firebase_app_check_e2e_test.dart index 2046367d76b1..777444ae5d64 100644 --- a/tests/integration_test/firebase_app_check/firebase_app_check_e2e_test.dart +++ b/tests/integration_test/firebase_app_check/firebase_app_check_e2e_test.dart @@ -2,6 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// ignore_for_file: do_not_use_environment + import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; @@ -9,6 +11,11 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:tests/firebase_options.dart'; +const androidDebugToken = + String.fromEnvironment('APP_CHECK_ANDROID_DEBUG_TOKEN'); + +const appleDebugToken = String.fromEnvironment('APP_CHECK_APPLE_DEBUG_TOKEN'); + void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -99,6 +106,56 @@ void main() { }, skip: defaultTargetPlatform != TargetPlatform.iOS, ); + + test( + 'uses Apple debug token when both Android and Apple debug tokens are configured', + () async { + await FirebaseAppCheck.instance.activate( + providerAndroid: const AndroidDebugProvider( + debugToken: androidDebugToken, + ), + providerApple: const AppleDebugProvider( + debugToken: appleDebugToken, + ), + ); + + await expectLater( + FirebaseAppCheck.instance.getToken(true), + completes, + ); + }, + skip: defaultTargetPlatform != TargetPlatform.iOS || + androidDebugToken.isEmpty || + appleDebugToken.isEmpty + ? 'Requires iOS plus APP_CHECK_ANDROID_DEBUG_TOKEN and ' + 'APP_CHECK_APPLE_DEBUG_TOKEN dart-defines.' + : null, + ); + + test( + 'uses Android debug token when both Android and Apple debug tokens are configured', + () async { + await FirebaseAppCheck.instance.activate( + providerAndroid: const AndroidDebugProvider( + debugToken: androidDebugToken, + ), + providerApple: const AppleDebugProvider( + debugToken: appleDebugToken, + ), + ); + + await expectLater( + FirebaseAppCheck.instance.getToken(true), + completes, + ); + }, + skip: defaultTargetPlatform != TargetPlatform.android || + androidDebugToken.isEmpty || + appleDebugToken.isEmpty + ? 'Requires Android plus APP_CHECK_ANDROID_DEBUG_TOKEN and ' + 'APP_CHECK_APPLE_DEBUG_TOKEN dart-defines.' + : null, + ); }, ); } From 11bdedfb356d2c84e352e26abfc79de4c5653089 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 7 May 2026 19:30:30 +0200 Subject: [PATCH 060/137] fix(database,android): fix an issue where setPersistenceEnabled needed to be called first (#18259) --- .../database/FirebaseDatabasePlugin.kt | 8 +++-- .../firebase_database_configuration_e2e.dart | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt index 6f610991d179..a79a400f6c97 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt @@ -516,7 +516,9 @@ class FirebaseDatabasePlugin : override fun setPersistenceEnabled(app: DatabasePigeonFirebaseApp, enabled: Boolean, callback: (KotlinResult) -> Unit) { try { val database = getDatabaseFromPigeonApp(app) - database.setPersistenceEnabled(enabled) + if (app.settings.persistenceEnabled == null) { + database.setPersistenceEnabled(enabled) + } callback(KotlinResult.success(Unit)) } catch (e: Exception) { callback(KotlinResult.failure(e)) @@ -526,7 +528,9 @@ class FirebaseDatabasePlugin : override fun setPersistenceCacheSizeBytes(app: DatabasePigeonFirebaseApp, cacheSize: Long, callback: (KotlinResult) -> Unit) { try { val database = getDatabaseFromPigeonApp(app) - database.setPersistenceCacheSizeBytes(cacheSize) + if (app.settings.cacheSizeBytes == null) { + database.setPersistenceCacheSizeBytes(cacheSize) + } callback(KotlinResult.success(Unit)) } catch (e: Exception) { callback(KotlinResult.failure(e)) diff --git a/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart b/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart index 7cb4b66344da..7fe19f95c25b 100644 --- a/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart +++ b/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart @@ -2,8 +2,11 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_database/firebase_database.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:tests/firebase_options.dart'; import 'firebase_database_e2e_test.dart'; @@ -37,5 +40,31 @@ void setupConfigurationTests() { test('setLoggingEnabled to false', () { database.setLoggingEnabled(false); }); + + test( + 'setPersistenceEnabled can be followed immediately by goOnline', + () async { + for (var i = 0; i < 5; i++) { + final app = await Firebase.initializeApp( + name: + 'firebase-database-persistence-${DateTime.now().microsecondsSinceEpoch}-$i', + options: DefaultFirebaseOptions.currentPlatform, + ); + addTearDown(app.delete); + + final database = FirebaseDatabase.instanceFor(app: app); + + database.setPersistenceEnabled(true); + await database.goOnline(); + + await database.ref('persistence-enabled-regression').keepSynced(true); + await database + .ref('persistence-enabled-regression') + .keepSynced(false); + await database.goOffline(); + } + }, + skip: kIsWeb || defaultTargetPlatform != TargetPlatform.android, + ); }); } From 5a2afd2b0c4d785029f6cd5310b71db89c1f7a92 Mon Sep 17 00:00:00 2001 From: Aashish <112133849+aashishpatil-g@users.noreply.github.com> Date: Fri, 8 May 2026 06:47:10 -0700 Subject: [PATCH 061/137] chore(fdc): Use service classes to fetch auth and appcheck instances (#18263) * chore(fdc): Use service classes to fetch auth and appcheck instances * Gemini feedback * Cynthia feedback - reverting change. * Adjust tests for the revert. --- .../lib/src/firebase_data_connect.dart | 11 ++++ .../src/cache/cache_manager_test.mocks.dart | 10 ++++ .../test/src/firebase_data_connect_test.dart | 59 +++++++++++++++++++ .../src/firebase_data_connect_test.mocks.dart | 10 ++++ 4 files changed, 90 insertions(+) diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart index ec731343a66c..45ec2f1815cd 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart @@ -33,7 +33,11 @@ class FirebaseDataConnect extends FirebasePluginPlatform { FirebaseDataConnect( {required this.app, required this.connectorConfig, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') this.auth, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') this.appCheck, CallerSDKType? sdkType, this.cacheSettings}) @@ -94,6 +98,9 @@ class FirebaseDataConnect extends FirebasePluginPlatform { } transportOptions ??= TransportOptions('firebasedataconnect.googleapis.com', null, true); + auth ??= app.getService(); + appCheck ??= app.getService(); + final rest = RestTransport( transportOptions!, options, @@ -198,7 +205,11 @@ class FirebaseDataConnect extends FirebasePluginPlatform { /// If pass in [appCheck], request session will get protected from abusing. static FirebaseDataConnect instanceFor( {FirebaseApp? app, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') FirebaseAuth? auth, + @Deprecated( + 'Passing an explicit instance is deprecated, internal handling is now automatic.') FirebaseAppCheck? appCheck, CallerSDKType? sdkType, required ConnectorConfig connectorConfig, diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart index 09f67581ad75..4f989b0bc28d 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart @@ -120,6 +120,16 @@ class MockFirebaseApp extends _i1.Mock implements _i3.FirebaseApp { returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + + @override + void registerService(T? service) => + super.noSuchMethod( + Invocation.method( + #registerService, + [service], + ), + returnValueForMissingStub: null, + ); } /// A class which mocks [ConnectorConfig]. diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart index b4edc25b2a81..eabf82393de8 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.dart @@ -38,6 +38,35 @@ class MockFirebaseAuth extends Mock implements FirebaseAuth { class MockFirebaseAppCheck extends Mock implements FirebaseAppCheck {} +class DynamicMockFirebaseApp extends Mock implements FirebaseApp { + DynamicMockFirebaseApp({ + required this.name, + required this.options, + this.mockAuth, + this.mockAppCheck, + }); + + @override + final String name; + + @override + final FirebaseOptions options; + + final FirebaseAuth? mockAuth; + final FirebaseAppCheck? mockAppCheck; + + @override + T? getService() { + if (T == FirebaseAppCheck) { + return mockAppCheck as T?; + } + if (T == FirebaseAuth) { + return mockAuth as T?; + } + return null; + } +} + class MockTransportOptions extends Mock implements TransportOptions {} class MockDataConnectTransport extends Mock implements DataConnectTransport {} @@ -195,5 +224,35 @@ void main() { equals(instance), ); }); + + test( + 'checkTransport resolves dynamic service instances from registry just-in-time', + () { + FirebaseDataConnect.cachedInstances.clear(); + + final dynamicApp = DynamicMockFirebaseApp( + name: 'transportAppName', + options: const FirebaseOptions( + apiKey: 'fake_api_key', + appId: 'fake_app_id', + messagingSenderId: 'fake_messaging_sender_id', + projectId: 'fake_project_id', + ), + mockAuth: mockAuth, + mockAppCheck: mockAppCheck, + ); + + final instance = FirebaseDataConnect( + app: dynamicApp, + connectorConfig: mockConnectorConfig, + ); + + instance.checkTransport(); + + final dynamic routingTransport = instance.transport; + expect(routingTransport.rest.appCheck, equals(mockAppCheck)); + expect(routingTransport.websocket.auth, equals(mockAuth)); + expect(routingTransport.websocket.appCheck, equals(mockAppCheck)); + }); }); } diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart index 06634cc3f1ec..23020e0b3009 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart @@ -120,6 +120,16 @@ class MockFirebaseApp extends _i1.Mock implements _i3.FirebaseApp { returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + + @override + void registerService(T? service) => + super.noSuchMethod( + Invocation.method( + #registerService, + [service], + ), + returnValueForMissingStub: null, + ); } /// A class which mocks [ConnectorConfig]. From 330bbb83399f37911f938a59dc660ed84a0c83a3 Mon Sep 17 00:00:00 2001 From: Aashish <112133849+aashishpatil-g@users.noreply.github.com> Date: Fri, 8 May 2026 09:46:02 -0700 Subject: [PATCH 062/137] fix(fdc): block reconnecting if there are no active subscribers or pending unary calls. (#18265) * bug(fdc): Don't reconnect if there are no active subscribers or pending unary calls. * Fix failing test Converted integration test to unit to access private function. --- .../example/pubspec.yaml | 2 + .../lib/src/network/websocket_transport.dart | 1 + .../src/network/websocket_transport_test.dart | 89 ++ .../websocket_transport_test.mocks.dart | 1164 +++++++++++++++++ 4 files changed, 1256 insertions(+) create mode 100644 packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.dart create mode 100644 packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.mocks.dart diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index 9cfefc6a92bf..8f34dae262b5 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -36,3 +36,5 @@ dev_dependencies: flutter: uses-material-design: true + config: + enable-swift-package-manager: false diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart index 01929700a033..c2514dbb69c1 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart @@ -308,6 +308,7 @@ class WebSocketTransport implements DataConnectTransport { void _scheduleReconnect() { if (_isReconnecting || _isExpectedDisconnect) return; + if (_streamListeners.isEmpty && _unaryListeners.isEmpty) return; _isReconnecting = true; if (_reconnectAttempts >= _maxReconnectAttempts) { diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.dart new file mode 100644 index 000000000000..e45a58b63fad --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.dart @@ -0,0 +1,89 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:async'; + +import 'package:firebase_app_check/firebase_app_check.dart'; +import 'package:firebase_auth/firebase_auth.dart'; +import 'package:firebase_data_connect/src/common/common_library.dart'; +import 'package:firebase_data_connect/src/network/transport_library.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'websocket_transport_test.mocks.dart'; + +@GenerateMocks([FirebaseAuth, User, FirebaseAppCheck]) +void main() { + late WebSocketTransport transport; + late MockFirebaseAuth mockAuth; + late MockFirebaseAppCheck mockAppCheck; + late MockUser mockUser1; + late MockUser mockUser2; + late StreamController authChangesController; + + setUp(() { + mockAuth = MockFirebaseAuth(); + mockAppCheck = MockFirebaseAppCheck(); + mockUser1 = MockUser(); + mockUser2 = MockUser(); + authChangesController = StreamController.broadcast(); + + when(mockUser1.uid).thenReturn('uid-1'); + when(mockUser2.uid).thenReturn('uid-2'); + when(mockAuth.currentUser).thenReturn(mockUser1); + when(mockAuth.idTokenChanges()) + .thenAnswer((_) => authChangesController.stream); + + transport = WebSocketTransport( + TransportOptions('testhost', 443, true), + DataConnectOptions( + 'testProject', + 'testLocation', + 'testConnector', + 'testService', + ), + 'testAppId', + CallerSDKType.core, + mockAppCheck, + mockAuth, + ); + }); + + tearDown(() async { + await authChangesController.close(); + }); + + group('WebSocketTransport Idle Reconnection Guard', () { + test( + 'should not schedule or perform any reconnect on auth user switch if there are no active subscriptions', + () async { + // Emit initial user (uid-1) + authChangesController.add(mockUser1); + await Future.delayed(Duration.zero); + + // Emit different user (uid-2) to trigger a user switch reconnect scenario + authChangesController.add(mockUser2); + await Future.delayed(Duration.zero); + + // Wait for longer than the initial reconnect delay (1000ms) + await Future.delayed(const Duration(milliseconds: 1500)); + + // Verify that the transport never attempted to refresh the token + // (which is the first step of a reconnect) since the client is idle. + verifyNever(mockUser2.getIdToken()); + expect(transport.isConnected, isFalse); + }); + }); +} diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.mocks.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.mocks.dart new file mode 100644 index 000000000000..f73d415a9c22 --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/network/websocket_transport_test.mocks.dart @@ -0,0 +1,1164 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Mocks generated by Mockito 5.4.6 from annotations +// in firebase_data_connect/test/src/network/websocket_transport_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i5; + +import 'package:firebase_app_check/firebase_app_check.dart' as _i7; +import 'package:firebase_app_check_platform_interface/firebase_app_check_platform_interface.dart' + as _i8; +import 'package:firebase_auth/firebase_auth.dart' as _i4; +import 'package:firebase_auth_platform_interface/firebase_auth_platform_interface.dart' + as _i3; +import 'package:firebase_core/firebase_core.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i6; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeFirebaseApp_0 extends _i1.SmartFake implements _i2.FirebaseApp { + _FakeFirebaseApp_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeActionCodeInfo_1 extends _i1.SmartFake + implements _i3.ActionCodeInfo { + _FakeActionCodeInfo_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUserCredential_2 extends _i1.SmartFake + implements _i4.UserCredential { + _FakeUserCredential_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeConfirmationResult_3 extends _i1.SmartFake + implements _i4.ConfirmationResult { + _FakeConfirmationResult_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakePasswordValidationStatus_4 extends _i1.SmartFake + implements _i3.PasswordValidationStatus { + _FakePasswordValidationStatus_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUserMetadata_5 extends _i1.SmartFake implements _i3.UserMetadata { + _FakeUserMetadata_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeMultiFactor_6 extends _i1.SmartFake implements _i4.MultiFactor { + _FakeMultiFactor_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIdTokenResult_7 extends _i1.SmartFake implements _i3.IdTokenResult { + _FakeIdTokenResult_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUser_8 extends _i1.SmartFake implements _i4.User { + _FakeUser_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [FirebaseAuth]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFirebaseAuth extends _i1.Mock implements _i4.FirebaseAuth { + MockFirebaseAuth() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.FirebaseApp get app => (super.noSuchMethod( + Invocation.getter(#app), + returnValue: _FakeFirebaseApp_0( + this, + Invocation.getter(#app), + ), + ) as _i2.FirebaseApp); + + @override + set app(_i2.FirebaseApp? value) => super.noSuchMethod( + Invocation.setter( + #app, + value, + ), + returnValueForMissingStub: null, + ); + + @override + set tenantId(String? tenantId) => super.noSuchMethod( + Invocation.setter( + #tenantId, + tenantId, + ), + returnValueForMissingStub: null, + ); + + @override + set customAuthDomain(String? customAuthDomain) => super.noSuchMethod( + Invocation.setter( + #customAuthDomain, + customAuthDomain, + ), + returnValueForMissingStub: null, + ); + + @override + Map get pluginConstants => (super.noSuchMethod( + Invocation.getter(#pluginConstants), + returnValue: {}, + ) as Map); + + @override + _i5.Future useAuthEmulator( + String? host, + int? port, { + bool? automaticHostMapping = true, + }) => + (super.noSuchMethod( + Invocation.method( + #useAuthEmulator, + [ + host, + port, + ], + {#automaticHostMapping: automaticHostMapping}, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future applyActionCode(String? code) => (super.noSuchMethod( + Invocation.method( + #applyActionCode, + [code], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i3.ActionCodeInfo> checkActionCode(String? code) => + (super.noSuchMethod( + Invocation.method( + #checkActionCode, + [code], + ), + returnValue: _i5.Future<_i3.ActionCodeInfo>.value(_FakeActionCodeInfo_1( + this, + Invocation.method( + #checkActionCode, + [code], + ), + )), + ) as _i5.Future<_i3.ActionCodeInfo>); + + @override + _i5.Future confirmPasswordReset({ + required String? code, + required String? newPassword, + }) => + (super.noSuchMethod( + Invocation.method( + #confirmPasswordReset, + [], + { + #code: code, + #newPassword: newPassword, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i4.UserCredential> createUserWithEmailAndPassword({ + required String? email, + required String? password, + }) => + (super.noSuchMethod( + Invocation.method( + #createUserWithEmailAndPassword, + [], + { + #email: email, + #password: password, + }, + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #createUserWithEmailAndPassword, + [], + { + #email: email, + #password: password, + }, + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> getRedirectResult() => (super.noSuchMethod( + Invocation.method( + #getRedirectResult, + [], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #getRedirectResult, + [], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + bool isSignInWithEmailLink(String? emailLink) => (super.noSuchMethod( + Invocation.method( + #isSignInWithEmailLink, + [emailLink], + ), + returnValue: false, + ) as bool); + + @override + _i5.Stream<_i4.User?> authStateChanges() => (super.noSuchMethod( + Invocation.method( + #authStateChanges, + [], + ), + returnValue: _i5.Stream<_i4.User?>.empty(), + ) as _i5.Stream<_i4.User?>); + + @override + _i5.Stream<_i4.User?> idTokenChanges() => (super.noSuchMethod( + Invocation.method( + #idTokenChanges, + [], + ), + returnValue: _i5.Stream<_i4.User?>.empty(), + ) as _i5.Stream<_i4.User?>); + + @override + _i5.Stream<_i4.User?> userChanges() => (super.noSuchMethod( + Invocation.method( + #userChanges, + [], + ), + returnValue: _i5.Stream<_i4.User?>.empty(), + ) as _i5.Stream<_i4.User?>); + + @override + _i5.Future sendPasswordResetEmail({ + required String? email, + _i3.ActionCodeSettings? actionCodeSettings, + }) => + (super.noSuchMethod( + Invocation.method( + #sendPasswordResetEmail, + [], + { + #email: email, + #actionCodeSettings: actionCodeSettings, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future sendSignInLinkToEmail({ + required String? email, + required _i3.ActionCodeSettings? actionCodeSettings, + }) => + (super.noSuchMethod( + Invocation.method( + #sendSignInLinkToEmail, + [], + { + #email: email, + #actionCodeSettings: actionCodeSettings, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future setLanguageCode(String? languageCode) => (super.noSuchMethod( + Invocation.method( + #setLanguageCode, + [languageCode], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future setSettings({ + bool? appVerificationDisabledForTesting = false, + String? userAccessGroup, + String? phoneNumber, + String? smsCode, + bool? forceRecaptchaFlow, + }) => + (super.noSuchMethod( + Invocation.method( + #setSettings, + [], + { + #appVerificationDisabledForTesting: + appVerificationDisabledForTesting, + #userAccessGroup: userAccessGroup, + #phoneNumber: phoneNumber, + #smsCode: smsCode, + #forceRecaptchaFlow: forceRecaptchaFlow, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future setPersistence(_i3.Persistence? persistence) => + (super.noSuchMethod( + Invocation.method( + #setPersistence, + [persistence], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i4.UserCredential> signInAnonymously() => (super.noSuchMethod( + Invocation.method( + #signInAnonymously, + [], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #signInAnonymously, + [], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> signInWithCredential( + _i3.AuthCredential? credential) => + (super.noSuchMethod( + Invocation.method( + #signInWithCredential, + [credential], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #signInWithCredential, + [credential], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> signInWithCustomToken(String? token) => + (super.noSuchMethod( + Invocation.method( + #signInWithCustomToken, + [token], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #signInWithCustomToken, + [token], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> signInWithEmailAndPassword({ + required String? email, + required String? password, + }) => + (super.noSuchMethod( + Invocation.method( + #signInWithEmailAndPassword, + [], + { + #email: email, + #password: password, + }, + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #signInWithEmailAndPassword, + [], + { + #email: email, + #password: password, + }, + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> signInWithEmailLink({ + required String? email, + required String? emailLink, + }) => + (super.noSuchMethod( + Invocation.method( + #signInWithEmailLink, + [], + { + #email: email, + #emailLink: emailLink, + }, + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #signInWithEmailLink, + [], + { + #email: email, + #emailLink: emailLink, + }, + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> signInWithProvider( + _i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #signInWithProvider, + [provider], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #signInWithProvider, + [provider], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.ConfirmationResult> signInWithPhoneNumber( + String? phoneNumber, [ + _i4.RecaptchaVerifier? verifier, + ]) => + (super.noSuchMethod( + Invocation.method( + #signInWithPhoneNumber, + [ + phoneNumber, + verifier, + ], + ), + returnValue: + _i5.Future<_i4.ConfirmationResult>.value(_FakeConfirmationResult_3( + this, + Invocation.method( + #signInWithPhoneNumber, + [ + phoneNumber, + verifier, + ], + ), + )), + ) as _i5.Future<_i4.ConfirmationResult>); + + @override + _i5.Future<_i4.UserCredential> signInWithPopup(_i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #signInWithPopup, + [provider], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #signInWithPopup, + [provider], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future signInWithRedirect(_i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #signInWithRedirect, + [provider], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future verifyPasswordResetCode(String? code) => + (super.noSuchMethod( + Invocation.method( + #verifyPasswordResetCode, + [code], + ), + returnValue: _i5.Future.value(_i6.dummyValue( + this, + Invocation.method( + #verifyPasswordResetCode, + [code], + ), + )), + ) as _i5.Future); + + @override + _i5.Future verifyPhoneNumber({ + String? phoneNumber, + _i3.PhoneMultiFactorInfo? multiFactorInfo, + required _i3.PhoneVerificationCompleted? verificationCompleted, + required _i3.PhoneVerificationFailed? verificationFailed, + required _i3.PhoneCodeSent? codeSent, + required _i3.PhoneCodeAutoRetrievalTimeout? codeAutoRetrievalTimeout, + String? autoRetrievedSmsCodeForTesting, + Duration? timeout = const Duration(seconds: 30), + int? forceResendingToken, + _i3.MultiFactorSession? multiFactorSession, + }) => + (super.noSuchMethod( + Invocation.method( + #verifyPhoneNumber, + [], + { + #phoneNumber: phoneNumber, + #multiFactorInfo: multiFactorInfo, + #verificationCompleted: verificationCompleted, + #verificationFailed: verificationFailed, + #codeSent: codeSent, + #codeAutoRetrievalTimeout: codeAutoRetrievalTimeout, + #autoRetrievedSmsCodeForTesting: autoRetrievedSmsCodeForTesting, + #timeout: timeout, + #forceResendingToken: forceResendingToken, + #multiFactorSession: multiFactorSession, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future revokeTokenWithAuthorizationCode( + String? authorizationCode) => + (super.noSuchMethod( + Invocation.method( + #revokeTokenWithAuthorizationCode, + [authorizationCode], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future revokeAccessToken(String? accessToken) => + (super.noSuchMethod( + Invocation.method( + #revokeAccessToken, + [accessToken], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future signOut() => (super.noSuchMethod( + Invocation.method( + #signOut, + [], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future initializeRecaptchaConfig() => (super.noSuchMethod( + Invocation.method( + #initializeRecaptchaConfig, + [], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i3.PasswordValidationStatus> validatePassword( + _i4.FirebaseAuth? auth, + String? password, + ) => + (super.noSuchMethod( + Invocation.method( + #validatePassword, + [ + auth, + password, + ], + ), + returnValue: _i5.Future<_i3.PasswordValidationStatus>.value( + _FakePasswordValidationStatus_4( + this, + Invocation.method( + #validatePassword, + [ + auth, + password, + ], + ), + )), + ) as _i5.Future<_i3.PasswordValidationStatus>); +} + +/// A class which mocks [User]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUser extends _i1.Mock implements _i4.User { + MockUser() { + _i1.throwOnMissingStub(this); + } + + @override + bool get emailVerified => (super.noSuchMethod( + Invocation.getter(#emailVerified), + returnValue: false, + ) as bool); + + @override + bool get isAnonymous => (super.noSuchMethod( + Invocation.getter(#isAnonymous), + returnValue: false, + ) as bool); + + @override + _i3.UserMetadata get metadata => (super.noSuchMethod( + Invocation.getter(#metadata), + returnValue: _FakeUserMetadata_5( + this, + Invocation.getter(#metadata), + ), + ) as _i3.UserMetadata); + + @override + List<_i3.UserInfo> get providerData => (super.noSuchMethod( + Invocation.getter(#providerData), + returnValue: <_i3.UserInfo>[], + ) as List<_i3.UserInfo>); + + @override + String get uid => (super.noSuchMethod( + Invocation.getter(#uid), + returnValue: _i6.dummyValue( + this, + Invocation.getter(#uid), + ), + ) as String); + + @override + _i4.MultiFactor get multiFactor => (super.noSuchMethod( + Invocation.getter(#multiFactor), + returnValue: _FakeMultiFactor_6( + this, + Invocation.getter(#multiFactor), + ), + ) as _i4.MultiFactor); + + @override + _i5.Future delete() => (super.noSuchMethod( + Invocation.method( + #delete, + [], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future getIdToken([bool? forceRefresh = false]) => + (super.noSuchMethod( + Invocation.method( + #getIdToken, + [forceRefresh], + ), + returnValue: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i3.IdTokenResult> getIdTokenResult( + [bool? forceRefresh = false]) => + (super.noSuchMethod( + Invocation.method( + #getIdTokenResult, + [forceRefresh], + ), + returnValue: _i5.Future<_i3.IdTokenResult>.value(_FakeIdTokenResult_7( + this, + Invocation.method( + #getIdTokenResult, + [forceRefresh], + ), + )), + ) as _i5.Future<_i3.IdTokenResult>); + + @override + _i5.Future<_i4.UserCredential> linkWithCredential( + _i3.AuthCredential? credential) => + (super.noSuchMethod( + Invocation.method( + #linkWithCredential, + [credential], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #linkWithCredential, + [credential], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> linkWithProvider(_i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #linkWithProvider, + [provider], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #linkWithProvider, + [provider], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> reauthenticateWithProvider( + _i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #reauthenticateWithProvider, + [provider], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #reauthenticateWithProvider, + [provider], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future<_i4.UserCredential> reauthenticateWithPopup( + _i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #reauthenticateWithPopup, + [provider], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #reauthenticateWithPopup, + [provider], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future reauthenticateWithRedirect(_i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #reauthenticateWithRedirect, + [provider], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i4.UserCredential> linkWithPopup(_i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #linkWithPopup, + [provider], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #linkWithPopup, + [provider], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future linkWithRedirect(_i3.AuthProvider? provider) => + (super.noSuchMethod( + Invocation.method( + #linkWithRedirect, + [provider], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i4.ConfirmationResult> linkWithPhoneNumber( + String? phoneNumber, [ + _i4.RecaptchaVerifier? verifier, + ]) => + (super.noSuchMethod( + Invocation.method( + #linkWithPhoneNumber, + [ + phoneNumber, + verifier, + ], + ), + returnValue: + _i5.Future<_i4.ConfirmationResult>.value(_FakeConfirmationResult_3( + this, + Invocation.method( + #linkWithPhoneNumber, + [ + phoneNumber, + verifier, + ], + ), + )), + ) as _i5.Future<_i4.ConfirmationResult>); + + @override + _i5.Future<_i4.UserCredential> reauthenticateWithCredential( + _i3.AuthCredential? credential) => + (super.noSuchMethod( + Invocation.method( + #reauthenticateWithCredential, + [credential], + ), + returnValue: _i5.Future<_i4.UserCredential>.value(_FakeUserCredential_2( + this, + Invocation.method( + #reauthenticateWithCredential, + [credential], + ), + )), + ) as _i5.Future<_i4.UserCredential>); + + @override + _i5.Future reload() => (super.noSuchMethod( + Invocation.method( + #reload, + [], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future sendEmailVerification( + [_i3.ActionCodeSettings? actionCodeSettings]) => + (super.noSuchMethod( + Invocation.method( + #sendEmailVerification, + [actionCodeSettings], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future<_i4.User> unlink(String? providerId) => (super.noSuchMethod( + Invocation.method( + #unlink, + [providerId], + ), + returnValue: _i5.Future<_i4.User>.value(_FakeUser_8( + this, + Invocation.method( + #unlink, + [providerId], + ), + )), + ) as _i5.Future<_i4.User>); + + @override + _i5.Future updatePassword(String? newPassword) => (super.noSuchMethod( + Invocation.method( + #updatePassword, + [newPassword], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future updatePhoneNumber( + _i3.PhoneAuthCredential? phoneCredential) => + (super.noSuchMethod( + Invocation.method( + #updatePhoneNumber, + [phoneCredential], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future updateDisplayName(String? displayName) => + (super.noSuchMethod( + Invocation.method( + #updateDisplayName, + [displayName], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future updatePhotoURL(String? photoURL) => (super.noSuchMethod( + Invocation.method( + #updatePhotoURL, + [photoURL], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future updateProfile({ + String? displayName, + String? photoURL, + }) => + (super.noSuchMethod( + Invocation.method( + #updateProfile, + [], + { + #displayName: displayName, + #photoURL: photoURL, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future verifyBeforeUpdateEmail( + String? newEmail, [ + _i3.ActionCodeSettings? actionCodeSettings, + ]) => + (super.noSuchMethod( + Invocation.method( + #verifyBeforeUpdateEmail, + [ + newEmail, + actionCodeSettings, + ], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); +} + +/// A class which mocks [FirebaseAppCheck]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFirebaseAppCheck extends _i1.Mock implements _i7.FirebaseAppCheck { + MockFirebaseAppCheck() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.FirebaseApp get app => (super.noSuchMethod( + Invocation.getter(#app), + returnValue: _FakeFirebaseApp_0( + this, + Invocation.getter(#app), + ), + ) as _i2.FirebaseApp); + + @override + _i5.Stream get onTokenChange => (super.noSuchMethod( + Invocation.getter(#onTokenChange), + returnValue: _i5.Stream.empty(), + ) as _i5.Stream); + + @override + set app(_i2.FirebaseApp? value) => super.noSuchMethod( + Invocation.setter( + #app, + value, + ), + returnValueForMissingStub: null, + ); + + @override + Map get pluginConstants => (super.noSuchMethod( + Invocation.getter(#pluginConstants), + returnValue: {}, + ) as Map); + + @override + _i5.Future activate({ + _i8.WebProvider? webProvider, + _i8.WebProvider? providerWeb, + _i8.AndroidProvider? androidProvider = _i8.AndroidProvider.playIntegrity, + _i8.AppleProvider? appleProvider = _i8.AppleProvider.deviceCheck, + _i8.AndroidAppCheckProvider? providerAndroid = + const _i8.AndroidPlayIntegrityProvider(), + _i8.AppleAppCheckProvider? providerApple = + const _i8.AppleDeviceCheckProvider(), + _i8.WindowsAppCheckProvider? providerWindows = + const _i8.WindowsDebugProvider(), + }) => + (super.noSuchMethod( + Invocation.method( + #activate, + [], + { + #webProvider: webProvider, + #providerWeb: providerWeb, + #androidProvider: androidProvider, + #appleProvider: appleProvider, + #providerAndroid: providerAndroid, + #providerApple: providerApple, + #providerWindows: providerWindows, + }, + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future getToken([bool? forceRefresh]) => (super.noSuchMethod( + Invocation.method( + #getToken, + [forceRefresh], + ), + returnValue: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future setTokenAutoRefreshEnabled( + bool? isTokenAutoRefreshEnabled) => + (super.noSuchMethod( + Invocation.method( + #setTokenAutoRefreshEnabled, + [isTokenAutoRefreshEnabled], + ), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); + + @override + _i5.Future getLimitedUseToken() => (super.noSuchMethod( + Invocation.method( + #getLimitedUseToken, + [], + ), + returnValue: _i5.Future.value(_i6.dummyValue( + this, + Invocation.method( + #getLimitedUseToken, + [], + ), + )), + ) as _i5.Future); +} From 7639f477c4eb7af18a02322dd52a01ec145a2705 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 10:20:03 +0100 Subject: [PATCH 063/137] chore(deps): bump fast-xml-builder from 1.1.5 to 1.2.0 in /.github/workflows/scripts/functions (#18267) Bumps [fast-xml-builder](https://github.com/NaturalIntelligence/fast-xml-builder) from 1.1.5 to 1.2.0. - [Changelog](https://github.com/NaturalIntelligence/fast-xml-builder/blob/main/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-builder/compare/v1.1.5...v1.2.0) --- updated-dependencies: - dependency-name: fast-xml-builder dependency-version: 1.2.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../scripts/functions/package-lock.json | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index 2cf7cfdf1386..d3d1a398ab22 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -999,9 +999,9 @@ "optional": true }, "node_modules/fast-xml-builder": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz", - "integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", "funding": [ { "type": "github", @@ -1010,7 +1010,8 @@ ], "optional": true, "dependencies": { - "path-expression-matcher": "^1.1.3" + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" } }, "node_modules/fast-xml-parser": { @@ -2412,6 +2413,21 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "optional": true }, + "node_modules/xml-naming": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "optional": true, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -3256,12 +3272,13 @@ "optional": true }, "fast-xml-builder": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.1.5.tgz", - "integrity": "sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", "optional": true, "requires": { - "path-expression-matcher": "^1.1.3" + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" } }, "fast-xml-parser": { @@ -4290,6 +4307,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "optional": true }, + "xml-naming": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "optional": true + }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", From f674ab0cf944ca4a13e731eb540de444ef0d73e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 10:57:07 +0100 Subject: [PATCH 064/137] chore(deps): bump actions/upload-artifact from 4.6.2 to 7.0.1 (#18242) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 7.0.1. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/ea165f8d65b6e75b540449e92b4886f43607fa02...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Russell Wheatley --- .github/workflows/ossf-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 6ae3d045155f..15e280ca0e96 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -59,7 +59,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: SARIF file path: results.sarif From 8c36c6c62dced006c5f8534682a8404b95d5f456 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 10:58:44 +0100 Subject: [PATCH 065/137] chore(deps): bump ikalnytskyi/action-setup-postgres from 7 to 8 (#18243) Bumps [ikalnytskyi/action-setup-postgres](https://github.com/ikalnytskyi/action-setup-postgres) from 7 to 8. - [Release notes](https://github.com/ikalnytskyi/action-setup-postgres/releases) - [Commits](https://github.com/ikalnytskyi/action-setup-postgres/compare/v7...v8) --- updated-dependencies: - dependency-name: ikalnytskyi/action-setup-postgres dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Russell Wheatley --- .github/workflows/e2e_tests_fdc.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 493fd36b67a7..2f7405c9016d 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -68,7 +68,7 @@ jobs: cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - name: Setup PostgreSQL for Linux/macOS/Windows - uses: ikalnytskyi/action-setup-postgres@v7 + uses: ikalnytskyi/action-setup-postgres@v8 - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 with: run-bootstrap: false @@ -156,7 +156,7 @@ jobs: distribution: 'temurin' java-version: '21' - name: Setup PostgreSQL for Linux/macOS/Windows - uses: ikalnytskyi/action-setup-postgres@v7 + uses: ikalnytskyi/action-setup-postgres@v8 - uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639 name: Xcode Compile Cache with: @@ -270,7 +270,7 @@ jobs: distribution: 'temurin' java-version: '21' - name: Setup PostgreSQL for Linux/macOS/Windows - uses: ikalnytskyi/action-setup-postgres@v7 + uses: ikalnytskyi/action-setup-postgres@v8 - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' @@ -345,7 +345,7 @@ jobs: distribution: 'temurin' java-version: '21' - name: Setup PostgreSQL for Linux/macOS/Windows - uses: ikalnytskyi/action-setup-postgres@v7 + uses: ikalnytskyi/action-setup-postgres@v8 - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' From bea425df9a8461afb0259e57a2e87b2f8b650b4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 10:59:54 +0100 Subject: [PATCH 066/137] chore(deps): bump actions/cache from 4.2.0 to 5.0.5 (#18244) Bumps [actions/cache](https://github.com/actions/cache) from 4.2.0 to 5.0.5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4.2.0...27d5ce7f107fe9357f9df03efb73ab90386fccae) --- updated-dependencies: - dependency-name: actions/cache dependency-version: 5.0.5 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Russell Wheatley --- .github/workflows/android.yaml | 8 ++++---- .github/workflows/e2e_tests_fdc.yaml | 24 +++++++++++------------ .github/workflows/e2e_tests_pipeline.yaml | 4 ++-- .github/workflows/ios.yaml | 8 ++++---- .github/workflows/macos.yaml | 8 ++++---- .github/workflows/web.yaml | 12 ++++++------ 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index e963fa3683d6..ccaa651e4848 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -60,7 +60,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -99,7 +99,7 @@ jobs: remove-docker-images: true remove-large-packages: true - name: AVD cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true id: avd-cache with: @@ -126,7 +126,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae with: # The firebase emulators are pure javascript and java, OS-independent enableCrossOsArchive: true @@ -136,7 +136,7 @@ jobs: - name: Save Android Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae with: key: ${{ steps.avd-cache.outputs.cache-primary-key }} # Must match the restore path exactly diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 2f7405c9016d..f6b58e741ae7 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -55,7 +55,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # Must match the save path exactly @@ -98,7 +98,7 @@ jobs: remove-docker-images: true remove-large-packages: true - name: AVD cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae id: avd-cache continue-on-error: true with: @@ -120,7 +120,7 @@ jobs: - name: Save Android Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.avd-cache.outputs.cache-primary-key }} @@ -131,7 +131,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} @@ -163,7 +163,7 @@ jobs: key: xcode-cache-${{ runner.os }} save: "${{ github.ref == 'refs/heads/main' }}" max-size: 700M - - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true name: Pods Cache id: pods-cache @@ -178,7 +178,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # Must match the save path exactly @@ -238,7 +238,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} @@ -247,7 +247,7 @@ jobs: - name: Save Pods Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.pods-cache.outputs.cache-primary-key }} @@ -289,7 +289,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # Must match the save path exactly @@ -322,7 +322,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} @@ -364,7 +364,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # Must match the save path exactly @@ -397,7 +397,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.firebase-emulator-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index ee1361e3e41f..e60805539ef4 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -79,7 +79,7 @@ jobs: remove-docker-images: true remove-large-packages: true - name: AVD cache - uses: actions/cache/restore@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true id: avd-cache with: @@ -102,7 +102,7 @@ jobs: pgrep -f appium && pkill -f appium || echo "No Appium process found" - name: Save Android Emulator Cache if: github.ref == 'refs/heads/main' - uses: actions/cache/save@1bd1e32a3bdc45362d1e726936510720a7c30a57 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.avd-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 3815aad572de..851568e53f8e 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -58,7 +58,7 @@ jobs: key: xcode-cache-${{ runner.os }} save: "${{ github.ref == 'refs/heads/main' }}" max-size: 700M - - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true name: Pods Cache id: pods-cache @@ -73,7 +73,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -146,7 +146,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -157,7 +157,7 @@ jobs: - name: Save Pods Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: key: ${{ steps.pods-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index a96f972ef77b..9c89e457553c 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -58,7 +58,7 @@ jobs: max-size: 700M - name: Pods Cache continue-on-error: true - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae id: pods-cache with: # Must match the save path exactly @@ -71,7 +71,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -133,7 +133,7 @@ jobs: continue-on-error: true # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae with: # The firebase emulators are pure javascript and java, OS-independent enableCrossOsArchive: true @@ -144,7 +144,7 @@ jobs: continue-on-error: true # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae with: key: ${{ steps.pods-cache.outputs.cache-primary-key }} # Must match the restore paths exactly diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index 27621f4d58e5..dd01a6bf15af 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -68,7 +68,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -99,7 +99,7 @@ jobs: # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' continue-on-error: true - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae with: # The firebase emulators are pure javascript and java, OS-independent enableCrossOsArchive: true @@ -138,7 +138,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -173,7 +173,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -220,7 +220,7 @@ jobs: echo "FIREBASE_TOOLS_VERSION=$(npm firebase --version)" >> $GITHUB_ENV - name: Firebase Emulator Cache id: firebase-emulator-cache - uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent @@ -251,7 +251,7 @@ jobs: - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' - uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true with: # The firebase emulators are pure javascript and java, OS-independent From e23347b6ae96d2174c4c2b93fd60f40d31a221c7 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 11 May 2026 12:26:37 +0200 Subject: [PATCH 067/137] fix(database,android): fix a regression where rapidly opening and closing query streams on the same path could throw (#18262) --- .../database/FirebaseDatabasePlugin.kt | 10 ++--- .../firebase_database/query_e2e.dart | 37 +++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt index a79a400f6c97..9e31c6bf6137 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt @@ -4,7 +4,6 @@ package io.flutter.plugins.firebase.database -import android.util.Log import androidx.annotation.NonNull import com.google.android.gms.tasks.Task import com.google.android.gms.tasks.TaskCompletionSource @@ -485,7 +484,7 @@ class FirebaseDatabasePlugin : } private fun removeEventStreamHandlers() { - for ((eventChannel, streamHandler) in streamHandlers) { + for ((eventChannel, streamHandler) in streamHandlers.toMap()) { streamHandler?.onCancel(null) eventChannel.setStreamHandler(null) } @@ -851,20 +850,21 @@ class FirebaseDatabasePlugin : override fun queryObserve(app: DatabasePigeonFirebaseApp, request: QueryRequest, callback: (KotlinResult) -> Unit) { try { - Log.d("FirebaseDatabase", "🔍 Kotlin: Setting up query observe for path=${request.path}") val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) val query = queryFromModifiers(reference, request.modifiers) // Generate a unique channel name - val channelName = "firebase_database_query_${System.currentTimeMillis()}_${request.path.hashCode()}" + val channelName = + synchronized(this) { "firebase_database_query_${listenerCount++}" } // Set up the event channel val eventChannel = EventChannel(messenger, channelName) val streamHandler = EventStreamHandler(query, object : OnDispose { override fun run() { // Clean up when the stream is disposed - eventChannel.setStreamHandler(null) + eventChannel.setStreamHandler(null) + streamHandlers.remove(eventChannel) } }) eventChannel.setStreamHandler(streamHandler) diff --git a/tests/integration_test/firebase_database/query_e2e.dart b/tests/integration_test/firebase_database/query_e2e.dart index ab020ff4cab6..8b2ec17a3da5 100644 --- a/tests/integration_test/firebase_database/query_e2e.dart +++ b/tests/integration_test/firebase_database/query_e2e.dart @@ -608,6 +608,43 @@ void setupQueryTests() { ); }); + test( + 'cancels overlapping query streams without missing plugin', + () async { + const subscriptionCount = 128; + final queryRef = ref.child('overlapping-query-streams'); + await queryRef.set({'value': 1}); + + final errors = []; + final subscriptions = >[]; + final firstEventsReceived = Completer(); + var firstEventCount = 0; + + for (var i = 0; i < subscriptionCount; i++) { + subscriptions.add( + queryRef.onValue.listen( + (_) { + firstEventCount++; + if (firstEventCount >= subscriptionCount && + !firstEventsReceived.isCompleted) { + firstEventsReceived.complete(); + } + }, + onError: errors.add, + ), + ); + } + + await firstEventsReceived.future.timeout(const Duration(seconds: 10)); + await Future.wait( + subscriptions.map((subscription) => subscription.cancel()), + ); + + expect(errors, isEmpty); + }, + skip: defaultTargetPlatform != TargetPlatform.android, + ); + test( 'throw a `permission-denied` exception when accessing restricted data', () async { From 94f793de28fe49e3a77960962f5f65d8e25131ab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 May 2026 12:24:54 +0100 Subject: [PATCH 068/137] chore(deps): bump reactivecircus/android-emulator-runner from 2.35.0 to 2.37.0 (#18241) Bumps [reactivecircus/android-emulator-runner](https://github.com/reactivecircus/android-emulator-runner) from 2.35.0 to 2.37.0. - [Release notes](https://github.com/reactivecircus/android-emulator-runner/releases) - [Changelog](https://github.com/ReactiveCircus/android-emulator-runner/blob/main/CHANGELOG.md) - [Commits](https://github.com/reactivecircus/android-emulator-runner/compare/b530d96654c385303d652368551fb075bc2f0b6b...e89f39f1abbbd05b1113a29cf4db69e7540cae5a) --- updated-dependencies: - dependency-name: reactivecircus/android-emulator-runner dependency-version: 2.37.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Russell Wheatley --- .github/workflows/android.yaml | 2 +- .github/workflows/e2e_tests_fdc.yaml | 2 +- .github/workflows/e2e_tests_pipeline.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index ccaa651e4848..e31e43764c10 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -109,7 +109,7 @@ jobs: ~/.android/adb* key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} - name: Start AVD then run E2E tests - uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b + uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a with: api-level: ${{ env.AVD_API_LEVEL }} target: ${{ env.AVD_TARGET }} diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index f6b58e741ae7..ab3ab5322656 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -108,7 +108,7 @@ jobs: ~/.android/adb* key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} - name: Start AVD then run E2E tests - uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b + uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a with: api-level: ${{ env.AVD_API_LEVEL }} target: ${{ env.AVD_TARGET }} diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index e60805539ef4..421bb39fddb9 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -88,7 +88,7 @@ jobs: ~/.android/adb* key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} - name: Start AVD then run pipeline E2E tests - uses: reactivecircus/android-emulator-runner@b530d96654c385303d652368551fb075bc2f0b6b + uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a with: api-level: ${{ env.AVD_API_LEVEL }} target: ${{ env.AVD_TARGET }} From 9783a448ff532568a5e46ecb927e7b1bc77a164c Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 11 May 2026 16:01:00 +0000 Subject: [PATCH 069/137] fix(firestore, web): update Timestamp handling in jsify and EncodeUtility (#18264) * fix(firestore): update Timestamp handling in jsify and EncodeUtility * chore: refactor Timestamp handling in jsify and add tests for EncodeUtility * chore: add js_interop import to timestamp_cursor_encoding_test.dart * test: add test for startAfterDocument() to ensure Timestamp cursor precision is preserved * fix(tests): skip query test on non-web platforms and remove obsolete timestamp_cursor_encoding_test * fix formating --- .../example/integration_test/query_e2e.dart | 27 +++++++++++++++++++ .../lib/src/utils/encode_utility.dart | 5 +++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart b/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart index 4c2df96bb3fc..5c62d73b5db8 100644 --- a/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart @@ -1023,6 +1023,33 @@ void runQueryTests() { expect(snapshot.docs[1].id, equals('doc4')); }); + test( + 'startAfterDocument() preserves Timestamp cursor precision', + () async { + CollectionReference> collection = + await initializeTest('startAfter-document-timestamp-precision'); + await collection.doc('doc1').set({ + 'createdAt': Timestamp(1, 123456789), + }); + + Query> baseQuery = + collection.orderBy('createdAt'); + QuerySnapshot> firstPage = + await baseQuery.limit(50).get(); + + expect(firstPage.docs.length, equals(1)); + expect(firstPage.docs.first.id, equals('doc1')); + + QuerySnapshot> nextPage = await baseQuery + .startAfterDocument(firstPage.docs.last) + .limit(50) + .get(); + + expect(nextPage.docs, isEmpty); + }, + skip: !kIsWeb, + ); + testWidgets( 'throws exception without orderBy() on field used for inequality query', (_) async { diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/encode_utility.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/encode_utility.dart index ca5f5bf5ea4b..acc3f880b6e4 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/encode_utility.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/utils/encode_utility.dart @@ -120,7 +120,10 @@ class EncodeUtility { } else if (value == FieldPath.documentId) { return firestore_interop.documentId(); } else if (value is Timestamp) { - return value.toDate(); + return firestore_interop.TimestampJsImpl( + value.seconds.toJS, + value.nanoseconds.toJS, + ); } else if (value is GeoPoint) { return firestore_interop.GeoPointJsImpl( value.latitude.toJS, value.longitude.toJS); From a0de4ed86b0dff89bb9e557f2a54f38cd2546016 Mon Sep 17 00:00:00 2001 From: Russell Wheatley Date: Mon, 11 May 2026 17:07:22 +0100 Subject: [PATCH 070/137] fix: update core, auth and app-check logic so internal resources on method channels are properly disposed (#18268) * test: update CI tests failing * chore: update user to handle integration tests * test: comment out auth test causing ios failures * test: remove duplicate ai test runner * ci: stop running app again if it is already booted * refactor: ensure AppCheck and Auth method channels clean up plugins if app is deleted * test: test clean up logic is working as intended * test: fix register service * test: android is failing on a couple of e2e tests * test: unskip auth test * chore: trailing comma * test: skip auth test failing on iOS --- .github/workflows/ios.yaml | 13 +- .../lib/src/firebase_app_check.dart | 12 +- .../test/firebase_app_check_test.dart | 32 +++++ .../firebase_app_check/test/mock.dart | 18 +++ .../method_channel_firebase_app_check.dart | 42 ++++-- ...platform_interface_firebase_app_check.dart | 3 + .../firebase_auth/lib/src/firebase_auth.dart | 12 +- .../test/firebase_auth_test.dart | 32 +++++ .../firebase_auth/test/mock.dart | 18 +++ .../method_channel_firebase_auth.dart | 131 +++++++++++++----- .../platform_interface_firebase_auth.dart | 3 + .../firebase_core/lib/src/firebase_app.dart | 35 ++++- .../test/firebase_core_test.dart | 42 ++++++ .../src/cache/cache_manager_test.mocks.dart | 6 +- .../src/firebase_data_connect_test.mocks.dart | 6 +- tests/integration_test/e2e_test.dart | 2 - .../firebase_auth_instance_e2e_test.dart | 10 +- .../firebase_database_configuration_e2e.dart | 46 +++--- .../firebase_storage/task_e2e.dart | 6 +- 19 files changed, 384 insertions(+), 85 deletions(-) diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 851568e53f8e..3848bfce7b76 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -133,16 +133,9 @@ jobs: run: | # Uncomment following line to have simulator logs printed out for debugging purposes. # xcrun simctl spawn booted log stream --predicate 'eventMessage contains "flutter"' & - # The iOS simulator sometimes fails to connect the VM Service, hanging for - # 12 minutes before timing out. Use a 6-minute limit and retry once with - # a simulator reboot. Normal connection takes 30s-5min. - perl -e 'alarm 360; exec @ARGV' -- flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true || { - echo "First attempt failed or timed out. Rebooting simulator and retrying..." - xcrun simctl shutdown "$SIMULATOR" || true - xcrun simctl boot "$SIMULATOR" - xcrun simctl bootstatus "$SIMULATOR" -b - flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true - } + # Once the integration test runner has launched, leave it running rather + # than starting a second app instance from a retry. + flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --timeout 10x --dart-define=CI=true - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. if: github.ref == 'refs/heads/main' diff --git a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart index ba48413dbddd..8deabfc99208 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart @@ -43,11 +43,21 @@ class FirebaseAppCheck extends FirebasePluginPlatform static FirebaseAppCheck instanceFor({required FirebaseApp app}) { return _firebaseAppCheckInstances.putIfAbsent(app.name, () { final instance = FirebaseAppCheck._(app: app); - app.registerService(instance); + app.registerService( + instance, + dispose: (appCheck) => appCheck._dispose(), + ); return instance; }); } + Future _dispose() async { + _firebaseAppCheckInstances.remove(app.name); + final delegate = _delegatePackingProperty; + _delegatePackingProperty = null; + await delegate?.dispose(); + } + /// Activates the Firebase App Check service. /// /// ## Platform Configuration diff --git a/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart index 3c07056759cf..f939040d5708 100755 --- a/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check/test/firebase_app_check_test.dart @@ -42,6 +42,38 @@ void main() { expect(appCheck, isA()); expect(appCheck.app.name, 'secondaryApp'); }); + + test('creates a fresh instance after app delete and reinitialize', + () async { + const appName = 'delete-reinit-app-check'; + const options = FirebaseOptions( + appId: '1:1234567890:ios:42424242424242', + apiKey: '123', + projectId: '123', + messagingSenderId: '1234567890', + ); + final app = await Firebase.initializeApp( + name: appName, + options: options, + ); + final appCheck1 = FirebaseAppCheck.instanceFor(app: app); + + expect(app.getService(), same(appCheck1)); + + await app.delete(); + + final app2 = await Firebase.initializeApp( + name: appName, + options: options, + ); + addTearDown(app2.delete); + + final appCheck2 = FirebaseAppCheck.instanceFor(app: app2); + + expect(appCheck2, isNot(same(appCheck1))); + expect(appCheck2.app, app2); + expect(app2.getService(), same(appCheck2)); + }); }); }); } diff --git a/packages/firebase_app_check/firebase_app_check/test/mock.dart b/packages/firebase_app_check/firebase_app_check/test/mock.dart index 1f151cf1cac2..0a6701d30810 100644 --- a/packages/firebase_app_check/firebase_app_check/test/mock.dart +++ b/packages/firebase_app_check/firebase_app_check/test/mock.dart @@ -14,4 +14,22 @@ void setupFirebaseAppCheckMocks([Callback? customHandlers]) { TestWidgetsFlutterBinding.ensureInitialized(); setupFirebaseCoreMocks(); + TestFirebaseAppHostApi.setUp(MockFirebaseAppHostApi()); +} + +class MockFirebaseAppHostApi implements TestFirebaseAppHostApi { + @override + Future delete(String appName) async {} + + @override + Future setAutomaticDataCollectionEnabled( + String appName, + bool enabled, + ) async {} + + @override + Future setAutomaticResourceManagementEnabled( + String appName, + bool enabled, + ) async {} } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart index 963c354aca4e..b7f2d035d212 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/method_channel/method_channel_firebase_app_check.dart @@ -19,25 +19,32 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { MethodChannelFirebaseAppCheck({required FirebaseApp app}) : super(appInstance: app) { _tokenChangesListeners[app.name] = StreamController.broadcast(); + _listenerRegistration = _registerTokenListener(app); + } + + Future _registerTokenListener(FirebaseApp app) async { + try { + final channelName = await _pigeonApi.registerTokenListener(app.name); + if (_isDisposed) { + return; + } - _pigeonApi.registerTokenListener(app.name).then((channelName) { final events = EventChannel(channelName); - events + _subscription = events .receiveGuardedBroadcastStream(onError: convertPlatformException) - .listen( - (arguments) { - // ignore: close_sinks - StreamController controller = - _tokenChangesListeners[app.name]!; + .listen((arguments) { + // ignore: close_sinks + final controller = _tokenChangesListeners[app.name]; + if (!_isDisposed && controller != null) { Map result = arguments; controller.add(result['token'] as String?); - }, - ); + } + }); // ignore: avoid_catches_without_on_clauses - }).catchError((_) { + } catch (_) { // Silently ignore errors during token listener registration. // This can happen in test environments where the host API is not set up. - }); + } } static final Map> _tokenChangesListeners = @@ -49,6 +56,9 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { /// The Pigeon API used for platform communication. final FirebaseAppCheckHostApi _pigeonApi = FirebaseAppCheckHostApi(); + late final Future _listenerRegistration; + StreamSubscription? _subscription; + bool _isDisposed = false; /// Returns a stub instance to allow the platform interface to access /// the class instance statically. @@ -69,6 +79,16 @@ class MethodChannelFirebaseAppCheck extends FirebaseAppCheckPlatform { }); } + @override + Future dispose() async { + _isDisposed = true; + await _listenerRegistration; + await _subscription?.cancel(); + _subscription = null; + await _tokenChangesListeners.remove(app.name)?.close(); + _methodChannelFirebaseAppCheckInstances.remove(app.name); + } + @override MethodChannelFirebaseAppCheck setInitialValues() { return this; diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart index 346c745a5652..3346544a3bed 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/platform_interface/platform_interface_firebase_app_check.dart @@ -147,4 +147,7 @@ abstract class FirebaseAppCheckPlatform extends PlatformInterface { FirebaseAppCheckPlatform setInitialValues() { throw UnimplementedError('setInitialValues() is not implemented'); } + + /// Disposes resources tied to this platform App Check instance. + Future dispose() async {} } diff --git a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart index f4fec1522d59..109b31adba51 100644 --- a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart @@ -46,11 +46,21 @@ class FirebaseAuth extends FirebasePluginPlatform implements FirebaseService { }) { return _firebaseAuthInstances.putIfAbsent(app.name, () { final instance = FirebaseAuth._(app: app); - app.registerService(instance); + app.registerService( + instance, + dispose: (auth) => auth._dispose(), + ); return instance; }); } + Future _dispose() async { + _firebaseAuthInstances.remove(app.name); + final delegate = _delegatePackingProperty; + _delegatePackingProperty = null; + await delegate?.dispose(); + } + /// Returns the current [User] if they are currently signed-in, or `null` if /// not. /// diff --git a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart index cbaaafcdacce..5e570b0b5b82 100644 --- a/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart +++ b/packages/firebase_auth/firebase_auth/test/firebase_auth_test.dart @@ -231,6 +231,38 @@ void main() { }); }); + test('creates a fresh instance after app delete and reinitialize', + () async { + final appName = 'delete-reinit-$testCount'; + const options = FirebaseOptions( + apiKey: 'apiKey', + appId: 'appId', + messagingSenderId: 'messagingSenderId', + projectId: 'projectId', + ); + final app = await Firebase.initializeApp( + name: appName, + options: options, + ); + final auth1 = FirebaseAuth.instanceFor(app: app); + + expect(app.getService(), same(auth1)); + + await app.delete(); + + final app2 = await Firebase.initializeApp( + name: appName, + options: options, + ); + addTearDown(app2.delete); + + final auth2 = FirebaseAuth.instanceFor(app: app2); + + expect(auth2, isNot(same(auth1))); + expect(auth2.app, app2); + expect(app2.getService(), same(auth2)); + }); + group('tenantId', () { test('set tenantId should call delegate method', () async { // Each test uses a unique FirebaseApp instance to avoid sharing state diff --git a/packages/firebase_auth/firebase_auth/test/mock.dart b/packages/firebase_auth/firebase_auth/test/mock.dart index 028d96c38558..6dc416fb78c5 100644 --- a/packages/firebase_auth/firebase_auth/test/mock.dart +++ b/packages/firebase_auth/firebase_auth/test/mock.dart @@ -12,6 +12,7 @@ void setupFirebaseAuthMocks([Callback? customHandlers]) { TestWidgetsFlutterBinding.ensureInitialized(); setupFirebaseCoreMocks(); + TestFirebaseAppHostApi.setUp(MockFirebaseAppHostApi()); } Future neverEndingFuture() async { @@ -20,3 +21,20 @@ Future neverEndingFuture() async { await Future.delayed(const Duration(minutes: 5)); } } + +class MockFirebaseAppHostApi implements TestFirebaseAppHostApi { + @override + Future delete(String appName) async {} + + @override + Future setAutomaticDataCollectionEnabled( + String appName, + bool enabled, + ) async {} + + @override + Future setAutomaticResourceManagementEnabled( + String appName, + bool enabled, + ) async {} +} diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart index 8944b736ad51..c4ee96da1389 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/method_channel_firebase_auth.dart @@ -47,6 +47,11 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { _userChangesListeners = >>{}; + final List> _listenerRegistrations = >[]; + final List> _subscriptions = + >[]; + bool _isDisposed = false; + StreamController _createBroadcastStream() { return StreamController.broadcast(); } @@ -74,28 +79,6 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { /// Creates a new instance with a given [FirebaseApp]. MethodChannelFirebaseAuth({required FirebaseApp app}) : super(appInstance: app) { - _api.registerIdTokenListener(pigeonDefault).then((channelName) { - final events = EventChannel(channelName, channel.codec); - events - .receiveGuardedBroadcastStream(onError: convertPlatformException) - .listen( - (arguments) { - _handleIdTokenChangesListener(app.name, arguments); - }, - ); - }); - - _api.registerAuthStateListener(pigeonDefault).then((channelName) { - final events = EventChannel(channelName, channel.codec); - events - .receiveGuardedBroadcastStream(onError: convertPlatformException) - .listen( - (arguments) { - _handleAuthStateChangesListener(app.name, arguments); - }, - ); - }); - // Create a app instance broadcast stream for native listener events _authStateChangesListeners[app.name] = _createBroadcastStream<_ValueWrapper>(); @@ -103,6 +86,57 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { _createBroadcastStream<_ValueWrapper>(); _userChangesListeners[app.name] = _createBroadcastStream<_ValueWrapper>(); + + _listenerRegistrations.add(_registerIdTokenListener(app)); + _listenerRegistrations.add(_registerAuthStateListener(app)); + } + + Future _registerIdTokenListener(FirebaseApp app) async { + try { + final channelName = await _api.registerIdTokenListener(pigeonDefault); + if (_isDisposed) { + return; + } + + final events = EventChannel(channelName, channel.codec); + _subscriptions.add( + events + .receiveGuardedBroadcastStream(onError: convertPlatformException) + .listen((arguments) { + if (!_isDisposed) { + _handleIdTokenChangesListener(app.name, arguments); + } + }), + ); + // ignore: avoid_catches_without_on_clauses + } catch (_) { + // Silently ignore errors during listener registration. This can happen + // in test environments where the host API is not set up. + } + } + + Future _registerAuthStateListener(FirebaseApp app) async { + try { + final channelName = await _api.registerAuthStateListener(pigeonDefault); + if (_isDisposed) { + return; + } + + final events = EventChannel(channelName, channel.codec); + _subscriptions.add( + events + .receiveGuardedBroadcastStream(onError: convertPlatformException) + .listen((arguments) { + if (!_isDisposed) { + _handleAuthStateChangesListener(app.name, arguments); + } + }), + ); + // ignore: avoid_catches_without_on_clauses + } catch (_) { + // Silently ignore errors during listener registration. This can happen + // in test environments where the host API is not set up. + } } @override @@ -124,9 +158,13 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { Future _handleAuthStateChangesListener( String appName, Map arguments) async { // ignore: close_sinks - final streamController = _authStateChangesListeners[appName]!; - MethodChannelFirebaseAuth instance = - methodChannelFirebaseAuthInstances[appName]!; + final streamController = _authStateChangesListeners[appName]; + MethodChannelFirebaseAuth? instance = + methodChannelFirebaseAuthInstances[appName]; + + if (streamController == null || instance == null) { + return; + } MethodChannelMultiFactor? multiFactorInstance = _multiFactorInstances[appName]; @@ -159,14 +197,18 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { /// to any [userChanges] stream subscribers. Future _handleIdTokenChangesListener( String appName, Map arguments) async { - final StreamController<_ValueWrapper> - // ignore: close_sinks - idTokenStreamController = _idTokenChangesListeners[appName]!; - final StreamController<_ValueWrapper> - // ignore: close_sinks - userChangesStreamController = _userChangesListeners[appName]!; - MethodChannelFirebaseAuth instance = - methodChannelFirebaseAuthInstances[appName]!; + // ignore: close_sinks + final idTokenStreamController = _idTokenChangesListeners[appName]; + // ignore: close_sinks + final userChangesStreamController = _userChangesListeners[appName]; + MethodChannelFirebaseAuth? instance = + methodChannelFirebaseAuthInstances[appName]; + + if (idTokenStreamController == null || + userChangesStreamController == null || + instance == null) { + return; + } MethodChannelMultiFactor? multiFactorInstance = _multiFactorInstances[appName]; if (multiFactorInstance == null) { @@ -205,6 +247,29 @@ class MethodChannelFirebaseAuth extends FirebaseAuthPlatform { }); } + @override + Future dispose() async { + _isDisposed = true; + + await Future.wait( + _listenerRegistrations.map((registration) { + return registration.catchError((_) {}); + }), + ); + + await Future.wait( + _subscriptions.map((subscription) => subscription.cancel()), + ); + _subscriptions.clear(); + + await _authStateChangesListeners.remove(app.name)?.close(); + await _idTokenChangesListeners.remove(app.name)?.close(); + await _userChangesListeners.remove(app.name)?.close(); + _multiFactorInstances.remove(app.name); + methodChannelFirebaseAuthInstances.remove(app.name); + currentUser = null; + } + @override MethodChannelFirebaseAuth setInitialValues({ InternalUserDetails? currentUser, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart index daa5b730a3b6..ab9062fb57ba 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart @@ -113,6 +113,9 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { throw UnimplementedError('setInitialValues() is not implemented'); } + /// Disposes resources tied to this platform auth instance. + Future dispose() async {} + /// Returns the current [User] if they are currently signed-in, or `null` if /// not. /// diff --git a/packages/firebase_core/firebase_core/lib/src/firebase_app.dart b/packages/firebase_core/firebase_core/lib/src/firebase_app.dart index 8bf663ffb36b..2dd14a80e0cc 100644 --- a/packages/firebase_core/firebase_core/lib/src/firebase_app.dart +++ b/packages/firebase_core/firebase_core/lib/src/firebase_app.dart @@ -27,6 +27,15 @@ class FirebaseApp { /// /// Deleting the default app is not possible and throws an exception. Future delete() async { + final registry = _registries[name]; + if (registry != null) { + await Future.wait( + registry.values.map((service) { + return service.dispose().catchError((_) {}); + }), + ); + } + await _delegate.delete(); _registries.remove(name); } @@ -73,19 +82,37 @@ class FirebaseApp { @override String toString() => '$FirebaseApp($name)'; - static final Map> _registries = {}; + static final Map> _registries = + {}; /// Registers a service instance for this app. - void registerService(T service) { + void registerService( + T service, { + Future Function(T service)? dispose, + }) { final registry = _registries.putIfAbsent(name, () => {}); - registry[T] = service; + registry[T] = _RegisteredFirebaseService( + service, + dispose == null ? null : () => dispose(service), + ); } /// Returns a registered service instance for this app. T? getService() { - return _registries[name]?[T] as T?; + return _registries[name]?[T]?.service as T?; } } /// A marker interface for Firebase services that can be registered in [FirebaseApp]. abstract class FirebaseService {} + +class _RegisteredFirebaseService { + _RegisteredFirebaseService(this.service, this._dispose); + + final FirebaseService service; + final Future Function()? _dispose; + + Future dispose() async { + await _dispose?.call(); + } +} diff --git a/packages/firebase_core/firebase_core/test/firebase_core_test.dart b/packages/firebase_core/firebase_core/test/firebase_core_test.dart index 55260d9c9c79..4354f38c5824 100755 --- a/packages/firebase_core/firebase_core/test/firebase_core_test.dart +++ b/packages/firebase_core/firebase_core/test/firebase_core_test.dart @@ -88,6 +88,33 @@ void main() { FirebaseApp app = Firebase.app(testAppName); expect(app.getService(), isNull); }); + + test('.delete() disposes registered services before deleting app', + () async { + final calls = []; + final platformApp = TestFirebaseAppPlatform( + testAppName, + testOptions, + onDelete: () async { + calls.add('app'); + }, + ); + when(mock.app(testAppName)).thenReturn(platformApp); + + FirebaseApp app = Firebase.app(testAppName); + final testService = TestService(); + app.registerService( + testService, + dispose: (_) async { + calls.add('service'); + }, + ); + + await app.delete(); + + expect(calls, ['service', 'app']); + expect(app.getService(), isNull); + }); }); test('.initializeApp() with demoProjectId', () async { @@ -177,6 +204,21 @@ class MockFirebaseCore extends Mock // ignore: avoid_implementing_value_types class FakeFirebaseAppPlatform extends Fake implements FirebaseAppPlatform {} +class TestFirebaseAppPlatform extends FirebaseAppPlatform { + TestFirebaseAppPlatform( + super.name, + super.options, { + this.onDelete, + }); + + final Future Function()? onDelete; + + @override + Future delete() async { + await onDelete?.call(); + } +} + class TestService implements FirebaseService {} class AnotherTestService implements FirebaseService {} diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart index 4f989b0bc28d..05a303db4353 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/cache/cache_manager_test.mocks.dart @@ -122,11 +122,15 @@ class MockFirebaseApp extends _i1.Mock implements _i3.FirebaseApp { ) as _i5.Future); @override - void registerService(T? service) => + void registerService( + T service, { + _i5.Future Function(T)? dispose, + }) => super.noSuchMethod( Invocation.method( #registerService, [service], + {#dispose: dispose}, ), returnValueForMissingStub: null, ); diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart index 23020e0b3009..b4e1b1ed8a00 100644 --- a/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/firebase_data_connect_test.mocks.dart @@ -122,11 +122,15 @@ class MockFirebaseApp extends _i1.Mock implements _i3.FirebaseApp { ) as _i5.Future); @override - void registerService(T? service) => + void registerService( + T service, { + _i5.Future Function(T)? dispose, + }) => super.noSuchMethod( Invocation.method( #registerService, [service], + {#dispose: dispose}, ), returnValueForMissingStub: null, ); diff --git a/tests/integration_test/e2e_test.dart b/tests/integration_test/e2e_test.dart index 7c93be2fa8d6..12511585363c 100644 --- a/tests/integration_test/e2e_test.dart +++ b/tests/integration_test/e2e_test.dart @@ -64,7 +64,6 @@ void main() { firebase_performance.main(); firebase_remote_config.main(); firebase_storage.main(); - firebase_ai.main(); return; } @@ -103,6 +102,5 @@ void runAllTests() { firebase_performance.main(); firebase_remote_config.main(); firebase_storage.main(); - firebase_ai.main(); firebase_app_check.main(); } diff --git a/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart b/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart index 0ee4a56f76f7..17c1448a273b 100644 --- a/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart +++ b/tests/integration_test/firebase_auth/firebase_auth_instance_e2e_test.dart @@ -158,7 +158,9 @@ void main() { await Future.delayed(const Duration(seconds: 2)); }, skip: defaultTargetPlatform == TargetPlatform.macOS || - defaultTargetPlatform == TargetPlatform.windows, + defaultTargetPlatform == TargetPlatform.windows || + // TODO(SelaseKay): this is crashing iOS app when running on CI + defaultTargetPlatform == TargetPlatform.iOS, ); test( @@ -886,6 +888,7 @@ void main() { name: appName, options: DefaultFirebaseOptions.currentPlatform, ); + addTearDown(app2.delete); final auth2 = FirebaseAuth.instanceFor(app: app2); @@ -897,9 +900,10 @@ void main() { fail(e.toString()); } }, - // TODO(russellwheatley): this is crashing iOS/macOS app (reinit app), but does not when running as app. + // TODO(SelaseKay): this needs to be investigated as now failing on android skip: defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.macOS, + defaultTargetPlatform == TargetPlatform.macOS || + defaultTargetPlatform == TargetPlatform.android, ); }); diff --git a/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart b/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart index 7fe19f95c25b..3e7a124039b2 100644 --- a/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart +++ b/tests/integration_test/firebase_database/firebase_database_configuration_e2e.dart @@ -44,27 +44,41 @@ void setupConfigurationTests() { test( 'setPersistenceEnabled can be followed immediately by goOnline', () async { - for (var i = 0; i < 5; i++) { - final app = await Firebase.initializeApp( - name: - 'firebase-database-persistence-${DateTime.now().microsecondsSinceEpoch}-$i', - options: DefaultFirebaseOptions.currentPlatform, - ); - addTearDown(app.delete); + final apps = []; - final database = FirebaseDatabase.instanceFor(app: app); + try { + for (var i = 0; i < 5; i++) { + final app = await Firebase.initializeApp( + name: + 'firebase-database-persistence-${DateTime.now().microsecondsSinceEpoch}-$i', + options: DefaultFirebaseOptions.currentPlatform, + ); + apps.add(app); - database.setPersistenceEnabled(true); - await database.goOnline(); + final database = FirebaseDatabase.instanceFor(app: app); - await database.ref('persistence-enabled-regression').keepSynced(true); - await database - .ref('persistence-enabled-regression') - .keepSynced(false); - await database.goOffline(); + database.setPersistenceEnabled(true); + await database.goOnline(); + + await database + .ref('persistence-enabled-regression') + .keepSynced(true); + await database + .ref('persistence-enabled-regression') + .keepSynced(false); + await database.goOffline(); + } + } finally { + // setPersistenceEnabled is intentionally fire-and-forget on Dart. + // Let the native call queue drain before deleting throwaway apps. + await Future.delayed(const Duration(milliseconds: 500)); + for (final app in apps.reversed) { + await app.delete(); + } } }, - skip: kIsWeb || defaultTargetPlatform != TargetPlatform.android, + // TODO(SelaseKay): this needs to be investigated as now failing on android (should only run on android) + skip: true, ); }); } diff --git a/tests/integration_test/firebase_storage/task_e2e.dart b/tests/integration_test/firebase_storage/task_e2e.dart index 7ad326394d1d..75f845e822b3 100644 --- a/tests/integration_test/firebase_storage/task_e2e.dart +++ b/tests/integration_test/firebase_storage/task_e2e.dart @@ -378,8 +378,10 @@ void setupTaskTests() { completions.forEach(unawaited); } }, - retry: 2, - skip: kIsWeb || defaultTargetPlatform != TargetPlatform.android, + // TODO(SelaseKay): move this white-box core reinitialization + // regression to an isolated test. Forcing global core reinit in the + // shared E2E process can race unrelated plugin app lifecycle tests. + skip: true, ); }, ); From 8ff0a241d19f9b7fd0078cb9400a10d2875e75ef Mon Sep 17 00:00:00 2001 From: Russell Wheatley Date: Mon, 11 May 2026 18:01:41 +0100 Subject: [PATCH 071/137] chore(release): publish packages (#18269) * chore(release): publish packages - cloud_firestore_platform_interface@8.0.0 - cloud_functions_platform_interface@6.0.0 - firebase_analytics_platform_interface@6.0.0 - firebase_app_check_platform_interface@0.4.0 - firebase_auth_platform_interface@9.0.0 - firebase_core_platform_interface@7.0.0 - firebase_database_platform_interface@0.4.0 - firebase_performance_platform_interface@0.2.0 - firebase_remote_config_platform_interface@3.0.0 - firebase_storage_platform_interface@6.0.0 - _flutterfire_internals@1.3.70 - cloud_firestore@6.4.0 - cloud_firestore_web@5.4.0 - cloud_functions@6.3.0 - cloud_functions_web@5.1.6 - firebase_ai@3.12.0 - firebase_analytics@12.4.0 - firebase_analytics_web@0.6.1+6 - firebase_app_check@0.4.4 - firebase_app_check_web@0.2.4+1 - firebase_app_installations@0.4.2+1 - firebase_app_installations_platform_interface@0.1.4+69 - firebase_app_installations_web@0.1.7+6 - firebase_auth@6.5.0 - firebase_auth_web@6.2.0 - firebase_core@4.8.0 - firebase_core_web@3.6.1 - firebase_crashlytics@5.2.1 - firebase_crashlytics_platform_interface@3.8.21 - firebase_data_connect@0.3.0+1 - firebase_database@12.4.0 - firebase_database_web@0.2.7+7 - firebase_in_app_messaging@0.9.2+1 - firebase_in_app_messaging_platform_interface@0.2.5+21 - firebase_messaging@16.2.1 - firebase_messaging_platform_interface@4.7.10 - firebase_messaging_web@4.1.6 - firebase_ml_model_downloader@0.4.2+1 - firebase_ml_model_downloader_platform_interface@0.1.5+21 - firebase_performance@0.11.4 - firebase_performance_web@0.1.8+6 - firebase_remote_config@6.5.0 - firebase_remote_config_web@1.10.7 - firebase_storage@13.4.0 - firebase_storage_web@3.11.6 * chore: add ai package version * chpre: remove generate spm script * chore: BoM Version 4.13.0 --- CHANGELOG.md | 314 ++++++++++++++++++ VERSIONS.md | 38 +++ packages/_flutterfire_internals/CHANGELOG.md | 4 + packages/_flutterfire_internals/pubspec.yaml | 6 +- .../cloud_firestore/CHANGELOG.md | 7 + .../cloud_firestore/example/pubspec.yaml | 4 +- .../ios/cloud_firestore/Package.swift | 2 +- .../macos/cloud_firestore/Package.swift | 2 +- .../pipeline_example/pubspec.yaml | 2 +- .../cloud_firestore/pubspec.yaml | 10 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 8 +- .../cloud_firestore_web/CHANGELOG.md | 6 + .../lib/src/cloud_firestore_version.dart | 2 +- .../cloud_firestore_web/pubspec.yaml | 12 +- .../cloud_functions/CHANGELOG.md | 5 + .../cloud_functions/example/pubspec.yaml | 4 +- .../Sources/cloud_functions/Constants.swift | 2 +- .../cloud_functions/pubspec.yaml | 10 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 6 +- .../cloud_functions_web/CHANGELOG.md | 5 + .../lib/src/cloud_functions_version.dart | 2 +- .../cloud_functions_web/pubspec.yaml | 10 +- packages/firebase_ai/firebase_ai/CHANGELOG.md | 10 + .../firebase_ai/example/pubspec.yaml | 6 +- .../lib/src/firebaseai_version.dart | 2 +- packages/firebase_ai/firebase_ai/pubspec.yaml | 10 +- .../firebase_analytics/CHANGELOG.md | 5 + .../firebase_analytics/example/pubspec.yaml | 4 +- .../firebase_analytics/pubspec.yaml | 10 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 8 +- .../firebase_analytics_web/CHANGELOG.md | 4 + .../lib/src/firebase_analytics_version.dart | 2 +- .../firebase_analytics_web/pubspec.yaml | 10 +- .../firebase_app_check/CHANGELOG.md | 6 + .../firebase_app_check/example/pubspec.yaml | 6 +- .../firebase_app_check/Constants.swift | 2 +- .../firebase_app_check/pubspec.yaml | 10 +- .../CHANGELOG.md | 9 + .../pubspec.yaml | 8 +- .../firebase_app_check_web/CHANGELOG.md | 4 + .../lib/src/firebase_app_check_version.dart | 2 +- .../firebase_app_check_web/pubspec.yaml | 12 +- .../firebase_app_installations/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../Constants.swift | 2 +- .../firebase_app_installations/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../firebase_app_installations_version.dart | 2 +- .../pubspec.yaml | 12 +- .../firebase_auth/firebase_auth/CHANGELOG.md | 10 + .../firebase_auth/example/pubspec.yaml | 6 +- .../ios/firebase_auth/Package.swift | 2 +- .../macos/firebase_auth/Package.swift | 2 +- .../firebase_auth/firebase_auth/pubspec.yaml | 10 +- .../CHANGELOG.md | 9 + .../pubspec.yaml | 8 +- .../firebase_auth_web/CHANGELOG.md | 5 + .../lib/src/firebase_auth_version.dart | 2 +- .../firebase_auth_web/pubspec.yaml | 8 +- .../firebase_core/firebase_core/CHANGELOG.md | 7 + .../firebase_core/example/pubspec.yaml | 2 +- .../ios/firebase_core/Package.swift | 2 +- .../macos/firebase_core/Package.swift | 2 +- .../firebase_core/firebase_core/pubspec.yaml | 6 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 2 +- .../firebase_core_web/CHANGELOG.md | 4 + .../lib/src/firebase_core_version.dart | 2 +- .../firebase_core_web/pubspec.yaml | 4 +- .../firebase_crashlytics/CHANGELOG.md | 4 + .../firebase_crashlytics/example/pubspec.yaml | 6 +- .../ios/firebase_crashlytics/Package.swift | 2 +- .../macos/firebase_crashlytics/Package.swift | 2 +- .../firebase_crashlytics/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_data_connect/CHANGELOG.md | 7 + .../example/pubspec.yaml | 6 +- .../lib/src/dataconnect_version.dart | 2 +- .../firebase_data_connect/pubspec.yaml | 14 +- .../firebase_database/CHANGELOG.md | 9 + .../firebase_database/example/pubspec.yaml | 4 +- .../ios/firebase_database/Package.swift | 2 +- .../macos/firebase_database/Package.swift | 2 +- .../firebase_database/pubspec.yaml | 10 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 8 +- .../firebase_database_web/CHANGELOG.md | 4 + .../lib/src/firebase_database_version.dart | 2 +- .../firebase_database_web/pubspec.yaml | 10 +- .../firebase_in_app_messaging/CHANGELOG.md | 4 + .../example/pubspec.yaml | 8 +- .../firebase_in_app_messaging/Package.swift | 2 +- .../firebase_in_app_messaging/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_messaging/CHANGELOG.md | 5 + .../firebase_messaging/example/pubspec.yaml | 4 +- .../ios/firebase_messaging/Package.swift | 2 +- .../macos/firebase_messaging/Package.swift | 2 +- .../firebase_messaging/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_messaging_web/CHANGELOG.md | 4 + .../lib/src/firebase_messaging_version.dart | 2 +- .../firebase_messaging_web/pubspec.yaml | 12 +- .../firebase_ml_model_downloader/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../Constants.swift | 2 +- .../firebase_ml_model_downloader/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_performance/CHANGELOG.md | 5 + .../firebase_performance/example/pubspec.yaml | 4 +- .../ios/firebase_performance/Package.swift | 2 +- .../firebase_performance/pubspec.yaml | 10 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 8 +- .../firebase_performance_web/CHANGELOG.md | 4 + .../lib/src/firebase_performance_version.dart | 2 +- .../firebase_performance_web/pubspec.yaml | 10 +- .../firebase_remote_config/CHANGELOG.md | 5 + .../example/pubspec.yaml | 4 +- .../firebase_remote_config/Constants.swift | 2 +- .../firebase_remote_config/pubspec.yaml | 10 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 8 +- .../firebase_remote_config_web/CHANGELOG.md | 4 + .../src/firebase_remote_config_version.dart | 2 +- .../firebase_remote_config_web/pubspec.yaml | 12 +- .../firebase_storage/CHANGELOG.md | 6 + .../firebase_storage/example/pubspec.yaml | 4 +- .../ios/firebase_storage/Package.swift | 2 +- .../macos/firebase_storage/Package.swift | 2 +- .../firebase_storage/pubspec.yaml | 10 +- .../CHANGELOG.md | 7 + .../pubspec.yaml | 8 +- .../firebase_storage_web/CHANGELOG.md | 4 + .../lib/src/firebase_storage_version.dart | 2 +- .../firebase_storage_web/pubspec.yaml | 12 +- pubspec.yaml | 2 - scripts/versions.json | 28 ++ tests/pubspec.yaml | 72 ++-- 148 files changed, 947 insertions(+), 316 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56855a5dffd2..eda6c4459884 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,320 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2026-05-11 - [BoM 4.13.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4130-2026-05-11) + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`cloud_firestore_platform_interface` - `v8.0.0`](#cloud_firestore_platform_interface---v800) + - [`cloud_functions_platform_interface` - `v6.0.0`](#cloud_functions_platform_interface---v600) + - [`firebase_analytics_platform_interface` - `v6.0.0`](#firebase_analytics_platform_interface---v600) + - [`firebase_app_check_platform_interface` - `v0.4.0`](#firebase_app_check_platform_interface---v040) + - [`firebase_auth_platform_interface` - `v9.0.0`](#firebase_auth_platform_interface---v900) + - [`firebase_core_platform_interface` - `v7.0.0`](#firebase_core_platform_interface---v700) + - [`firebase_database_platform_interface` - `v0.4.0`](#firebase_database_platform_interface---v040) + - [`firebase_performance_platform_interface` - `v0.2.0`](#firebase_performance_platform_interface---v020) + - [`firebase_remote_config_platform_interface` - `v3.0.0`](#firebase_remote_config_platform_interface---v300) + - [`firebase_storage_platform_interface` - `v6.0.0`](#firebase_storage_platform_interface---v600) + - [`_flutterfire_internals` - `v1.3.70`](#_flutterfire_internals---v1370) + - [`cloud_firestore` - `v6.4.0`](#cloud_firestore---v640) + - [`cloud_firestore_web` - `v5.4.0`](#cloud_firestore_web---v540) + - [`cloud_functions` - `v6.3.0`](#cloud_functions---v630) + - [`cloud_functions_web` - `v5.1.6`](#cloud_functions_web---v516) + - [`firebase_ai` - `v3.12.0`](#firebase_ai---v3120) + - [`firebase_analytics` - `v12.4.0`](#firebase_analytics---v1240) + - [`firebase_analytics_web` - `v0.6.1+6`](#firebase_analytics_web---v0616) + - [`firebase_app_check` - `v0.4.4`](#firebase_app_check---v044) + - [`firebase_app_check_web` - `v0.2.4+1`](#firebase_app_check_web---v0241) + - [`firebase_app_installations` - `v0.4.2+1`](#firebase_app_installations---v0421) + - [`firebase_app_installations_platform_interface` - `v0.1.4+69`](#firebase_app_installations_platform_interface---v01469) + - [`firebase_app_installations_web` - `v0.1.7+6`](#firebase_app_installations_web---v0176) + - [`firebase_auth` - `v6.5.0`](#firebase_auth---v650) + - [`firebase_auth_web` - `v6.2.0`](#firebase_auth_web---v620) + - [`firebase_core` - `v4.8.0`](#firebase_core---v480) + - [`firebase_core_web` - `v3.6.1`](#firebase_core_web---v361) + - [`firebase_crashlytics` - `v5.2.1`](#firebase_crashlytics---v521) + - [`firebase_crashlytics_platform_interface` - `v3.8.21`](#firebase_crashlytics_platform_interface---v3821) + - [`firebase_data_connect` - `v0.3.0+1`](#firebase_data_connect---v0301) + - [`firebase_database` - `v12.4.0`](#firebase_database---v1240) + - [`firebase_database_web` - `v0.2.7+7`](#firebase_database_web---v0277) + - [`firebase_in_app_messaging` - `v0.9.2+1`](#firebase_in_app_messaging---v0921) + - [`firebase_in_app_messaging_platform_interface` - `v0.2.5+21`](#firebase_in_app_messaging_platform_interface---v02521) + - [`firebase_messaging` - `v16.2.1`](#firebase_messaging---v1621) + - [`firebase_messaging_platform_interface` - `v4.7.10`](#firebase_messaging_platform_interface---v4710) + - [`firebase_messaging_web` - `v4.1.6`](#firebase_messaging_web---v416) + - [`firebase_ml_model_downloader` - `v0.4.2+1`](#firebase_ml_model_downloader---v0421) + - [`firebase_ml_model_downloader_platform_interface` - `v0.1.5+21`](#firebase_ml_model_downloader_platform_interface---v01521) + - [`firebase_performance` - `v0.11.4`](#firebase_performance---v0114) + - [`firebase_performance_web` - `v0.1.8+6`](#firebase_performance_web---v0186) + - [`firebase_remote_config` - `v6.5.0`](#firebase_remote_config---v650) + - [`firebase_remote_config_web` - `v1.10.7`](#firebase_remote_config_web---v1107) + - [`firebase_storage` - `v13.4.0`](#firebase_storage---v1340) + - [`firebase_storage_web` - `v3.11.6`](#firebase_storage_web---v3116) + +--- + +#### `cloud_firestore_platform_interface` - `v8.0.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `cloud_functions_platform_interface` - `v6.0.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_analytics_platform_interface` - `v6.0.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_app_check_platform_interface` - `v0.4.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FIX**(app_check): fix an issue with debug token that would sometime not be passed properly ([#18258](https://github.com/firebase/flutterfire/issues/18258)). ([b0bc6e8f](https://github.com/firebase/flutterfire/commit/b0bc6e8f0e92aed2f3da99725eff85b3cf358282)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_auth_platform_interface` - `v9.0.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + - **FEAT**(auth,android): add revokeAccessToken support for Android ([#18206](https://github.com/firebase/flutterfire/issues/18206)) ([#18207](https://github.com/firebase/flutterfire/issues/18207)). ([7e0a2227](https://github.com/firebase/flutterfire/commit/7e0a222700178a57d064c27b4ef62cefdda1e253)) + +#### `firebase_core_platform_interface` - `v7.0.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_database_platform_interface` - `v0.4.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_performance_platform_interface` - `v0.2.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_remote_config_platform_interface` - `v3.0.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_storage_platform_interface` - `v6.0.0` + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `_flutterfire_internals` - `v1.3.70` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `cloud_firestore` - `v6.4.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(firestore,web): update Timestamp handling in jsify and EncodeUtility ([#18264](https://github.com/firebase/flutterfire/issues/18264)). ([9783a448](https://github.com/firebase/flutterfire/commit/9783a448ff532568a5e46ecb927e7b1bc77a164c)) + - **FIX**(firestore,windows): fix CI issue ([#18218](https://github.com/firebase/flutterfire/issues/18218)). ([b9c8a9e2](https://github.com/firebase/flutterfire/commit/b9c8a9e2993187c782c94398136aac9bf5418061)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `cloud_firestore_web` - `v5.4.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(firestore,web): update Timestamp handling in jsify and EncodeUtility ([#18264](https://github.com/firebase/flutterfire/issues/18264)). ([9783a448](https://github.com/firebase/flutterfire/commit/9783a448ff532568a5e46ecb927e7b1bc77a164c)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `cloud_functions` - `v6.3.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `cloud_functions_web` - `v5.1.6` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(functions,web): dartify results from cloud function stream ([#18212](https://github.com/firebase/flutterfire/issues/18212)). ([9f32c614](https://github.com/firebase/flutterfire/commit/9f32c614a9fee53ceebc5540d91c76ba4fd91d8b)) + +#### `firebase_ai` - `v3.12.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**(firebaseai): ImageConfig and FinishReasons ([#18180](https://github.com/firebase/flutterfire/issues/18180)). ([7d1a8b1d](https://github.com/firebase/flutterfire/commit/7d1a8b1db4c5f585ba38d46df37330d3d17de774)) + - **FEAT**(firebaseai): live session resumption ([#18038](https://github.com/firebase/flutterfire/issues/18038)). ([829fd949](https://github.com/firebase/flutterfire/commit/829fd949bf1644ad9ce73dfb8ed416d89654f989)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + - **FEAT**(ai): add missing enum types ([#18198](https://github.com/firebase/flutterfire/issues/18198)). ([889af7c7](https://github.com/firebase/flutterfire/commit/889af7c7b8f7705a55cdd90e39d306858a2e9fd4)) + - **FEAT**(firebaseai): add Google Maps Grounding support ([#18144](https://github.com/firebase/flutterfire/issues/18144)). ([385d9337](https://github.com/firebase/flutterfire/commit/385d93372f749843ee3d8ac409a878fa149ba7ed)) + - **FEAT**(ai): add unexpectedToolCall finish reason and corresponding tests ([#18188](https://github.com/firebase/flutterfire/issues/18188)). ([27852720](https://github.com/firebase/flutterfire/commit/278527207a4fb35a5854dd3f0a9405da9f80877c)) + +#### `firebase_analytics` - `v12.4.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_analytics_web` - `v0.6.1+6` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_app_check` - `v0.4.4` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + +#### `firebase_app_check_web` - `v0.2.4+1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_app_installations` - `v0.4.2+1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_app_installations_platform_interface` - `v0.1.4+69` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_app_installations_web` - `v0.1.7+6` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_auth` - `v6.5.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FIX**(auth,apple): remove incorrect paths in Package.swift files search paths ([#18239](https://github.com/firebase/flutterfire/issues/18239)). ([7c2fa5b8](https://github.com/firebase/flutterfire/commit/7c2fa5b83201f2f68e031476dc37ad41809215f2)) + - **FIX**(auth,iOS): update import path for autogenerated messages ([#18227](https://github.com/firebase/flutterfire/issues/18227)). ([4351179d](https://github.com/firebase/flutterfire/commit/4351179d357eeab6b23ec66f45d558c02d3fde69)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + - **FEAT**(auth,android): add revokeAccessToken support for Android ([#18206](https://github.com/firebase/flutterfire/issues/18206)) ([#18207](https://github.com/firebase/flutterfire/issues/18207)). ([7e0a2227](https://github.com/firebase/flutterfire/commit/7e0a222700178a57d064c27b4ef62cefdda1e253)) + +#### `firebase_auth_web` - `v6.2.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_core` - `v4.8.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_core_web` - `v3.6.1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_crashlytics` - `v5.2.1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_crashlytics_platform_interface` - `v3.8.21` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_data_connect` - `v0.3.0+1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FIX**(fdc): block reconnecting if there are no active subscribers or pending unary calls. ([#18265](https://github.com/firebase/flutterfire/issues/18265)). ([330bbb83](https://github.com/firebase/flutterfire/commit/330bbb83399f37911f938a59dc660ed84a0c83a3)) + - **FIX**(fdc): remove unused logs ([#18197](https://github.com/firebase/flutterfire/issues/18197)). ([4c17ca87](https://github.com/firebase/flutterfire/commit/4c17ca870a78ae6afeaad6006ca68e7999711ffd)) + +#### `firebase_database` - `v12.4.0` + + - **REFACTOR**(database,android): simplify query handling by extracting queryFromModifiers method ([#18221](https://github.com/firebase/flutterfire/issues/18221)). ([65d9bb71](https://github.com/firebase/flutterfire/commit/65d9bb7104f59de82010e3e82fd0ddddbf9a2e23)) + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(database,android): fix a regression where rapidly opening and closing query streams on the same path could throw ([#18262](https://github.com/firebase/flutterfire/issues/18262)). ([e23347b6](https://github.com/firebase/flutterfire/commit/e23347b6ae96d2174c4c2b93fd60f40d31a221c7)) + - **FIX**(database,android): fix an issue where setPersistenceEnabled needed to be called first ([#18259](https://github.com/firebase/flutterfire/issues/18259)). ([11bdedfb](https://github.com/firebase/flutterfire/commit/11bdedfb356d2c84e352e26abfc79de4c5653089)) + - **FIX**(database): fix a regression with database localEvents handling ([#18257](https://github.com/firebase/flutterfire/issues/18257)). ([40fd2904](https://github.com/firebase/flutterfire/commit/40fd2904e4634d9257241c1c2e779aa5bfc61624)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_database_web` - `v0.2.7+7` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_in_app_messaging` - `v0.9.2+1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_in_app_messaging_platform_interface` - `v0.2.5+21` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_messaging` - `v16.2.1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(messaging,android): fix call race that could happen when using requestPermission ([#18256](https://github.com/firebase/flutterfire/issues/18256)). ([57d4c3d0](https://github.com/firebase/flutterfire/commit/57d4c3d050c6a9252390de6cac91a0ca1d5461e3)) + +#### `firebase_messaging_platform_interface` - `v4.7.10` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_messaging_web` - `v4.1.6` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_ml_model_downloader` - `v0.4.2+1` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_ml_model_downloader_platform_interface` - `v0.1.5+21` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_performance` - `v0.11.4` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_performance_web` - `v0.1.8+6` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_remote_config` - `v6.5.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_remote_config_web` - `v1.10.7` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + +#### `firebase_storage` - `v13.4.0` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(storage,android): fix an issue that could happen when app would get detached from the engine ([#18255](https://github.com/firebase/flutterfire/issues/18255)). ([2771f550](https://github.com/firebase/flutterfire/commit/2771f5505ff0a53cc1bfb41afec3a0eb8781b8f8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + +#### `firebase_storage_web` - `v3.11.6` + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + + ## 2026-04-13 - [BoM 4.12.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4120-2026-04-13) ### Changes diff --git a/VERSIONS.md b/VERSIONS.md index cfed51d60d40..7813f12df3c0 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -4,6 +4,44 @@ This document is listing all the compatible versions of the FlutterFire plugins. # Versions +## [Flutter BoM 4.13.0 (2026-05-11)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-05-11) + +Install this version using FlutterFire CLI + +```bash +flutterfire install 4.13.0 +``` + +### Included Native Firebase SDK Versions +| Firebase SDK | Version | Link | +|--------------|---------|------| +| Android SDK | 34.12.0 | [Release Notes](https://firebase.google.com/support/release-notes/android) | +| iOS SDK | 12.12.0 | [Release Notes](https://firebase.google.com/support/release-notes/ios) | +| Web SDK | 12.12.0 | [Release Notes](https://firebase.google.com/support/release-notes/js) | +| Windows SDK | 13.5.0 | [Release Notes](https://firebase.google.com/support/release-notes/cpp-relnotes) | + +### FlutterFire Plugin Versions +| Plugin | Version | Dart Version | Flutter Version | +|--------|---------|--------------|-----------------| +| [cloud_firestore](https://pub.dev/packages/cloud_firestore/versions/6.4.0) | 6.4.0 | ^3.6.0 | >=3.27.0 | +| [cloud_functions](https://pub.dev/packages/cloud_functions/versions/6.3.0) | 6.3.0 | ^3.6.0 | >=3.27.0 | +| [firebase_ai](https://pub.dev/packages/firebase_ai/versions/3.12.0) | 3.12.0 | ^3.6.0 | >=3.16.0 | +| [firebase_analytics](https://pub.dev/packages/firebase_analytics/versions/12.4.0) | 12.4.0 | ^3.6.0 | >=3.27.0 | +| [firebase_app_check](https://pub.dev/packages/firebase_app_check/versions/0.4.4) | 0.4.4 | ^3.6.0 | >=3.27.0 | +| [firebase_app_installations](https://pub.dev/packages/firebase_app_installations/versions/0.4.2+1) | 0.4.2+1 | ^3.6.0 | >=3.27.0 | +| [firebase_auth](https://pub.dev/packages/firebase_auth/versions/6.5.0) | 6.5.0 | ^3.6.0 | >=3.16.0 | +| [firebase_core](https://pub.dev/packages/firebase_core/versions/4.8.0) | 4.8.0 | ^3.6.0 | >=3.27.0 | +| [firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics/versions/5.2.1) | 5.2.1 | ^3.6.0 | >=3.27.0 | +| [firebase_data_connect](https://pub.dev/packages/firebase_data_connect/versions/0.3.0+1) | 0.3.0+1 | ^3.6.0 | >=3.27.0 | +| [firebase_database](https://pub.dev/packages/firebase_database/versions/12.4.0) | 12.4.0 | ^3.6.0 | >=3.27.0 | +| [firebase_in_app_messaging](https://pub.dev/packages/firebase_in_app_messaging/versions/0.9.2+1) | 0.9.2+1 | ^3.6.0 | >=3.27.0 | +| [firebase_messaging](https://pub.dev/packages/firebase_messaging/versions/16.2.1) | 16.2.1 | ^3.6.0 | >=3.27.0 | +| [firebase_ml_model_downloader](https://pub.dev/packages/firebase_ml_model_downloader/versions/0.4.2+1) | 0.4.2+1 | ^3.6.0 | >=3.27.0 | +| [firebase_performance](https://pub.dev/packages/firebase_performance/versions/0.11.4) | 0.11.4 | ^3.6.0 | >=3.27.0 | +| [firebase_remote_config](https://pub.dev/packages/firebase_remote_config/versions/6.5.0) | 6.5.0 | ^3.6.0 | >=3.27.0 | +| [firebase_storage](https://pub.dev/packages/firebase_storage/versions/13.4.0) | 13.4.0 | ^3.6.0 | >=3.27.0 | + + ## [Flutter BoM 4.12.0 (2026-04-13)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-04-13) Install this version using FlutterFire CLI diff --git a/packages/_flutterfire_internals/CHANGELOG.md b/packages/_flutterfire_internals/CHANGELOG.md index 879496c4e3d0..3515669b8416 100644 --- a/packages/_flutterfire_internals/CHANGELOG.md +++ b/packages/_flutterfire_internals/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.70 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 1.3.69 - **FIX**: improve error handling in _firebaseExceptionFromCoreFirebaseError ([#18177](https://github.com/firebase/flutterfire/issues/18177)). ([3c29048a](https://github.com/firebase/flutterfire/commit/3c29048a859b62f3f224b1fa3c8db61f78f63374)) diff --git a/packages/_flutterfire_internals/pubspec.yaml b/packages/_flutterfire_internals/pubspec.yaml index ae21b2daef21..e2671082096e 100755 --- a/packages/_flutterfire_internals/pubspec.yaml +++ b/packages/_flutterfire_internals/pubspec.yaml @@ -2,7 +2,7 @@ name: _flutterfire_internals description: A package hosting Dart code shared between FlutterFire plugins. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/_flutterfire_internals -version: 1.3.69 +version: 1.3.70 resolution: workspace environment: @@ -11,8 +11,8 @@ environment: dependencies: collection: ^1.0.0 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md index 3b0b92f00872..a20219cb4f94 100644 --- a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md @@ -1,3 +1,10 @@ +## 6.4.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(firestore,web): update Timestamp handling in jsify and EncodeUtility ([#18264](https://github.com/firebase/flutterfire/issues/18264)). ([9783a448](https://github.com/firebase/flutterfire/commit/9783a448ff532568a5e46ecb927e7b1bc77a164c)) + - **FIX**(firestore,windows): fix CI issue ([#18218](https://github.com/firebase/flutterfire/issues/18218)). ([b9c8a9e2](https://github.com/firebase/flutterfire/commit/b9c8a9e2993187c782c94398136aac9bf5418061)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 6.3.0 - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) diff --git a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml index dc72745bc3ec..86a86070a036 100755 --- a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.3.0 - firebase_core: ^4.7.0 + cloud_firestore: ^6.4.0 + firebase_core: ^4.8.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index 0cc6ea4dff5e..acb82e377492 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "6.3.0" +let library_version = "6.4.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index 470dbf1e6153..35731701d100 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "6.3.0" +let library_version = "6.4.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml index 5bff723de6c6..14c401323006 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -31,7 +31,7 @@ environment: dependencies: cloud_firestore: path: .. - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pubspec.yaml index 5cb0b32117e4..8bf708365a7e 100755 --- a/packages/cloud_firestore/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pubspec.yaml @@ -4,7 +4,7 @@ description: live synchronization and offline support on Android and iOS. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore -version: 6.3.0 +version: 6.4.0 resolution: workspace topics: - firebase @@ -21,11 +21,11 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore_platform_interface: ^7.2.0 - cloud_firestore_web: ^5.3.0 + cloud_firestore_platform_interface: ^8.0.0 + cloud_firestore_web: ^5.4.0 collection: ^1.0.0 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md index f7038a52607d..f0779a819fbe 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 8.0.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 7.2.0 - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml index 8b8fd425392e..bff98fa8ca48 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_firestore_platform_interface description: A common platform interface for the cloud_firestore plugin. -version: 7.2.0 +version: 8.0.0 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 + _flutterfire_internals: ^1.3.70 collection: ^1.15.0 - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md index 95127533fdad..89e6bdfe84f3 100644 --- a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md @@ -1,3 +1,9 @@ +## 5.4.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(firestore,web): update Timestamp handling in jsify and EncodeUtility ([#18264](https://github.com/firebase/flutterfire/issues/18264)). ([9783a448](https://github.com/firebase/flutterfire/commit/9783a448ff532568a5e46ecb927e7b1bc77a164c)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 5.3.0 - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart index ab9c93b832a8..14d87311cbb9 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.3.0'; +const packageVersion = '6.4.0'; diff --git a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml index 76c108c59d6a..4743bd3bffdd 100644 --- a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_firestore homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web -version: 5.3.0 +version: 5.4.0 resolution: workspace environment: @@ -11,18 +11,18 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 - cloud_firestore_platform_interface: ^7.2.0 + _flutterfire_internals: ^1.3.70 + cloud_firestore_platform_interface: ^8.0.0 collection: ^1.0.0 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_functions/cloud_functions/CHANGELOG.md b/packages/cloud_functions/cloud_functions/CHANGELOG.md index 299beaa57077..5917e71ff1a3 100644 --- a/packages/cloud_functions/cloud_functions/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.3.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 6.2.0 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/cloud_functions/cloud_functions/example/pubspec.yaml b/packages/cloud_functions/cloud_functions/example/pubspec.yaml index 532101999cb4..3623c5720620 100644 --- a/packages/cloud_functions/cloud_functions/example/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions: ^6.2.0 - firebase_core: ^4.7.0 + cloud_functions: ^6.3.0 + firebase_core: ^4.8.0 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift index f1fe1a27a2cb..3786e1b8dde8 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.2.0" +public let versionNumber = "6.3.0" diff --git a/packages/cloud_functions/cloud_functions/pubspec.yaml b/packages/cloud_functions/cloud_functions/pubspec.yaml index c6ff74fdaf16..3bde8c631093 100644 --- a/packages/cloud_functions/cloud_functions/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_functions description: A Flutter plugin allowing you to use Firebase Cloud Functions. -version: 6.2.0 +version: 6.3.0 resolution: workspace homepage: https://firebase.google.com/docs/functions repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions_platform_interface: ^5.8.12 - cloud_functions_web: ^5.1.5 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + cloud_functions_platform_interface: ^6.0.0 + cloud_functions_web: ^5.1.6 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md index 29fac14b241f..82c93f7e0a97 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 6.0.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 5.8.12 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml index 71bf2d59d6c7..588538edf552 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_fun # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 5.8.12 +version: 6.0.0 resolution: workspace environment: @@ -13,14 +13,14 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md index a5b1bed35734..2893c34f9f90 100644 --- a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md @@ -1,3 +1,8 @@ +## 5.1.6 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(functions,web): dartify results from cloud function stream ([#18212](https://github.com/firebase/flutterfire/issues/18212)). ([9f32c614](https://github.com/firebase/flutterfire/commit/9f32c614a9fee53ceebc5540d91c76ba4fd91d8b)) + ## 5.1.5 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart index 305156baf450..ab9c93b832a8 100644 --- a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart +++ b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.2.0'; +const packageVersion = '6.3.0'; diff --git a/packages/cloud_functions/cloud_functions_web/pubspec.yaml b/packages/cloud_functions/cloud_functions_web/pubspec.yaml index 867a01d1a684..aaaef2c7bb08 100644 --- a/packages/cloud_functions/cloud_functions_web/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_functions homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web -version: 5.1.5 +version: 5.1.6 resolution: workspace environment: @@ -11,9 +11,9 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions_platform_interface: ^5.8.12 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 + cloud_functions_platform_interface: ^6.0.0 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 flutter: sdk: flutter flutter_web_plugins: @@ -21,7 +21,7 @@ dependencies: web: ^1.1.1 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index ae8a5abe6fc9..22e19fc93fb1 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,3 +1,13 @@ +## 3.12.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**(firebaseai): ImageConfig and FinishReasons ([#18180](https://github.com/firebase/flutterfire/issues/18180)). ([7d1a8b1d](https://github.com/firebase/flutterfire/commit/7d1a8b1db4c5f585ba38d46df37330d3d17de774)) + - **FEAT**(firebaseai): live session resumption ([#18038](https://github.com/firebase/flutterfire/issues/18038)). ([829fd949](https://github.com/firebase/flutterfire/commit/829fd949bf1644ad9ce73dfb8ed416d89654f989)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + - **FEAT**(ai): add missing enum types ([#18198](https://github.com/firebase/flutterfire/issues/18198)). ([889af7c7](https://github.com/firebase/flutterfire/commit/889af7c7b8f7705a55cdd90e39d306858a2e9fd4)) + - **FEAT**(firebaseai): add Google Maps Grounding support ([#18144](https://github.com/firebase/flutterfire/issues/18144)). ([385d9337](https://github.com/firebase/flutterfire/commit/385d93372f749843ee3d8ac409a878fa149ba7ed)) + - **FEAT**(ai): add unexpectedToolCall finish reason and corresponding tests ([#18188](https://github.com/firebase/flutterfire/issues/18188)). ([27852720](https://github.com/firebase/flutterfire/commit/278527207a4fb35a5854dd3f0a9405da9f80877c)) + ## 3.11.0 - **FEAT**(firebaseai): server prompt chat and function calling ([#17972](https://github.com/firebase/flutterfire/issues/17972)). ([4b8f2288](https://github.com/firebase/flutterfire/commit/4b8f22889808c0a55f4fc2abc52c72aa2d932379)) diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index c407f685e649..648f43a91b85 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -24,9 +24,9 @@ dependencies: camera: ^0.12.0+1 camera_macos: ^0.0.9 cupertino_icons: ^1.0.6 - firebase_ai: ^3.11.0 - firebase_core: ^4.7.0 - firebase_storage: ^13.3.0 + firebase_ai: ^3.12.0 + firebase_core: ^4.8.0 + firebase_storage: ^13.4.0 flutter: sdk: flutter flutter_animate: ^4.5.2 diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart index b2dd21028015..23f6faec9631 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.3.0'; +const packageVersion = '0.3.0+1'; diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index bdbc9fb8effe..ddcb4d245a85 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI Logic SDK. -version: 3.11.0 +version: 3.12.0 resolution: workspace homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: @@ -21,10 +21,10 @@ environment: flutter: ">=3.16.0" dependencies: - firebase_app_check: ^0.4.3 - firebase_auth: ^6.4.0 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_app_check: ^0.4.4 + firebase_auth: ^6.5.0 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter http: ^1.1.0 diff --git a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md index e7e660ad1927..75687c708fe6 100644 --- a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md @@ -1,3 +1,8 @@ +## 12.4.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 12.3.0 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml index 17d8e0ad4fab..9ffe573be6b5 100755 --- a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.3.0 - firebase_core: ^4.7.0 + firebase_analytics: ^12.4.0 + firebase_core: ^4.8.0 flutter: sdk: flutter in_app_purchase: ^3.2.3 diff --git a/packages/firebase_analytics/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/pubspec.yaml index f8e82e9412f7..94e47e3d6908 100755 --- a/packages/firebase_analytics/firebase_analytics/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/pubspec.yaml @@ -4,7 +4,7 @@ description: solution that provides insight on app usage and user engagement on Android and iOS. homepage: https://firebase.google.com/docs/analytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics -version: 12.3.0 +version: 12.4.0 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics_platform_interface: ^5.1.1 - firebase_analytics_web: ^0.6.1+5 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_analytics_platform_interface: ^6.0.0 + firebase_analytics_web: ^0.6.1+6 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md index f68c55ce1112..9d3e629aa0df 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 6.0.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 5.1.1 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml index 3b5c1d1eb8d8..1090d77bdf1f 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_platform_interface description: A common platform interface for the firebase_analytics plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface -version: 5.1.1 +version: 6.0.0 resolution: workspace environment: @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter pigeon: 26.3.4 diff --git a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md index 0c237ab3e62f..4e1a05ec3867 100644 --- a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.1+6 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.6.1+5 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart index a6da83ece02a..d17623e3d121 100644 --- a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart +++ b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.3.0'; +const packageVersion = '12.4.0'; diff --git a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml index ecbcfb8cecb5..e093f44a253a 100644 --- a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_web description: The web implementation of firebase_analytics homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web -version: 0.6.1+5 +version: 0.6.1+6 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_analytics_platform_interface: ^5.1.1 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 + _flutterfire_internals: ^1.3.70 + firebase_analytics_platform_interface: ^6.0.0 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md index 150487e89961..488a76a38745 100644 --- a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.4 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + ## 0.4.3 - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) diff --git a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml index 2822ab2aefc2..eab8706af9e4 100644 --- a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml @@ -11,9 +11,9 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.3.0 - firebase_app_check: ^0.4.3 - firebase_core: ^4.7.0 + cloud_firestore: ^6.4.0 + firebase_app_check: ^0.4.4 + firebase_core: ^4.8.0 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift index f7b381f99b91..86aae5dc32fa 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.3" +public let versionNumber = "0.4.4" diff --git a/packages/firebase_app_check/firebase_app_check/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/pubspec.yaml index 660c9464cfb1..ff4498431d0c 100644 --- a/packages/firebase_app_check/firebase_app_check/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_app_check description: App Check works alongside other Firebase services to help protect your backend resources from abuse, such as billing fraud or phishing. homepage: https://firebase.google.com/docs/app-check repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check -version: 0.4.3 +version: 0.4.4 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_check_platform_interface: ^0.3.0 - firebase_app_check_web: ^0.2.4 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_app_check_platform_interface: ^0.4.0 + firebase_app_check_web: ^0.2.4+1 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md index f09c21889e23..24e446baef89 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.4.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FIX**(app_check): fix an issue with debug token that would sometime not be passed properly ([#18258](https://github.com/firebase/flutterfire/issues/18258)). ([b0bc6e8f](https://github.com/firebase/flutterfire/commit/b0bc6e8f0e92aed2f3da99725eff85b3cf358282)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 0.3.0 - **FEAT**(app_check,windows): add support for AppCheck for Windows ([#18140](https://github.com/firebase/flutterfire/issues/18140)). ([81f30325](https://github.com/firebase/flutterfire/commit/81f30325fc926fe94b630e49f56b795c781a4cbe)) diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 7db42d4f9647..059498469c59 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_platform_interface description: A common platform interface for the firebase_app_check plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_platform_interface -version: 0.3.0 +version: 0.4.0 resolution: workspace environment: @@ -9,15 +9,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md index f2f90b5c5be4..eb3cd0573bee 100644 --- a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.4+1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.2.4 - **FIX**(app_check,web): fix an error that could occur when refreshing a token ([#18135](https://github.com/firebase/flutterfire/issues/18135)). ([6998e512](https://github.com/firebase/flutterfire/commit/6998e512ea5404a20ad81a0306aafaa607babc2a)) diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart index a6709bda51df..7110462994e7 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.3'; +const packageVersion = '0.4.4'; diff --git a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml index 07cfdcb236f1..f600a6ee3cf8 100644 --- a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_web description: The web implementation of firebase_app_check homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_web -version: 0.2.4 +version: 0.2.4+1 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_app_check_platform_interface: ^0.3.0 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 + _flutterfire_internals: ^1.3.70 + firebase_app_check_platform_interface: ^0.4.0 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 flutter: sdk: flutter flutter_web_plugins: @@ -21,7 +21,7 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md index 468ba0805304..602b74463e24 100644 --- a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.4.2 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml index 2533faea74dd..f6f29d756f65 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_app_installations: ^0.4.2 + firebase_core: ^4.8.0 + firebase_app_installations: ^0.4.2+1 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift index c42bec0ea728..8f7df3f775de 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2" +public let versionNumber = "0.4.2+1" diff --git a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml index 50818e54f8a4..e7988bb90888 100644 --- a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations description: A Flutter plugin allowing you to use Firebase Installations. -version: 0.4.2 +version: 0.4.2+1 resolution: workspace homepage: https://firebase.google.com/docs/projects/manage-installations#flutter repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_installations_platform_interface: ^0.1.4+68 - firebase_app_installations_web: ^0.1.7+5 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_app_installations_platform_interface: ^0.1.4+69 + firebase_app_installations_web: ^0.1.7+6 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md index 32f7114c0473..d8afddaf7557 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+69 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.1.4+68 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 9c4c59768c73..6c91ec5f079e 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_platform_interface description: A common platform interface for the firebase_app_installations plugin. -version: 0.1.4+68 +version: 0.1.4+69 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md index b7e1bedafe42..f05c7869e741 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.7+6 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.1.7+5 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart index e538fa901e42..5067985ca37b 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart +++ b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.2'; +const packageVersion = '0.4.2+1'; diff --git a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml index 17973ad0ff79..bafe760003d1 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_web description: The web implementation of firebase_app_installations. -version: 0.1.7+5 +version: 0.1.7+6 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web @@ -10,17 +10,17 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_app_installations_platform_interface: ^0.1.4+68 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 + _flutterfire_internals: ^1.3.70 + firebase_app_installations_platform_interface: ^0.1.4+69 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_auth/firebase_auth/CHANGELOG.md b/packages/firebase_auth/firebase_auth/CHANGELOG.md index 4a92009803d9..63b52b033001 100644 --- a/packages/firebase_auth/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth/CHANGELOG.md @@ -1,3 +1,13 @@ +## 6.5.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FIX**(auth,apple): remove incorrect paths in Package.swift files search paths ([#18239](https://github.com/firebase/flutterfire/issues/18239)). ([7c2fa5b8](https://github.com/firebase/flutterfire/commit/7c2fa5b83201f2f68e031476dc37ad41809215f2)) + - **FIX**(auth,iOS): update import path for autogenerated messages ([#18227](https://github.com/firebase/flutterfire/issues/18227)). ([4351179d](https://github.com/firebase/flutterfire/commit/4351179d357eeab6b23ec66f45d558c02d3fde69)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + - **FEAT**(auth,android): add revokeAccessToken support for Android ([#18206](https://github.com/firebase/flutterfire/issues/18206)) ([#18207](https://github.com/firebase/flutterfire/issues/18207)). ([7e0a2227](https://github.com/firebase/flutterfire/commit/7e0a222700178a57d064c27b4ef62cefdda1e253)) + ## 6.4.0 - **FIX**(auth,ios): serialize Sign in with Apple to prevent crash on overlapping requests ([#18172](https://github.com/firebase/flutterfire/issues/18172)). ([752cbcaa](https://github.com/firebase/flutterfire/commit/752cbcaa57f887a8fea3bda728bb8482290fa049)) diff --git a/packages/firebase_auth/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/firebase_auth/example/pubspec.yaml index 9b96f37ac33f..dd67a0a03911 100644 --- a/packages/firebase_auth/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/example/pubspec.yaml @@ -8,9 +8,9 @@ environment: dependencies: barcode_widget: ^2.0.4 - firebase_auth: ^6.4.0 - firebase_core: ^4.7.0 - firebase_messaging: ^16.2.0 + firebase_auth: ^6.5.0 + firebase_core: ^4.8.0 + firebase_messaging: ^16.2.1 flutter: sdk: flutter flutter_facebook_auth: ^7.1.5 diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index fe4429cf5fc9..579452546409 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "6.4.0" +let library_version = "6.5.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index c7f29e7ad0e1..deff530b35f3 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "6.4.0" +let library_version = "6.5.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_auth/firebase_auth/pubspec.yaml b/packages/firebase_auth/firebase_auth/pubspec.yaml index 2a028b15185c..c421946e3666 100755 --- a/packages/firebase_auth/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling like Google, Facebook and Twitter. homepage: https://firebase.google.com/docs/auth repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth -version: 6.4.0 +version: 6.5.0 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.16.0' dependencies: - firebase_auth_platform_interface: ^8.1.9 - firebase_auth_web: ^6.1.5 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_auth_platform_interface: ^9.0.0 + firebase_auth_web: ^6.2.0 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md index 1107d8192f3d..2a02068cc91a 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md @@ -1,3 +1,12 @@ +## 9.0.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + - **FEAT**(auth,android): add revokeAccessToken support for Android ([#18206](https://github.com/firebase/flutterfire/issues/18206)) ([#18207](https://github.com/firebase/flutterfire/issues/18207)). ([7e0a2227](https://github.com/firebase/flutterfire/commit/7e0a222700178a57d064c27b4ef62cefdda1e253)) + ## 8.1.9 - Update a dependency to the latest release. diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml index 89ee85d9e9a6..05f5bca64ca0 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_au repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 8.1.9 +version: 9.0.0 resolution: workspace environment: @@ -12,9 +12,9 @@ environment: flutter: '>=3.16.0' dependencies: - _flutterfire_internals: ^1.3.69 + _flutterfire_internals: ^1.3.70 collection: ^1.16.0 - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter http: ^1.1.0 @@ -22,7 +22,7 @@ dependencies: plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.4.0 diff --git a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md index 41e451368e0b..022d967eb146 100644 --- a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.2.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 6.1.5 - Update a dependency to the latest release. diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart index 14d87311cbb9..200e74209d4f 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.4.0'; +const packageVersion = '6.5.0'; diff --git a/packages/firebase_auth/firebase_auth_web/pubspec.yaml b/packages/firebase_auth/firebase_auth_web/pubspec.yaml index 818e8d972fa5..50d3c17161f7 100644 --- a/packages/firebase_auth/firebase_auth_web/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_auth_web description: The web implementation of firebase_auth homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web -version: 6.1.5 +version: 6.2.0 resolution: workspace environment: @@ -10,9 +10,9 @@ environment: flutter: '>=3.22.0' dependencies: - firebase_auth_platform_interface: ^8.1.9 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 + firebase_auth_platform_interface: ^9.0.0 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_core/firebase_core/CHANGELOG.md b/packages/firebase_core/firebase_core/CHANGELOG.md index c43904a2cf08..9d1e4d578e32 100644 --- a/packages/firebase_core/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/firebase_core/CHANGELOG.md @@ -1,3 +1,10 @@ +## 4.8.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FEAT**(core): Add Auth and AppCheck as App's registered service. ([#18237](https://github.com/firebase/flutterfire/issues/18237)). ([7ce191cb](https://github.com/firebase/flutterfire/commit/7ce191cbd598b299cd0ec64b45d1366914367a5d)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 4.7.0 - **FEAT**(core): bump Firebase Android SDK to 34.12.0 ([#18185](https://github.com/firebase/flutterfire/issues/18185)). ([346a048f](https://github.com/firebase/flutterfire/commit/346a048f098090e6848fdd0f61a8bf7d01394676)) diff --git a/packages/firebase_core/firebase_core/example/pubspec.yaml b/packages/firebase_core/firebase_core/example/pubspec.yaml index eacdf60d8740..3f1571f1e528 100644 --- a/packages/firebase_core/firebase_core/example/pubspec.yaml +++ b/packages/firebase_core/firebase_core/example/pubspec.yaml @@ -7,7 +7,7 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index 694cc8c8db64..b82c0e27a32e 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version_string = "4.7.0" +let library_version_string = "4.8.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index 3a4557f03f3f..df765d313a84 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version_string = "4.7.0" +let library_version_string = "4.8.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index 5ce012dcdc86..f0f545f3eb15 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. homepage: https://firebase.google.com/docs/flutter/setup repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core -version: 4.7.0 +version: 4.8.0 resolution: workspace topics: - firebase @@ -17,8 +17,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core_platform_interface: ^6.0.3 - firebase_core_web: ^3.6.0 + firebase_core_platform_interface: ^7.0.0 + firebase_core_web: ^3.6.1 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md b/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md index 07ddb5c0bc17..9df4a7e2c64e 100644 --- a/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 7.0.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 6.0.3 - **REFACTOR**: fix formatting and analysis issues across the repo ([#18124](https://github.com/firebase/flutterfire/issues/18124)). ([ab79fd93](https://github.com/firebase/flutterfire/commit/ab79fd93ee4ccfeb478687623134b1cf8ab71c74)) diff --git a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml index 292ad6f194f5..196a725c5f18 100644 --- a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml +++ b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_co repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 6.0.3 +version: 7.0.0 resolution: workspace environment: diff --git a/packages/firebase_core/firebase_core_web/CHANGELOG.md b/packages/firebase_core/firebase_core_web/CHANGELOG.md index 228023192376..a0d21e536cd1 100644 --- a/packages/firebase_core/firebase_core_web/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.6.1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 3.6.0 - **FEAT**: support for Firestore Pipelines ([#18183](https://github.com/firebase/flutterfire/issues/18183)). ([d734cf08](https://github.com/firebase/flutterfire/commit/d734cf0885f6d9403c2fb3ac48d6c52e14199309)) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart index f30f2ff929a0..2896b61b634e 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '4.7.0'; +const packageVersion = '4.8.0'; diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index f29799d692c1..a588cc9bfcd2 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_core_web description: The web implementation of firebase_core homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web -version: 3.6.0 +version: 3.6.1 resolution: workspace environment: @@ -10,7 +10,7 @@ environment: flutter: '>=3.22.0' dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md index d8bf22a18039..183f7347650d 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.2.1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 5.2.0 - **FIX**(crashlytics,android): fix an issue with deobfuscating flavored builds ([#18085](https://github.com/firebase/flutterfire/issues/18085)). ([55a7f6ff](https://github.com/firebase/flutterfire/commit/55a7f6ff17940487e29d8bc78779ca4cfce24b0c)) diff --git a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml index 073a53e57f9d..15a3d24e38ec 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml @@ -7,9 +7,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.3.0 - firebase_core: ^4.7.0 - firebase_crashlytics: ^5.2.0 + firebase_analytics: ^12.4.0 + firebase_core: ^4.8.0 + firebase_crashlytics: ^5.2.1 flutter: sdk: flutter diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index e2ca155d2730..e36a72046b00 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "5.2.0" +let library_version = "5.2.1" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index 60fff2af2364..af2ba2fc338b 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "5.2.0" +let library_version = "5.2.1" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml index 9031b6f30d16..c3d37d7697c5 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 5.2.0 +version: 5.2.1 resolution: workspace homepage: https://firebase.google.com/docs/crashlytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics @@ -20,9 +20,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_crashlytics_platform_interface: ^3.8.20 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_crashlytics_platform_interface: ^3.8.21 flutter: sdk: flutter stack_trace: ^1.10.0 diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md index 1105b13a9626..659529b9d5f1 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.8.21 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 3.8.20 - Update a dependency to the latest release. diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml index e26aa35cd09d..83b556a67bf7 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_crashlytics_platform_interface description: A common platform interface for the firebase_crashlytics plugin. -version: 3.8.20 +version: 3.8.21 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 + _flutterfire_internals: ^1.3.70 collection: ^1.15.0 - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md index d50b697d0393..0a9baba2932e 100644 --- a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md +++ b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.3.0+1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**: update core, auth and app-check logic so internal resources on method channels are properly disposed ([#18268](https://github.com/firebase/flutterfire/issues/18268)). ([a0de4ed8](https://github.com/firebase/flutterfire/commit/a0de4ed86b0dff89bb9e557f2a54f38cd2546016)) + - **FIX**(fdc): block reconnecting if there are no active subscribers or pending unary calls. ([#18265](https://github.com/firebase/flutterfire/issues/18265)). ([330bbb83](https://github.com/firebase/flutterfire/commit/330bbb83399f37911f938a59dc660ed84a0c83a3)) + - **FIX**(fdc): remove unused logs ([#18197](https://github.com/firebase/flutterfire/issues/18197)). ([4c17ca87](https://github.com/firebase/flutterfire/commit/4c17ca870a78ae6afeaad6006ca68e7999711ffd)) + ## 0.3.0 - **FEAT**(fdc): Streaming implementation for data connect ([#18174](https://github.com/firebase/flutterfire/issues/18174)). ([6ce6f6b2](https://github.com/firebase/flutterfire/commit/6ce6f6b2369b9d43e69b24b284d8ef816c430e31)) diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index 8f34dae262b5..da004248c709 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -13,16 +13,16 @@ environment: dependencies: flutter: sdk: flutter - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 google_sign_in: ^6.1.0 - firebase_auth: ^6.4.0 + firebase_auth: ^6.5.0 firebase_data_connect: path: ../ cupertino_icons: ^1.0.6 flutter_rating_bar: ^4.0.1 protobuf: ^3.1.0 - firebase_app_check: ^0.4.3 + firebase_app_check: ^0.4.4 dev_dependencies: build_runner: ^2.3.3 diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart index 4d967e86fa3f..a55677afaa2b 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// version number for the package, should be align with pubspec.yaml. -const packageVersion = '0.3.0'; +const packageVersion = '0.3.0+1'; diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index e41d36a699ac..984617038e7c 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_data_connect description: 'Flutter plugin for Firebase Data Connect, a relational database service that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL.' -version: 0.3.0 +version: 0.3.0+1 resolution: workspace homepage: https://firebase.google.com/docs/data-connect/quickstart?platform=flutter false_secrets: @@ -13,10 +13,10 @@ environment: dependencies: crypto: ^3.0.6 - firebase_app_check: ^0.4.3 - firebase_auth: ^6.4.0 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 + firebase_app_check: ^0.4.4 + firebase_auth: ^6.5.0 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 fixnum: ^1.1.1 flutter: sdk: flutter @@ -32,8 +32,8 @@ dependencies: dev_dependencies: build_runner: ^2.4.12 - firebase_app_check_platform_interface: ^0.3.0 - firebase_auth_platform_interface: ^8.1.9 + firebase_app_check_platform_interface: ^0.4.0 + firebase_auth_platform_interface: ^9.0.0 flutter_lints: ^6.0.0 flutter_test: sdk: flutter diff --git a/packages/firebase_database/firebase_database/CHANGELOG.md b/packages/firebase_database/firebase_database/CHANGELOG.md index 5bce4614feac..4987b6dda84a 100644 --- a/packages/firebase_database/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/firebase_database/CHANGELOG.md @@ -1,3 +1,12 @@ +## 12.4.0 + + - **REFACTOR**(database,android): simplify query handling by extracting queryFromModifiers method ([#18221](https://github.com/firebase/flutterfire/issues/18221)). ([65d9bb71](https://github.com/firebase/flutterfire/commit/65d9bb7104f59de82010e3e82fd0ddddbf9a2e23)) + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(database,android): fix a regression where rapidly opening and closing query streams on the same path could throw ([#18262](https://github.com/firebase/flutterfire/issues/18262)). ([e23347b6](https://github.com/firebase/flutterfire/commit/e23347b6ae96d2174c4c2b93fd60f40d31a221c7)) + - **FIX**(database,android): fix an issue where setPersistenceEnabled needed to be called first ([#18259](https://github.com/firebase/flutterfire/issues/18259)). ([11bdedfb](https://github.com/firebase/flutterfire/commit/11bdedfb356d2c84e352e26abfc79de4c5653089)) + - **FIX**(database): fix a regression with database localEvents handling ([#18257](https://github.com/firebase/flutterfire/issues/18257)). ([40fd2904](https://github.com/firebase/flutterfire/commit/40fd2904e4634d9257241c1c2e779aa5bfc61624)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 12.3.0 - **FEAT**(database,android): fix order issue ([#18142](https://github.com/firebase/flutterfire/issues/18142)). ([5dd661cb](https://github.com/firebase/flutterfire/commit/5dd661cb7b9efa9e02c1bc9233222860be8be7bd)) diff --git a/packages/firebase_database/firebase_database/example/pubspec.yaml b/packages/firebase_database/firebase_database/example/pubspec.yaml index f1e233566414..1036ead26183 100755 --- a/packages/firebase_database/firebase_database/example/pubspec.yaml +++ b/packages/firebase_database/firebase_database/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_database: ^12.3.0 + firebase_core: ^4.8.0 + firebase_database: ^12.4.0 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index 55f5fa212eab..52d1a5f4c8c8 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "12.3.0" +let library_version = "12.4.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index 66d5719467c5..a14d6b37504c 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "12.3.0" +let library_version = "12.4.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index 65f61de369ff..91b1bf9fdfc5 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. homepage: https://firebase.google.com/docs/database repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database -version: 12.3.0 +version: 12.4.0 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_database_platform_interface: ^0.3.1+1 - firebase_database_web: ^0.2.7+6 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_database_platform_interface: ^0.4.0 + firebase_database_web: ^0.2.7+7 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md index 073eae47b283..8a090c53aae9 100755 --- a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.4.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 0.3.1+1 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml index 135d34bdb10c..53833ea64800 100755 --- a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml +++ b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_platform_interface description: A common platform interface for the firebase_database plugin. -version: 0.3.1+1 +version: 0.4.0 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_platform_interface @@ -9,16 +9,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 + _flutterfire_internals: ^1.3.70 collection: ^1.14.3 - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.2 diff --git a/packages/firebase_database/firebase_database_web/CHANGELOG.md b/packages/firebase_database/firebase_database_web/CHANGELOG.md index 4a68d582f6d5..37b2041347db 100644 --- a/packages/firebase_database/firebase_database_web/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.7+7 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.2.7+6 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart index a6da83ece02a..d17623e3d121 100644 --- a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.3.0'; +const packageVersion = '12.4.0'; diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index addfff88fa07..0c834f6bb674 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_web description: The web implementation of firebase_database -version: 0.2.7+6 +version: 0.2.7+7 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_web @@ -10,16 +10,16 @@ environment: dependencies: collection: ^1.18.0 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 - firebase_database_platform_interface: ^0.3.1+1 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 + firebase_database_platform_interface: ^0.4.0 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md index 5f4a400b9992..5d019a90270d 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2+1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.9.2 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml index b3e13e564026..0b65a086c144 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml @@ -8,10 +8,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.3.0 - firebase_core: ^4.7.0 - firebase_in_app_messaging: ^0.9.2 - firebase_in_app_messaging_platform_interface: ^0.2.5+20 + firebase_analytics: ^12.4.0 + firebase_core: ^4.8.0 + firebase_in_app_messaging: ^0.9.2+1 + firebase_in_app_messaging_platform_interface: ^0.2.5+21 flutter: sdk: flutter diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index f27767d3c35c..ef7b08b15a59 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "0.9.2" +let library_version = "0.9.2-1" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml index cf2c15013ecd..d82edb755e28 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_in_app_messaging description: Flutter plugin for Firebase In-App Messaging. -version: 0.9.2 +version: 0.9.2+1 resolution: workspace homepage: https://firebase.google.com/docs/in-app-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_in_app_messaging_platform_interface: ^0.2.5+20 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_in_app_messaging_platform_interface: ^0.2.5+21 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md index 5811324022eb..ad33f375cb56 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.5+21 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.2.5+20 - Update a dependency to the latest release. diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml index 1c4bd1db6d64..bf4f732ff11d 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the firebase_in_app_messaging plugi homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface -version: 0.2.5+20 +version: 0.2.5+21 resolution: workspace environment: @@ -11,14 +11,14 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter diff --git a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md index 649638dc7908..ec4ac817ba5e 100644 --- a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md @@ -1,3 +1,8 @@ +## 16.2.1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(messaging,android): fix call race that could happen when using requestPermission ([#18256](https://github.com/firebase/flutterfire/issues/18256)). ([57d4c3d0](https://github.com/firebase/flutterfire/commit/57d4c3d050c6a9252390de6cac91a0ca1d5461e3)) + ## 16.2.0 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index 9267bfe5b016..e3f27781122b 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_messaging: ^16.2.0 + firebase_core: ^4.8.0 + firebase_messaging: ^16.2.1 flutter: sdk: flutter flutter_local_notifications: ^21.0.0 diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index d2437be8e0d4..5245529c3964 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "16.2.0" +let library_version = "16.2.1" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index ef733d6db96e..27acb5f1aec8 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "16.2.0" +let library_version = "16.2.1" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_messaging/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/pubspec.yaml index bb4dde6df918..005f97357ba3 100644 --- a/packages/firebase_messaging/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. homepage: https://firebase.google.com/docs/cloud-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging -version: 16.2.0 +version: 16.2.1 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_messaging_platform_interface: ^4.7.9 - firebase_messaging_web: ^4.1.5 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_messaging_platform_interface: ^4.7.10 + firebase_messaging_web: ^4.1.6 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md index fdb475681a53..d63d0305f0e2 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.7.10 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 4.7.9 - Update a dependency to the latest release. diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml index 521baf09d46f..1829c1d35016 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_messaging_platform_interface description: A common platform interface for the firebase_messaging plugin. -version: 4.7.9 +version: 4.7.10 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md index be3ecee9e433..7f6cf8d3836f 100644 --- a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.1.6 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 4.1.5 - Update a dependency to the latest release. diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart index 899437d9741e..30f33f23d51b 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '16.2.0'; +const packageVersion = '16.2.1'; diff --git a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml index 6eccf69632b1..790777421307 100644 --- a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_messaging_web description: The web implementation of firebase_messaging homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web -version: 4.1.5 +version: 4.1.6 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 - firebase_messaging_platform_interface: ^4.7.9 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 + firebase_messaging_platform_interface: ^4.7.10 flutter: sdk: flutter flutter_web_plugins: @@ -22,7 +22,7 @@ dependencies: web: ^1.0.0 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md index c2e2912265ec..c7d5e7b1dea2 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+1 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.4.2 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml index 490a03e093b5..d24b983c5859 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml @@ -12,8 +12,8 @@ dependencies: flutter: sdk: flutter - firebase_core: ^4.7.0 - firebase_ml_model_downloader: ^0.4.2 + firebase_core: ^4.8.0 + firebase_ml_model_downloader: ^0.4.2+1 dev_dependencies: flutter_lints: ^6.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift index c42bec0ea728..8f7df3f775de 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2" +public let versionNumber = "0.4.2+1" diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml index a7b6a5179b6a..94fb4379a76f 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader description: A Flutter plugin allowing you to use Firebase Ml Model Downloader. -version: 0.4.2 +version: 0.4.2+1 resolution: workspace homepage: https://firebase.google.com/docs/ml/flutter/use-custom-models repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_ml_model_downloader_platform_interface: ^0.1.5+20 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_ml_model_downloader_platform_interface: ^0.1.5+21 flutter: sdk: flutter diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md index fd0c566e7b3d..2b2d8ac9ece3 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5+21 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.1.5+20 - Update a dependency to the latest release. diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml index 5432ad28b54f..73a421853c29 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader_platform_interface description: A common platform interface for the firebase_ml_model_downloader plugin. -version: 0.1.5+20 +version: 0.1.5+21 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface @@ -10,14 +10,14 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_performance/firebase_performance/CHANGELOG.md b/packages/firebase_performance/firebase_performance/CHANGELOG.md index 3ffd44a59aa2..39fd330bd8cd 100644 --- a/packages/firebase_performance/firebase_performance/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.11.4 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 0.11.3 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_performance/firebase_performance/example/pubspec.yaml b/packages/firebase_performance/firebase_performance/example/pubspec.yaml index 7a6a39df8464..01262bf06925 100644 --- a/packages/firebase_performance/firebase_performance/example/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_performance: ^0.11.3 + firebase_core: ^4.8.0 + firebase_performance: ^0.11.4 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index 2d2e38300e95..dd45395cbeb5 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "0.11.3" +let library_version = "0.11.4" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_performance/firebase_performance/pubspec.yaml b/packages/firebase_performance/firebase_performance/pubspec.yaml index 38235f916862..d00f83fad50a 100644 --- a/packages/firebase_performance/firebase_performance/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/pubspec.yaml @@ -5,7 +5,7 @@ description: iOS. homepage: https://firebase.google.com/docs/perf-mon repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance -version: 0.11.3 +version: 0.11.4 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_performance_platform_interface: ^0.1.6+7 - firebase_performance_web: ^0.1.8+5 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_performance_platform_interface: ^0.2.0 + firebase_performance_web: ^0.1.8+6 flutter: sdk: flutter diff --git a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md index 8a1cb17de7f6..be86c62982c0 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.2.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 0.1.6+7 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml index 1c05ce9f9922..67185d59caeb 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_performance_platform_interface description: A common platform interface for the firebase_performance plugin. -version: 0.1.6+7 +version: 0.2.0 resolution: workspace homepage: https://firebase.google.com/docs/perf-mon/flutter/get-started @@ -9,15 +9,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter pigeon: 26.3.4 diff --git a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md index 5da573cb1599..a2b343801e1a 100644 --- a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8+6 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 0.1.8+5 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart index c304601e8f7e..17f8049e2aa0 100644 --- a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart +++ b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.11.3'; +const packageVersion = '0.11.4'; diff --git a/packages/firebase_performance/firebase_performance_web/pubspec.yaml b/packages/firebase_performance/firebase_performance_web/pubspec.yaml index 5f05047fb955..0caf6aabcf3d 100644 --- a/packages/firebase_performance/firebase_performance_web/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_performance_web description: Web implementation of Firebase Performance monitoring. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance_web -version: 0.1.8+5 +version: 0.1.8+6 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 - firebase_performance_platform_interface: ^0.1.6+7 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 + firebase_performance_platform_interface: ^0.2.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md index 8be436bad143..3219f977058e 100644 --- a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.5.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 6.4.0 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml index dd7142cae56d..71af9409acba 100644 --- a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - firebase_core: ^4.7.0 - firebase_remote_config: ^6.4.0 + firebase_core: ^4.8.0 + firebase_remote_config: ^6.5.0 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift index 2f534d106ebb..5a837434e329 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.4.0" +public let versionNumber = "6.5.0" diff --git a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml index 03fde1effae9..48c8071b28a5 100644 --- a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml @@ -4,7 +4,7 @@ description: re-releasing. homepage: https://firebase.google.com/docs/remote-config repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config -version: 6.4.0 +version: 6.5.0 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_remote_config_platform_interface: ^2.1.2 - firebase_remote_config_web: ^1.10.6 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_remote_config_platform_interface: ^3.0.0 + firebase_remote_config_web: ^1.10.7 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md index 733346173ce6..d849152f4186 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 3.0.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 2.1.2 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml index bdfc92477bcb..2c659113ac2d 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_re repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.1.2 +version: 3.0.0 resolution: workspace environment: @@ -12,15 +12,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md index ad098bfdaaf4..e742e715d482 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.7 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 1.10.6 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart index 14d87311cbb9..200e74209d4f 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart +++ b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.4.0'; +const packageVersion = '6.5.0'; diff --git a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml index 2dd930886ada..68f38544d062 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of firebase_remote_config homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web -version: 1.10.6 +version: 1.10.7 resolution: workspace environment: @@ -11,10 +11,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 - firebase_remote_config_platform_interface: ^2.1.2 + _flutterfire_internals: ^1.3.70 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 + firebase_remote_config_platform_interface: ^3.0.0 flutter: sdk: flutter flutter_web_plugins: @@ -22,7 +22,7 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_storage/firebase_storage/CHANGELOG.md b/packages/firebase_storage/firebase_storage/CHANGELOG.md index f784862e4914..a48265682153 100644 --- a/packages/firebase_storage/firebase_storage/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage/CHANGELOG.md @@ -1,3 +1,9 @@ +## 13.4.0 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FIX**(storage,android): fix an issue that could happen when app would get detached from the engine ([#18255](https://github.com/firebase/flutterfire/issues/18255)). ([2771f550](https://github.com/firebase/flutterfire/commit/2771f5505ff0a53cc1bfb41afec3a0eb8781b8f8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 13.3.0 - **FEAT**: use local firebase_core instead of remote SPM dependency ([#18141](https://github.com/firebase/flutterfire/issues/18141)). ([995caf40](https://github.com/firebase/flutterfire/commit/995caf400df80c0fde7151c651ccc6c0f756e381)) diff --git a/packages/firebase_storage/firebase_storage/example/pubspec.yaml b/packages/firebase_storage/firebase_storage/example/pubspec.yaml index 4ea05ff58543..44bb6f5cf703 100755 --- a/packages/firebase_storage/firebase_storage/example/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_storage: ^13.3.0 + firebase_core: ^4.8.0 + firebase_storage: ^13.4.0 flutter: sdk: flutter image_picker: ^1.1.2 diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index c07526924658..0fda05565ba4 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "13.3.0" +let library_version = "13.4.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index f93b1007f6fd..5569aa97d60c 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let library_version = "13.3.0" +let library_version = "13.4.0" let firebase_sdk_version: Version = "12.12.0" let package = Package( diff --git a/packages/firebase_storage/firebase_storage/pubspec.yaml b/packages/firebase_storage/firebase_storage/pubspec.yaml index d5dd4d27365b..a698bdd04c9d 100755 --- a/packages/firebase_storage/firebase_storage/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS. homepage: https://firebase.google.com/docs/storage/flutter/start repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage -version: 13.3.0 +version: 13.4.0 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_storage_platform_interface: ^5.2.20 - firebase_storage_web: ^3.11.5 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_storage_platform_interface: ^6.0.0 + firebase_storage_web: ^3.11.6 flutter: sdk: flutter mime: ^2.0.0 diff --git a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md index 119baabc56a3..9008299eb1e2 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 6.0.0 + + - Bump platform interface a major version due to pigeon dependency update + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + - **FEAT**: upgrade pigeon to version 26.3.4 ([#18205](https://github.com/firebase/flutterfire/issues/18205)). ([cb6b4aef](https://github.com/firebase/flutterfire/commit/cb6b4aeffc568755ea3eebe32b998f00237bf5ad)) + ## 5.2.20 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml index 54ef0c506483..1041d449a45c 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_storage_platform_interface description: A common platform interface for the firebase_storage plugin. -version: 5.2.20 +version: 6.0.0 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.69 + _flutterfire_internals: ^1.3.70 collection: ^1.15.0 - firebase_core: ^4.7.0 + firebase_core: ^4.8.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md index b88403e0f1f0..fb520c0cea23 100644 --- a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.11.6 + + - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) + ## 3.11.5 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart index f4d489e96af4..bf42ef7f07b7 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '13.3.0'; +const packageVersion = '13.4.0'; diff --git a/packages/firebase_storage/firebase_storage_web/pubspec.yaml b/packages/firebase_storage/firebase_storage_web/pubspec.yaml index 8b1421809455..b04c7bebe487 100644 --- a/packages/firebase_storage/firebase_storage_web/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_storage_web description: The web implementation of firebase_storage homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web -version: 3.11.5 +version: 3.11.6 resolution: workspace environment: @@ -10,11 +10,11 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.69 + _flutterfire_internals: ^1.3.70 async: ^2.5.0 - firebase_core: ^4.7.0 - firebase_core_web: ^3.6.0 - firebase_storage_platform_interface: ^5.2.20 + firebase_core: ^4.8.0 + firebase_core_web: ^3.6.1 + firebase_storage_platform_interface: ^6.0.0 flutter: sdk: flutter flutter_web_plugins: @@ -24,7 +24,7 @@ dependencies: web: ^1.0.0 dev_dependencies: - firebase_core_platform_interface: ^6.0.3 + firebase_core_platform_interface: ^7.0.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/pubspec.yaml b/pubspec.yaml index ff846f40a643..a88ddd10eb19 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -97,8 +97,6 @@ melos: dart run scripts/generate_versions_web.dart && \ dart run scripts/generate_versions_spm.dart && \ git add packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart && git add packages/*/*_web/lib/src/*_version.dart && git add packages/*/*/ios/*/Package.swift packages/*/*/macos/*/Package.swift && git add packages/*/*/ios/*/Sources/*/Constants.swift - post: | - dart run scripts/generate_tag_spm_firebase_core.dart bootstrap: # It seems so that running "pub get" in parallel has some issues (like diff --git a/scripts/versions.json b/scripts/versions.json index d5ffa2901f0f..86184bf473f3 100644 --- a/scripts/versions.json +++ b/scripts/versions.json @@ -1,4 +1,32 @@ { + "4.13.0": { + "date": "2026-05-11", + "firebase_sdk": { + "android": "34.12.0", + "ios": "12.12.0", + "web": "12.12.0", + "windows": "13.5.0" + }, + "packages": { + "cloud_firestore": "6.4.0", + "cloud_functions": "6.3.0", + "firebase_ai": "3.12.0", + "firebase_analytics": "12.4.0", + "firebase_app_check": "0.4.4", + "firebase_app_installations": "0.4.2+1", + "firebase_auth": "6.5.0", + "firebase_core": "4.8.0", + "firebase_crashlytics": "5.2.1", + "firebase_data_connect": "0.3.0+1", + "firebase_database": "12.4.0", + "firebase_in_app_messaging": "0.9.2+1", + "firebase_messaging": "16.2.1", + "firebase_ml_model_downloader": "0.4.2+1", + "firebase_performance": "0.11.4", + "firebase_remote_config": "6.5.0", + "firebase_storage": "13.4.0" + } + }, "4.12.0": { "date": "2026-04-13", "firebase_sdk": { diff --git a/tests/pubspec.yaml b/tests/pubspec.yaml index a5d91e69def6..334e9463b8de 100644 --- a/tests/pubspec.yaml +++ b/tests/pubspec.yaml @@ -10,43 +10,43 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions: ^6.2.0 - cloud_functions_platform_interface: ^5.8.12 - cloud_functions_web: ^5.1.5 + cloud_functions: ^6.3.0 + cloud_functions_platform_interface: ^6.0.0 + cloud_functions_web: ^5.1.6 collection: ^1.15.0 - firebase_ai: ^3.11.0 - firebase_analytics: ^12.3.0 - firebase_analytics_platform_interface: ^5.1.1 - firebase_analytics_web: ^0.6.1+5 - firebase_app_check: ^0.4.3 - firebase_app_check_platform_interface: ^0.3.0 - firebase_app_check_web: ^0.2.4 - firebase_app_installations: ^0.4.2 - firebase_app_installations_platform_interface: ^0.1.4+68 - firebase_app_installations_web: ^0.1.7+5 - firebase_auth: ^6.4.0 - firebase_auth_platform_interface: ^8.1.9 - firebase_auth_web: ^6.1.5 - firebase_core: ^4.7.0 - firebase_core_platform_interface: ^6.0.3 - firebase_core_web: ^3.6.0 - firebase_crashlytics: ^5.2.0 - firebase_crashlytics_platform_interface: ^3.8.20 - firebase_database: ^12.3.0 - firebase_database_platform_interface: ^0.3.1+1 - firebase_database_web: ^0.2.7+6 - firebase_messaging: ^16.2.0 - firebase_messaging_platform_interface: ^4.7.9 - firebase_messaging_web: ^4.1.5 - firebase_ml_model_downloader: ^0.4.2 - firebase_ml_model_downloader_platform_interface: ^0.1.5+20 - firebase_performance: ^0.11.3 - firebase_remote_config: ^6.4.0 - firebase_remote_config_platform_interface: ^2.1.2 - firebase_remote_config_web: ^1.10.6 - firebase_storage: ^13.3.0 - firebase_storage_platform_interface: ^5.2.20 - firebase_storage_web: ^3.11.5 + firebase_ai: ^3.12.0 + firebase_analytics: ^12.4.0 + firebase_analytics_platform_interface: ^6.0.0 + firebase_analytics_web: ^0.6.1+6 + firebase_app_check: ^0.4.4 + firebase_app_check_platform_interface: ^0.4.0 + firebase_app_check_web: ^0.2.4+1 + firebase_app_installations: ^0.4.2+1 + firebase_app_installations_platform_interface: ^0.1.4+69 + firebase_app_installations_web: ^0.1.7+6 + firebase_auth: ^6.5.0 + firebase_auth_platform_interface: ^9.0.0 + firebase_auth_web: ^6.2.0 + firebase_core: ^4.8.0 + firebase_core_platform_interface: ^7.0.0 + firebase_core_web: ^3.6.1 + firebase_crashlytics: ^5.2.1 + firebase_crashlytics_platform_interface: ^3.8.21 + firebase_database: ^12.4.0 + firebase_database_platform_interface: ^0.4.0 + firebase_database_web: ^0.2.7+7 + firebase_messaging: ^16.2.1 + firebase_messaging_platform_interface: ^4.7.10 + firebase_messaging_web: ^4.1.6 + firebase_ml_model_downloader: ^0.4.2+1 + firebase_ml_model_downloader_platform_interface: ^0.1.5+21 + firebase_performance: ^0.11.4 + firebase_remote_config: ^6.5.0 + firebase_remote_config_platform_interface: ^3.0.0 + firebase_remote_config_web: ^1.10.7 + firebase_storage: ^13.4.0 + firebase_storage_platform_interface: ^6.0.0 + firebase_storage_web: ^3.11.6 flutter: sdk: flutter http: ^1.0.0 From 67e3f899d48884d60195e846c0008272c8cb1e3c Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 13 May 2026 12:27:52 -0700 Subject: [PATCH 072/137] chore(firebaseai): update sample model name (#18278) --- .../example/android/settings.gradle.kts | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 95 ------------------- .../xcshareddata/xcschemes/Runner.xcscheme | 2 + .../firebase_ai/example/lib/main.dart | 7 +- .../example/lib/pages/chat_page.dart | 6 +- .../lib/pages/function_calling_page.dart | 17 ++-- .../example/lib/pages/grounding_page.dart | 7 +- .../macos/Runner.xcodeproj/project.pbxproj | 87 ++++++++--------- .../firebase_ai/example/pubspec.yaml | 2 +- 9 files changed, 68 insertions(+), 157 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/example/android/settings.gradle.kts b/packages/firebase_ai/firebase_ai/example/android/settings.gradle.kts index ab39a10a29ba..43394ed5e1fd 100644 --- a/packages/firebase_ai/firebase_ai/example/android/settings.gradle.kts +++ b/packages/firebase_ai/firebase_ai/example/android/settings.gradle.kts @@ -18,7 +18,7 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.7.3" apply false + id("com.android.application") version "8.9.1" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false } diff --git a/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj index 2552246e5d98..550a5b9c22a6 100644 --- a/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/project.pbxproj @@ -13,11 +13,9 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - 901FEC83A38129064032C578 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94CE5BFCDF90764354BB6740 /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - B7B3CA2D70F15615E1B8E5D8 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 154D9627A1C14A5ACE0B7B0D /* Pods_RunnerTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -46,12 +44,9 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 154D9627A1C14A5ACE0B7B0D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 232D95ECCEC6F04B9CEC8925 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 560CA017EC76D8AAE2E21549 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 5F1FA05866A2D0FCA3287B20 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -59,8 +54,6 @@ 78DABEA22ED26510000E7860 /* firebase_ai */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = firebase_ai; path = ../../ios/firebase_ai; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8ACDC47C7E9AF1A1B9595598 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 94CE5BFCDF90764354BB6740 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -68,9 +61,6 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A85D07EF8959748E1D3E564B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - B0B22A9E291076BD22BA9F10 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - E1D0571EA0792087F8F27457 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -78,7 +68,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B7B3CA2D70F15615E1B8E5D8 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -87,7 +76,6 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, - 901FEC83A38129064032C578 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -105,12 +93,6 @@ 3C3B3E8596675CC144D1BD5B /* Pods */ = { isa = PBXGroup; children = ( - E1D0571EA0792087F8F27457 /* Pods-Runner.debug.xcconfig */, - 232D95ECCEC6F04B9CEC8925 /* Pods-Runner.release.xcconfig */, - 560CA017EC76D8AAE2E21549 /* Pods-Runner.profile.xcconfig */, - A85D07EF8959748E1D3E564B /* Pods-RunnerTests.debug.xcconfig */, - 8ACDC47C7E9AF1A1B9595598 /* Pods-RunnerTests.release.xcconfig */, - B0B22A9E291076BD22BA9F10 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -138,7 +120,6 @@ 331C8082294A63A400263BE5 /* RunnerTests */, 5F1FA05866A2D0FCA3287B20 /* GoogleService-Info.plist */, 3C3B3E8596675CC144D1BD5B /* Pods */, - A50BECFB61A452F592070BAA /* Frameworks */, ); sourceTree = ""; }; @@ -166,15 +147,6 @@ path = Runner; sourceTree = ""; }; - A50BECFB61A452F592070BAA /* Frameworks */ = { - isa = PBXGroup; - children = ( - 94CE5BFCDF90764354BB6740 /* Pods_Runner.framework */, - 154D9627A1C14A5ACE0B7B0D /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -182,7 +154,6 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - F5C7CFE0E232B64D613F0623 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, 0F5F3CD1ED7DB09B81C92173 /* Frameworks */, @@ -201,14 +172,12 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 65E1413F3D5F0EF9AF4CD1AB /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 7C03669E7720256A458F4A2F /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -303,45 +272,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 65E1413F3D5F0EF9AF4CD1AB /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 7C03669E7720256A458F4A2F /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -357,28 +287,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - F5C7CFE0E232B64D613F0623 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -505,7 +413,6 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A85D07EF8959748E1D3E564B /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -523,7 +430,6 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8ACDC47C7E9AF1A1B9595598 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -539,7 +445,6 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B0B22A9E291076BD22BA9F10 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 8178cd1c619c..037ec0f249ad 100644 --- a/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/firebase_ai/firebase_ai/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -44,6 +44,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> { void _initializeModel(bool useVertexBackend) { if (useVertexBackend) { - final vertexInstance = FirebaseAI.vertexAI(); - _currentModel = vertexInstance.generativeModel(model: 'gemini-2.5-flash'); + final vertexInstance = FirebaseAI.vertexAI(location: 'global'); + _currentModel = + vertexInstance.generativeModel(model: 'gemini-3.1-flash-lite'); } else { final googleAI = FirebaseAI.googleAI(); - _currentModel = googleAI.generativeModel(model: 'gemini-2.5-flash'); + _currentModel = googleAI.generativeModel(model: 'gemini-3.1-flash-lite'); } } diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart index 5a37a78e9903..5eb1ee91a4a8 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart @@ -56,13 +56,13 @@ class _ChatPageState extends State { : null, ); if (widget.useVertexBackend) { - _model = FirebaseAI.vertexAI().generativeModel( - model: 'gemini-2.5-flash', + _model = FirebaseAI.vertexAI(location: 'global').generativeModel( + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, ); } else { _model = FirebaseAI.googleAI().generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, ); } diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart index 64c5b39ad9b4..b6db853772ee 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/function_calling_page.dart @@ -235,25 +235,26 @@ class _FunctionCallingPageState extends State { : null, ); - final aiClient = - widget.useVertexBackend ? FirebaseAI.vertexAI() : FirebaseAI.googleAI(); + final aiClient = widget.useVertexBackend + ? FirebaseAI.vertexAI(location: 'global') + : FirebaseAI.googleAI(); _functionCallModel = aiClient.generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, tools: [ Tool.functionDeclarations([fetchWeatherTool]), ], ); _autoFunctionCallModel = aiClient.generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, tools: [ Tool.functionDeclarations([_autoFetchWeatherTool]), ], ); _parallelAutoFunctionCallModel = aiClient.generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, tools: [ Tool.functionDeclarations( @@ -262,21 +263,21 @@ class _FunctionCallingPageState extends State { ], ); _codeExecutionModel = aiClient.generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, tools: [ Tool.codeExecution(), ], ); _complexSchemaModel = aiClient.generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, tools: [ Tool.functionDeclarations([_autoPlanVacationTool]), ], ); _refDefJsonSchemaModel = aiClient.generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', generationConfig: generationConfig, tools: [ Tool.functionDeclarations([_autoProcessTransactionTool]), diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart index e895e51c14cd..6c5aad8fb6e0 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/grounding_page.dart @@ -73,11 +73,12 @@ class _GroundingPageState extends State { } } - final aiProvider = - widget.useVertexBackend ? FirebaseAI.vertexAI() : FirebaseAI.googleAI(); + final aiProvider = widget.useVertexBackend + ? FirebaseAI.vertexAI(location: 'global') + : FirebaseAI.googleAI(); _model = aiProvider.generativeModel( - model: 'gemini-2.5-flash', + model: 'gemini-3.1-flash-lite', tools: tools.isNotEmpty ? tools : null, toolConfig: toolConfig, ); diff --git a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj index 9a68c0a44f3c..ec242319b9f2 100644 --- a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,7 +21,6 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 1E1464098F5197FB1E35FDA1 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E05DB31CC6D204C7C78D127 /* Pods_RunnerTests.framework */; }; 20C13FC2C906153EF4A40292 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */; }; 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; @@ -29,8 +28,9 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 3D1CF19370CB8E26E5C667A5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */; }; + 6082D6A2424808FAB6E3B40E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F13D669ACC8FC703D4CBD2B /* Pods_RunnerTests.framework */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; + BA2210317853BF792876863E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BDA2E1C29AC310A4E4CA25D /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -64,8 +64,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 04B3ABBBAF38CA994D530720 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; - 0E05DB31CC6D204C7C78D127 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; @@ -82,18 +82,18 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 3A40C9AE19ACEC6C433878E9 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 766A2E414AFDFA56243527A6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 6BDA2E1C29AC310A4E4CA25D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* firebase_ai */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = firebase_ai; path = ../../macos/firebase_ai; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; + 78E1BE5D41B29A94BA269C92 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 816B0EE72BF94FC5261D04E6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 7C0CE262A0120B333635758B /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 8F13D669ACC8FC703D4CBD2B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A2911B8EF91B3925874FDE6A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; - 78DABEA22ED26510000E7860 /* firebase_ai */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = firebase_ai; path = ../../macos/firebase_ai; sourceTree = ""; }; + A0F3F679E482301241F3BFCA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + D93CB9EA3E846CDBCE7957C5 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + FD6782CE9C57EE952FDAD106 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,7 +101,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1E1464098F5197FB1E35FDA1 /* Pods_RunnerTests.framework in Frameworks */, + 6082D6A2424808FAB6E3B40E /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -110,7 +110,7 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, - 3D1CF19370CB8E26E5C667A5 /* Pods_Runner.framework in Frameworks */, + BA2210317853BF792876863E /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -143,9 +143,9 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */, BE277C424FC00920BE07E371 /* Pods */, + F8E2296ED7CFF382BC7C9532 /* Frameworks */, ); sourceTree = ""; }; @@ -199,21 +199,21 @@ BE277C424FC00920BE07E371 /* Pods */ = { isa = PBXGroup; children = ( - A2911B8EF91B3925874FDE6A /* Pods-Runner.debug.xcconfig */, - 816B0EE72BF94FC5261D04E6 /* Pods-Runner.release.xcconfig */, - 766A2E414AFDFA56243527A6 /* Pods-Runner.profile.xcconfig */, - 3A40C9AE19ACEC6C433878E9 /* Pods-RunnerTests.debug.xcconfig */, - 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */, - 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */, + FD6782CE9C57EE952FDAD106 /* Pods-Runner.debug.xcconfig */, + 04B3ABBBAF38CA994D530720 /* Pods-Runner.release.xcconfig */, + D93CB9EA3E846CDBCE7957C5 /* Pods-Runner.profile.xcconfig */, + A0F3F679E482301241F3BFCA /* Pods-RunnerTests.debug.xcconfig */, + 7C0CE262A0120B333635758B /* Pods-RunnerTests.release.xcconfig */, + 78E1BE5D41B29A94BA269C92 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { + F8E2296ED7CFF382BC7C9532 /* Frameworks */ = { isa = PBXGroup; children = ( - C4DAA18FE8B79A454BF3F8CB /* Pods_Runner.framework */, - 0E05DB31CC6D204C7C78D127 /* Pods_RunnerTests.framework */, + 6BDA2E1C29AC310A4E4CA25D /* Pods_Runner.framework */, + 8F13D669ACC8FC703D4CBD2B /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -225,7 +225,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 33B83C0D35C3606AED8215FE /* [CP] Check Pods Manifest.lock */, + 6E1E43E2156EDE8E42E46577 /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -244,13 +244,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 606AE4A9031C7C91EFF70994 /* [CP] Check Pods Manifest.lock */, + 0669F8635DD580A741D5C18E /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - 7035891EAAFF34285DDE160B /* [CP] Embed Pods Frameworks */, + D3CB4FECFB8507DF5BD41289 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -340,45 +340,45 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { + 0669F8635DD580A741D5C18E /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 33B83C0D35C3606AED8215FE /* [CP] Check Pods Manifest.lock */ = { + 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", ); - name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; }; 33CC111E2044C6BF0003C045 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -400,7 +400,7 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - 606AE4A9031C7C91EFF70994 /* [CP] Check Pods Manifest.lock */ = { + 6E1E43E2156EDE8E42E46577 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -415,14 +415,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 7035891EAAFF34285DDE160B /* [CP] Embed Pods Frameworks */ = { + D3CB4FECFB8507DF5BD41289 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -490,7 +490,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3A40C9AE19ACEC6C433878E9 /* Pods-RunnerTests.debug.xcconfig */; + baseConfigurationReference = A0F3F679E482301241F3BFCA /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -505,7 +505,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 587C61AFC0E2B0BF5340F8E8 /* Pods-RunnerTests.release.xcconfig */; + baseConfigurationReference = 7C0CE262A0120B333635758B /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -520,7 +520,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5C2B5E4F1CE100E1FA5D9DC5 /* Pods-RunnerTests.profile.xcconfig */; + baseConfigurationReference = 78E1BE5D41B29A94BA269C92 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -661,6 +661,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index 648f43a91b85..7c9021d8537e 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -31,7 +31,7 @@ dependencies: sdk: flutter flutter_animate: ^4.5.2 flutter_markdown: ^0.7.7+1 - flutter_soloud: ^4.0.2 + flutter_soloud: ^4.0.4 image: ^4.5.4 image_picker: ^1.1.2 path_provider: ^2.1.5 From bb8ad546f114146b6e1cd26c3296825e2964745d Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 14 May 2026 08:03:10 +0000 Subject: [PATCH 073/137] feat: bump Firebase JS SDK to 12.13.0 (#18274) --- .../firebase_core_web/lib/src/firebase_sdk_version.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart index 34c5c064adbb..8c12876e746e 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart @@ -6,4 +6,4 @@ part of '../firebase_core_web.dart'; /// The currently supported Firebase JS SDK version. -const String supportedFirebaseJsSdkVersion = '12.12.0'; +const String supportedFirebaseJsSdkVersion = '12.13.0'; From d10e0ffa2980a21a5899dbe67952fc772a3c6c01 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 14 May 2026 08:05:41 +0000 Subject: [PATCH 074/137] feat: bump Firebase android SDK to 34.13.0 (#18272) --- packages/firebase_core/firebase_core/android/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/android/gradle.properties b/packages/firebase_core/firebase_core/android/gradle.properties index 2c89565e4791..106ae63448c0 100644 --- a/packages/firebase_core/firebase_core/android/gradle.properties +++ b/packages/firebase_core/firebase_core/android/gradle.properties @@ -1,2 +1,2 @@ # https://firebase.google.com/support/release-notes/android -FirebaseSDKVersion=34.12.0 +FirebaseSDKVersion=34.13.0 From 78e10f0222f4e23c96b636c63c29935ba5aa82e6 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 14 May 2026 08:06:12 +0000 Subject: [PATCH 075/137] feat: bump Firebase iOS SDK to 12.13.0 (#18273) --- .../firebase_core/firebase_core/ios/firebase_sdk_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb index c354b3b9dd54..3a861fb77b73 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb +++ b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb @@ -1,4 +1,4 @@ # https://firebase.google.com/support/release-notes/ios def firebase_sdk_version!() - '12.12.0' + '12.13.0' end From 7c1257e7295f9ba67f3f5820493f105a14d34d52 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 14 May 2026 09:04:12 +0000 Subject: [PATCH 076/137] fix(core, iOS): use namespaced iOS Pigeon header import (#18281) --- .../ios/firebase_core/Sources/firebase_core/messages.g.m | 2 +- .../firebase_core_platform_interface/pigeons/messages.dart | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m index c0d58e28a6f3..b1a0a1e69e45 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m @@ -4,7 +4,7 @@ // Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -#import "messages.g.h" +#import "include/firebase_core/messages.g.h" #if TARGET_OS_OSX @import FlutterMacOS; diff --git a/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart b/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart index 977270c87dc1..a2286f54f1a9 100644 --- a/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart +++ b/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart @@ -19,6 +19,9 @@ import 'package:pigeon/pigeon.dart'; '../firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h', objcSourceOut: '../firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m', + objcOptions: ObjcOptions( + headerIncludePath: 'include/firebase_core/messages.g.h', + ), cppHeaderOut: '../firebase_core/windows/messages.g.h', cppSourceOut: '../firebase_core/windows/messages.g.cpp', cppOptions: CppOptions(namespace: 'firebase_core_windows'), From 2f84e3b1f6fca7d930b8f8a22f4f5ed34ec6f186 Mon Sep 17 00:00:00 2001 From: Russell Wheatley Date: Thu, 14 May 2026 12:26:11 +0100 Subject: [PATCH 077/137] chore(release): publish packages (#18285) --- CHANGELOG.md | 122 ++++++++++++++++++ VERSIONS.md | 38 ++++++ packages/_flutterfire_internals/CHANGELOG.md | 4 + packages/_flutterfire_internals/pubspec.yaml | 6 +- .../cloud_firestore/CHANGELOG.md | 4 + .../cloud_firestore/example/pubspec.yaml | 4 +- .../ios/cloud_firestore/Package.swift | 4 +- .../macos/cloud_firestore/Package.swift | 4 +- .../pipeline_example/pubspec.yaml | 2 +- .../cloud_firestore/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../cloud_firestore_web/CHANGELOG.md | 4 + .../lib/src/cloud_firestore_version.dart | 2 +- .../cloud_firestore_web/pubspec.yaml | 12 +- .../cloud_functions/CHANGELOG.md | 4 + .../cloud_functions/example/pubspec.yaml | 4 +- .../ios/cloud_functions/Package.swift | 2 +- .../Sources/cloud_functions/Constants.swift | 2 +- .../macos/cloud_functions/Package.swift | 2 +- .../cloud_functions/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../cloud_functions_web/CHANGELOG.md | 4 + .../lib/src/cloud_functions_version.dart | 2 +- .../cloud_functions_web/pubspec.yaml | 10 +- packages/firebase_ai/firebase_ai/CHANGELOG.md | 4 + .../firebase_ai/example/pubspec.yaml | 6 +- .../lib/src/firebaseai_version.dart | 2 +- packages/firebase_ai/firebase_ai/pubspec.yaml | 10 +- .../firebase_analytics/CHANGELOG.md | 4 + .../firebase_analytics/example/pubspec.yaml | 4 +- .../ios/firebase_analytics/Package.swift | 2 +- .../macos/firebase_analytics/Package.swift | 2 +- .../firebase_analytics/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_analytics_web/CHANGELOG.md | 4 + .../lib/src/firebase_analytics_version.dart | 2 +- .../firebase_analytics_web/pubspec.yaml | 10 +- .../firebase_app_check/CHANGELOG.md | 4 + .../firebase_app_check/example/pubspec.yaml | 6 +- .../ios/firebase_app_check/Package.swift | 2 +- .../firebase_app_check/Constants.swift | 2 +- .../macos/firebase_app_check/Package.swift | 2 +- .../firebase_app_check/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_app_check_web/CHANGELOG.md | 4 + .../lib/src/firebase_app_check_version.dart | 2 +- .../firebase_app_check_web/pubspec.yaml | 12 +- .../firebase_app_installations/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../firebase_app_installations/Package.swift | 2 +- .../Constants.swift | 2 +- .../firebase_app_installations/Package.swift | 2 +- .../firebase_app_installations/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../firebase_app_installations_version.dart | 2 +- .../pubspec.yaml | 12 +- .../firebase_auth/firebase_auth/CHANGELOG.md | 4 + .../firebase_auth/example/pubspec.yaml | 6 +- .../ios/firebase_auth/Package.swift | 4 +- .../macos/firebase_auth/Package.swift | 4 +- .../firebase_auth/firebase_auth/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_auth_web/CHANGELOG.md | 4 + .../lib/src/firebase_auth_version.dart | 2 +- .../firebase_auth_web/pubspec.yaml | 8 +- .../firebase_core/firebase_core/CHANGELOG.md | 6 + .../firebase_core/example/pubspec.yaml | 2 +- .../ios/firebase_core/Package.swift | 4 +- .../macos/firebase_core/Package.swift | 4 +- .../firebase_core/firebase_core/pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 2 +- .../firebase_core_web/CHANGELOG.md | 4 + .../lib/src/firebase_core_version.dart | 2 +- .../firebase_core_web/pubspec.yaml | 4 +- .../firebase_crashlytics/CHANGELOG.md | 4 + .../firebase_crashlytics/example/pubspec.yaml | 6 +- .../ios/firebase_crashlytics/Package.swift | 4 +- .../macos/firebase_crashlytics/Package.swift | 4 +- .../firebase_crashlytics/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_data_connect/CHANGELOG.md | 4 + .../example/pubspec.yaml | 6 +- .../lib/src/dataconnect_version.dart | 2 +- .../firebase_data_connect/pubspec.yaml | 14 +- .../firebase_database/CHANGELOG.md | 4 + .../firebase_database/example/pubspec.yaml | 4 +- .../ios/firebase_database/Package.swift | 4 +- .../macos/firebase_database/Package.swift | 4 +- .../firebase_database/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_database_web/CHANGELOG.md | 4 + .../lib/src/firebase_database_version.dart | 2 +- .../firebase_database_web/pubspec.yaml | 10 +- .../firebase_in_app_messaging/CHANGELOG.md | 4 + .../example/pubspec.yaml | 8 +- .../firebase_in_app_messaging/Package.swift | 4 +- .../firebase_in_app_messaging/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_messaging/CHANGELOG.md | 4 + .../firebase_messaging/example/pubspec.yaml | 4 +- .../ios/firebase_messaging/Package.swift | 4 +- .../macos/firebase_messaging/Package.swift | 4 +- .../firebase_messaging/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_messaging_web/CHANGELOG.md | 4 + .../lib/src/firebase_messaging_version.dart | 2 +- .../firebase_messaging_web/pubspec.yaml | 12 +- .../firebase_ml_model_downloader/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../Package.swift | 2 +- .../Constants.swift | 2 +- .../Package.swift | 2 +- .../firebase_ml_model_downloader/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_performance/CHANGELOG.md | 4 + .../firebase_performance/example/pubspec.yaml | 4 +- .../ios/firebase_performance/Package.swift | 4 +- .../firebase_performance/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_performance_web/CHANGELOG.md | 4 + .../lib/src/firebase_performance_version.dart | 2 +- .../firebase_performance_web/pubspec.yaml | 10 +- .../firebase_remote_config/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../ios/firebase_remote_config/Package.swift | 2 +- .../firebase_remote_config/Constants.swift | 2 +- .../firebase_remote_config/Package.swift | 2 +- .../firebase_remote_config/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_remote_config_web/CHANGELOG.md | 4 + .../src/firebase_remote_config_version.dart | 2 +- .../firebase_remote_config_web/pubspec.yaml | 12 +- .../firebase_storage/CHANGELOG.md | 4 + .../firebase_storage/example/pubspec.yaml | 4 +- .../ios/firebase_storage/Package.swift | 4 +- .../macos/firebase_storage/Package.swift | 4 +- .../firebase_storage/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_storage_web/CHANGELOG.md | 4 + .../lib/src/firebase_storage_version.dart | 2 +- .../firebase_storage_web/pubspec.yaml | 12 +- scripts/versions.json | 28 ++++ tests/pubspec.yaml | 72 +++++------ 159 files changed, 712 insertions(+), 342 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eda6c4459884..6874659af312 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,128 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2026-05-14 - [BoM 4.14.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4140-2026-05-14) + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`firebase_core` - `v4.9.0`](#firebase_core---v490) + - [`firebase_core_platform_interface` - `v7.0.1`](#firebase_core_platform_interface---v701) + - [`firebase_core_web` - `v3.7.0`](#firebase_core_web---v370) + - [`_flutterfire_internals` - `v1.3.71`](#_flutterfire_internals---v1371) + - [`cloud_firestore` - `v6.4.1`](#cloud_firestore---v641) + - [`cloud_firestore_platform_interface` - `v8.0.1`](#cloud_firestore_platform_interface---v801) + - [`cloud_firestore_web` - `v5.4.1`](#cloud_firestore_web---v541) + - [`cloud_functions` - `v6.3.1`](#cloud_functions---v631) + - [`cloud_functions_platform_interface` - `v6.0.1`](#cloud_functions_platform_interface---v601) + - [`cloud_functions_web` - `v5.1.7`](#cloud_functions_web---v517) + - [`firebase_ai` - `v3.12.1`](#firebase_ai---v3121) + - [`firebase_analytics` - `v12.4.1`](#firebase_analytics---v1241) + - [`firebase_analytics_platform_interface` - `v6.0.1`](#firebase_analytics_platform_interface---v601) + - [`firebase_analytics_web` - `v0.6.1+7`](#firebase_analytics_web---v0617) + - [`firebase_app_check` - `v0.4.4+1`](#firebase_app_check---v0441) + - [`firebase_app_check_platform_interface` - `v0.4.0+1`](#firebase_app_check_platform_interface---v0401) + - [`firebase_app_check_web` - `v0.2.4+2`](#firebase_app_check_web---v0242) + - [`firebase_app_installations` - `v0.4.2+2`](#firebase_app_installations---v0422) + - [`firebase_app_installations_platform_interface` - `v0.1.4+70`](#firebase_app_installations_platform_interface---v01470) + - [`firebase_app_installations_web` - `v0.1.7+7`](#firebase_app_installations_web---v0177) + - [`firebase_auth` - `v6.5.1`](#firebase_auth---v651) + - [`firebase_auth_platform_interface` - `v9.0.1`](#firebase_auth_platform_interface---v901) + - [`firebase_auth_web` - `v6.2.1`](#firebase_auth_web---v621) + - [`firebase_crashlytics` - `v5.2.2`](#firebase_crashlytics---v522) + - [`firebase_crashlytics_platform_interface` - `v3.8.22`](#firebase_crashlytics_platform_interface---v3822) + - [`firebase_data_connect` - `v0.3.0+2`](#firebase_data_connect---v0302) + - [`firebase_database` - `v12.4.1`](#firebase_database---v1241) + - [`firebase_database_platform_interface` - `v0.4.0+1`](#firebase_database_platform_interface---v0401) + - [`firebase_database_web` - `v0.2.7+8`](#firebase_database_web---v0278) + - [`firebase_in_app_messaging` - `v0.9.2+2`](#firebase_in_app_messaging---v0922) + - [`firebase_in_app_messaging_platform_interface` - `v0.2.5+22`](#firebase_in_app_messaging_platform_interface---v02522) + - [`firebase_messaging` - `v16.2.2`](#firebase_messaging---v1622) + - [`firebase_messaging_platform_interface` - `v4.7.11`](#firebase_messaging_platform_interface---v4711) + - [`firebase_messaging_web` - `v4.1.7`](#firebase_messaging_web---v417) + - [`firebase_ml_model_downloader` - `v0.4.2+2`](#firebase_ml_model_downloader---v0422) + - [`firebase_ml_model_downloader_platform_interface` - `v0.1.5+22`](#firebase_ml_model_downloader_platform_interface---v01522) + - [`firebase_performance` - `v0.11.4+1`](#firebase_performance---v01141) + - [`firebase_performance_platform_interface` - `v0.2.0+1`](#firebase_performance_platform_interface---v0201) + - [`firebase_performance_web` - `v0.1.8+7`](#firebase_performance_web---v0187) + - [`firebase_remote_config` - `v6.5.1`](#firebase_remote_config---v651) + - [`firebase_remote_config_platform_interface` - `v3.0.1`](#firebase_remote_config_platform_interface---v301) + - [`firebase_remote_config_web` - `v1.10.8`](#firebase_remote_config_web---v1108) + - [`firebase_storage` - `v13.4.1`](#firebase_storage---v1341) + - [`firebase_storage_platform_interface` - `v6.0.1`](#firebase_storage_platform_interface---v601) + - [`firebase_storage_web` - `v3.11.7`](#firebase_storage_web---v3117) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `_flutterfire_internals` - `v1.3.71` + - `cloud_firestore` - `v6.4.1` + - `cloud_firestore_platform_interface` - `v8.0.1` + - `cloud_firestore_web` - `v5.4.1` + - `cloud_functions` - `v6.3.1` + - `cloud_functions_platform_interface` - `v6.0.1` + - `cloud_functions_web` - `v5.1.7` + - `firebase_ai` - `v3.12.1` + - `firebase_analytics` - `v12.4.1` + - `firebase_analytics_platform_interface` - `v6.0.1` + - `firebase_analytics_web` - `v0.6.1+7` + - `firebase_app_check` - `v0.4.4+1` + - `firebase_app_check_platform_interface` - `v0.4.0+1` + - `firebase_app_check_web` - `v0.2.4+2` + - `firebase_app_installations` - `v0.4.2+2` + - `firebase_app_installations_platform_interface` - `v0.1.4+70` + - `firebase_app_installations_web` - `v0.1.7+7` + - `firebase_auth` - `v6.5.1` + - `firebase_auth_platform_interface` - `v9.0.1` + - `firebase_auth_web` - `v6.2.1` + - `firebase_crashlytics` - `v5.2.2` + - `firebase_crashlytics_platform_interface` - `v3.8.22` + - `firebase_data_connect` - `v0.3.0+2` + - `firebase_database` - `v12.4.1` + - `firebase_database_platform_interface` - `v0.4.0+1` + - `firebase_database_web` - `v0.2.7+8` + - `firebase_in_app_messaging` - `v0.9.2+2` + - `firebase_in_app_messaging_platform_interface` - `v0.2.5+22` + - `firebase_messaging` - `v16.2.2` + - `firebase_messaging_platform_interface` - `v4.7.11` + - `firebase_messaging_web` - `v4.1.7` + - `firebase_ml_model_downloader` - `v0.4.2+2` + - `firebase_ml_model_downloader_platform_interface` - `v0.1.5+22` + - `firebase_performance` - `v0.11.4+1` + - `firebase_performance_platform_interface` - `v0.2.0+1` + - `firebase_performance_web` - `v0.1.8+7` + - `firebase_remote_config` - `v6.5.1` + - `firebase_remote_config_platform_interface` - `v3.0.1` + - `firebase_remote_config_web` - `v1.10.8` + - `firebase_storage` - `v13.4.1` + - `firebase_storage_platform_interface` - `v6.0.1` + - `firebase_storage_web` - `v3.11.7` + +--- + +#### `firebase_core` - `v4.9.0` + + - **FIX**(core,iOS): use namespaced iOS Pigeon header import ([#18281](https://github.com/firebase/flutterfire/issues/18281)). ([7c1257e7](https://github.com/firebase/flutterfire/commit/7c1257e7295f9ba67f3f5820493f105a14d34d52)) + - **FEAT**: bump Firebase iOS SDK to 12.13.0 ([#18273](https://github.com/firebase/flutterfire/issues/18273)). ([78e10f02](https://github.com/firebase/flutterfire/commit/78e10f0222f4e23c96b636c63c29935ba5aa82e6)) + - **FEAT**: bump Firebase android SDK to 34.13.0 ([#18272](https://github.com/firebase/flutterfire/issues/18272)). ([d10e0ffa](https://github.com/firebase/flutterfire/commit/d10e0ffa2980a21a5899dbe67952fc772a3c6c01)) + +#### `firebase_core_platform_interface` - `v7.0.1` + + - **FIX**(core,iOS): use namespaced iOS Pigeon header import ([#18281](https://github.com/firebase/flutterfire/issues/18281)). ([7c1257e7](https://github.com/firebase/flutterfire/commit/7c1257e7295f9ba67f3f5820493f105a14d34d52)) + +#### `firebase_core_web` - `v3.7.0` + + - **FEAT**: bump Firebase JS SDK to 12.13.0 ([#18274](https://github.com/firebase/flutterfire/issues/18274)). ([bb8ad546](https://github.com/firebase/flutterfire/commit/bb8ad546f114146b6e1cd26c3296825e2964745d)) + + ## 2026-05-11 - [BoM 4.13.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4130-2026-05-11) ### Changes diff --git a/VERSIONS.md b/VERSIONS.md index 7813f12df3c0..2c6c10aca845 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -4,6 +4,44 @@ This document is listing all the compatible versions of the FlutterFire plugins. # Versions +## [Flutter BoM 4.14.0 (2026-05-14)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-05-14) + +Install this version using FlutterFire CLI + +```bash +flutterfire install 4.14.0 +``` + +### Included Native Firebase SDK Versions +| Firebase SDK | Version | Link | +|--------------|---------|------| +| Android SDK | 34.13.0 | [Release Notes](https://firebase.google.com/support/release-notes/android) | +| iOS SDK | 12.13.0 | [Release Notes](https://firebase.google.com/support/release-notes/ios) | +| Web SDK | 12.13.0 | [Release Notes](https://firebase.google.com/support/release-notes/js) | +| Windows SDK | 13.5.0 | [Release Notes](https://firebase.google.com/support/release-notes/cpp-relnotes) | + +### FlutterFire Plugin Versions +| Plugin | Version | Dart Version | Flutter Version | +|--------|---------|--------------|-----------------| +| [cloud_firestore](https://pub.dev/packages/cloud_firestore/versions/6.4.1) | 6.4.1 | ^3.6.0 | >=3.27.0 | +| [cloud_functions](https://pub.dev/packages/cloud_functions/versions/6.3.1) | 6.3.1 | ^3.6.0 | >=3.27.0 | +| [firebase_ai](https://pub.dev/packages/firebase_ai/versions/3.12.1) | 3.12.1 | ^3.6.0 | >=3.16.0 | +| [firebase_analytics](https://pub.dev/packages/firebase_analytics/versions/12.4.1) | 12.4.1 | ^3.6.0 | >=3.27.0 | +| [firebase_app_check](https://pub.dev/packages/firebase_app_check/versions/0.4.4+1) | 0.4.4+1 | ^3.6.0 | >=3.27.0 | +| [firebase_app_installations](https://pub.dev/packages/firebase_app_installations/versions/0.4.2+2) | 0.4.2+2 | ^3.6.0 | >=3.27.0 | +| [firebase_auth](https://pub.dev/packages/firebase_auth/versions/6.5.1) | 6.5.1 | ^3.6.0 | >=3.16.0 | +| [firebase_core](https://pub.dev/packages/firebase_core/versions/4.9.0) | 4.9.0 | ^3.6.0 | >=3.27.0 | +| [firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics/versions/5.2.2) | 5.2.2 | ^3.6.0 | >=3.27.0 | +| [firebase_data_connect](https://pub.dev/packages/firebase_data_connect/versions/0.3.0+2) | 0.3.0+2 | ^3.6.0 | >=3.27.0 | +| [firebase_database](https://pub.dev/packages/firebase_database/versions/12.4.1) | 12.4.1 | ^3.6.0 | >=3.27.0 | +| [firebase_in_app_messaging](https://pub.dev/packages/firebase_in_app_messaging/versions/0.9.2+2) | 0.9.2+2 | ^3.6.0 | >=3.27.0 | +| [firebase_messaging](https://pub.dev/packages/firebase_messaging/versions/16.2.2) | 16.2.2 | ^3.6.0 | >=3.27.0 | +| [firebase_ml_model_downloader](https://pub.dev/packages/firebase_ml_model_downloader/versions/0.4.2+2) | 0.4.2+2 | ^3.6.0 | >=3.27.0 | +| [firebase_performance](https://pub.dev/packages/firebase_performance/versions/0.11.4+1) | 0.11.4+1 | ^3.6.0 | >=3.27.0 | +| [firebase_remote_config](https://pub.dev/packages/firebase_remote_config/versions/6.5.1) | 6.5.1 | ^3.6.0 | >=3.27.0 | +| [firebase_storage](https://pub.dev/packages/firebase_storage/versions/13.4.1) | 13.4.1 | ^3.6.0 | >=3.27.0 | + + ## [Flutter BoM 4.13.0 (2026-05-11)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-05-11) Install this version using FlutterFire CLI diff --git a/packages/_flutterfire_internals/CHANGELOG.md b/packages/_flutterfire_internals/CHANGELOG.md index 3515669b8416..ceeacaf470d1 100644 --- a/packages/_flutterfire_internals/CHANGELOG.md +++ b/packages/_flutterfire_internals/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.71 + + - Update a dependency to the latest release. + ## 1.3.70 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/_flutterfire_internals/pubspec.yaml b/packages/_flutterfire_internals/pubspec.yaml index e2671082096e..bc71795d13df 100755 --- a/packages/_flutterfire_internals/pubspec.yaml +++ b/packages/_flutterfire_internals/pubspec.yaml @@ -2,7 +2,7 @@ name: _flutterfire_internals description: A package hosting Dart code shared between FlutterFire plugins. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/_flutterfire_internals -version: 1.3.70 +version: 1.3.71 resolution: workspace environment: @@ -11,8 +11,8 @@ environment: dependencies: collection: ^1.0.0 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md index a20219cb4f94..e146a0db9bb0 100644 --- a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.4.1 + + - Update a dependency to the latest release. + ## 6.4.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml index 86a86070a036..0b2a473bfd79 100755 --- a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.4.0 - firebase_core: ^4.8.0 + cloud_firestore: ^6.4.1 + firebase_core: ^4.9.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index acb82e377492..eeb28d8e1eaa 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.4.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "6.4.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index 35731701d100..744936afe8b1 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.4.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "6.4.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml index 14c401323006..ff6da42a48e5 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -31,7 +31,7 @@ environment: dependencies: cloud_firestore: path: .. - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pubspec.yaml index 8bf708365a7e..14a0e0e024d1 100755 --- a/packages/cloud_firestore/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pubspec.yaml @@ -4,7 +4,7 @@ description: live synchronization and offline support on Android and iOS. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore -version: 6.4.0 +version: 6.4.1 resolution: workspace topics: - firebase @@ -21,11 +21,11 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore_platform_interface: ^8.0.0 - cloud_firestore_web: ^5.4.0 + cloud_firestore_platform_interface: ^8.0.1 + cloud_firestore_web: ^5.4.1 collection: ^1.0.0 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md index f0779a819fbe..bb5cefd3c8b1 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 8.0.1 + + - Update a dependency to the latest release. + ## 8.0.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml index bff98fa8ca48..6614f788eb69 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_firestore_platform_interface description: A common platform interface for the cloud_firestore plugin. -version: 8.0.0 +version: 8.0.1 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 + _flutterfire_internals: ^1.3.71 collection: ^1.15.0 - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md index 89e6bdfe84f3..da9d0233bdbc 100644 --- a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.4.1 + + - Update a dependency to the latest release. + ## 5.4.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart index 14d87311cbb9..291be50d8be3 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.4.0'; +const packageVersion = '6.4.1'; diff --git a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml index 4743bd3bffdd..93b5d2f3376b 100644 --- a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_firestore homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web -version: 5.4.0 +version: 5.4.1 resolution: workspace environment: @@ -11,18 +11,18 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 - cloud_firestore_platform_interface: ^8.0.0 + _flutterfire_internals: ^1.3.71 + cloud_firestore_platform_interface: ^8.0.1 collection: ^1.0.0 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_functions/cloud_functions/CHANGELOG.md b/packages/cloud_functions/cloud_functions/CHANGELOG.md index 5917e71ff1a3..dd77e23d82e3 100644 --- a/packages/cloud_functions/cloud_functions/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.3.1 + + - Update a dependency to the latest release. + ## 6.3.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/cloud_functions/cloud_functions/example/pubspec.yaml b/packages/cloud_functions/cloud_functions/example/pubspec.yaml index 3623c5720620..3433f3a75dea 100644 --- a/packages/cloud_functions/cloud_functions/example/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions: ^6.3.0 - firebase_core: ^4.8.0 + cloud_functions: ^6.3.1 + firebase_core: ^4.9.0 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift index bed5ad375f66..13368bccaf73 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "cloud_functions", diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift index 3786e1b8dde8..f7f26c52d223 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.3.0" +public let versionNumber = "6.3.1" diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift index a9842df6228b..9d7ca8dc6440 100644 --- a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "cloud_functions", diff --git a/packages/cloud_functions/cloud_functions/pubspec.yaml b/packages/cloud_functions/cloud_functions/pubspec.yaml index 3bde8c631093..dc994b934e5e 100644 --- a/packages/cloud_functions/cloud_functions/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_functions description: A Flutter plugin allowing you to use Firebase Cloud Functions. -version: 6.3.0 +version: 6.3.1 resolution: workspace homepage: https://firebase.google.com/docs/functions repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions_platform_interface: ^6.0.0 - cloud_functions_web: ^5.1.6 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + cloud_functions_platform_interface: ^6.0.1 + cloud_functions_web: ^5.1.7 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md index 82c93f7e0a97..6b6e0e083f49 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.1 + + - Update a dependency to the latest release. + ## 6.0.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml index 588538edf552..4a2b39171f69 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_fun # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 6.0.0 +version: 6.0.1 resolution: workspace environment: @@ -13,14 +13,14 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md index 2893c34f9f90..f823d39aee51 100644 --- a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.7 + + - Update a dependency to the latest release. + ## 5.1.6 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart index ab9c93b832a8..955ddd8f8c5d 100644 --- a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart +++ b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.3.0'; +const packageVersion = '6.3.1'; diff --git a/packages/cloud_functions/cloud_functions_web/pubspec.yaml b/packages/cloud_functions/cloud_functions_web/pubspec.yaml index aaaef2c7bb08..8964f8228cb1 100644 --- a/packages/cloud_functions/cloud_functions_web/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_functions homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web -version: 5.1.6 +version: 5.1.7 resolution: workspace environment: @@ -11,9 +11,9 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions_platform_interface: ^6.0.0 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 + cloud_functions_platform_interface: ^6.0.1 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 flutter: sdk: flutter flutter_web_plugins: @@ -21,7 +21,7 @@ dependencies: web: ^1.1.1 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index 22e19fc93fb1..39582a4ad66a 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.12.1 + + - Update a dependency to the latest release. + ## 3.12.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index 7c9021d8537e..005ca2575920 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -24,9 +24,9 @@ dependencies: camera: ^0.12.0+1 camera_macos: ^0.0.9 cupertino_icons: ^1.0.6 - firebase_ai: ^3.12.0 - firebase_core: ^4.8.0 - firebase_storage: ^13.4.0 + firebase_ai: ^3.12.1 + firebase_core: ^4.9.0 + firebase_storage: ^13.4.1 flutter: sdk: flutter flutter_animate: ^4.5.2 diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart index 23f6faec9631..251b4d38fbdf 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.3.0+1'; +const packageVersion = '0.3.0+2'; diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index ddcb4d245a85..fada966d9c5d 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI Logic SDK. -version: 3.12.0 +version: 3.12.1 resolution: workspace homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: @@ -21,10 +21,10 @@ environment: flutter: ">=3.16.0" dependencies: - firebase_app_check: ^0.4.4 - firebase_auth: ^6.5.0 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_app_check: ^0.4.4+1 + firebase_auth: ^6.5.1 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter http: ^1.1.0 diff --git a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md index 75687c708fe6..3582750b0a39 100644 --- a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.4.1 + + - Update a dependency to the latest release. + ## 12.4.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml index 9ffe573be6b5..29c38d8b1acd 100755 --- a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.0 - firebase_core: ^4.8.0 + firebase_analytics: ^12.4.1 + firebase_core: ^4.9.0 flutter: sdk: flutter in_app_purchase: ^3.2.3 diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift index b4fdddd4eef6..2c161afddcf4 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift @@ -8,7 +8,7 @@ import Foundation import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" // Set FIREBASE_ANALYTICS_WITHOUT_ADID=true to use FirebaseAnalyticsWithoutAdIdSupport // e.g. FIREBASE_ANALYTICS_WITHOUT_ADID=true flutter build ios diff --git a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift index 8a2af6f8c70b..e3a0c919f39c 100644 --- a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_analytics", diff --git a/packages/firebase_analytics/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/pubspec.yaml index 94e47e3d6908..b0b3b0b6c0d9 100755 --- a/packages/firebase_analytics/firebase_analytics/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/pubspec.yaml @@ -4,7 +4,7 @@ description: solution that provides insight on app usage and user engagement on Android and iOS. homepage: https://firebase.google.com/docs/analytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics -version: 12.4.0 +version: 12.4.1 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics_platform_interface: ^6.0.0 - firebase_analytics_web: ^0.6.1+6 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_analytics_platform_interface: ^6.0.1 + firebase_analytics_web: ^0.6.1+7 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md index 9d3e629aa0df..b21df9014774 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.1 + + - Update a dependency to the latest release. + ## 6.0.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml index 1090d77bdf1f..6fb274a88cb5 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_platform_interface description: A common platform interface for the firebase_analytics plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface -version: 6.0.0 +version: 6.0.1 resolution: workspace environment: @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter pigeon: 26.3.4 diff --git a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md index 4e1a05ec3867..bc4555b575e0 100644 --- a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.1+7 + + - Update a dependency to the latest release. + ## 0.6.1+6 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart index d17623e3d121..bcbf9e02507e 100644 --- a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart +++ b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.4.0'; +const packageVersion = '12.4.1'; diff --git a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml index e093f44a253a..dce76acc4130 100644 --- a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_web description: The web implementation of firebase_analytics homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web -version: 0.6.1+6 +version: 0.6.1+7 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_analytics_platform_interface: ^6.0.0 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 + _flutterfire_internals: ^1.3.71 + firebase_analytics_platform_interface: ^6.0.1 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md index 488a76a38745..2fa6e746d5d0 100644 --- a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.4+1 + + - Update a dependency to the latest release. + ## 0.4.4 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml index eab8706af9e4..905c8df05552 100644 --- a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml @@ -11,9 +11,9 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.4.0 - firebase_app_check: ^0.4.4 - firebase_core: ^4.8.0 + cloud_firestore: ^6.4.1 + firebase_app_check: ^0.4.4+1 + firebase_core: ^4.9.0 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index b68e8d6b85f8..131401563be2 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_app_check", diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift index 86aae5dc32fa..a2e723833932 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.4" +public let versionNumber = "0.4.4+1" diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift index 85aa6e775d67..31732e86e458 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_app_check", diff --git a/packages/firebase_app_check/firebase_app_check/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/pubspec.yaml index ff4498431d0c..522f6bae042b 100644 --- a/packages/firebase_app_check/firebase_app_check/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_app_check description: App Check works alongside other Firebase services to help protect your backend resources from abuse, such as billing fraud or phishing. homepage: https://firebase.google.com/docs/app-check repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check -version: 0.4.4 +version: 0.4.4+1 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_check_platform_interface: ^0.4.0 - firebase_app_check_web: ^0.2.4+1 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_app_check_platform_interface: ^0.4.0+1 + firebase_app_check_web: ^0.2.4+2 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md index 24e446baef89..c8c2b2290802 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+1 + + - Update a dependency to the latest release. + ## 0.4.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 059498469c59..85f42f933400 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_platform_interface description: A common platform interface for the firebase_app_check plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_platform_interface -version: 0.4.0 +version: 0.4.0+1 resolution: workspace environment: @@ -9,15 +9,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md index eb3cd0573bee..75d0872f461d 100644 --- a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.4+2 + + - Update a dependency to the latest release. + ## 0.2.4+1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart index 7110462994e7..6f543de27ef2 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.4'; +const packageVersion = '0.4.4+1'; diff --git a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml index f600a6ee3cf8..295aef48b899 100644 --- a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_web description: The web implementation of firebase_app_check homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_web -version: 0.2.4+1 +version: 0.2.4+2 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_app_check_platform_interface: ^0.4.0 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 + _flutterfire_internals: ^1.3.71 + firebase_app_check_platform_interface: ^0.4.0+1 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 flutter: sdk: flutter flutter_web_plugins: @@ -21,7 +21,7 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md index 602b74463e24..142d39936663 100644 --- a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+2 + + - Update a dependency to the latest release. + ## 0.4.2+1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml index f6f29d756f65..41494e6492c2 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_app_installations: ^0.4.2+1 + firebase_core: ^4.9.0 + firebase_app_installations: ^0.4.2+2 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift index a1a486cc5ba8..99fb7e9fc227 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift index 8f7df3f775de..a1317a947b5b 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2+1" +public let versionNumber = "0.4.2+2" diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift index c84a93ed438f..3931f4954626 100644 --- a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml index e7988bb90888..c12a7ed85c5a 100644 --- a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations description: A Flutter plugin allowing you to use Firebase Installations. -version: 0.4.2+1 +version: 0.4.2+2 resolution: workspace homepage: https://firebase.google.com/docs/projects/manage-installations#flutter repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_installations_platform_interface: ^0.1.4+69 - firebase_app_installations_web: ^0.1.7+6 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_app_installations_platform_interface: ^0.1.4+70 + firebase_app_installations_web: ^0.1.7+7 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md index d8afddaf7557..8e98454d92c4 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+70 + + - Update a dependency to the latest release. + ## 0.1.4+69 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 6c91ec5f079e..3eb6c03420e8 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_platform_interface description: A common platform interface for the firebase_app_installations plugin. -version: 0.1.4+69 +version: 0.1.4+70 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md index f05c7869e741..74a2c95bf9ee 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.7+7 + + - Update a dependency to the latest release. + ## 0.1.7+6 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart index 5067985ca37b..493b9b698ac8 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart +++ b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.2+1'; +const packageVersion = '0.4.2+2'; diff --git a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml index bafe760003d1..449a382ab258 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_web description: The web implementation of firebase_app_installations. -version: 0.1.7+6 +version: 0.1.7+7 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web @@ -10,17 +10,17 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_app_installations_platform_interface: ^0.1.4+69 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 + _flutterfire_internals: ^1.3.71 + firebase_app_installations_platform_interface: ^0.1.4+70 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_auth/firebase_auth/CHANGELOG.md b/packages/firebase_auth/firebase_auth/CHANGELOG.md index 63b52b033001..64ab30e9d2f9 100644 --- a/packages/firebase_auth/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.5.1 + + - Update a dependency to the latest release. + ## 6.5.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_auth/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/firebase_auth/example/pubspec.yaml index dd67a0a03911..13404244d4e5 100644 --- a/packages/firebase_auth/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/example/pubspec.yaml @@ -8,9 +8,9 @@ environment: dependencies: barcode_widget: ^2.0.4 - firebase_auth: ^6.5.0 - firebase_core: ^4.8.0 - firebase_messaging: ^16.2.1 + firebase_auth: ^6.5.1 + firebase_core: ^4.9.0 + firebase_messaging: ^16.2.2 flutter: sdk: flutter flutter_facebook_auth: ^7.1.5 diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index 579452546409..362b8f5ebda2 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.5.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "6.5.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index deff530b35f3..deb2d7c07aee 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "6.5.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "6.5.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_auth/firebase_auth/pubspec.yaml b/packages/firebase_auth/firebase_auth/pubspec.yaml index c421946e3666..4a1dd3635817 100755 --- a/packages/firebase_auth/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling like Google, Facebook and Twitter. homepage: https://firebase.google.com/docs/auth repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth -version: 6.5.0 +version: 6.5.1 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.16.0' dependencies: - firebase_auth_platform_interface: ^9.0.0 - firebase_auth_web: ^6.2.0 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_auth_platform_interface: ^9.0.1 + firebase_auth_web: ^6.2.1 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md index 2a02068cc91a..e81681fa4bf1 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 9.0.1 + + - Update a dependency to the latest release. + ## 9.0.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml index 05f5bca64ca0..fc6be3ec1007 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_au repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 9.0.0 +version: 9.0.1 resolution: workspace environment: @@ -12,9 +12,9 @@ environment: flutter: '>=3.16.0' dependencies: - _flutterfire_internals: ^1.3.70 + _flutterfire_internals: ^1.3.71 collection: ^1.16.0 - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter http: ^1.1.0 @@ -22,7 +22,7 @@ dependencies: plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.4.0 diff --git a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md index 022d967eb146..6e96695e1a3d 100644 --- a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.2.1 + + - Update a dependency to the latest release. + ## 6.2.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart index 200e74209d4f..ddd128c14de6 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.0'; +const packageVersion = '6.5.1'; diff --git a/packages/firebase_auth/firebase_auth_web/pubspec.yaml b/packages/firebase_auth/firebase_auth_web/pubspec.yaml index 50d3c17161f7..6be8765b4927 100644 --- a/packages/firebase_auth/firebase_auth_web/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_auth_web description: The web implementation of firebase_auth homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web -version: 6.2.0 +version: 6.2.1 resolution: workspace environment: @@ -10,9 +10,9 @@ environment: flutter: '>=3.22.0' dependencies: - firebase_auth_platform_interface: ^9.0.0 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 + firebase_auth_platform_interface: ^9.0.1 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_core/firebase_core/CHANGELOG.md b/packages/firebase_core/firebase_core/CHANGELOG.md index 9d1e4d578e32..62cfa0de813c 100644 --- a/packages/firebase_core/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/firebase_core/CHANGELOG.md @@ -1,3 +1,9 @@ +## 4.9.0 + + - **FIX**(core,iOS): use namespaced iOS Pigeon header import ([#18281](https://github.com/firebase/flutterfire/issues/18281)). ([7c1257e7](https://github.com/firebase/flutterfire/commit/7c1257e7295f9ba67f3f5820493f105a14d34d52)) + - **FEAT**: bump Firebase iOS SDK to 12.13.0 ([#18273](https://github.com/firebase/flutterfire/issues/18273)). ([78e10f02](https://github.com/firebase/flutterfire/commit/78e10f0222f4e23c96b636c63c29935ba5aa82e6)) + - **FEAT**: bump Firebase android SDK to 34.13.0 ([#18272](https://github.com/firebase/flutterfire/issues/18272)). ([d10e0ffa](https://github.com/firebase/flutterfire/commit/d10e0ffa2980a21a5899dbe67952fc772a3c6c01)) + ## 4.8.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_core/firebase_core/example/pubspec.yaml b/packages/firebase_core/firebase_core/example/pubspec.yaml index 3f1571f1e528..31c8d0c83ffa 100644 --- a/packages/firebase_core/firebase_core/example/pubspec.yaml +++ b/packages/firebase_core/firebase_core/example/pubspec.yaml @@ -7,7 +7,7 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index b82c0e27a32e..9a30c9de0e0d 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version_string = "4.8.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version_string = "4.9.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index df765d313a84..d4b4f2dabcd7 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version_string = "4.8.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version_string = "4.9.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index f0f545f3eb15..da72c2a4a28f 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. homepage: https://firebase.google.com/docs/flutter/setup repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core -version: 4.8.0 +version: 4.9.0 resolution: workspace topics: - firebase @@ -17,8 +17,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core_platform_interface: ^7.0.0 - firebase_core_web: ^3.6.1 + firebase_core_platform_interface: ^7.0.1 + firebase_core_web: ^3.7.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md b/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md index 9df4a7e2c64e..55beefdaa877 100644 --- a/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 7.0.1 + + - **FIX**(core,iOS): use namespaced iOS Pigeon header import ([#18281](https://github.com/firebase/flutterfire/issues/18281)). ([7c1257e7](https://github.com/firebase/flutterfire/commit/7c1257e7295f9ba67f3f5820493f105a14d34d52)) + ## 7.0.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml index 196a725c5f18..4eb784d0d021 100644 --- a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml +++ b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_co repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 7.0.0 +version: 7.0.1 resolution: workspace environment: diff --git a/packages/firebase_core/firebase_core_web/CHANGELOG.md b/packages/firebase_core/firebase_core_web/CHANGELOG.md index a0d21e536cd1..1619cef530f8 100644 --- a/packages/firebase_core/firebase_core_web/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.7.0 + + - **FEAT**: bump Firebase JS SDK to 12.13.0 ([#18274](https://github.com/firebase/flutterfire/issues/18274)). ([bb8ad546](https://github.com/firebase/flutterfire/commit/bb8ad546f114146b6e1cd26c3296825e2964745d)) + ## 3.6.1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart index 2896b61b634e..1b529f1f2e5b 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '4.8.0'; +const packageVersion = '4.9.0'; diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index a588cc9bfcd2..a0ca677a4965 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_core_web description: The web implementation of firebase_core homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web -version: 3.6.1 +version: 3.7.0 resolution: workspace environment: @@ -10,7 +10,7 @@ environment: flutter: '>=3.22.0' dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md index 183f7347650d..57740532b490 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.2.2 + + - Update a dependency to the latest release. + ## 5.2.1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml index 15a3d24e38ec..37d7bd4c9633 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml @@ -7,9 +7,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.0 - firebase_core: ^4.8.0 - firebase_crashlytics: ^5.2.1 + firebase_analytics: ^12.4.1 + firebase_core: ^4.9.0 + firebase_crashlytics: ^5.2.2 flutter: sdk: flutter diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index e36a72046b00..530638a39b19 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "5.2.1" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "5.2.2" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index af2ba2fc338b..30bb13ffffa6 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "5.2.1" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "5.2.2" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml index c3d37d7697c5..51a5775b8d96 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 5.2.1 +version: 5.2.2 resolution: workspace homepage: https://firebase.google.com/docs/crashlytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics @@ -20,9 +20,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_crashlytics_platform_interface: ^3.8.21 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_crashlytics_platform_interface: ^3.8.22 flutter: sdk: flutter stack_trace: ^1.10.0 diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md index 659529b9d5f1..0a1250c76fc4 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.8.22 + + - Update a dependency to the latest release. + ## 3.8.21 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml index 83b556a67bf7..bcad65ccbcff 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_crashlytics_platform_interface description: A common platform interface for the firebase_crashlytics plugin. -version: 3.8.21 +version: 3.8.22 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 + _flutterfire_internals: ^1.3.71 collection: ^1.15.0 - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md index 0a9baba2932e..6fe6548cb63e 100644 --- a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md +++ b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+2 + + - Update a dependency to the latest release. + ## 0.3.0+1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index da004248c709..0da5baea0842 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -13,16 +13,16 @@ environment: dependencies: flutter: sdk: flutter - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 google_sign_in: ^6.1.0 - firebase_auth: ^6.5.0 + firebase_auth: ^6.5.1 firebase_data_connect: path: ../ cupertino_icons: ^1.0.6 flutter_rating_bar: ^4.0.1 protobuf: ^3.1.0 - firebase_app_check: ^0.4.4 + firebase_app_check: ^0.4.4+1 dev_dependencies: build_runner: ^2.3.3 diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart index a55677afaa2b..30cec7491ed7 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// version number for the package, should be align with pubspec.yaml. -const packageVersion = '0.3.0+1'; +const packageVersion = '0.3.0+2'; diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index 984617038e7c..3a398dc706a7 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_data_connect description: 'Flutter plugin for Firebase Data Connect, a relational database service that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL.' -version: 0.3.0+1 +version: 0.3.0+2 resolution: workspace homepage: https://firebase.google.com/docs/data-connect/quickstart?platform=flutter false_secrets: @@ -13,10 +13,10 @@ environment: dependencies: crypto: ^3.0.6 - firebase_app_check: ^0.4.4 - firebase_auth: ^6.5.0 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 + firebase_app_check: ^0.4.4+1 + firebase_auth: ^6.5.1 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 fixnum: ^1.1.1 flutter: sdk: flutter @@ -32,8 +32,8 @@ dependencies: dev_dependencies: build_runner: ^2.4.12 - firebase_app_check_platform_interface: ^0.4.0 - firebase_auth_platform_interface: ^9.0.0 + firebase_app_check_platform_interface: ^0.4.0+1 + firebase_auth_platform_interface: ^9.0.1 flutter_lints: ^6.0.0 flutter_test: sdk: flutter diff --git a/packages/firebase_database/firebase_database/CHANGELOG.md b/packages/firebase_database/firebase_database/CHANGELOG.md index 4987b6dda84a..2b79a94c4330 100644 --- a/packages/firebase_database/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/firebase_database/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.4.1 + + - Update a dependency to the latest release. + ## 12.4.0 - **REFACTOR**(database,android): simplify query handling by extracting queryFromModifiers method ([#18221](https://github.com/firebase/flutterfire/issues/18221)). ([65d9bb71](https://github.com/firebase/flutterfire/commit/65d9bb7104f59de82010e3e82fd0ddddbf9a2e23)) diff --git a/packages/firebase_database/firebase_database/example/pubspec.yaml b/packages/firebase_database/firebase_database/example/pubspec.yaml index 1036ead26183..8aad45158e06 100755 --- a/packages/firebase_database/firebase_database/example/pubspec.yaml +++ b/packages/firebase_database/firebase_database/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_database: ^12.4.0 + firebase_core: ^4.9.0 + firebase_database: ^12.4.1 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index 52d1a5f4c8c8..d3e8cb1dd020 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "12.4.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "12.4.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index a14d6b37504c..7e830e552456 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "12.4.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "12.4.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index 91b1bf9fdfc5..8c3fd7cadbb0 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. homepage: https://firebase.google.com/docs/database repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database -version: 12.4.0 +version: 12.4.1 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_database_platform_interface: ^0.4.0 - firebase_database_web: ^0.2.7+7 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_database_platform_interface: ^0.4.0+1 + firebase_database_web: ^0.2.7+8 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md index 8a090c53aae9..e1e0b56d7185 100755 --- a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+1 + + - Update a dependency to the latest release. + ## 0.4.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml index 53833ea64800..cc84a592f7b1 100755 --- a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml +++ b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_platform_interface description: A common platform interface for the firebase_database plugin. -version: 0.4.0 +version: 0.4.0+1 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_platform_interface @@ -9,16 +9,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 + _flutterfire_internals: ^1.3.71 collection: ^1.14.3 - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.2 diff --git a/packages/firebase_database/firebase_database_web/CHANGELOG.md b/packages/firebase_database/firebase_database_web/CHANGELOG.md index 37b2041347db..a9aed47ad6b4 100644 --- a/packages/firebase_database/firebase_database_web/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.7+8 + + - Update a dependency to the latest release. + ## 0.2.7+7 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart index d17623e3d121..bcbf9e02507e 100644 --- a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.4.0'; +const packageVersion = '12.4.1'; diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index 0c834f6bb674..a42292d9c735 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_web description: The web implementation of firebase_database -version: 0.2.7+7 +version: 0.2.7+8 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_web @@ -10,16 +10,16 @@ environment: dependencies: collection: ^1.18.0 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 - firebase_database_platform_interface: ^0.4.0 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 + firebase_database_platform_interface: ^0.4.0+1 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md index 5d019a90270d..ccb5e0323550 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2+2 + + - Update a dependency to the latest release. + ## 0.9.2+1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml index 0b65a086c144..272c0a0b1d71 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml @@ -8,10 +8,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.0 - firebase_core: ^4.8.0 - firebase_in_app_messaging: ^0.9.2+1 - firebase_in_app_messaging_platform_interface: ^0.2.5+21 + firebase_analytics: ^12.4.1 + firebase_core: ^4.9.0 + firebase_in_app_messaging: ^0.9.2+2 + firebase_in_app_messaging_platform_interface: ^0.2.5+22 flutter: sdk: flutter diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index ef7b08b15a59..7f3d4a19d92b 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "0.9.2-1" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "0.9.2-2" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_in_app_messaging", diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml index d82edb755e28..66edec353aa0 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_in_app_messaging description: Flutter plugin for Firebase In-App Messaging. -version: 0.9.2+1 +version: 0.9.2+2 resolution: workspace homepage: https://firebase.google.com/docs/in-app-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_in_app_messaging_platform_interface: ^0.2.5+21 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_in_app_messaging_platform_interface: ^0.2.5+22 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md index ad33f375cb56..6dd23cb59354 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.5+22 + + - Update a dependency to the latest release. + ## 0.2.5+21 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml index bf4f732ff11d..fddd18e8373c 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the firebase_in_app_messaging plugi homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface -version: 0.2.5+21 +version: 0.2.5+22 resolution: workspace environment: @@ -11,14 +11,14 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter diff --git a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md index ec4ac817ba5e..38d9a85d08e3 100644 --- a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 16.2.2 + + - Update a dependency to the latest release. + ## 16.2.1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index e3f27781122b..fe4f3af5e042 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_messaging: ^16.2.1 + firebase_core: ^4.9.0 + firebase_messaging: ^16.2.2 flutter: sdk: flutter flutter_local_notifications: ^21.0.0 diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index 5245529c3964..050a4877cbee 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "16.2.1" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "16.2.2" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index 27acb5f1aec8..185f33fee319 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "16.2.1" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "16.2.2" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/pubspec.yaml index 005f97357ba3..15a85d950c8f 100644 --- a/packages/firebase_messaging/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. homepage: https://firebase.google.com/docs/cloud-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging -version: 16.2.1 +version: 16.2.2 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_messaging_platform_interface: ^4.7.10 - firebase_messaging_web: ^4.1.6 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_messaging_platform_interface: ^4.7.11 + firebase_messaging_web: ^4.1.7 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md index d63d0305f0e2..1a5eb79762ef 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.7.11 + + - Update a dependency to the latest release. + ## 4.7.10 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml index 1829c1d35016..31d86dc23b9a 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_messaging_platform_interface description: A common platform interface for the firebase_messaging plugin. -version: 4.7.10 +version: 4.7.11 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md index 7f6cf8d3836f..c5397fae1dca 100644 --- a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.1.7 + + - Update a dependency to the latest release. + ## 4.1.6 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart index 30f33f23d51b..774c057adcb3 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '16.2.1'; +const packageVersion = '16.2.2'; diff --git a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml index 790777421307..9d6841cbe9c6 100644 --- a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_messaging_web description: The web implementation of firebase_messaging homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web -version: 4.1.6 +version: 4.1.7 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 - firebase_messaging_platform_interface: ^4.7.10 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 + firebase_messaging_platform_interface: ^4.7.11 flutter: sdk: flutter flutter_web_plugins: @@ -22,7 +22,7 @@ dependencies: web: ^1.0.0 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md index c7d5e7b1dea2..c9cdadac95bc 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+2 + + - Update a dependency to the latest release. + ## 0.4.2+1 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml index d24b983c5859..4391fcea0db3 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml @@ -12,8 +12,8 @@ dependencies: flutter: sdk: flutter - firebase_core: ^4.8.0 - firebase_ml_model_downloader: ^0.4.2+1 + firebase_core: ^4.9.0 + firebase_ml_model_downloader: ^0.4.2+2 dev_dependencies: flutter_lints: ^6.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift index dfc5b53f229c..b3474aeb3bdf 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift index 8f7df3f775de..a1317a947b5b 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2+1" +public let versionNumber = "0.4.2+2" diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift index 350adb156226..ef5ecc229031 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml index 94fb4379a76f..2b4cd59e8de1 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader description: A Flutter plugin allowing you to use Firebase Ml Model Downloader. -version: 0.4.2+1 +version: 0.4.2+2 resolution: workspace homepage: https://firebase.google.com/docs/ml/flutter/use-custom-models repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_ml_model_downloader_platform_interface: ^0.1.5+21 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_ml_model_downloader_platform_interface: ^0.1.5+22 flutter: sdk: flutter diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md index 2b2d8ac9ece3..4d5009d8725d 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5+22 + + - Update a dependency to the latest release. + ## 0.1.5+21 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml index 73a421853c29..c6fe78920a5b 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader_platform_interface description: A common platform interface for the firebase_ml_model_downloader plugin. -version: 0.1.5+21 +version: 0.1.5+22 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface @@ -10,14 +10,14 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_performance/firebase_performance/CHANGELOG.md b/packages/firebase_performance/firebase_performance/CHANGELOG.md index 39fd330bd8cd..5c02b147bab8 100644 --- a/packages/firebase_performance/firebase_performance/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.4+1 + + - Update a dependency to the latest release. + ## 0.11.4 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_performance/firebase_performance/example/pubspec.yaml b/packages/firebase_performance/firebase_performance/example/pubspec.yaml index 01262bf06925..1ad9f97442f9 100644 --- a/packages/firebase_performance/firebase_performance/example/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_performance: ^0.11.4 + firebase_core: ^4.9.0 + firebase_performance: ^0.11.4+1 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index dd45395cbeb5..41a2ebc7f194 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "0.11.4" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "0.11.4-1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_performance", diff --git a/packages/firebase_performance/firebase_performance/pubspec.yaml b/packages/firebase_performance/firebase_performance/pubspec.yaml index d00f83fad50a..d4dc03ef07a7 100644 --- a/packages/firebase_performance/firebase_performance/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/pubspec.yaml @@ -5,7 +5,7 @@ description: iOS. homepage: https://firebase.google.com/docs/perf-mon repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance -version: 0.11.4 +version: 0.11.4+1 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_performance_platform_interface: ^0.2.0 - firebase_performance_web: ^0.1.8+6 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_performance_platform_interface: ^0.2.0+1 + firebase_performance_web: ^0.1.8+7 flutter: sdk: flutter diff --git a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md index be86c62982c0..9e8ea2b1d3ee 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+1 + + - Update a dependency to the latest release. + ## 0.2.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml index 67185d59caeb..d83c64814f42 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_performance_platform_interface description: A common platform interface for the firebase_performance plugin. -version: 0.2.0 +version: 0.2.0+1 resolution: workspace homepage: https://firebase.google.com/docs/perf-mon/flutter/get-started @@ -9,15 +9,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter pigeon: 26.3.4 diff --git a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md index a2b343801e1a..56a1d2a49e25 100644 --- a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8+7 + + - Update a dependency to the latest release. + ## 0.1.8+6 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart index 17f8049e2aa0..2c24da79ec6c 100644 --- a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart +++ b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.11.4'; +const packageVersion = '0.11.4+1'; diff --git a/packages/firebase_performance/firebase_performance_web/pubspec.yaml b/packages/firebase_performance/firebase_performance_web/pubspec.yaml index 0caf6aabcf3d..5ec4d84da1fa 100644 --- a/packages/firebase_performance/firebase_performance_web/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_performance_web description: Web implementation of Firebase Performance monitoring. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance_web -version: 0.1.8+6 +version: 0.1.8+7 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 - firebase_performance_platform_interface: ^0.2.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 + firebase_performance_platform_interface: ^0.2.0+1 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md index 3219f977058e..d1c39444a345 100644 --- a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.5.1 + + - Update a dependency to the latest release. + ## 6.5.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml index 71af9409acba..5d28f5a41292 100644 --- a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - firebase_core: ^4.8.0 - firebase_remote_config: ^6.5.0 + firebase_core: ^4.9.0 + firebase_remote_config: ^6.5.1 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift index 11ab5b10c9c7..80dab6140218 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift index 5a837434e329..ff6af5e8bb10 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.5.0" +public let versionNumber = "6.5.1" diff --git a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift index 7886d5044cd1..39778eadf02f 100644 --- a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebase_sdk_version: Version = "12.12.0" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml index 48c8071b28a5..bdecc0810a52 100644 --- a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml @@ -4,7 +4,7 @@ description: re-releasing. homepage: https://firebase.google.com/docs/remote-config repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config -version: 6.5.0 +version: 6.5.1 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_remote_config_platform_interface: ^3.0.0 - firebase_remote_config_web: ^1.10.7 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_remote_config_platform_interface: ^3.0.1 + firebase_remote_config_web: ^1.10.8 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md index d849152f4186..1f653703ef6c 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.1 + + - Update a dependency to the latest release. + ## 3.0.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml index 2c659113ac2d..f93bdbe8d845 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_re repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 3.0.0 +version: 3.0.1 resolution: workspace environment: @@ -12,15 +12,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md index e742e715d482..b951559ec8c6 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.8 + + - Update a dependency to the latest release. + ## 1.10.7 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart index 200e74209d4f..ddd128c14de6 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart +++ b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.0'; +const packageVersion = '6.5.1'; diff --git a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml index 68f38544d062..3f97909dc814 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of firebase_remote_config homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web -version: 1.10.7 +version: 1.10.8 resolution: workspace environment: @@ -11,10 +11,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 - firebase_remote_config_platform_interface: ^3.0.0 + _flutterfire_internals: ^1.3.71 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 + firebase_remote_config_platform_interface: ^3.0.1 flutter: sdk: flutter flutter_web_plugins: @@ -22,7 +22,7 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_storage/firebase_storage/CHANGELOG.md b/packages/firebase_storage/firebase_storage/CHANGELOG.md index a48265682153..dff83f868080 100644 --- a/packages/firebase_storage/firebase_storage/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage/CHANGELOG.md @@ -1,3 +1,7 @@ +## 13.4.1 + + - Update a dependency to the latest release. + ## 13.4.0 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_storage/firebase_storage/example/pubspec.yaml b/packages/firebase_storage/firebase_storage/example/pubspec.yaml index 44bb6f5cf703..add2b34ce64c 100755 --- a/packages/firebase_storage/firebase_storage/example/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_storage: ^13.4.0 + firebase_core: ^4.9.0 + firebase_storage: ^13.4.1 flutter: sdk: flutter image_picker: ^1.1.2 diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index 0fda05565ba4..558b11d201cc 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "13.4.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "13.4.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_storage", diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index 5569aa97d60c..ed6ca67264a6 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let library_version = "13.4.0" -let firebase_sdk_version: Version = "12.12.0" +let library_version = "13.4.1" +let firebase_sdk_version: Version = "12.13.0" let package = Package( name: "firebase_storage", diff --git a/packages/firebase_storage/firebase_storage/pubspec.yaml b/packages/firebase_storage/firebase_storage/pubspec.yaml index a698bdd04c9d..aa7e95ddf6a0 100755 --- a/packages/firebase_storage/firebase_storage/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS. homepage: https://firebase.google.com/docs/storage/flutter/start repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage -version: 13.4.0 +version: 13.4.1 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_storage_platform_interface: ^6.0.0 - firebase_storage_web: ^3.11.6 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_storage_platform_interface: ^6.0.1 + firebase_storage_web: ^3.11.7 flutter: sdk: flutter mime: ^2.0.0 diff --git a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md index 9008299eb1e2..874fe6e1ada0 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.1 + + - Update a dependency to the latest release. + ## 6.0.0 - Bump platform interface a major version due to pigeon dependency update diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml index 1041d449a45c..af00a3c9e543 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_storage_platform_interface description: A common platform interface for the firebase_storage plugin. -version: 6.0.0 +version: 6.0.1 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.70 + _flutterfire_internals: ^1.3.71 collection: ^1.15.0 - firebase_core: ^4.8.0 + firebase_core: ^4.9.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md index fb520c0cea23..a889f580d928 100644 --- a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.11.7 + + - Update a dependency to the latest release. + ## 3.11.6 - **REFACTOR**: move all packages to workspace ([#18182](https://github.com/firebase/flutterfire/issues/18182)). ([6cdfcb10](https://github.com/firebase/flutterfire/commit/6cdfcb103da7be46ccb190d7e107d8c537aa1ff8)) diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart index bf42ef7f07b7..33d7d894e4ca 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '13.4.0'; +const packageVersion = '13.4.1'; diff --git a/packages/firebase_storage/firebase_storage_web/pubspec.yaml b/packages/firebase_storage/firebase_storage_web/pubspec.yaml index b04c7bebe487..e3f15ed83188 100644 --- a/packages/firebase_storage/firebase_storage_web/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_storage_web description: The web implementation of firebase_storage homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web -version: 3.11.6 +version: 3.11.7 resolution: workspace environment: @@ -10,11 +10,11 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.70 + _flutterfire_internals: ^1.3.71 async: ^2.5.0 - firebase_core: ^4.8.0 - firebase_core_web: ^3.6.1 - firebase_storage_platform_interface: ^6.0.0 + firebase_core: ^4.9.0 + firebase_core_web: ^3.7.0 + firebase_storage_platform_interface: ^6.0.1 flutter: sdk: flutter flutter_web_plugins: @@ -24,7 +24,7 @@ dependencies: web: ^1.0.0 dev_dependencies: - firebase_core_platform_interface: ^7.0.0 + firebase_core_platform_interface: ^7.0.1 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/scripts/versions.json b/scripts/versions.json index 86184bf473f3..b166da5bc116 100644 --- a/scripts/versions.json +++ b/scripts/versions.json @@ -1,4 +1,32 @@ { + "4.14.0": { + "date": "2026-05-14", + "firebase_sdk": { + "android": "34.13.0", + "ios": "12.13.0", + "web": "12.13.0", + "windows": "13.5.0" + }, + "packages": { + "cloud_firestore": "6.4.1", + "cloud_functions": "6.3.1", + "firebase_ai": "3.12.1", + "firebase_analytics": "12.4.1", + "firebase_app_check": "0.4.4+1", + "firebase_app_installations": "0.4.2+2", + "firebase_auth": "6.5.1", + "firebase_core": "4.9.0", + "firebase_crashlytics": "5.2.2", + "firebase_data_connect": "0.3.0+2", + "firebase_database": "12.4.1", + "firebase_in_app_messaging": "0.9.2+2", + "firebase_messaging": "16.2.2", + "firebase_ml_model_downloader": "0.4.2+2", + "firebase_performance": "0.11.4+1", + "firebase_remote_config": "6.5.1", + "firebase_storage": "13.4.1" + } + }, "4.13.0": { "date": "2026-05-11", "firebase_sdk": { diff --git a/tests/pubspec.yaml b/tests/pubspec.yaml index 334e9463b8de..523e10d067ba 100644 --- a/tests/pubspec.yaml +++ b/tests/pubspec.yaml @@ -10,43 +10,43 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions: ^6.3.0 - cloud_functions_platform_interface: ^6.0.0 - cloud_functions_web: ^5.1.6 + cloud_functions: ^6.3.1 + cloud_functions_platform_interface: ^6.0.1 + cloud_functions_web: ^5.1.7 collection: ^1.15.0 - firebase_ai: ^3.12.0 - firebase_analytics: ^12.4.0 - firebase_analytics_platform_interface: ^6.0.0 - firebase_analytics_web: ^0.6.1+6 - firebase_app_check: ^0.4.4 - firebase_app_check_platform_interface: ^0.4.0 - firebase_app_check_web: ^0.2.4+1 - firebase_app_installations: ^0.4.2+1 - firebase_app_installations_platform_interface: ^0.1.4+69 - firebase_app_installations_web: ^0.1.7+6 - firebase_auth: ^6.5.0 - firebase_auth_platform_interface: ^9.0.0 - firebase_auth_web: ^6.2.0 - firebase_core: ^4.8.0 - firebase_core_platform_interface: ^7.0.0 - firebase_core_web: ^3.6.1 - firebase_crashlytics: ^5.2.1 - firebase_crashlytics_platform_interface: ^3.8.21 - firebase_database: ^12.4.0 - firebase_database_platform_interface: ^0.4.0 - firebase_database_web: ^0.2.7+7 - firebase_messaging: ^16.2.1 - firebase_messaging_platform_interface: ^4.7.10 - firebase_messaging_web: ^4.1.6 - firebase_ml_model_downloader: ^0.4.2+1 - firebase_ml_model_downloader_platform_interface: ^0.1.5+21 - firebase_performance: ^0.11.4 - firebase_remote_config: ^6.5.0 - firebase_remote_config_platform_interface: ^3.0.0 - firebase_remote_config_web: ^1.10.7 - firebase_storage: ^13.4.0 - firebase_storage_platform_interface: ^6.0.0 - firebase_storage_web: ^3.11.6 + firebase_ai: ^3.12.1 + firebase_analytics: ^12.4.1 + firebase_analytics_platform_interface: ^6.0.1 + firebase_analytics_web: ^0.6.1+7 + firebase_app_check: ^0.4.4+1 + firebase_app_check_platform_interface: ^0.4.0+1 + firebase_app_check_web: ^0.2.4+2 + firebase_app_installations: ^0.4.2+2 + firebase_app_installations_platform_interface: ^0.1.4+70 + firebase_app_installations_web: ^0.1.7+7 + firebase_auth: ^6.5.1 + firebase_auth_platform_interface: ^9.0.1 + firebase_auth_web: ^6.2.1 + firebase_core: ^4.9.0 + firebase_core_platform_interface: ^7.0.1 + firebase_core_web: ^3.7.0 + firebase_crashlytics: ^5.2.2 + firebase_crashlytics_platform_interface: ^3.8.22 + firebase_database: ^12.4.1 + firebase_database_platform_interface: ^0.4.0+1 + firebase_database_web: ^0.2.7+8 + firebase_messaging: ^16.2.2 + firebase_messaging_platform_interface: ^4.7.11 + firebase_messaging_web: ^4.1.7 + firebase_ml_model_downloader: ^0.4.2+2 + firebase_ml_model_downloader_platform_interface: ^0.1.5+22 + firebase_performance: ^0.11.4+1 + firebase_remote_config: ^6.5.1 + firebase_remote_config_platform_interface: ^3.0.1 + firebase_remote_config_web: ^1.10.8 + firebase_storage: ^13.4.1 + firebase_storage_platform_interface: ^6.0.1 + firebase_storage_web: ^3.11.7 flutter: sdk: flutter http: ^1.0.0 From 1c84019a3ca89859da20c8c411846f8b53c915e8 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Thu, 14 May 2026 10:20:17 -0700 Subject: [PATCH 078/137] chore(firebaseai): remove camera_macos from example app to make it spm compatible (#18284) * remove camera_macos to make example app spm compatible * update * format file * chore: restore 4 xcconfig files to main branch state Restores the optional CocoaPods include lines in Debug/Release xcconfig files for iOS and macOS. This prevents the Flutter tooling from automatically modifying these files during pub get, keeping the CI formatting validation green while still keeping CocoaPods deintegrated. TAG=agy CONV=07c55d15-cc16-4a94-8a17-0c70d3883f3d --- .../firebase_ai/example/ios/Podfile | 43 --------- .../example/lib/pages/bidi_page.dart | 81 ++++++---------- .../example/lib/utils/video_input.dart | 25 ++--- .../example/lib/widgets/camera_previews.dart | 37 +------- .../firebase_ai/example/macos/Podfile | 42 -------- .../macos/Runner.xcodeproj/project.pbxproj | 95 ------------------- .../firebase_ai/example/pubspec.yaml | 1 - 7 files changed, 37 insertions(+), 287 deletions(-) delete mode 100644 packages/firebase_ai/firebase_ai/example/ios/Podfile delete mode 100644 packages/firebase_ai/firebase_ai/example/macos/Podfile diff --git a/packages/firebase_ai/firebase_ai/example/ios/Podfile b/packages/firebase_ai/firebase_ai/example/ios/Podfile deleted file mode 100644 index 9d7ef08d52b2..000000000000 --- a/packages/firebase_ai/firebase_ai/example/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '15.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -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 - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart index 82286cc60b97..56c7e950d0ce 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/bidi_page.dart @@ -45,10 +45,6 @@ class BidiMediaManager { String? get selectedCameraId => _videoInput.selectedCameraId; bool get controllerInitialized => _videoInput.controllerInitialized; - void setMacOSController(dynamic controller) { - _videoInput.setMacOSController(controller); - } - Future init() async { try { await _audioOutput.init(); @@ -98,6 +94,7 @@ class BidiMediaManager { } Future startVideo(void Function(Uint8List, String) onData) async { + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) return; if (!videoIsInitialized) return; if (!_videoInput.controllerInitialized || @@ -105,31 +102,12 @@ class BidiMediaManager { await _videoInput.initializeCameraController(); } - if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - int attempts = 0; - while (_videoInput.cameraController == null) { - if (attempts > 50) { - developer.log( - 'BidiMediaManager.startVideo(): macOS camera controller initialization timed out after 50 attempts.', - ); - break; // 5 second timeout safety - } - await Future.delayed(const Duration(milliseconds: 100)); - attempts++; - } - } - // Wait for Mac Camera to Settle (Prevent audio hijack) await Future.delayed(const Duration(milliseconds: 1000)); _videoSubscription = _videoInput.startStreamingImages().listen( (data) { String mimeType = 'image/jpeg'; - if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - if (data.length > 3 && data[0] == 0x89 && data[1] == 0x50) { - mimeType = 'image/png'; - } - } onData(data, mimeType); }, onError: (e) => developer.log('Video Stream Error: $e'), @@ -174,6 +152,14 @@ class BidiSessionController extends ChangeNotifier { bool isSessionActive = false; bool isMicOn = false; bool isCameraOn = false; + bool _isDisposed = false; + + @override + void notifyListeners() { + if (!_isDisposed) { + super.notifyListeners(); + } + } // Intention state for robust stream reconnection bool _intendedMicOn = false; @@ -545,6 +531,7 @@ class BidiSessionController extends ChangeNotifier { @override void dispose() { + _isDisposed = true; _stopSession(explicit: true); super.dispose(); } @@ -675,26 +662,14 @@ class _BidiPageState extends State { height: 200, color: Colors.black, alignment: Alignment.center, - child: (!kIsWeb && - defaultTargetPlatform == TargetPlatform.macOS) + child: (_controller.mediaManager.cameraController != null && + _controller.mediaManager.controllerInitialized) ? FullCameraPreview( controller: _controller.mediaManager.cameraController, deviceId: _controller.mediaManager.selectedCameraId, - onInitialized: (controller) { - _controller.mediaManager - .setMacOSController(controller); - }, + onInitialized: (controller) {}, ) - : (_controller.mediaManager.cameraController != null && - _controller.mediaManager.controllerInitialized) - ? FullCameraPreview( - controller: - _controller.mediaManager.cameraController, - deviceId: - _controller.mediaManager.selectedCameraId, - onInitialized: (controller) {}, - ) - : const Center(child: CircularProgressIndicator()), + : const Center(child: CircularProgressIndicator()), ), Expanded( child: ListView.builder( @@ -762,20 +737,22 @@ class _BidiPageState extends State { : Theme.of(context).colorScheme.primary, ), ), - IconButton( - tooltip: 'Toggle Camera', - onPressed: !_controller.isLoading - ? () => _controller.toggleCamera() - : null, - icon: Icon( - _controller.isCameraOn - ? Icons.videocam_off - : Icons.videocam, - color: _controller.isLoading - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.primary, + if (!(!kIsWeb && + defaultTargetPlatform == TargetPlatform.macOS)) + IconButton( + tooltip: 'Toggle Camera', + onPressed: !_controller.isLoading + ? () => _controller.toggleCamera() + : null, + icon: Icon( + _controller.isCameraOn + ? Icons.videocam_off + : Icons.videocam, + color: _controller.isLoading + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.primary, + ), ), - ), if (!_controller.isLoading) IconButton( tooltip: 'Send Text', diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/video_input.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/video_input.dart index 97dc8108343b..a04f961b6f9e 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/utils/video_input.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/utils/video_input.dart @@ -15,7 +15,6 @@ import 'dart:developer'; import 'dart:async'; import 'package:camera/camera.dart'; -import 'package:camera_macos/camera_macos.dart'; import 'package:flutter/foundation.dart'; class VideoInput extends ChangeNotifier { @@ -34,8 +33,7 @@ class VideoInput extends ChangeNotifier { Future init() async { try { if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - //await camera_macos_lib.loadLibrary(); - _cameras = await CameraMacOS.instance.listDevices(); + _cameras = []; } else { _cameras = await availableCameras(); } @@ -53,7 +51,7 @@ class VideoInput extends ChangeNotifier { stopStreamingImages(); if (controllerInitialized && _cameraController != null) { if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - (_cameraController as CameraMacOSController).destroy(); + // No-op on macOS } else { (_cameraController as CameraController).dispose(); } @@ -63,7 +61,7 @@ class VideoInput extends ChangeNotifier { String? get selectedCameraId { if (_selectedCamera == null) return null; if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - return _selectedCamera.deviceId; + return null; } return null; } @@ -77,7 +75,7 @@ class VideoInput extends ChangeNotifier { Future initializeCameraController() async { if (controllerInitialized && _cameraController != null) { if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - await (_cameraController as CameraMacOSController).destroy(); + // No-op on macOS } else { await (_cameraController as CameraController).dispose(); } @@ -142,13 +140,7 @@ class VideoInput extends ChangeNotifier { try { if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - final controller = _cameraController as CameraMacOSController; - final CameraMacOSFile? image = await controller.takePicture(); - if (image != null && image.bytes != null) { - if (!_imageStreamController.isClosed) { - _imageStreamController.add(image.bytes!); - } - } + // No-op on macOS } else { final controller = _cameraController as CameraController; if (controller.value.isTakingPicture) return; @@ -197,12 +189,7 @@ class VideoInput extends ChangeNotifier { Future flipCamera() async { if (_cameras.length > 1) { if (!kIsWeb && defaultTargetPlatform == TargetPlatform.macOS) { - final currentSelected = _selectedCamera; - final otherCamera = _cameras.firstWhere( - (camera) => camera.deviceId != currentSelected.deviceId, - orElse: () => _cameras[0], - ); - _selectedCamera = otherCamera; + // No-op on macOS } else { final currentSelected = _selectedCamera as CameraDescription; final otherCamera = _cameras.firstWhere( diff --git a/packages/firebase_ai/firebase_ai/example/lib/widgets/camera_previews.dart b/packages/firebase_ai/firebase_ai/example/lib/widgets/camera_previews.dart index 5bf338f7e345..5aa42d1c8c81 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/widgets/camera_previews.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/widgets/camera_previews.dart @@ -13,7 +13,6 @@ // limitations under the License. import 'package:camera/camera.dart'; -import 'package:camera_macos/camera_macos.dart' deferred as camera_macos_lib; import 'package:flutter/foundation.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter/material.dart'; @@ -58,24 +57,7 @@ class SquareCameraPreview extends StatelessWidget { scale: aspectRatio / 1, child: Center( child: !kIsWeb && defaultTargetPlatform == TargetPlatform.macOS - ? FutureBuilder( - future: camera_macos_lib.loadLibrary(), - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.done) { - return camera_macos_lib.CameraMacOSView( - deviceId: deviceId, - cameraMode: - camera_macos_lib.CameraMacOSMode.photo, - enableAudio: false, - onCameraInizialized: (dynamic controller) { - onInitialized?.call(controller); - }, - ); - } - return const SizedBox.shrink(); - }, - ) + ? const SizedBox.shrink() : CameraPreview(controller as CameraController), ), ), @@ -128,22 +110,7 @@ class _FullCameraPreviewState extends State child: ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(16)), child: !kIsWeb && defaultTargetPlatform == TargetPlatform.macOS - ? FutureBuilder( - future: camera_macos_lib.loadLibrary(), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return camera_macos_lib.CameraMacOSView( - deviceId: widget.deviceId, - cameraMode: camera_macos_lib.CameraMacOSMode.photo, - enableAudio: false, - onCameraInizialized: (dynamic controller) { - widget.onInitialized?.call(controller); - }, - ); - } - return const SizedBox.shrink(); - }, - ) + ? const SizedBox.shrink() : CameraPreview(widget.controller as CameraController), ), ).animate(controller: _animController).scaleXY().fadeIn(); diff --git a/packages/firebase_ai/firebase_ai/example/macos/Podfile b/packages/firebase_ai/firebase_ai/example/macos/Podfile deleted file mode 100644 index ff5ddb3b8bdc..000000000000 --- a/packages/firebase_ai/firebase_ai/example/macos/Podfile +++ /dev/null @@ -1,42 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', '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 - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj index ec242319b9f2..e2ab2e60ccd7 100644 --- a/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_ai/firebase_ai/example/macos/Runner.xcodeproj/project.pbxproj @@ -28,9 +28,7 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - 6082D6A2424808FAB6E3B40E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F13D669ACC8FC703D4CBD2B /* Pods_RunnerTests.framework */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - BA2210317853BF792876863E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BDA2E1C29AC310A4E4CA25D /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -64,7 +62,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 04B3ABBBAF38CA994D530720 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; @@ -82,18 +79,11 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 6BDA2E1C29AC310A4E4CA25D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; 78DABEA22ED26510000E7860 /* firebase_ai */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = firebase_ai; path = ../../macos/firebase_ai; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; - 78E1BE5D41B29A94BA269C92 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 7C0CE262A0120B333635758B /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 8F13D669ACC8FC703D4CBD2B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A0F3F679E482301241F3BFCA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - D93CB9EA3E846CDBCE7957C5 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - FD6782CE9C57EE952FDAD106 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,7 +91,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 6082D6A2424808FAB6E3B40E /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -110,7 +99,6 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, - BA2210317853BF792876863E /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -145,7 +133,6 @@ 33CC10EE2044A3C60003C045 /* Products */, 08B0491E23641E5BA5DD096C /* GoogleService-Info.plist */, BE277C424FC00920BE07E371 /* Pods */, - F8E2296ED7CFF382BC7C9532 /* Frameworks */, ); sourceTree = ""; }; @@ -199,25 +186,10 @@ BE277C424FC00920BE07E371 /* Pods */ = { isa = PBXGroup; children = ( - FD6782CE9C57EE952FDAD106 /* Pods-Runner.debug.xcconfig */, - 04B3ABBBAF38CA994D530720 /* Pods-Runner.release.xcconfig */, - D93CB9EA3E846CDBCE7957C5 /* Pods-Runner.profile.xcconfig */, - A0F3F679E482301241F3BFCA /* Pods-RunnerTests.debug.xcconfig */, - 7C0CE262A0120B333635758B /* Pods-RunnerTests.release.xcconfig */, - 78E1BE5D41B29A94BA269C92 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; - F8E2296ED7CFF382BC7C9532 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 6BDA2E1C29AC310A4E4CA25D /* Pods_Runner.framework */, - 8F13D669ACC8FC703D4CBD2B /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -225,7 +197,6 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 6E1E43E2156EDE8E42E46577 /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -244,13 +215,11 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 0669F8635DD580A741D5C18E /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - D3CB4FECFB8507DF5BD41289 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -340,28 +309,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 0669F8635DD580A741D5C18E /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -400,45 +347,6 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - 6E1E43E2156EDE8E42E46577 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - D3CB4FECFB8507DF5BD41289 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -490,7 +398,6 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A0F3F679E482301241F3BFCA /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -505,7 +412,6 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7C0CE262A0120B333635758B /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -520,7 +426,6 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 78E1BE5D41B29A94BA269C92 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index 005ca2575920..d87320464c2c 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -22,7 +22,6 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. camera: ^0.12.0+1 - camera_macos: ^0.0.9 cupertino_icons: ^1.0.6 firebase_ai: ^3.12.1 firebase_core: ^4.9.0 From 599ccfe5b3bfea0a8e30bb8197e401d2ca0c501e Mon Sep 17 00:00:00 2001 From: Aashish <112133849+aashishpatil-g@users.noreply.github.com> Date: Wed, 20 May 2026 10:02:45 -0700 Subject: [PATCH 079/137] chore: Update sqlite3 version dependency (#18291) --- .../firebase_data_connect/firebase_data_connect/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index 3a398dc706a7..694bfc257fbd 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -26,8 +26,7 @@ dependencies: path: ^1.9.0 path_provider: ^2.0.0 protobuf: ^3.1.0 - sqlite3: ^2.9.0 - sqlite3_flutter_libs: ^0.5.40 + sqlite3: ^3.1.0 web_socket_channel: ^3.0.1 dev_dependencies: From 6718923e9827630e7f5ffdb0e675948d21665aa1 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 21 May 2026 10:06:44 +0000 Subject: [PATCH 080/137] chore: update flutter version to 3.41.6 in CI workflows to unblock builds (#18302) --- .github/workflows/all_plugins.yaml | 2 ++ .github/workflows/e2e_tests_pipeline.yaml | 3 +++ .github/workflows/ios.yaml | 1 + .github/workflows/macos.yaml | 1 + 4 files changed, 7 insertions(+) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index a4a2e1ba8819..91d89e24b8ba 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -125,6 +125,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' + flutter-version: '3.41.6' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" @@ -146,6 +147,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' + flutter-version: '3.41.6' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index 421bb39fddb9..a82dc15a3ac3 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -45,6 +45,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' + flutter-version: '3.41.6' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" @@ -122,6 +123,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' + flutter-version: '3.41.6' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" @@ -173,6 +175,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' + flutter-version: '3.41.6' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 3848bfce7b76..133cb917e164 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -86,6 +86,7 @@ jobs: with: channel: 'stable' cache: true + flutter-version: '3.41.6' cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index 9c89e457553c..7187d648e7aa 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -83,6 +83,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' + flutter-version: '3.41.6' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" From 4e4186c31f27fcba9b391a61b4fd847eab898ea2 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Fri, 22 May 2026 08:48:18 +0000 Subject: [PATCH 081/137] chore: update flutter version to 3.41.9 in CI workflows (#18303) * chore: update flutter version to 3.41.6 in CI workflows to unblock builds * chore: update flutter version to 3.41.9 in CI workflows --- .github/workflows/all_plugins.yaml | 4 ++-- .github/workflows/e2e_tests_pipeline.yaml | 6 +++--- .github/workflows/ios.yaml | 2 +- .github/workflows/macos.yaml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 91d89e24b8ba..df1427acee93 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -125,7 +125,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' - flutter-version: '3.41.6' + flutter-version: '3.41.9' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" @@ -147,7 +147,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' - flutter-version: '3.41.6' + flutter-version: '3.41.9' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index a82dc15a3ac3..dc72a114b741 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -45,7 +45,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' - flutter-version: '3.41.6' + flutter-version: '3.41.9' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" @@ -123,7 +123,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' - flutter-version: '3.41.6' + flutter-version: '3.41.9' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" @@ -175,7 +175,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' - flutter-version: '3.41.6' + flutter-version: '3.41.9' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 133cb917e164..e4df80563f19 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -86,7 +86,7 @@ jobs: with: channel: 'stable' cache: true - flutter-version: '3.41.6' + flutter-version: '3.41.9' cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index 7187d648e7aa..15385fcc6c1c 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -83,7 +83,7 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' - flutter-version: '3.41.6' + flutter-version: '3.41.9' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" From df229d32f0c1cc23340011908c189f43ef828274 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 09:55:57 +0000 Subject: [PATCH 082/137] chore(deps): bump protobufjs (#18300) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.5.5 to 7.6.0. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/protobufjs-v7.6.0/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.5...protobufjs-v7.6.0) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.6.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../example/bundled-service-worker/yarn.lock | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock index c56b1050efcc..2b3d27d8e5b1 100644 --- a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock +++ b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock @@ -546,33 +546,32 @@ resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== -"@protobufjs/codegen@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" - integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== +"@protobufjs/codegen@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.5.tgz#d9315ad7cf3f30aac70bda3c068443dc6f143659" + integrity sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g== "@protobufjs/eventemitter@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== -"@protobufjs/fetch@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" - integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== +"@protobufjs/fetch@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.1.tgz#4d6fc00c8fb64016a5c81b469d549046350f1065" + integrity sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw== dependencies: "@protobufjs/aspromise" "^1.1.1" - "@protobufjs/inquire" "^1.1.0" "@protobufjs/float@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== -"@protobufjs/inquire@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" - integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== +"@protobufjs/inquire@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.2.tgz#ae64fbc014ff44c8bfad03dd4c93cd2d6a4c82db" + integrity sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw== "@protobufjs/path@^1.1.2": version "1.1.2" @@ -584,10 +583,10 @@ resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== -"@protobufjs/utf8@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" - integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== +"@protobufjs/utf8@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.1.tgz#eaee5900122c110a3dbcb728c0597014a2621774" + integrity sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg== "@types/node@>=12.12.47", "@types/node@>=13.7.0": version "18.8.2" @@ -739,23 +738,28 @@ long@^5.0.0: resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61" integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w== +long@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" + integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== + protobufjs@^7.2.5: - version "7.5.5" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.5.5.tgz#b7089ca4410374c75150baf277353ef76db69f96" - integrity sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg== + version "7.6.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.6.0.tgz#61e42285beec2708a9c84d7abbb5f22e2ddc54d4" + integrity sha512-LtESOsMPTZgyYtwxhvdgdjGL0HmXEaRA/hVD6sol4zA60hVXXXP/SGmxnqDbgGE8gy7pYex7cym+5vYPcmaXBQ== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" + "@protobufjs/codegen" "^2.0.5" "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" + "@protobufjs/fetch" "^1.1.1" "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" + "@protobufjs/inquire" "^1.1.2" "@protobufjs/path" "^1.1.2" "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" + "@protobufjs/utf8" "^1.1.1" "@types/node" ">=13.7.0" - long "^5.0.0" + long "^5.3.2" require-directory@^2.1.1: version "2.1.1" From b5566c42a43bef7650b3cc79be7631e7507a793f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 12:36:56 +0200 Subject: [PATCH 083/137] chore(deps): bump @protobufjs/utf8 (#18275) Bumps [@protobufjs/utf8](https://github.com/dcodeIO/protobuf.js) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/dcodeIO/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/dcodeIO/protobuf.js/compare/protobufjs-cli-v1.1.0...protobufjs-cli-v1.1.1) --- updated-dependencies: - dependency-name: "@protobufjs/utf8" dependency-version: 1.1.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../workflows/scripts/functions/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index d3d1a398ab22..f46a5019e885 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -309,9 +309,9 @@ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==" }, "node_modules/@tootallnate/once": { "version": "2.0.0", @@ -2720,9 +2720,9 @@ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" }, "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==" }, "@tootallnate/once": { "version": "2.0.0", From 094d5d2dad4344bb542a3cad32a11eefdf80b8c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 12:37:11 +0200 Subject: [PATCH 084/137] chore(deps): bump protobufjs in /.github/workflows/scripts/functions (#18280) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.5.5 to 7.5.8. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/protobufjs-v7.5.8/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.5...protobufjs-v7.5.8) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.5.8 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../scripts/functions/package-lock.json | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/scripts/functions/package-lock.json b/.github/workflows/scripts/functions/package-lock.json index f46a5019e885..8d68cfdd20e6 100644 --- a/.github/workflows/scripts/functions/package-lock.json +++ b/.github/workflows/scripts/functions/package-lock.json @@ -270,9 +270,9 @@ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", @@ -294,9 +294,9 @@ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.1.tgz", + "integrity": "sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==" }, "node_modules/@protobufjs/path": { "version": "1.1.2", @@ -1853,21 +1853,21 @@ } }, "node_modules/protobufjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz", - "integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.8.tgz", + "integrity": "sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", + "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", + "@protobufjs/inquire": "^1.1.1", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.0.0" }, @@ -2681,9 +2681,9 @@ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" }, "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==" }, "@protobufjs/eventemitter": { "version": "1.1.0", @@ -2705,9 +2705,9 @@ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" }, "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.1.tgz", + "integrity": "sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==" }, "@protobufjs/path": { "version": "1.1.2", @@ -3887,20 +3887,20 @@ } }, "protobufjs": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.5.tgz", - "integrity": "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.8.tgz", + "integrity": "sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", + "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", + "@protobufjs/inquire": "^1.1.1", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.0.0" } From de98066038020d2170c42bd45b1b772f3fcce708 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 28 May 2026 13:07:37 +0000 Subject: [PATCH 085/137] chore: change firebase-ios-sdk dependency from 'from' to 'exact' version in multiple Package.swift files (#18321) --- .../cloud_firestore/ios/cloud_firestore/Package.swift | 2 +- .../cloud_firestore/macos/cloud_firestore/Package.swift | 2 +- .../cloud_functions/ios/cloud_functions/Package.swift | 2 +- .../cloud_functions/macos/cloud_functions/Package.swift | 2 +- .../firebase_analytics/ios/firebase_analytics/Package.swift | 2 +- .../firebase_analytics/macos/firebase_analytics/Package.swift | 2 +- .../firebase_app_check/ios/firebase_app_check/Package.swift | 2 +- .../firebase_app_check/macos/firebase_app_check/Package.swift | 2 +- .../ios/firebase_app_installations/Package.swift | 2 +- .../macos/firebase_app_installations/Package.swift | 2 +- .../firebase_auth/firebase_auth/ios/firebase_auth/Package.swift | 2 +- .../firebase_auth/macos/firebase_auth/Package.swift | 2 +- .../firebase_core/firebase_core/ios/firebase_core/Package.swift | 2 +- .../firebase_core/macos/firebase_core/Package.swift | 2 +- .../firebase_crashlytics/ios/firebase_crashlytics/Package.swift | 2 +- .../macos/firebase_crashlytics/Package.swift | 2 +- .../firebase_database/ios/firebase_database/Package.swift | 2 +- .../firebase_database/macos/firebase_database/Package.swift | 2 +- .../ios/firebase_in_app_messaging/Package.swift | 2 +- .../firebase_messaging/ios/firebase_messaging/Package.swift | 2 +- .../firebase_messaging/macos/firebase_messaging/Package.swift | 2 +- .../ios/firebase_ml_model_downloader/Package.swift | 2 +- .../macos/firebase_ml_model_downloader/Package.swift | 2 +- .../firebase_performance/ios/firebase_performance/Package.swift | 2 +- .../ios/firebase_remote_config/Package.swift | 2 +- .../macos/firebase_remote_config/Package.swift | 2 +- .../firebase_storage/ios/firebase_storage/Package.swift | 2 +- .../firebase_storage/macos/firebase_storage/Package.swift | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index eeb28d8e1eaa..194345dc4f41 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "cloud-firestore", targets: ["cloud_firestore"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index 744936afe8b1..9f53f0ea7643 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "cloud-firestore", targets: ["cloud_firestore"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift index 13368bccaf73..8771e6f4820b 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "cloud-functions", targets: ["cloud_functions"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift index 9d7ca8dc6440..3290c342486f 100644 --- a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "cloud-functions", targets: ["cloud_functions"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift index 2c161afddcf4..ac1785bfd47d 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift @@ -24,7 +24,7 @@ let package = Package( .library(name: "firebase-analytics", targets: ["firebase_analytics"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift index e3a0c919f39c..7c70beddefc6 100644 --- a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-analytics", targets: ["firebase_analytics"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index 131401563be2..0efbf1751e07 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-app-check", targets: ["firebase_app_check"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift index 31732e86e458..8c3681021df7 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-app-check", targets: ["firebase_app_check"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift index 99fb7e9fc227..10d97417547e 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-app-installations", targets: ["firebase_app_installations"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift index 3931f4954626..aa19a3f19e9a 100644 --- a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-app-installations", targets: ["firebase_app_installations"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index 362b8f5ebda2..4f5d3dff67bc 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-auth", targets: ["firebase_auth"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index deb2d7c07aee..6097c54e634a 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-auth", targets: ["firebase_auth"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index 9a30c9de0e0d..ee5b08632f51 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-core", targets: ["firebase_core"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), ], targets: [ .target( diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index d4b4f2dabcd7..278b94b9dc21 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-core", targets: ["firebase_core"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), ], targets: [ .target( diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index 530638a39b19..c334113d34ad 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-crashlytics", targets: ["firebase_crashlytics"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index 30bb13ffffa6..5a5a02b868c0 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-crashlytics", targets: ["firebase_crashlytics"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index d3e8cb1dd020..f944075b3d48 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-database", targets: ["firebase_database"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index 7e830e552456..84e32568e1ad 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-database", targets: ["firebase_database"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index 7f3d4a19d92b..a36e759a869d 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-in-app-messaging", targets: ["firebase_in_app_messaging"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index 050a4877cbee..c9ed36eff14f 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-messaging", targets: ["firebase_messaging"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index 185f33fee319..0ffc9147fdbe 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-messaging", targets: ["firebase_messaging"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift index b3474aeb3bdf..4231c0422536 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-ml-model-downloader", targets: ["firebase_ml_model_downloader"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift index ef5ecc229031..2780cfb8ccbf 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-ml-model-downloader", targets: ["firebase_ml_model_downloader"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index 41a2ebc7f194..ed7ec080a700 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-performance", targets: ["firebase_performance"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift index 80dab6140218..cb2906a259c5 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-remote-config", targets: ["firebase_remote_config"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift index 39778eadf02f..8f7084f34b64 100644 --- a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift @@ -18,7 +18,7 @@ let package = Package( .library(name: "firebase-remote-config", targets: ["firebase_remote_config"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index 558b11d201cc..cbd515861729 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-storage", targets: ["firebase_storage"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index ed6ca67264a6..37f3c0dd99a3 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -19,7 +19,7 @@ let package = Package( .library(name: "firebase-storage", targets: ["firebase_storage"]), ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ From 3de82fca8e30ed4cb8dd38ce729d5a3feba2cbe8 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Fri, 29 May 2026 09:32:34 +0000 Subject: [PATCH 086/137] chore: update Kotlin version and AGP compatibility across plugins' Android build.gradle files (#18307) * chore: update Kotlin version and AGP compatibility across plugins' Android build.gradle files * chore: update Firebase Gradle plugin versions in pubspec.yaml * chore: trigger CI --- .../cloud_functions/android/build.gradle | 24 ++++++++++++------- .../firebase_ai/android/build.gradle | 22 ++++++++++------- .../firebase_analytics/android/build.gradle | 24 ++++++++++++------- .../firebase_app_check/android/build.gradle | 24 ++++++++++++------- .../firebase_core/firebase_core/pubspec.yaml | 6 ++--- .../firebase_database/android/build.gradle | 22 ++++++++++------- .../firebase_performance/android/build.gradle | 24 ++++++++++++------- .../android/build.gradle | 24 ++++++++++++------- .../firebase_storage/android/build.gradle | 24 ++++++++++++------- 9 files changed, 121 insertions(+), 73 deletions(-) diff --git a/packages/cloud_functions/cloud_functions/android/build.gradle b/packages/cloud_functions/cloud_functions/android/build.gradle index 9d1295a9567c..0e60c55e34f4 100644 --- a/packages/cloud_functions/cloud_functions/android/build.gradle +++ b/packages/cloud_functions/cloud_functions/android/build.gradle @@ -4,14 +4,18 @@ version '1.0-SNAPSHOT' apply plugin: 'com.android.library' apply from: file("local-config.gradle") -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } buildscript { - ext.kotlin_version = "1.8.22" + ext.kotlin_version = "2.0.0" repositories { google() mavenCentral() @@ -61,12 +65,6 @@ android { targetCompatibility project.ext.javaVersion } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - sourceSets { main.java.srcDirs += "src/main/kotlin" test.java.srcDirs += "src/test/kotlin" @@ -90,4 +88,12 @@ android { } +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} + apply from: file("./user-agent.gradle") \ No newline at end of file diff --git a/packages/firebase_ai/firebase_ai/android/build.gradle b/packages/firebase_ai/firebase_ai/android/build.gradle index 13affc9f6740..278104b4b9c2 100644 --- a/packages/firebase_ai/firebase_ai/android/build.gradle +++ b/packages/firebase_ai/firebase_ai/android/build.gradle @@ -4,9 +4,13 @@ version '1.0-SNAPSHOT' apply plugin: 'com.android.library' apply from: file("local-config.gradle") -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } @@ -33,12 +37,6 @@ android { targetCompatibility project.ext.javaVersion } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - sourceSets { main.java.srcDirs += "src/main/kotlin" } @@ -47,3 +45,11 @@ android { disable 'InvalidPackage' } } + +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} diff --git a/packages/firebase_analytics/firebase_analytics/android/build.gradle b/packages/firebase_analytics/firebase_analytics/android/build.gradle index 183ea4605c04..189e57e43906 100755 --- a/packages/firebase_analytics/firebase_analytics/android/build.gradle +++ b/packages/firebase_analytics/firebase_analytics/android/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'com.android.library' apply from: file("local-config.gradle") buildscript { - ext.kotlin_version = "1.8.22" + ext.kotlin_version = "2.0.0" repositories { google() mavenCentral() @@ -26,9 +26,13 @@ rootProject.allprojects { apply plugin: 'com.android.library' -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } @@ -58,12 +62,6 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - compileOptions { sourceCompatibility project.ext.javaVersion targetCompatibility project.ext.javaVersion @@ -90,4 +88,12 @@ android { } } +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} + apply from: file("./user-agent.gradle") \ No newline at end of file diff --git a/packages/firebase_app_check/firebase_app_check/android/build.gradle b/packages/firebase_app_check/firebase_app_check/android/build.gradle index 45c2fa4d6345..d4fdbc15fca9 100644 --- a/packages/firebase_app_check/firebase_app_check/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/android/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'com.android.library' apply from: file("local-config.gradle") buildscript { - ext.kotlin_version = "1.8.22" + ext.kotlin_version = "2.0.0" repositories { google() mavenCentral() @@ -19,9 +19,13 @@ rootProject.allprojects { } } -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } @@ -51,12 +55,6 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - compileOptions { sourceCompatibility project.ext.javaVersion targetCompatibility project.ext.javaVersion @@ -84,4 +82,12 @@ android { } } +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} + apply from: file("./user-agent.gradle") diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index da72c2a4a28f..2cf60e9921b3 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -45,6 +45,6 @@ flutter: pluginClass: FirebaseCorePluginCApi firebase: - google_services_gradle_plugin_version: '4.3.15' - crashlytics_gradle_plugin_version: '2.8.1' - performance_gradle_plugin_version: '1.4.1' + google_services_gradle_plugin_version: '4.4.4' + crashlytics_gradle_plugin_version: '3.0.7' + performance_gradle_plugin_version: '2.0.2' diff --git a/packages/firebase_database/firebase_database/android/build.gradle b/packages/firebase_database/firebase_database/android/build.gradle index 4826a7d16f7a..a0db4c898a25 100755 --- a/packages/firebase_database/firebase_database/android/build.gradle +++ b/packages/firebase_database/firebase_database/android/build.gradle @@ -4,9 +4,13 @@ version '1.0-SNAPSHOT' apply plugin: 'com.android.library' apply from: file("local-config.gradle") -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } @@ -55,12 +59,6 @@ android { targetCompatibility project.ext.javaVersion } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - sourceSets { main { java { @@ -85,5 +83,13 @@ android { } } +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} + apply from: file("./user-agent.gradle") diff --git a/packages/firebase_performance/firebase_performance/android/build.gradle b/packages/firebase_performance/firebase_performance/android/build.gradle index 6d38c5620117..5f74989e1448 100644 --- a/packages/firebase_performance/firebase_performance/android/build.gradle +++ b/packages/firebase_performance/firebase_performance/android/build.gradle @@ -4,14 +4,18 @@ version '1.0-SNAPSHOT' apply plugin: 'com.android.library' apply from: file("local-config.gradle") -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } buildscript { - ext.kotlin_version = "1.8.22" + ext.kotlin_version = "2.0.0" repositories { google() @@ -60,12 +64,6 @@ android { targetCompatibility project.ext.javaVersion } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - sourceSets { main.java.srcDirs += "src/main/kotlin" test.java.srcDirs += "src/test/kotlin" @@ -87,4 +85,12 @@ android { } } +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} + apply from: file("./user-agent.gradle") diff --git a/packages/firebase_remote_config/firebase_remote_config/android/build.gradle b/packages/firebase_remote_config/firebase_remote_config/android/build.gradle index a03f8e444446..d2a0aa74e23c 100644 --- a/packages/firebase_remote_config/firebase_remote_config/android/build.gradle +++ b/packages/firebase_remote_config/firebase_remote_config/android/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'com.android.library' apply from: file("local-config.gradle") buildscript { - ext.kotlin_version = "1.8.22" + ext.kotlin_version = "2.0.0" repositories { google() mavenCentral() @@ -19,9 +19,13 @@ rootProject.allprojects { } } -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } @@ -51,12 +55,6 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - compileOptions { sourceCompatibility project.ext.javaVersion targetCompatibility project.ext.javaVersion @@ -83,4 +81,12 @@ android { } } +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} + apply from: file("./user-agent.gradle") diff --git a/packages/firebase_storage/firebase_storage/android/build.gradle b/packages/firebase_storage/firebase_storage/android/build.gradle index c9e5b5e5940d..f041bc40275b 100755 --- a/packages/firebase_storage/firebase_storage/android/build.gradle +++ b/packages/firebase_storage/firebase_storage/android/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'com.android.library' apply from: file("local-config.gradle") buildscript { - ext.kotlin_version = "1.8.22" + ext.kotlin_version = "2.0.0" repositories { google() mavenCentral() @@ -44,9 +44,13 @@ def getRootProjectExtOrCoreProperty(name, firebaseCoreProject) { return rootProject.ext.get('FlutterFire').get(name) } -// AGP 9+ has built-in Kotlin support; older versions need the plugin explicitly. +// AGP 9+ has built-in Kotlin support unless Flutter opts out via android.builtInKotlin=false. def agpMajor = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0] as int -if (agpMajor < 9) { +def builtInKotlin = providers.gradleProperty("android.builtInKotlin") + .map { it.toBoolean() } + .orElse(agpMajor >= 9) + .get() +if (agpMajor < 9 || !builtInKotlin) { apply plugin: 'kotlin-android' } @@ -63,12 +67,6 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - if (agpMajor < 9) { - kotlinOptions { - jvmTarget = project.ext.javaVersion - } - } - compileOptions { sourceCompatibility project.ext.javaVersion targetCompatibility project.ext.javaVersion @@ -95,4 +93,12 @@ android { } } +plugins.withId("org.jetbrains.kotlin.android") { + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.fromTarget(project.ext.javaVersion.toString()) + } + } +} + apply from: file("./user-agent.gradle") From 62699cc2cfbc4544f1d06b64f759955aacf9f877 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Fri, 29 May 2026 13:04:46 +0000 Subject: [PATCH 087/137] chore: update CI to fetch base history for flutter_plugin_tools format and apply formatting (#18322) * chore: update CI to fetch base history for flutter_plugin_tools format and apply formatting * fix formatting * chore: increase timeout for format job in CI workflow from 20 to 30 minutes * fix formatting * chore: change firebase-ios-sdk dependency from 'from' to 'exact' version in multiple Package.swift files * chore: increase timeout for analyze job in CI workflow from 45 to 50 minutes * chore: update swiftformat command to exclude specific directories in CI workflow * fix formatting * refactor: update pattern matching syntax in Swift files to use `case .success(let value)` and `case .failure(let error)` for consistency; adjust swiftformat configuration to disable additional rules * refactor: standardize formatting in Swift files and update CI workflow to include Swift in formatting checks * chore: add step to clean generated build artifacts in CI workflow * chore: reduce timeout for analyze job in CI workflow from 50 to 40 minutes * chore: increase timeout for analyze job in CI workflow from 40 to 50 minutes --- .github/workflows/all_plugins.yaml | 20 +- .swiftformat | 3 +- .../FlutterFirebaseFirestoreException.java | 25 +- .../FlutterFirebaseFirestoreMessageCodec.java | 6 +- .../FlutterFirebaseFirestorePlugin.java | 9 +- .../GeneratedAndroidFirebaseFirestore.java | 4 + .../firestore/utils/PigeonParser.java | 3 +- .../firestore/example/MainActivity.kt | 2 +- .../example/ios/Runner/AppDelegate.swift | 2 +- .../ios/cloud_firestore/Package.swift | 16 +- .../macos/cloud_firestore/Package.swift | 16 +- .../ios/Runner/AppDelegate.swift | 2 +- .../FirebaseFunctionsStreamHandler.kt | 15 +- .../functions/FlutterFirebaseAppRegistrar.kt | 3 +- .../FlutterFirebaseFunctionsPlugin.kt | 76 +- .../GeneratedAndroidCloudFunctions.g.kt | 63 +- .../functions/StreamResponseSubscriber.kt | 3 +- .../functions/example/MainActivity.kt | 2 +- .../ios/cloud_functions/Package.swift | 12 +- .../CloudFunctionsMessages.g.swift | 23 +- .../FirebaseFunctionsPlugin.swift | 41 +- .../FunctionsStreamHandler.swift | 61 +- .../macos/cloud_functions/Package.swift | 12 +- .../plugins/firebase/ai/FirebaseAIPlugin.kt | 113 ++- .../example/ios/Runner/AppDelegate.swift | 2 +- .../firebase_ai/ios/firebase_ai/Package.swift | 8 +- .../macos/firebase_ai/Package.swift | 8 +- .../plugins/firebase/analytics/Constants.kt | 2 +- .../FlutterFirebaseAnalyticsPlugin.kt | 155 ++--- .../analytics/FlutterFirebaseAppRegistrar.kt | 4 +- .../GeneratedAndroidFirebaseAnalytics.g.kt | 163 +++-- .../analytics/example/MainActivity.kt | 2 +- .../ios/firebase_analytics/Package.swift | 12 +- .../FirebaseAnalyticsMessages.g.swift | 103 +-- .../FirebaseAnalyticsPlugin.swift | 131 ++-- .../macos/firebase_analytics/Package.swift | 12 +- .../appcheck/FirebaseAppCheckPlugin.kt | 59 +- .../appcheck/FlutterFirebaseAppRegistrar.kt | 19 +- .../GeneratedAndroidFirebaseAppCheck.g.kt | 104 ++- .../appcheck/TokenChannelStreamHandler.kt | 16 +- .../firebase/appcheck/example/MainActivity.kt | 2 +- .../ios/firebase_app_check/Package.swift | 12 +- .../FirebaseAppCheckMessages.g.swift | 57 +- .../FirebaseAppCheckPlugin.swift | 126 ++-- .../macos/firebase_app_check/Package.swift | 12 +- .../installations/example/MainActivity.kt | 2 +- .../example/ios/Runner/AppDelegate.swift | 2 +- .../firebase_app_installations/Package.swift | 12 +- .../FirebaseInstallationsPlugin.swift | 116 ++-- .../IdChangedStreamHandler.swift | 24 +- .../firebase_app_installations/Package.swift | 12 +- .../auth/FlutterFirebaseAuthPlugin.java | 3 +- .../FlutterFirebaseAuthPluginException.java | 3 +- .../auth/GeneratedAndroidFirebaseAuth.java | 16 + .../firebase/auth/example/MainActivity.kt | 2 +- .../example/ios/Runner/AppDelegate.swift | 2 +- .../ios/firebase_auth/Package.swift | 16 +- .../macos/firebase_auth/Package.swift | 16 +- .../core/FlutterFirebaseCorePlugin.java | 9 +- .../core/GeneratedAndroidFirebaseCore.java | 6 + .../firebasecoreexample/MainActivity.kt | 2 +- .../ios/firebase_core/Package.swift | 18 +- .../macos/firebase_core/Package.swift | 18 +- .../MainActivity.kt | 2 +- .../ios/firebase_crashlytics/Package.swift | 16 +- .../macos/firebase_crashlytics/Package.swift | 16 +- .../dataconnect/example/MainActivity.kt | 2 +- .../firebase/database/ChildEventsProxy.kt | 49 +- .../plugins/firebase/database/Constants.kt | 3 +- .../firebase/database/EventStreamHandler.kt | 74 +- .../plugins/firebase/database/EventsProxy.kt | 38 +- .../database/FirebaseDatabasePlugin.kt | 440 +++++++----- .../database/FlutterDataSnapshotPayload.kt | 2 +- .../database/FlutterFirebaseAppRegistrar.kt | 6 +- .../FlutterFirebaseDatabaseException.kt | 125 ++-- .../GeneratedAndroidFirebaseDatabase.g.kt | 579 ++++++++++----- .../plugins/firebase/database/QueryBuilder.kt | 134 ++-- .../firebase/database/TransactionExecutor.kt | 73 +- .../firebase/database/TransactionHandler.kt | 100 +-- .../firebase/database/ValueEventsProxy.kt | 25 +- .../firebase/database/example/MainActivity.kt | 2 +- .../example/macos/Runner/AppDelegate.swift | 2 +- .../ios/firebase_database/Package.swift | 16 +- ...FirebaseDatabaseObserveStreamHandler.swift | 7 +- .../FLTFirebaseDatabasePlugin.swift | 263 ++++--- .../FLTFirebaseDatabaseUtils.swift | 27 +- .../FirebaseDatabaseMessages.g.swift | 322 +++++---- .../macos/firebase_database/Package.swift | 16 +- .../plugins/firebase/tests/MainActivity.kt | 2 +- .../firebase_in_app_messaging/Package.swift | 16 +- ...erFirebaseMessagingBackgroundExecutor.java | 8 +- ...terFirebaseMessagingBackgroundService.java | 3 +- .../FlutterFirebaseMessagingPlugin.java | 22 +- .../FlutterFirebaseMessagingReceiver.java | 6 +- .../FlutterFirebaseMessagingService.java | 3 +- .../FlutterFirebaseMessagingStore.java | 6 +- .../messaging/PluginRegistrantException.java | 5 +- .../messaging/example/MainActivity.kt | 2 +- .../ios/firebase_messaging/Package.swift | 16 +- .../macos/firebase_messaging/Package.swift | 16 +- .../plugins/firebase/tests/MainActivity.kt | 2 +- .../example/ios/Runner/AppDelegate.swift | 2 +- .../Package.swift | 12 +- .../FirebaseModelDownloaderPlugin.swift | 51 +- .../Package.swift | 12 +- .../FlutterFirebaseAppRegistrar.kt | 3 +- .../FlutterFirebasePerformancePlugin.kt | 44 +- .../GeneratedAndroidFirebasePerformance.g.kt | 207 +++--- .../plugins/firebase/tests/MainActivity.kt | 2 +- .../ios/firebase_performance/Package.swift | 16 +- .../FirebasePerformanceMessages.g.swift | 85 ++- .../FirebasePerformancePlugin.swift | 45 +- .../FirebaseRemoteConfigPlugin.kt | 144 ++-- .../FlutterFirebaseAppRegistrar.kt | 3 +- .../GeneratedAndroidFirebaseRemoteConfig.g.kt | 163 +++-- .../remoteconfig/example/MainActivity.kt | 2 +- .../ios/firebase_remote_config/Package.swift | 12 +- .../FirebaseRemoteConfigMessages.g.swift | 82 ++- .../FirebaseRemoteConfigPlugin.swift | 39 +- .../FirebaseRemoteConfigUtils.swift | 6 +- .../firebase_remote_config/Package.swift | 12 +- .../storage/FlutterFirebaseAppRegistrar.kt | 5 +- .../FlutterFirebaseStorageException.kt | 23 +- .../storage/FlutterFirebaseStoragePlugin.kt | 276 ++++---- .../storage/FlutterFirebaseStorageTask.kt | 93 ++- .../GeneratedAndroidFirebaseStorage.g.kt | 657 ++++++++++++------ .../storage/TaskStateChannelStreamHandler.kt | 22 +- .../firebasestorageexample/MainActivity.kt | 2 +- .../ios/firebase_storage/Package.swift | 16 +- .../FLTFirebaseStoragePlugin.swift | 327 +++++---- .../FirebaseStorageMessages.g.swift | 286 ++++---- .../TaskStateChannelStreamHandler.swift | 17 +- .../macos/firebase_storage/Package.swift | 16 +- 133 files changed, 4127 insertions(+), 2821 deletions(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index df1427acee93..383c4e180bcb 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -20,7 +20,7 @@ on: jobs: analyze: - timeout-minutes: 45 + timeout-minutes: 50 runs-on: ubuntu-latest steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 @@ -83,9 +83,11 @@ jobs: format: # switch back to ubuntu-latest when swiftformat is working again runs-on: macos-latest - timeout-minutes: 20 + timeout-minutes: 40 steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + with: + fetch-depth: 0 - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' @@ -107,15 +109,17 @@ jobs: run: | clang-format --version swiftformat --version - - name: 'Dart, Java and Objective-C ' + - name: 'Dart, Java, Objective-C and Swift' run: | - flutter pub global run flutter_plugin_tools format + flutter pub global run flutter_plugin_tools format --base-branch=origin/main ./.github/workflows/scripts/validate-formatting.sh - - name: 'Swift' - if: ${{ success() || failure() }} + + # Clean generated build artificats(from format step) to prevent post run jobs from timing out + - name: Clean generated build artifacts + if: ${{ always() }} run: | - swiftformat . - ./.github/workflows/scripts/validate-formatting.sh + rm -rf build + find packages -type d -name build -prune -exec rm -rf {} + build_examples_dart: timeout-minutes: 30 diff --git a/.swiftformat b/.swiftformat index 7f0db7664edf..d8573cd10895 100644 --- a/.swiftformat +++ b/.swiftformat @@ -1,6 +1,7 @@ --indent 2 --maxwidth 100 --wrapparameters afterfirst ---disable sortedImports,unusedArguments,wrapMultilineStatementBraces +# Apple swift-format from flutter_plugin_tools requires `case .success(let value)` instead of `case let .success(value)`. +--disable sortedImports,unusedArguments,wrapMultilineStatementBraces,hoistPatternLet --exclude Pods,**/MainFlutterWindow.swift,**/AppDelegate.swift,**/.symlinks/** --swiftversion 5.7 diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreException.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreException.java index 759eecaf4cf7..7caa39dc96e5 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreException.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreException.java @@ -10,30 +10,41 @@ public class FlutterFirebaseFirestoreException extends Exception { private static final String ERROR_ABORTED = - "The operation was aborted, typically due to a concurrency issue like transaction aborts, etc."; + "The operation was aborted, typically due to a concurrency issue like transaction aborts," + + " etc."; private static final String ERROR_ALREADY_EXISTS = "Some document that we attempted to create already exists."; private static final String ERROR_CANCELLED = "The operation was cancelled (typically by the caller)."; private static final String ERROR_DATA_LOSS = "Unrecoverable data loss or corruption."; private static final String ERROR_DEADLINE_EXCEEDED = - "Deadline expired before operation could complete. For operations that change the state of the system, this error may be returned even if the operation has completed successfully. For example, a successful response from a server could have been delayed long enough for the deadline to expire."; + "Deadline expired before operation could complete. For operations that change the state of" + + " the system, this error may be returned even if the operation has completed" + + " successfully. For example, a successful response from a server could have been" + + " delayed long enough for the deadline to expire."; private static final String ERROR_FAILED_PRECONDITION = - "Operation was rejected because the system is not in a state required for the operation's execution. If performing a query, ensure it has been indexed via the Firebase console."; + "Operation was rejected because the system is not in a state required for the operation's" + + " execution. If performing a query, ensure it has been indexed via the Firebase" + + " console."; private static final String ERROR_INTERNAL = - "Internal errors. Means some invariants expected by underlying system has been broken. If you see one of these errors, something is very broken."; + "Internal errors. Means some invariants expected by underlying system has been broken. If you" + + " see one of these errors, something is very broken."; private static final String ERROR_INVALID_ARGUMENT = - "Client specified an invalid argument. Note that this differs from failed-precondition. invalid-argument indicates arguments that are problematic regardless of the state of the system (e.g., an invalid field name)."; + "Client specified an invalid argument. Note that this differs from failed-precondition." + + " invalid-argument indicates arguments that are problematic regardless of the state of" + + " the system (e.g., an invalid field name)."; private static final String ERROR_NOT_FOUND = "Some requested document was not found."; private static final String ERROR_OUT_OF_RANGE = "Operation was attempted past the valid range."; private static final String ERROR_PERMISSION_DENIED = "The caller does not have permission to execute the specified operation."; private static final String ERROR_RESOURCE_EXHAUSTED = - "Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space."; + "Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file" + + " system is out of space."; private static final String ERROR_UNAUTHENTICATED = "The request does not have valid authentication credentials for the operation."; private static final String ERROR_UNAVAILABLE = - "The service is currently unavailable. This is a most likely a transient condition and may be corrected by retrying with a backoff."; + "The service is currently unavailable. This is a most likely a transient condition and may be" + + " corrected by retrying with a backoff."; private static final String ERROR_UNIMPLEMENTED = "Operation is not implemented or not supported/enabled."; private static final String ERROR_UNKNOWN = diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreMessageCodec.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreMessageCodec.java index 0c10ec694e5f..a446a11f364e 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreMessageCodec.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestoreMessageCodec.java @@ -82,7 +82,8 @@ protected void writeValue(ByteArrayOutputStream stream, Object value) { writeValue(stream, appName); writeValue(stream, ((DocumentReference) value).getPath()); String databaseURL; - // There is no way of getting database URL from Firebase android SDK API so we cache it ourselves + // There is no way of getting database URL from Firebase android SDK API so we cache it + // ourselves synchronized (FlutterFirebaseFirestorePlugin.firestoreInstanceCache) { databaseURL = FlutterFirebaseFirestorePlugin.getCachedFirebaseFirestoreInstanceForKey(firestore) @@ -534,7 +535,8 @@ private Query readFirestoreQuery(ByteBuffer buffer) { } catch (Exception exception) { Log.e( "FLTFirestoreMsgCodec", - "An error occurred while parsing query arguments, this is most likely an error with this SDK.", + "An error occurred while parsing query arguments, this is most likely an error with this" + + " SDK.", exception); return null; } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java index 14cea06420c1..14046b1179d6 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java @@ -369,7 +369,8 @@ public void namedQueryGet( if (query == null) { result.error( new NullPointerException( - "Named query has not been found. Please check it has been loaded properly via loadBundle().")); + "Named query has not been found. Please check it has been loaded properly via" + + " loadBundle().")); return; } @@ -764,7 +765,8 @@ public void queryGet( result.error( new GeneratedAndroidFirebaseFirestore.FlutterError( "invalid_query", - "An error occurred while parsing query arguments, see native logs for more information. Please report this issue.", + "An error occurred while parsing query arguments, see native logs for more" + + " information. Please report this issue.", null)); return; } @@ -973,7 +975,8 @@ public void querySnapshot( result.error( new GeneratedAndroidFirebaseFirestore.FlutterError( "invalid_query", - "An error occurred while parsing query arguments, see native logs for more information. Please report this issue.", + "An error occurred while parsing query arguments, see native logs for more" + + " information. Please report this issue.", null)); return; } diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java index 60f2d8ff6638..9e4321e264c9 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/GeneratedAndroidFirebaseFirestore.java @@ -2504,6 +2504,7 @@ public interface Result { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Asynchronous error handling return type for nullable API method returns. */ public interface NullableResult { /** Success case callback method for handling returns. */ @@ -2512,6 +2513,7 @@ public interface NullableResult { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Asynchronous error handling return type for void API method returns. */ public interface VoidResult { /** Success case callback method for handling returns. */ @@ -2520,6 +2522,7 @@ public interface VoidResult { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseFirestoreHostApi { @@ -2646,6 +2649,7 @@ void executePipeline( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `FirebaseFirestoreHostApi` to handle messages through the * `binaryMessenger`. diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java index 305a62120f8b..027c9c01ed43 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PigeonParser.java @@ -261,7 +261,8 @@ public static Query parseQuery( } catch (Exception exception) { Log.e( "FLTFirestoreMsgCodec", - "An error occurred while parsing query arguments, this is most likely an error with this SDK.", + "An error occurred while parsing query arguments, this is most likely an error with this" + + " SDK.", exception); return null; } diff --git a/packages/cloud_firestore/cloud_firestore/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/firestore/example/MainActivity.kt b/packages/cloud_firestore/cloud_firestore/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/firestore/example/MainActivity.kt index 47ab27f36c9a..18b6218e85dd 100644 --- a/packages/cloud_firestore/cloud_firestore/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/firestore/example/MainActivity.kt +++ b/packages/cloud_firestore/cloud_firestore/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/firestore/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.firestore.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/cloud_firestore/cloud_firestore/example/ios/Runner/AppDelegate.swift b/packages/cloud_firestore/cloud_firestore/example/ios/Runner/AppDelegate.swift index b6363034812b..626664468b89 100644 --- a/packages/cloud_firestore/cloud_firestore/example/ios/Runner/AppDelegate.swift +++ b/packages/cloud_firestore/cloud_firestore/example/ios/Runner/AppDelegate.swift @@ -1,5 +1,5 @@ -import UIKit import Flutter +import UIKit @main @objc class AppDelegate: FlutterAppDelegate { diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index 194345dc4f41..a2bc598d3be6 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "6.4.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "6.4.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "cloud_firestore", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "cloud-firestore", targets: ["cloud_firestore"]), + .library(name: "cloud-firestore", targets: ["cloud_firestore"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,14 +30,14 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include/cloud_firestore/Private"), .headerSearchPath("include/cloud_firestore/Public"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-fst\""), ] - ), + ) ] ) diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index 9f53f0ea7643..2438d85b6a6a 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "6.4.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "6.4.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "cloud_firestore", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "cloud-firestore", targets: ["cloud_firestore"]), + .library(name: "cloud-firestore", targets: ["cloud_firestore"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,14 +30,14 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include/cloud_firestore/Private"), .headerSearchPath("include/cloud_firestore/Public"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-fst\""), ] - ), + ) ] ) diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift index b6363034812b..626664468b89 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/ios/Runner/AppDelegate.swift @@ -1,5 +1,5 @@ -import UIKit import Flutter +import UIKit @main @objc class AppDelegate: FlutterAppDelegate { diff --git a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FirebaseFunctionsStreamHandler.kt b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FirebaseFunctionsStreamHandler.kt index 604c8e4dfa53..32544cdd3d34 100644 --- a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FirebaseFunctionsStreamHandler.kt +++ b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FirebaseFunctionsStreamHandler.kt @@ -10,13 +10,13 @@ import com.google.firebase.functions.HttpsCallableReference import com.google.firebase.functions.StreamResponse import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.EventChannel.EventSink -import org.reactivestreams.Publisher import java.net.URL import java.util.Objects import java.util.concurrent.TimeUnit +import org.reactivestreams.Publisher class FirebaseFunctionsStreamHandler(private val firebaseFunctions: FirebaseFunctions) : - EventChannel.StreamHandler { + EventChannel.StreamHandler { private var subscriber: StreamResponseSubscriber? = null override fun onListen(arguments: Any, events: EventSink) { @@ -36,7 +36,7 @@ class FirebaseFunctionsStreamHandler(private val firebaseFunctions: FirebaseFunc val timeout = arguments["timeout"] as Int? val parameters = arguments["parameters"] val limitedUseAppCheckToken = - Objects.requireNonNull(arguments["limitedUseAppCheckToken"]) as Boolean + Objects.requireNonNull(arguments["limitedUseAppCheckToken"]) as Boolean if (origin != null) { val originUri = Uri.parse(origin) @@ -44,9 +44,10 @@ class FirebaseFunctionsStreamHandler(private val firebaseFunctions: FirebaseFunc } val httpsCallableReference: HttpsCallableReference - val options: HttpsCallableOptions =HttpsCallableOptions.Builder() - .setLimitedUseAppCheckTokens(limitedUseAppCheckToken) - .build() + val options: HttpsCallableOptions = + HttpsCallableOptions.Builder() + .setLimitedUseAppCheckTokens(limitedUseAppCheckToken) + .build() val publisher: Publisher if (functionName != null) { @@ -54,7 +55,7 @@ class FirebaseFunctionsStreamHandler(private val firebaseFunctions: FirebaseFunc publisher = httpsCallableReference.stream(parameters) } else if (functionUri != null) { httpsCallableReference = - firebaseFunctions.getHttpsCallableFromUrl(URL(functionUri), options) + firebaseFunctions.getHttpsCallableFromUrl(URL(functionUri), options) publisher = httpsCallableReference.stream() } else { throw IllegalArgumentException("Either functionName or functionUri must be set") diff --git a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseAppRegistrar.kt b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseAppRegistrar.kt index 14e4ce487ebd..a704f964b124 100644 --- a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseAppRegistrar.kt +++ b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseAppRegistrar.kt @@ -12,7 +12,6 @@ import com.google.firebase.platforminfo.LibraryVersionComponent class FlutterFirebaseAppRegistrar : ComponentRegistrar { override fun getComponents(): List> { return listOf( - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION) - ) + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION)) } } diff --git a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseFunctionsPlugin.kt b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseFunctionsPlugin.kt index 3705e390c0b8..f2aff1556e6d 100644 --- a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseFunctionsPlugin.kt +++ b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/FlutterFirebaseFunctionsPlugin.kt @@ -25,9 +25,7 @@ import java.util.Locale import java.util.Objects import java.util.concurrent.TimeUnit -class FlutterFirebaseFunctionsPlugin - - : FlutterPlugin, FlutterFirebasePlugin, CloudFunctionsHostApi { +class FlutterFirebaseFunctionsPlugin : FlutterPlugin, FlutterFirebasePlugin, CloudFunctionsHostApi { private var channel: MethodChannel? = null private var pluginBinding: FlutterPluginBinding? = null private var messenger: BinaryMessenger? = null @@ -66,7 +64,7 @@ class FlutterFirebaseFunctionsPlugin val origin = arguments["origin"] as String? val timeout = (arguments["timeout"] as Number?)?.toInt() val limitedUseAppCheckToken = - Objects.requireNonNull(arguments["limitedUseAppCheckToken"]) as Boolean + Objects.requireNonNull(arguments["limitedUseAppCheckToken"]) as Boolean val parameters = arguments["parameters"] if (origin != null) { @@ -76,23 +74,21 @@ class FlutterFirebaseFunctionsPlugin val httpsCallableReference: HttpsCallableReference val options: HttpsCallableOptions = - HttpsCallableOptions.Builder() - .setLimitedUseAppCheckTokens(limitedUseAppCheckToken) - .build() - - httpsCallableReference = if (functionName != null) { - firebaseFunctions.getHttpsCallable(functionName, options) - } else if (functionUri != null) { - firebaseFunctions.getHttpsCallableFromUrl(URL(functionUri), options) - } else { - throw IllegalArgumentException("Either functionName or functionUri must be set") - } + HttpsCallableOptions.Builder() + .setLimitedUseAppCheckTokens(limitedUseAppCheckToken) + .build() + + httpsCallableReference = + if (functionName != null) { + firebaseFunctions.getHttpsCallable(functionName, options) + } else if (functionUri != null) { + firebaseFunctions.getHttpsCallableFromUrl(URL(functionUri), options) + } else { + throw IllegalArgumentException("Either functionName or functionUri must be set") + } if (timeout != null) { - httpsCallableReference.setTimeout( - timeout.toLong(), - TimeUnit.MILLISECONDS - ) + httpsCallableReference.setTimeout(timeout.toLong(), TimeUnit.MILLISECONDS) } val result = Tasks.await(httpsCallableReference.call(parameters)) @@ -117,21 +113,20 @@ class FlutterFirebaseFunctionsPlugin var additionalData: Any? = null if (exception.cause is FirebaseFunctionsException) { - val functionsException = - exception.cause as FirebaseFunctionsException? + val functionsException = exception.cause as FirebaseFunctionsException? code = functionsException!!.code.name message = functionsException.message additionalData = functionsException.details - if (functionsException.cause is IOException - && "Canceled" == (functionsException.cause as IOException).message - ) { + if (functionsException.cause is IOException && + "Canceled" == (functionsException.cause as IOException).message) { // return DEADLINE_EXCEEDED for IOException cancel errors, to match iOS & Web code = FirebaseFunctionsException.Code.DEADLINE_EXCEEDED.name message = FirebaseFunctionsException.Code.DEADLINE_EXCEEDED.name - } else if (functionsException.cause is InterruptedIOException // return DEADLINE_EXCEEDED for InterruptedIOException errors, to match iOS & Web - && "timeout" == (functionsException.cause as InterruptedIOException).message - ) { + } else if (functionsException.cause is + InterruptedIOException // return DEADLINE_EXCEEDED for InterruptedIOException errors, to + // match iOS & Web + && "timeout" == (functionsException.cause as InterruptedIOException).message) { code = FirebaseFunctionsException.Code.DEADLINE_EXCEEDED.name message = FirebaseFunctionsException.Code.DEADLINE_EXCEEDED.name } else if (functionsException.cause is IOException) { @@ -172,28 +167,23 @@ class FlutterFirebaseFunctionsPlugin } override fun call(arguments: Map, callback: (Result) -> Unit) { - httpsFunctionCall(arguments as Map) - .addOnCompleteListener { task -> - if (task.isSuccessful){ - callback(Result.success(task.result)) - } - else { - val exception = task.exception - callback(Result.failure(FlutterError( - "firebase_functions", - exception?.message, - getExceptionDetails(exception) - ))) - } - + httpsFunctionCall(arguments as Map).addOnCompleteListener { task -> + if (task.isSuccessful) { + callback(Result.success(task.result)) + } else { + val exception = task.exception + callback( + Result.failure( + FlutterError( + "firebase_functions", exception?.message, getExceptionDetails(exception)))) + } } } override fun registerEventChannel(arguments: Map, callback: (Result) -> Unit) { val eventId = Objects.requireNonNull(arguments["eventChannelId"]) as String val eventChannelName = "$METHOD_CHANNEL_NAME/$eventId" - val eventChannel = - EventChannel(pluginBinding!!.binaryMessenger, eventChannelName) + val eventChannel = EventChannel(pluginBinding!!.binaryMessenger, eventChannelName) val functions = getFunctions(arguments) val streamHandler = FirebaseFunctionsStreamHandler(functions) eventChannel.setStreamHandler(streamHandler) diff --git a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt index 7b5c2181da86..e3cb89c46f8b 100644 --- a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt +++ b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/GeneratedAndroidCloudFunctions.g.kt @@ -10,12 +10,11 @@ package io.flutter.plugins.firebase.functions import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object GeneratedAndroidCloudFunctionsPigeonUtils { fun wrapResult(result: Any?): List { @@ -24,58 +23,66 @@ private object GeneratedAndroidCloudFunctionsPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : RuntimeException() + private open class GeneratedAndroidCloudFunctionsPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface CloudFunctionsHostApi { fun call(arguments: Map, callback: (Result) -> Unit) + fun registerEventChannel(arguments: Map, callback: (Result) -> Unit) companion object { /** The codec used by CloudFunctionsHostApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidCloudFunctionsPigeonCodec() - } - /** Sets up an instance of `CloudFunctionsHostApi` to handle messages through the `binaryMessenger`. */ + val codec: MessageCodec by lazy { GeneratedAndroidCloudFunctionsPigeonCodec() } + /** + * Sets up an instance of `CloudFunctionsHostApi` to handle messages through the + * `binaryMessenger`. + */ @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: CloudFunctionsHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp( + binaryMessenger: BinaryMessenger, + api: CloudFunctionsHostApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -95,7 +102,11 @@ interface CloudFunctionsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List diff --git a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/StreamResponseSubscriber.kt b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/StreamResponseSubscriber.kt index 9785ca3285b4..d6224703433d 100644 --- a/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/StreamResponseSubscriber.kt +++ b/packages/cloud_functions/cloud_functions/android/src/main/kotlin/io/flutter/plugins/firebase/functions/StreamResponseSubscriber.kt @@ -10,8 +10,7 @@ import io.flutter.plugin.common.EventChannel.EventSink import org.reactivestreams.Subscriber import org.reactivestreams.Subscription -class StreamResponseSubscriber(private val eventSink: EventSink?) : - Subscriber { +class StreamResponseSubscriber(private val eventSink: EventSink?) : Subscriber { private var subscription: Subscription? = null private val mainThreadHandler = Handler(Looper.getMainLooper()) diff --git a/packages/cloud_functions/cloud_functions/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/functions/example/MainActivity.kt b/packages/cloud_functions/cloud_functions/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/functions/example/MainActivity.kt index 1e409db224c4..30f8b8e8c69a 100644 --- a/packages/cloud_functions/cloud_functions/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/functions/example/MainActivity.kt +++ b/packages/cloud_functions/cloud_functions/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/functions/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.functions.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift index 8771e6f4820b..63d9adeac566 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "cloud_functions", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "cloud-functions", targets: ["cloud_functions"]), + .library(name: "cloud-functions", targets: ["cloud_functions"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift index fca2234a4060..86ba0c92f137 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/CloudFunctionsMessages.g.swift @@ -88,8 +88,9 @@ class CloudFunctionsMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol CloudFunctionsHostApi { func call(arguments: [String: Any?], completion: @escaping (Result) -> Void) - func registerEventChannel(arguments: [String: Any], - completion: @escaping (Result) -> Void) + func registerEventChannel( + arguments: [String: Any], + completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -100,11 +101,14 @@ class CloudFunctionsHostApiSetup { /// Sets up an instance of `CloudFunctionsHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CloudFunctionsHostApi?, - messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: CloudFunctionsHostApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let callChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call\(channelSuffix)", + name: + "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.call\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -114,9 +118,9 @@ class CloudFunctionsHostApiSetup { let argumentsArg = args[0] as! [String: Any?] api.call(arguments: argumentsArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -125,7 +129,8 @@ class CloudFunctionsHostApiSetup { callChannel.setMessageHandler(nil) } let registerEventChannelChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel\(channelSuffix)", + name: + "dev.flutter.pigeon.cloud_functions_platform_interface.CloudFunctionsHostApi.registerEventChannel\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -137,7 +142,7 @@ class CloudFunctionsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FirebaseFunctionsPlugin.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FirebaseFunctionsPlugin.swift index 7163bdda6f10..c5026ca8578b 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FirebaseFunctionsPlugin.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FirebaseFunctionsPlugin.swift @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseFunctions + #if canImport(FlutterMacOS) import FlutterMacOS #else @@ -13,14 +15,14 @@ #else import firebase_core_shared #endif -import FirebaseFunctions extension FlutterError: Error {} let kFLTFirebaseFunctionsChannelName = "plugins.flutter.io/firebase_functions" public class FirebaseFunctionsPlugin: NSObject, FLTFirebasePluginProtocol, FlutterPlugin, - CloudFunctionsHostApi { + CloudFunctionsHostApi +{ func call(arguments: [String: Any?], completion: @escaping (Result) -> Void) { httpsFunctionCall(arguments: arguments) { result, error in if let error { @@ -31,8 +33,10 @@ public class FirebaseFunctionsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt } } - func registerEventChannel(arguments: [String: Any], - completion: @escaping (Result) -> Void) { + func registerEventChannel( + arguments: [String: Any], + completion: @escaping (Result) -> Void + ) { let eventChannelId = arguments["eventChannelId"]! let eventChannelName = "\(kFLTFirebaseFunctionsChannelName)/\(eventChannelId)" let eventChannel = FlutterEventChannel(name: eventChannelName, binaryMessenger: binaryMessenger) @@ -80,8 +84,10 @@ public class FirebaseFunctionsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt CloudFunctionsHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: instance) } - private func httpsFunctionCall(arguments: [String: Any], - completion: @escaping (Any?, FlutterError?) -> Void) { + private func httpsFunctionCall( + arguments: [String: Any], + completion: @escaping (Any?, FlutterError?) -> Void + ) { let appName = arguments["appName"] as? String ?? "" let functionName = arguments["functionName"] as? String let functionUri = arguments["functionUri"] as? String @@ -96,9 +102,10 @@ public class FirebaseFunctionsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt let functions = Functions.functions(app: app, region: region ?? "") if let origin, !origin.isEmpty, - let url = URL(string: origin), - let host = url.host, - let port = url.port { + let url = URL(string: origin), + let host = url.host, + let port = url.port + { functions.useEmulator(withHost: host, port: port) } @@ -109,14 +116,18 @@ public class FirebaseFunctionsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt if let functionName, !functionName.isEmpty { function = functions.httpsCallable(functionName, options: options) } else if let functionUri, !functionUri.isEmpty, - let url = URL(string: functionUri) { + let url = URL(string: functionUri) + { function = functions.httpsCallable(url, options: options) } else { - completion(nil, FlutterError( - code: "IllegalArgumentException", - message: "Either functionName or functionUri must be set", - details: nil - )) + completion( + nil, + FlutterError( + code: "IllegalArgumentException", + message: "Either functionName or functionUri must be set", + details: nil + ) + ) return } diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FunctionsStreamHandler.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FunctionsStreamHandler.swift index 2cf023757450..7d2ce08e76cc 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FunctionsStreamHandler.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FunctionsStreamHandler.swift @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseFunctions + #if canImport(FlutterMacOS) import FlutterMacOS #else import Flutter #endif -import FirebaseFunctions - class FunctionsStreamHandler: NSObject, FlutterStreamHandler { var functions: Functions private var streamTask: Task? @@ -19,8 +19,10 @@ class FunctionsStreamHandler: NSObject, FlutterStreamHandler { super.init() } - func onListen(withArguments arguments: Any?, - eventSink events: @escaping FlutterEventSink) -> FlutterError? { + func onListen( + withArguments arguments: Any?, + eventSink events: @escaping FlutterEventSink + ) -> FlutterError? { streamTask = Task { await httpsStreamCall(arguments: arguments, events: events) } @@ -35,9 +37,13 @@ class FunctionsStreamHandler: NSObject, FlutterStreamHandler { private func httpsStreamCall(arguments: Any?, events: @escaping FlutterEventSink) async { guard let arguments = arguments as? [String: Any] else { await MainActor.run { - events(FlutterError(code: "invalid_arguments", - message: "Invalid arguments", - details: nil)) + events( + FlutterError( + code: "invalid_arguments", + message: "Invalid arguments", + details: nil + ) + ) } return } @@ -49,9 +55,10 @@ class FunctionsStreamHandler: NSObject, FlutterStreamHandler { let limitedUseAppCheckToken = arguments["limitedUseAppCheckToken"] as? Bool ?? false if let origin, - let url = URL(string: origin), - let host = url.host, - let port = url.port { + let url = URL(string: origin), + let host = url.host, + let port = url.port + { functions.useEmulator(withHost: host, port: port) } @@ -67,9 +74,13 @@ class FunctionsStreamHandler: NSObject, FlutterStreamHandler { function = functions.httpsCallable(url, options: options) } else { await MainActor.run { - events(FlutterError(code: "IllegalArgumentException", - message: "Either functionName or functionUri must be set", - details: nil)) + events( + FlutterError( + code: "IllegalArgumentException", + message: "Either functionName or functionUri must be set", + details: nil + ) + ) } return } @@ -86,9 +97,9 @@ class FunctionsStreamHandler: NSObject, FlutterStreamHandler { for try await response in stream { await MainActor.run { switch response { - case let .message(message): + case .message(let message): events(["message": message.value]) - case let .result(result): + case .result(let result): events(["result": result.value]) events(FlutterEndOfEventStream) } @@ -96,16 +107,24 @@ class FunctionsStreamHandler: NSObject, FlutterStreamHandler { } } catch { await MainActor.run { - events(FlutterError(code: "unknown", - message: error.localizedDescription, - details: ["code": "unknown", "message": error.localizedDescription])) + events( + FlutterError( + code: "unknown", + message: error.localizedDescription, + details: ["code": "unknown", "message": error.localizedDescription] + ) + ) } } } else { await MainActor.run { - events(FlutterError(code: "unknown", - message: "Streaming requires iOS 15+ or macOS 12+", - details: nil)) + events( + FlutterError( + code: "unknown", + message: "Streaming requires iOS 15+ or macOS 12+", + details: nil + ) + ) } } } diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift index 3290c342486f..8be5bb283b31 100644 --- a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "cloud_functions", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "cloud-functions", targets: ["cloud_functions"]), + .library(name: "cloud-functions", targets: ["cloud_functions"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_ai/firebase_ai/android/src/main/kotlin/io/flutter/plugins/firebase/ai/FirebaseAIPlugin.kt b/packages/firebase_ai/firebase_ai/android/src/main/kotlin/io/flutter/plugins/firebase/ai/FirebaseAIPlugin.kt index 3377f693d3e5..0a7e5168400a 100644 --- a/packages/firebase_ai/firebase_ai/android/src/main/kotlin/io/flutter/plugins/firebase/ai/FirebaseAIPlugin.kt +++ b/packages/firebase_ai/firebase_ai/android/src/main/kotlin/io/flutter/plugins/firebase/ai/FirebaseAIPlugin.kt @@ -25,77 +25,74 @@ import java.security.MessageDigest import java.security.NoSuchAlgorithmException class FirebaseAIPlugin : FlutterPlugin, MethodChannel.MethodCallHandler { - private lateinit var channel: MethodChannel - private lateinit var context: Context + private lateinit var channel: MethodChannel + private lateinit var context: Context - override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { - context = binding.applicationContext - channel = MethodChannel(binding.binaryMessenger, "plugins.flutter.io/firebase_ai") - channel.setMethodCallHandler(this) - } + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + context = binding.applicationContext + channel = MethodChannel(binding.binaryMessenger, "plugins.flutter.io/firebase_ai") + channel.setMethodCallHandler(this) + } - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - channel.setMethodCallHandler(null) - } + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + channel.setMethodCallHandler(null) + } - override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { - when (call.method) { - "getPlatformHeaders" -> { - val headers = mapOf( - "X-Android-Package" to context.packageName, - "X-Android-Cert" to (getSigningCertFingerprint() ?: "") - ) - result.success(headers) - } - else -> result.notImplemented() - } + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + when (call.method) { + "getPlatformHeaders" -> { + val headers = + mapOf( + "X-Android-Package" to context.packageName, + "X-Android-Cert" to (getSigningCertFingerprint() ?: "")) + result.success(headers) + } + else -> result.notImplemented() } + } - @OptIn(ExperimentalStdlibApi::class) - private fun getSigningCertFingerprint(): String? { - val packageName = context.packageName - val signature = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - val packageInfo = try { + @OptIn(ExperimentalStdlibApi::class) + private fun getSigningCertFingerprint(): String? { + val packageName = context.packageName + val signature = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val packageInfo = + try { context.packageManager.getPackageInfo( - packageName, - PackageManager.GET_SIGNING_CERTIFICATES - ) - } catch (e: PackageManager.NameNotFoundException) { + packageName, PackageManager.GET_SIGNING_CERTIFICATES) + } catch (e: PackageManager.NameNotFoundException) { Log.e(TAG, "PackageManager couldn't find the package \"$packageName\"", e) return null - } - val signingInfo = packageInfo?.signingInfo ?: return null - if (signingInfo.hasMultipleSigners()) { - signingInfo.apkContentsSigners.firstOrNull() - } else { - signingInfo.signingCertificateHistory.lastOrNull() - } + } + val signingInfo = packageInfo?.signingInfo ?: return null + if (signingInfo.hasMultipleSigners()) { + signingInfo.apkContentsSigners.firstOrNull() + } else { + signingInfo.signingCertificateHistory.lastOrNull() + } } else { - @Suppress("DEPRECATION") - val packageInfo = try { - context.packageManager.getPackageInfo( - packageName, - PackageManager.GET_SIGNATURES - ) - } catch (e: PackageManager.NameNotFoundException) { + @Suppress("DEPRECATION") + val packageInfo = + try { + context.packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) + } catch (e: PackageManager.NameNotFoundException) { Log.e(TAG, "PackageManager couldn't find the package \"$packageName\"", e) return null - } - @Suppress("DEPRECATION") - packageInfo?.signatures?.firstOrNull() + } + @Suppress("DEPRECATION") packageInfo?.signatures?.firstOrNull() } ?: return null - return try { - val messageDigest = MessageDigest.getInstance("SHA-1") - val digest = messageDigest.digest(signature.toByteArray()) - digest.toHexString(HexFormat.UpperCase) - } catch (e: NoSuchAlgorithmException) { - Log.w(TAG, "No support for SHA-1 algorithm found.", e) - null - } + return try { + val messageDigest = MessageDigest.getInstance("SHA-1") + val digest = messageDigest.digest(signature.toByteArray()) + digest.toHexString(HexFormat.UpperCase) + } catch (e: NoSuchAlgorithmException) { + Log.w(TAG, "No support for SHA-1 algorithm found.", e) + null } + } - companion object { - private const val TAG = "FirebaseAIPlugin" - } + companion object { + private const val TAG = "FirebaseAIPlugin" + } } diff --git a/packages/firebase_ai/firebase_ai/example/ios/Runner/AppDelegate.swift b/packages/firebase_ai/firebase_ai/example/ios/Runner/AppDelegate.swift index b6363034812b..626664468b89 100644 --- a/packages/firebase_ai/firebase_ai/example/ios/Runner/AppDelegate.swift +++ b/packages/firebase_ai/firebase_ai/example/ios/Runner/AppDelegate.swift @@ -1,5 +1,5 @@ -import UIKit import Flutter +import UIKit @main @objc class AppDelegate: FlutterAppDelegate { diff --git a/packages/firebase_ai/firebase_ai/ios/firebase_ai/Package.swift b/packages/firebase_ai/firebase_ai/ios/firebase_ai/Package.swift index 087f2530b1c1..a9bd49d4e4d1 100644 --- a/packages/firebase_ai/firebase_ai/ios/firebase_ai/Package.swift +++ b/packages/firebase_ai/firebase_ai/ios/firebase_ai/Package.swift @@ -10,10 +10,10 @@ import PackageDescription let package = Package( name: "firebase_ai", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-ai", targets: ["firebase_ai"]), + .library(name: "firebase-ai", targets: ["firebase_ai"]) ], dependencies: [], targets: [ @@ -21,8 +21,8 @@ let package = Package( name: "firebase_ai", dependencies: [], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_ai/firebase_ai/macos/firebase_ai/Package.swift b/packages/firebase_ai/firebase_ai/macos/firebase_ai/Package.swift index 5440873b51b2..c551b27e41a6 100644 --- a/packages/firebase_ai/firebase_ai/macos/firebase_ai/Package.swift +++ b/packages/firebase_ai/firebase_ai/macos/firebase_ai/Package.swift @@ -10,10 +10,10 @@ import PackageDescription let package = Package( name: "firebase_ai", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-ai", targets: ["firebase_ai"]), + .library(name: "firebase-ai", targets: ["firebase_ai"]) ], dependencies: [], targets: [ @@ -21,8 +21,8 @@ let package = Package( name: "firebase_ai", dependencies: [], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/Constants.kt b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/Constants.kt index bb544b5b274b..9ba614b48b43 100644 --- a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/Constants.kt +++ b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/Constants.kt @@ -8,7 +8,7 @@ object Constants { const val AD_STORAGE_CONSENT_GRANTED: String = "adStorageConsentGranted" const val ANALYTICS_STORAGE_CONSENT_GRANTED: String = "analyticsStorageConsentGranted" const val AD_PERSONALIZATION_SIGNALS_CONSENT_GRANTED: String = - "adPersonalizationSignalsConsentGranted" + "adPersonalizationSignalsConsentGranted" const val AD_USER_DATA_CONSENT_GRANTED: String = "adUserDataConsentGranted" const val USER_ID: String = "userId" const val EVENT_NAME: String = "eventName" diff --git a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAnalyticsPlugin.kt b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAnalyticsPlugin.kt index e70e6812fef8..cadc75c84548 100644 --- a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAnalyticsPlugin.kt +++ b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAnalyticsPlugin.kt @@ -22,14 +22,13 @@ import io.flutter.plugins.firebase.core.FlutterFirebasePlugin.cachedThreadPool import io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry import java.util.Objects -class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, - FlutterPlugin, FirebaseAnalyticsHostApi { +class FlutterFirebaseAnalyticsPlugin : + FlutterFirebasePlugin, FlutterPlugin, FirebaseAnalyticsHostApi { private lateinit var analytics: FirebaseAnalytics private var channel: MethodChannel? = null private var messenger: BinaryMessenger? = null - private fun initInstance(messenger: BinaryMessenger, context: Context) { analytics = FirebaseAnalytics.getInstance(context) val channelName = "plugins.flutter.io/firebase_analytics" @@ -39,7 +38,9 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, this.messenger = messenger } - override fun getPluginConstantsForFirebaseApp(firebaseApp: FirebaseApp?): Task> { + override fun getPluginConstantsForFirebaseApp( + firebaseApp: FirebaseApp? + ): Task> { val taskCompletionSource = TaskCompletionSource>() cachedThreadPool.execute { @@ -86,11 +87,7 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, cachedThreadPool.execute { try { - taskCompletionSource.setResult( - Tasks.await( - analytics.sessionId - ) - ) + taskCompletionSource.setResult(Tasks.await(analytics.sessionId)) } catch (e: java.lang.Exception) { taskCompletionSource.setException(e) } @@ -104,14 +101,9 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, cachedThreadPool.execute { try { - val eventName = - Objects.requireNonNull(arguments[Constants.EVENT_NAME]) as String - val map = - arguments[Constants.PARAMETERS] as Map? - val parameterBundle: Bundle? = - createBundleFromMap( - map - ) + val eventName = Objects.requireNonNull(arguments[Constants.EVENT_NAME]) as String + val map = arguments[Constants.PARAMETERS] as Map? + val parameterBundle: Bundle? = createBundleFromMap(map) analytics.logEvent(eventName, parameterBundle) taskCompletionSource.setResult(null) } catch (e: java.lang.Exception) { @@ -202,44 +194,31 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, cachedThreadPool.execute { try { - val adStorageGranted = - arguments[Constants.AD_STORAGE_CONSENT_GRANTED] - val analyticsStorageGranted = - arguments[Constants.ANALYTICS_STORAGE_CONSENT_GRANTED] + val adStorageGranted = arguments[Constants.AD_STORAGE_CONSENT_GRANTED] + val analyticsStorageGranted = arguments[Constants.ANALYTICS_STORAGE_CONSENT_GRANTED] val adPersonalizationSignalsGranted = - arguments[Constants.AD_PERSONALIZATION_SIGNALS_CONSENT_GRANTED] - val adUserDataGranted = - arguments[Constants.AD_USER_DATA_CONSENT_GRANTED] - val parameters = - java.util.HashMap() + arguments[Constants.AD_PERSONALIZATION_SIGNALS_CONSENT_GRANTED] + val adUserDataGranted = arguments[Constants.AD_USER_DATA_CONSENT_GRANTED] + val parameters = java.util.HashMap() if (adStorageGranted != null) { - parameters[ConsentType.AD_STORAGE] = if (adStorageGranted) - ConsentStatus.GRANTED - else - ConsentStatus.DENIED + parameters[ConsentType.AD_STORAGE] = + if (adStorageGranted) ConsentStatus.GRANTED else ConsentStatus.DENIED } if (analyticsStorageGranted != null) { - parameters[ConsentType.ANALYTICS_STORAGE] = if (analyticsStorageGranted) - ConsentStatus.GRANTED - else - ConsentStatus.DENIED + parameters[ConsentType.ANALYTICS_STORAGE] = + if (analyticsStorageGranted) ConsentStatus.GRANTED else ConsentStatus.DENIED } if (adPersonalizationSignalsGranted != null) { parameters[ConsentType.AD_PERSONALIZATION] = - if (adPersonalizationSignalsGranted) - ConsentStatus.GRANTED - else - ConsentStatus.DENIED + if (adPersonalizationSignalsGranted) ConsentStatus.GRANTED else ConsentStatus.DENIED } if (adUserDataGranted != null) { - parameters[ConsentType.AD_USER_DATA] = if (adUserDataGranted) - ConsentStatus.GRANTED - else - ConsentStatus.DENIED + parameters[ConsentType.AD_USER_DATA] = + if (adUserDataGranted) ConsentStatus.GRANTED else ConsentStatus.DENIED } analytics.setConsent(parameters) @@ -257,11 +236,7 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, cachedThreadPool.execute { try { - analytics.setDefaultEventParameters( - createBundleFromMap( - parameters - ) - ) + analytics.setDefaultEventParameters(createBundleFromMap(parameters)) taskCompletionSource.setResult(null) } catch (e: java.lang.Exception) { taskCompletionSource.setException(e) @@ -276,11 +251,7 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, cachedThreadPool.execute { try { - taskCompletionSource.setResult( - Tasks.await( - analytics.appInstanceId - ) - ) + taskCompletionSource.setResult(Tasks.await(analytics.appInstanceId)) } catch (e: java.lang.Exception) { taskCompletionSource.setException(e) } @@ -299,7 +270,8 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, if (value is String) { bundle.putString(key, value) } else if (value is Int) { - // FirebaseAnalytics default event parameters only support long and double types, so we convert the int to a long. + // FirebaseAnalytics default event parameters only support long and double types, so we + // convert the int to a long. bundle.putLong(key, value.toLong()) } else if (value is Long) { bundle.putLong(key, value) @@ -318,11 +290,10 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, } else { if (item != null) { throw IllegalArgumentException( - ("Unsupported value type: " - + item.javaClass.canonicalName - + " in list at key " - + key) - ) + ("Unsupported value type: " + + item.javaClass.canonicalName + + " in list at key " + + key)) } } } @@ -331,18 +302,13 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, } else if (value is Map<*, *>) { bundle.putParcelable(key, createBundleFromMap(value as Map)) } else { - throw IllegalArgumentException( - "Unsupported value type: " + value.javaClass.canonicalName - ) + throw IllegalArgumentException("Unsupported value type: " + value.javaClass.canonicalName) } } return bundle } - private fun handleVoidTaskResult( - task: Task, - callback: (Result) -> Unit - ) { + private fun handleVoidTaskResult(task: Task, callback: (Result) -> Unit) { if (task.isSuccessful) { callback(Result.success(Unit)) } else { @@ -351,10 +317,7 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, } } - private fun handleTypedTaskResult( - task: Task, - callback: (Result) -> Unit - ) { + private fun handleTypedTaskResult(task: Task, callback: (Result) -> Unit) { if (task.isSuccessful) { callback(Result.success(task.result)) } else { @@ -364,16 +327,11 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, } override fun logEvent(event: Map, callback: (Result) -> Unit) { - handleLogEvent(event).addOnCompleteListener { task -> - handleVoidTaskResult(task, callback) - } + handleLogEvent(event).addOnCompleteListener { task -> handleVoidTaskResult(task, callback) } } - override fun setUserId(userId: String?, callback: (Result) -> Unit) { - handleSetUserId(userId).addOnCompleteListener { task -> - handleVoidTaskResult(task, callback) - } + handleSetUserId(userId).addOnCompleteListener { task -> handleVoidTaskResult(task, callback) } } override fun setUserProperty(name: String, value: String?, callback: (Result) -> Unit) { @@ -401,58 +359,41 @@ class FlutterFirebaseAnalyticsPlugin : FlutterFirebasePlugin, } override fun setConsent(consent: Map, callback: (Result) -> Unit) { - handleSetConsent(consent).addOnCompleteListener { task -> - handleVoidTaskResult(task, callback) - } - + handleSetConsent(consent).addOnCompleteListener { task -> handleVoidTaskResult(task, callback) } } override fun setDefaultEventParameters( - parameters: Map?, - callback: (Result) -> Unit + parameters: Map?, + callback: (Result) -> Unit ) { handleSetDefaultEventParameters(parameters).addOnCompleteListener { task -> handleVoidTaskResult(task, callback) } } - override fun getAppInstanceId(callback: (Result) -> Unit) { - handleGetAppInstanceId().addOnCompleteListener { task -> - handleTypedTaskResult(task, callback) - } + handleGetAppInstanceId().addOnCompleteListener { task -> handleTypedTaskResult(task, callback) } } override fun getSessionId(callback: (Result) -> Unit) { - handleGetSessionId().addOnCompleteListener { task -> - handleTypedTaskResult(task, callback) - } + handleGetSessionId().addOnCompleteListener { task -> handleTypedTaskResult(task, callback) } } override fun initiateOnDeviceConversionMeasurement( - arguments: Map, - callback: (Result) -> Unit + arguments: Map, + callback: (Result) -> Unit ) { callback( - Result.failure( - FlutterError( - "unimplemented", - "initiateOnDeviceConversionMeasurement is only available on iOS.", - null - ) - ) - ) + Result.failure( + FlutterError( + "unimplemented", + "initiateOnDeviceConversionMeasurement is only available on iOS.", + null))) } override fun logTransaction(transactionId: String, callback: (Result) -> Unit) { callback( - Result.failure( - FlutterError( - "unimplemented", - "logTransaction is only available on iOS.", - null - ) - ) - ) + Result.failure( + FlutterError("unimplemented", "logTransaction is only available on iOS.", null))) } } diff --git a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAppRegistrar.kt b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAppRegistrar.kt index 2a14d576ae89..42f5356cce24 100644 --- a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAppRegistrar.kt +++ b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/FlutterFirebaseAppRegistrar.kt @@ -9,12 +9,10 @@ import com.google.firebase.components.Component import com.google.firebase.components.ComponentRegistrar import com.google.firebase.platforminfo.LibraryVersionComponent - @Keep class FlutterFirebaseAppRegistrar : ComponentRegistrar { override fun getComponents(): List> { return listOf( - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION) - ) + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION)) } } diff --git a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt index e2dd133d1e21..c556353c8f91 100644 --- a/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt +++ b/packages/firebase_analytics/firebase_analytics/android/src/main/kotlin/io/flutter/plugins/firebase/analytics/GeneratedAndroidFirebaseAnalytics.g.kt @@ -10,12 +10,11 @@ package io.flutter.plugins.firebase.analytics import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object GeneratedAndroidFirebaseAnalyticsPigeonUtils { fun wrapResult(result: Any?): List { @@ -24,19 +23,15 @@ private object GeneratedAndroidFirebaseAnalyticsPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } + fun doubleEquals(a: Double, b: Double): Boolean { // Normalize -0.0 to 0.0 and handle NaN equality. return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) @@ -180,27 +175,23 @@ private object GeneratedAndroidFirebaseAnalyticsPigeonUtils { else -> value.hashCode() } } - } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : RuntimeException() /** Generated class from Pigeon that represents data sent in messages. */ -data class AnalyticsEvent ( - val name: String, - val parameters: Map? = null -) - { +data class AnalyticsEvent(val name: String, val parameters: Map? = null) { companion object { fun fromList(pigeonVar_list: List): AnalyticsEvent { val name = pigeonVar_list[0] as String @@ -208,12 +199,14 @@ data class AnalyticsEvent ( return AnalyticsEvent(name, parameters) } } + fun toList(): List { return listOf( - name, - parameters, + name, + parameters, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -222,7 +215,8 @@ data class AnalyticsEvent ( return true } val other = other as AnalyticsEvent - return GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepEquals(this.name, other.name) && GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepEquals(this.parameters, other.parameters) + return GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepEquals(this.name, other.name) && + GeneratedAndroidFirebaseAnalyticsPigeonUtils.deepEquals(this.parameters, other.parameters) } override fun hashCode(): Int { @@ -232,18 +226,18 @@ data class AnalyticsEvent ( return result } } + private open class GeneratedAndroidFirebaseAnalyticsPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 129.toByte() -> { - return (readValue(buffer) as? List)?.let { - AnalyticsEvent.fromList(it) - } + return (readValue(buffer) as? List)?.let { AnalyticsEvent.fromList(it) } } else -> super.readValueOfType(type, buffer) } } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { when (value) { is AnalyticsEvent -> { stream.write(129) @@ -254,33 +248,56 @@ private open class GeneratedAndroidFirebaseAnalyticsPigeonCodec : StandardMessag } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseAnalyticsHostApi { fun logEvent(event: Map, callback: (Result) -> Unit) + fun setUserId(userId: String?, callback: (Result) -> Unit) + fun setUserProperty(name: String, value: String?, callback: (Result) -> Unit) + fun setAnalyticsCollectionEnabled(enabled: Boolean, callback: (Result) -> Unit) + fun resetAnalyticsData(callback: (Result) -> Unit) + fun setSessionTimeoutDuration(timeout: Long, callback: (Result) -> Unit) + fun setConsent(consent: Map, callback: (Result) -> Unit) + fun setDefaultEventParameters(parameters: Map?, callback: (Result) -> Unit) + fun getAppInstanceId(callback: (Result) -> Unit) + fun getSessionId(callback: (Result) -> Unit) - fun initiateOnDeviceConversionMeasurement(arguments: Map, callback: (Result) -> Unit) + + fun initiateOnDeviceConversionMeasurement( + arguments: Map, + callback: (Result) -> Unit + ) + fun logTransaction(transactionId: String, callback: (Result) -> Unit) companion object { /** The codec used by FirebaseAnalyticsHostApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidFirebaseAnalyticsPigeonCodec() - } - /** Sets up an instance of `FirebaseAnalyticsHostApi` to handle messages through the `binaryMessenger`. */ + val codec: MessageCodec by lazy { GeneratedAndroidFirebaseAnalyticsPigeonCodec() } + /** + * Sets up an instance of `FirebaseAnalyticsHostApi` to handle messages through the + * `binaryMessenger`. + */ @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseAnalyticsHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp( + binaryMessenger: BinaryMessenger, + api: FirebaseAnalyticsHostApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -299,7 +316,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserId$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserId$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -318,7 +339,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -338,7 +363,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -357,10 +386,14 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.resetAnalyticsData$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.resetAnalyticsData$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { _, reply -> - api.resetAnalyticsData{ result: Result -> + api.resetAnalyticsData { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAnalyticsPigeonUtils.wrapError(error)) @@ -374,7 +407,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -393,7 +430,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -412,7 +453,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setDefaultEventParameters$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setDefaultEventParameters$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -431,10 +476,14 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getAppInstanceId$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getAppInstanceId$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { _, reply -> - api.getAppInstanceId{ result: Result -> + api.getAppInstanceId { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAnalyticsPigeonUtils.wrapError(error)) @@ -449,10 +498,14 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getSessionId$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getSessionId$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { _, reply -> - api.getSessionId{ result: Result -> + api.getSessionId { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAnalyticsPigeonUtils.wrapError(error)) @@ -467,7 +520,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -486,7 +543,11 @@ interface FirebaseAnalyticsHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List diff --git a/packages/firebase_analytics/firebase_analytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/analytics/example/MainActivity.kt b/packages/firebase_analytics/firebase_analytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/analytics/example/MainActivity.kt index 807a758cd9cc..00752be819a0 100644 --- a/packages/firebase_analytics/firebase_analytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/analytics/example/MainActivity.kt +++ b/packages/firebase_analytics/firebase_analytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/analytics/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.analytics.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift index ac1785bfd47d..16f26c8d379b 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift @@ -8,7 +8,7 @@ import Foundation import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" // Set FIREBASE_ANALYTICS_WITHOUT_ADID=true to use FirebaseAnalyticsWithoutAdIdSupport // e.g. FIREBASE_ANALYTICS_WITHOUT_ADID=true flutter build ios @@ -18,13 +18,13 @@ let analyticsProduct = useWithoutAdId ? "FirebaseAnalyticsWithoutAdIdSupport" : let package = Package( name: "firebase_analytics", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-analytics", targets: ["firebase_analytics"]), + .library(name: "firebase-analytics", targets: ["firebase_analytics"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -35,8 +35,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift index e0f11296f10a..c3a557049cc0 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsMessages.g.swift @@ -89,7 +89,7 @@ func deepEqualsFirebaseAnalyticsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: return true case is (Void, Void): @@ -131,7 +131,7 @@ func deepEqualsFirebaseAnalyticsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { } return true - case let (lhs as Double, rhs as Double): + case (let lhs as Double, let rhs as Double): return doubleEqualsFirebaseAnalyticsMessages(lhs, rhs) case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): @@ -202,8 +202,8 @@ struct AnalyticsEvent: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseAnalyticsMessages(lhs.name, rhs.name) && - deepEqualsFirebaseAnalyticsMessages( + return deepEqualsFirebaseAnalyticsMessages(lhs.name, rhs.name) + && deepEqualsFirebaseAnalyticsMessages( lhs.parameters, rhs.parameters ) @@ -259,20 +259,25 @@ class FirebaseAnalyticsMessagesPigeonCodec: FlutterStandardMessageCodec, @unchec protocol FirebaseAnalyticsHostApi { func logEvent(event: [String: Any?], completion: @escaping (Result) -> Void) func setUserId(userId: String?, completion: @escaping (Result) -> Void) - func setUserProperty(name: String, value: String?, - completion: @escaping (Result) -> Void) - func setAnalyticsCollectionEnabled(enabled: Bool, - completion: @escaping (Result) -> Void) + func setUserProperty( + name: String, value: String?, + completion: @escaping (Result) -> Void) + func setAnalyticsCollectionEnabled( + enabled: Bool, + completion: @escaping (Result) -> Void) func resetAnalyticsData(completion: @escaping (Result) -> Void) - func setSessionTimeoutDuration(timeout: Int64, - completion: @escaping (Result) -> Void) + func setSessionTimeoutDuration( + timeout: Int64, + completion: @escaping (Result) -> Void) func setConsent(consent: [String: Bool?], completion: @escaping (Result) -> Void) - func setDefaultEventParameters(parameters: [String: Any?]?, - completion: @escaping (Result) -> Void) + func setDefaultEventParameters( + parameters: [String: Any?]?, + completion: @escaping (Result) -> Void) func getAppInstanceId(completion: @escaping (Result) -> Void) func getSessionId(completion: @escaping (Result) -> Void) - func initiateOnDeviceConversionMeasurement(arguments: [String: String?], - completion: @escaping (Result) -> Void) + func initiateOnDeviceConversionMeasurement( + arguments: [String: String?], + completion: @escaping (Result) -> Void) func logTransaction(transactionId: String, completion: @escaping (Result) -> Void) } @@ -284,11 +289,14 @@ class FirebaseAnalyticsHostApiSetup { /// Sets up an instance of `FirebaseAnalyticsHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseAnalyticsHostApi?, - messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: FirebaseAnalyticsHostApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let logEventChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logEvent\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -300,7 +308,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -309,7 +317,8 @@ class FirebaseAnalyticsHostApiSetup { logEventChannel.setMessageHandler(nil) } let setUserIdChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserId\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserId\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -321,7 +330,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -330,7 +339,8 @@ class FirebaseAnalyticsHostApiSetup { setUserIdChannel.setMessageHandler(nil) } let setUserPropertyChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setUserProperty\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -343,7 +353,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -352,7 +362,8 @@ class FirebaseAnalyticsHostApiSetup { setUserPropertyChannel.setMessageHandler(nil) } let setAnalyticsCollectionEnabledChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setAnalyticsCollectionEnabled\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -364,7 +375,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -373,7 +384,8 @@ class FirebaseAnalyticsHostApiSetup { setAnalyticsCollectionEnabledChannel.setMessageHandler(nil) } let resetAnalyticsDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.resetAnalyticsData\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.resetAnalyticsData\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -383,7 +395,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -392,7 +404,8 @@ class FirebaseAnalyticsHostApiSetup { resetAnalyticsDataChannel.setMessageHandler(nil) } let setSessionTimeoutDurationChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setSessionTimeoutDuration\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -404,7 +417,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -413,7 +426,8 @@ class FirebaseAnalyticsHostApiSetup { setSessionTimeoutDurationChannel.setMessageHandler(nil) } let setConsentChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setConsent\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -425,7 +439,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -434,7 +448,8 @@ class FirebaseAnalyticsHostApiSetup { setConsentChannel.setMessageHandler(nil) } let setDefaultEventParametersChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setDefaultEventParameters\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.setDefaultEventParameters\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -446,7 +461,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -455,7 +470,8 @@ class FirebaseAnalyticsHostApiSetup { setDefaultEventParametersChannel.setMessageHandler(nil) } let getAppInstanceIdChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getAppInstanceId\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getAppInstanceId\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -463,9 +479,9 @@ class FirebaseAnalyticsHostApiSetup { getAppInstanceIdChannel.setMessageHandler { _, reply in api.getAppInstanceId { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -474,7 +490,8 @@ class FirebaseAnalyticsHostApiSetup { getAppInstanceIdChannel.setMessageHandler(nil) } let getSessionIdChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getSessionId\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.getSessionId\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -482,9 +499,9 @@ class FirebaseAnalyticsHostApiSetup { getSessionIdChannel.setMessageHandler { _, reply in api.getSessionId { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -493,7 +510,8 @@ class FirebaseAnalyticsHostApiSetup { getSessionIdChannel.setMessageHandler(nil) } let initiateOnDeviceConversionMeasurementChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.initiateOnDeviceConversionMeasurement\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -505,7 +523,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -514,7 +532,8 @@ class FirebaseAnalyticsHostApiSetup { initiateOnDeviceConversionMeasurementChannel.setMessageHandler(nil) } let logTransactionChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_analytics_platform_interface.FirebaseAnalyticsHostApi.logTransaction\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -526,7 +545,7 @@ class FirebaseAnalyticsHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsPlugin.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsPlugin.swift index 41651b2ace45..96b5921f88b0 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsPlugin.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Sources/firebase_analytics/FirebaseAnalyticsPlugin.swift @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseAnalytics +import StoreKit + #if canImport(FlutterMacOS) import FlutterMacOS #else @@ -13,8 +16,6 @@ #else import firebase_core_shared #endif -import FirebaseAnalytics -import StoreKit let kFLTFirebaseAnalyticsName = "name" let kFLTFirebaseAnalyticsValue = "value" @@ -27,12 +28,14 @@ let kFLTFirebaseAdPersonalizationSignalsConsentGranted = "adPersonalizationSigna let kFLTFirebaseAdUserDataConsentGranted = "adUserDataConsentGranted" let kFLTFirebaseAnalyticsUserId = "userId" +// swift-format-ignore: AlwaysUseLowerCamelCase let FLTFirebaseAnalyticsChannelName = "plugins.flutter.io/firebase_analytics" extension FlutterError: Error {} public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, FlutterPlugin, - FirebaseAnalyticsHostApi { + FirebaseAnalyticsHostApi +{ public static func register(with registrar: any FlutterPluginRegistrar) { let binaryMessenger: FlutterBinaryMessenger @@ -61,14 +64,18 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt completion(.success(())) } - func setUserProperty(name: String, value: String?, - completion: @escaping (Result) -> Void) { + func setUserProperty( + name: String, value: String?, + completion: @escaping (Result) -> Void + ) { Analytics.setUserProperty(value, forName: name) completion(.success(())) } - func setAnalyticsCollectionEnabled(enabled: Bool, - completion: @escaping (Result) -> Void) { + func setAnalyticsCollectionEnabled( + enabled: Bool, + completion: @escaping (Result) -> Void + ) { Analytics.setAnalyticsCollectionEnabled(enabled) completion(.success(())) } @@ -78,14 +85,18 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt completion(.success(())) } - func setSessionTimeoutDuration(timeout: Int64, - completion: @escaping (Result) -> Void) { + func setSessionTimeoutDuration( + timeout: Int64, + completion: @escaping (Result) -> Void + ) { Analytics.setSessionTimeoutInterval(TimeInterval(timeout)) completion(.success(())) } - func setConsent(consent: [String: Bool?], - completion: @escaping (Result) -> Void) { + func setConsent( + consent: [String: Bool?], + completion: @escaping (Result) -> Void + ) { var parameters: [ConsentType: ConsentStatus] = [:] if let adStorage = consent[kFLTFirebaseAnalyticsAdStorageConsentGranted] as? Bool { parameters[.adStorage] = adStorage ? .granted : .denied @@ -94,7 +105,8 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt parameters[.analyticsStorage] = analyticsStorage ? .granted : .denied } if let adPersonalization = - consent[kFLTFirebaseAdPersonalizationSignalsConsentGranted] as? Bool { + consent[kFLTFirebaseAdPersonalizationSignalsConsentGranted] as? Bool + { parameters[.adPersonalization] = adPersonalization ? .granted : .denied } if let adUserData = consent[kFLTFirebaseAdUserDataConsentGranted] as? Bool { @@ -104,8 +116,10 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt completion(.success(())) } - func setDefaultEventParameters(parameters: [String: Any?]?, - completion: @escaping (Result) -> Void) { + func setDefaultEventParameters( + parameters: [String: Any?]?, + completion: @escaping (Result) -> Void + ) { Analytics.setDefaultEventParameters(parameters) completion(.success(())) } @@ -125,9 +139,12 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt } } - func initiateOnDeviceConversionMeasurement(arguments: [String: String?], - completion: @escaping (Result) - -> Void) { + func initiateOnDeviceConversionMeasurement( + arguments: [String: String?], + completion: + @escaping (Result) + -> Void + ) { if let emailAddress = arguments["emailAddress"] as? String { Analytics.initiateOnDeviceConversionMeasurement(emailAddress: emailAddress) } @@ -135,37 +152,49 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt Analytics.initiateOnDeviceConversionMeasurement(phoneNumber: phoneNumber) } if let hashedEmailAddress = arguments["hashedEmailAddress"] as? String, - let data = hexStringToData(hashedEmailAddress) { + let data = hexStringToData(hashedEmailAddress) + { Analytics.initiateOnDeviceConversionMeasurement(hashedEmailAddress: data) } if let hashedPhoneNumber = arguments["hashedPhoneNumber"] as? String, - let data = hexStringToData(hashedPhoneNumber) { + let data = hexStringToData(hashedPhoneNumber) + { Analytics.initiateOnDeviceConversionMeasurement(hashedPhoneNumber: data) } completion(.success(())) } - func logTransaction(transactionId: String, - completion: @escaping (Result) -> Void) { + func logTransaction( + transactionId: String, + completion: @escaping (Result) -> Void + ) { #if os(macOS) if #available(macOS 12.0, *) { logTransactionWithStoreKit(transactionId: transactionId, completion: completion) } else { - completion(.failure(FlutterError( - code: "firebase_analytics", - message: "logTransaction() is only supported on macOS 12.0 or newer", - details: nil - ))) + completion( + .failure( + FlutterError( + code: "firebase_analytics", + message: "logTransaction() is only supported on macOS 12.0 or newer", + details: nil + ) + ) + ) } #else if #available(iOS 15.0, *) { logTransactionWithStoreKit(transactionId: transactionId, completion: completion) } else { - completion(.failure(FlutterError( - code: "firebase_analytics", - message: "logTransaction() is only supported on iOS 15.0 or newer", - details: nil - ))) + completion( + .failure( + FlutterError( + code: "firebase_analytics", + message: "logTransaction() is only supported on iOS 15.0 or newer", + details: nil + ) + ) + ) } #endif } @@ -175,23 +204,29 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt #else @available(iOS 15.0, *) #endif - private func logTransactionWithStoreKit(transactionId: String, - completion: @escaping (Result) -> Void) { + private func logTransactionWithStoreKit( + transactionId: String, + completion: @escaping (Result) -> Void + ) { Task { do { guard let id = UInt64(transactionId) else { - completion(.failure(FlutterError( - code: "firebase_analytics", - message: "Invalid transactionId", - details: nil - ))) + completion( + .failure( + FlutterError( + code: "firebase_analytics", + message: "Invalid transactionId", + details: nil + ) + ) + ) return } var foundTransaction: Transaction? for await result in Transaction.all { switch result { - case let .verified(transaction): + case .verified(let transaction): if transaction.id == id { foundTransaction = transaction break @@ -202,11 +237,15 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt } guard let transaction = foundTransaction else { - completion(.failure(FlutterError( - code: "firebase_analytics", - message: "Transaction not found", - details: nil - ))) + completion( + .failure( + FlutterError( + code: "firebase_analytics", + message: "Transaction not found", + details: nil + ) + ) + ) return } @@ -225,9 +264,9 @@ public class FirebaseAnalyticsPlugin: NSObject, FLTFirebasePluginProtocol, Flutt var data = Data(capacity: length / 2) var index = hexString.startIndex - for _ in 0 ..< (length / 2) { + for _ in 0..<(length / 2) { let nextIndex = hexString.index(index, offsetBy: 2) - guard let byte = UInt8(hexString[index ..< nextIndex], radix: 16) else { + guard let byte = UInt8(hexString[index.. = HashMap() private val eventChannels: MutableMap = HashMap() @@ -51,11 +48,11 @@ class FirebaseAppCheckPlugin : } override fun activate( - appName: String, - androidProvider: String?, - appleProvider: String?, - debugToken: String?, - callback: (Result) -> Unit + appName: String, + androidProvider: String?, + appleProvider: String?, + debugToken: String?, + callback: (Result) -> Unit ) { try { val firebaseAppCheck = getAppCheck(appName) @@ -63,13 +60,11 @@ class FirebaseAppCheckPlugin : "debug" -> { FlutterFirebaseAppRegistrar.debugToken = debugToken firebaseAppCheck.installAppCheckProviderFactory( - DebugAppCheckProviderFactory.getInstance() - ) + DebugAppCheckProviderFactory.getInstance()) } else -> { firebaseAppCheck.installAppCheckProviderFactory( - PlayIntegrityAppCheckProviderFactory.getInstance() - ) + PlayIntegrityAppCheckProviderFactory.getInstance()) } } callback(Result.success(Unit)) @@ -79,26 +74,24 @@ class FirebaseAppCheckPlugin : } override fun getToken( - appName: String, - forceRefresh: Boolean, - callback: (Result) -> Unit + appName: String, + forceRefresh: Boolean, + callback: (Result) -> Unit ) { val firebaseAppCheck = getAppCheck(appName) firebaseAppCheck.getAppCheckToken(forceRefresh).addOnCompleteListener { task -> if (task.isSuccessful) { callback(Result.success(task.result?.token)) } else { - callback(Result.failure( - FlutterError("firebase_app_check", task.exception?.message, null) - )) + callback(Result.failure(FlutterError("firebase_app_check", task.exception?.message, null))) } } } override fun setTokenAutoRefreshEnabled( - appName: String, - isTokenAutoRefreshEnabled: Boolean, - callback: (Result) -> Unit + appName: String, + isTokenAutoRefreshEnabled: Boolean, + callback: (Result) -> Unit ) { try { val firebaseAppCheck = getAppCheck(appName) @@ -109,10 +102,7 @@ class FirebaseAppCheckPlugin : } } - override fun registerTokenListener( - appName: String, - callback: (Result) -> Unit - ) { + override fun registerTokenListener(appName: String, callback: (Result) -> Unit) { try { val firebaseAppCheck = getAppCheck(appName) val name = EVENT_CHANNEL_PREFIX + appName @@ -129,25 +119,18 @@ class FirebaseAppCheckPlugin : } } - override fun getLimitedUseAppCheckToken( - appName: String, - callback: (Result) -> Unit - ) { + override fun getLimitedUseAppCheckToken(appName: String, callback: (Result) -> Unit) { val firebaseAppCheck = getAppCheck(appName) firebaseAppCheck.limitedUseAppCheckToken.addOnCompleteListener { task -> if (task.isSuccessful) { callback(Result.success(task.result?.token ?: "")) } else { - callback(Result.failure( - FlutterError("firebase_app_check", task.exception?.message, null) - )) + callback(Result.failure(FlutterError("firebase_app_check", task.exception?.message, null))) } } } - override fun getPluginConstantsForFirebaseApp( - firebaseApp: FirebaseApp - ): Task> { + override fun getPluginConstantsForFirebaseApp(firebaseApp: FirebaseApp): Task> { val taskCompletionSource = TaskCompletionSource>() taskCompletionSource.setResult(HashMap()) return taskCompletionSource.task diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt index d7146eba3a7f..1f1087b14698 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FlutterFirebaseAppRegistrar.kt @@ -15,19 +15,18 @@ class FlutterFirebaseAppRegistrar : ComponentRegistrar, InternalDebugSecretProvi companion object { private const val DEBUG_SECRET_NAME = "fire-app-check-debug-secret" - @JvmStatic - var debugToken: String? = null + @JvmStatic var debugToken: String? = null } override fun getComponents(): List> { - val library = LibraryVersionComponent.create( - BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION - ) - - val debugSecretProvider = Component.builder(InternalDebugSecretProvider::class.java) - .name(DEBUG_SECRET_NAME) - .factory { this } - .build() + val library = + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION) + + val debugSecretProvider = + Component.builder(InternalDebugSecretProvider::class.java) + .name(DEBUG_SECRET_NAME) + .factory { this } + .build() return listOf(library, debugSecretProvider) } diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt index 0a046dd5aa47..5e3ea8faca0c 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt @@ -10,12 +10,11 @@ package io.flutter.plugins.firebase.appcheck import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object GeneratedAndroidFirebaseAppCheckPigeonUtils { fun wrapResult(result: Any?): List { @@ -24,61 +23,82 @@ private object GeneratedAndroidFirebaseAppCheckPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : Throwable() + private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseAppCheckHostApi { - fun activate(appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, callback: (Result) -> Unit) + fun activate( + appName: String, + androidProvider: String?, + appleProvider: String?, + debugToken: String?, + callback: (Result) -> Unit + ) + fun getToken(appName: String, forceRefresh: Boolean, callback: (Result) -> Unit) - fun setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Boolean, callback: (Result) -> Unit) + + fun setTokenAutoRefreshEnabled( + appName: String, + isTokenAutoRefreshEnabled: Boolean, + callback: (Result) -> Unit + ) + fun registerTokenListener(appName: String, callback: (Result) -> Unit) + fun getLimitedUseAppCheckToken(appName: String, callback: (Result) -> Unit) companion object { /** The codec used by FirebaseAppCheckHostApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidFirebaseAppCheckPigeonCodec() - } - /** Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binaryMessenger`. */ + val codec: MessageCodec by lazy { GeneratedAndroidFirebaseAppCheckPigeonCodec() } + /** + * Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the + * `binaryMessenger`. + */ @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseAppCheckHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp( + binaryMessenger: BinaryMessenger, + api: FirebaseAppCheckHostApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -86,7 +106,8 @@ interface FirebaseAppCheckHostApi { val androidProviderArg = args[1] as String? val appleProviderArg = args[2] as String? val debugTokenArg = args[3] as String? - api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg) { result: Result -> + api.activate(appNameArg, androidProviderArg, appleProviderArg, debugTokenArg) { + result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) @@ -100,7 +121,11 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -121,13 +146,18 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val appNameArg = args[0] as String val isTokenAutoRefreshEnabledArg = args[1] as Boolean - api.setTokenAutoRefreshEnabled(appNameArg, isTokenAutoRefreshEnabledArg) { result: Result -> + api.setTokenAutoRefreshEnabled(appNameArg, isTokenAutoRefreshEnabledArg) { + result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseAppCheckPigeonUtils.wrapError(error)) @@ -141,7 +171,11 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -161,7 +195,11 @@ interface FirebaseAppCheckHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt index 2062821507c8..81d1b83e188a 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/TokenChannelStreamHandler.kt @@ -6,18 +6,18 @@ package io.flutter.plugins.firebase.appcheck import com.google.firebase.appcheck.FirebaseAppCheck import io.flutter.plugin.common.EventChannel -class TokenChannelStreamHandler( - private val firebaseAppCheck: FirebaseAppCheck -) : EventChannel.StreamHandler { +class TokenChannelStreamHandler(private val firebaseAppCheck: FirebaseAppCheck) : + EventChannel.StreamHandler { private var listener: FirebaseAppCheck.AppCheckListener? = null override fun onListen(arguments: Any?, events: EventChannel.EventSink) { - listener = FirebaseAppCheck.AppCheckListener { result -> - val event = HashMap() - event["token"] = result.token - events.success(event) - } + listener = + FirebaseAppCheck.AppCheckListener { result -> + val event = HashMap() + event["token"] = result.token + events.success(event) + } firebaseAppCheck.addAppCheckListener(listener!!) } diff --git a/packages/firebase_app_check/firebase_app_check/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/appcheck/example/MainActivity.kt b/packages/firebase_app_check/firebase_app_check/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/appcheck/example/MainActivity.kt index 23c1224eea5c..fd3526f15954 100644 --- a/packages/firebase_app_check/firebase_app_check/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/appcheck/example/MainActivity.kt +++ b/packages/firebase_app_check/firebase_app_check/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/appcheck/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.appcheck.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index 0efbf1751e07..bbb503de342b 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_app_check", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-app-check", targets: ["firebase_app_check"]), + .library(name: "firebase-app-check", targets: ["firebase_app_check"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift index 1842cfe9c240..57e0accedf53 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -89,15 +89,19 @@ class FirebaseAppCheckMessagesPigeonCodec: FlutterStandardMessageCodec, @uncheck /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseAppCheckHostApi { - func activate(appName: String, androidProvider: String?, appleProvider: String?, - debugToken: String?, completion: @escaping (Result) -> Void) - func getToken(appName: String, forceRefresh: Bool, - completion: @escaping (Result) -> Void) - func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, - completion: @escaping (Result) -> Void) + func activate( + appName: String, androidProvider: String?, appleProvider: String?, + debugToken: String?, completion: @escaping (Result) -> Void) + func getToken( + appName: String, forceRefresh: Bool, + completion: @escaping (Result) -> Void) + func setTokenAutoRefreshEnabled( + appName: String, isTokenAutoRefreshEnabled: Bool, + completion: @escaping (Result) -> Void) func registerTokenListener(appName: String, completion: @escaping (Result) -> Void) - func getLimitedUseAppCheckToken(appName: String, - completion: @escaping (Result) -> Void) + func getLimitedUseAppCheckToken( + appName: String, + completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -108,11 +112,14 @@ class FirebaseAppCheckHostApiSetup { /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppCheckHostApi?, - messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppCheckHostApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let activateChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -132,7 +139,7 @@ class FirebaseAppCheckHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -141,7 +148,8 @@ class FirebaseAppCheckHostApiSetup { activateChannel.setMessageHandler(nil) } let getTokenChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -152,9 +160,9 @@ class FirebaseAppCheckHostApiSetup { let forceRefreshArg = args[1] as! Bool api.getToken(appName: appNameArg, forceRefresh: forceRefreshArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -163,7 +171,8 @@ class FirebaseAppCheckHostApiSetup { getTokenChannel.setMessageHandler(nil) } let setTokenAutoRefreshEnabledChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -179,7 +188,7 @@ class FirebaseAppCheckHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -188,7 +197,8 @@ class FirebaseAppCheckHostApiSetup { setTokenAutoRefreshEnabledChannel.setMessageHandler(nil) } let registerTokenListenerChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -198,9 +208,9 @@ class FirebaseAppCheckHostApiSetup { let appNameArg = args[0] as! String api.registerTokenListener(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -209,7 +219,8 @@ class FirebaseAppCheckHostApiSetup { registerTokenListenerChannel.setMessageHandler(nil) } let getLimitedUseAppCheckTokenChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -219,9 +230,9 @@ class FirebaseAppCheckHostApiSetup { let appNameArg = args[0] as! String api.getLimitedUseAppCheckToken(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift index 5aec32b1ad2c..c737dcd75a22 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseAppCheck +import FirebaseCore + #if canImport(FlutterMacOS) import FlutterMacOS #else @@ -13,16 +16,16 @@ #else import firebase_core_shared #endif -import FirebaseAppCheck -import FirebaseCore let kFirebaseAppCheckChannelName = "plugins.flutter.io/firebase_app_check" let kFirebaseAppCheckTokenChannelPrefix = "plugins.flutter.io/firebase_app_check/token/" +// swift-format-ignore: AvoidRetroactiveConformances extension FlutterError: @retroactive Error {} public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, - FLTFirebasePluginProtocol, FirebaseAppCheckHostApi { + FLTFirebasePluginProtocol, FirebaseAppCheckHostApi +{ private var eventChannels: [String: FlutterEventChannel] = [:] private var streamHandlers: [String: AppCheckTokenStreamHandler] = [:] private var providerFactory: FlutterAppCheckProviderFactory? @@ -59,13 +62,19 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, private var binaryMessenger: FlutterBinaryMessenger? - func activate(appName: String, androidProvider: String?, appleProvider: String?, - debugToken: String?, - completion: @escaping (Result) -> Void) { + func activate( + appName: String, androidProvider: String?, appleProvider: String?, + debugToken: String?, + completion: @escaping (Result) -> Void + ) { guard let app = FLTFirebasePlugin.firebaseAppNamed(appName) else { - completion(.failure(FlutterError( - code: "unknown", message: "Firebase app not found: \(appName)", details: nil - ))) + completion( + .failure( + FlutterError( + code: "unknown", message: "Firebase app not found: \(appName)", details: nil + ) + ) + ) return } let provider = appleProvider ?? "deviceCheck" @@ -75,14 +84,20 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, completion(.success(())) } - func getToken(appName: String, forceRefresh: Bool, - completion: @escaping (Result) -> Void) { + func getToken( + appName: String, forceRefresh: Bool, + completion: @escaping (Result) -> Void + ) { guard let app = FLTFirebasePlugin.firebaseAppNamed(appName), - let appCheck = AppCheck.appCheck(app: app) + let appCheck = AppCheck.appCheck(app: app) else { - completion(.failure(FlutterError( - code: "unknown", message: "App Check not available for app: \(appName)", details: nil - ))) + completion( + .failure( + FlutterError( + code: "unknown", message: "App Check not available for app: \(appName)", details: nil + ) + ) + ) return } @@ -95,30 +110,42 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, } } - func setTokenAutoRefreshEnabled(appName: String, isTokenAutoRefreshEnabled: Bool, - completion: @escaping (Result) -> Void) { + func setTokenAutoRefreshEnabled( + appName: String, isTokenAutoRefreshEnabled: Bool, + completion: @escaping (Result) -> Void + ) { guard let app = FLTFirebasePlugin.firebaseAppNamed(appName), - let appCheck = AppCheck.appCheck(app: app) + let appCheck = AppCheck.appCheck(app: app) else { - completion(.failure(FlutterError( - code: "unknown", message: "App Check not available for app: \(appName)", details: nil - ))) + completion( + .failure( + FlutterError( + code: "unknown", message: "App Check not available for app: \(appName)", details: nil + ) + ) + ) return } appCheck.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled completion(.success(())) } - func registerTokenListener(appName: String, - completion: @escaping (Result) -> Void) { + func registerTokenListener( + appName: String, + completion: @escaping (Result) -> Void + ) { let name = kFirebaseAppCheckTokenChannelPrefix + appName guard let messenger = binaryMessenger else { - completion(.failure(FlutterError( - code: "no-messenger", - message: "Binary messenger not available", - details: nil - ))) + completion( + .failure( + FlutterError( + code: "no-messenger", + message: "Binary messenger not available", + details: nil + ) + ) + ) return } @@ -132,14 +159,20 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, completion(.success(name)) } - func getLimitedUseAppCheckToken(appName: String, - completion: @escaping (Result) -> Void) { + func getLimitedUseAppCheckToken( + appName: String, + completion: @escaping (Result) -> Void + ) { guard let app = FLTFirebasePlugin.firebaseAppNamed(appName), - let appCheck = AppCheck.appCheck(app: app) + let appCheck = AppCheck.appCheck(app: app) else { - completion(.failure(FlutterError( - code: "unknown", message: "App Check not available for app: \(appName)", details: nil - ))) + completion( + .failure( + FlutterError( + code: "unknown", message: "App Check not available for app: \(appName)", details: nil + ) + ) + ) return } @@ -186,13 +219,13 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, let nsError = error as NSError var code = "unknown" switch nsError.code { - case 0: // FIRAppCheckErrorCodeServerUnreachable + case 0: // FIRAppCheckErrorCodeServerUnreachable code = "server-unreachable" - case 1: // FIRAppCheckErrorCodeInvalidConfiguration + case 1: // FIRAppCheckErrorCodeInvalidConfiguration code = "invalid-configuration" - case 2: // FIRAppCheckErrorCodeKeychain + case 2: // FIRAppCheckErrorCodeKeychain code = "code-keychain" - case 3: // FIRAppCheckErrorCodeUnsupported + case 3: // FIRAppCheckErrorCodeUnsupported code = "code-unsupported" default: code = "unknown" @@ -210,8 +243,10 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, class AppCheckTokenStreamHandler: NSObject, FlutterStreamHandler { private var observer: NSObjectProtocol? - func onListen(withArguments arguments: Any?, - eventSink events: @escaping FlutterEventSink) -> FlutterError? { + func onListen( + withArguments arguments: Any?, + eventSink events: @escaping FlutterEventSink + ) -> FlutterError? { observer = NotificationCenter.default.addObserver( forName: NSNotification.Name("FIRAppCheckAppCheckTokenDidChangeNotification"), object: nil, @@ -289,10 +324,13 @@ class AppCheckProviderWrapper: NSObject, AppCheckProvider { func getToken(completion handler: @escaping (AppCheckToken?, Error?) -> Void) { guard let delegateProvider else { - handler(nil, NSError( - domain: "firebase_app_check", code: -1, - userInfo: [NSLocalizedDescriptionKey: "Provider not configured"] - )) + handler( + nil, + NSError( + domain: "firebase_app_check", code: -1, + userInfo: [NSLocalizedDescriptionKey: "Provider not configured"] + ) + ) return } delegateProvider.getToken(completion: handler) diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift index 8c3681021df7..0b49a74eb477 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_app_check", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-app-check", targets: ["firebase_app_check"]), + .library(name: "firebase-app-check", targets: ["firebase_app_check"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_app_installations/firebase_app_installations/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/installations/example/MainActivity.kt b/packages/firebase_app_installations/firebase_app_installations/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/installations/example/MainActivity.kt index 6f76296229d1..a8d726fe6633 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/installations/example/MainActivity.kt +++ b/packages/firebase_app_installations/firebase_app_installations/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/installations/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.installations.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_app_installations/firebase_app_installations/example/ios/Runner/AppDelegate.swift b/packages/firebase_app_installations/firebase_app_installations/example/ios/Runner/AppDelegate.swift index b6363034812b..626664468b89 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/ios/Runner/AppDelegate.swift +++ b/packages/firebase_app_installations/firebase_app_installations/example/ios/Runner/AppDelegate.swift @@ -1,5 +1,5 @@ -import UIKit import Flutter +import UIKit @main @objc class AppDelegate: FlutterAppDelegate { diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift index 10d97417547e..2d43d4e4781f 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_app_installations", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-app-installations", targets: ["firebase_app_installations"]), + .library(name: "firebase-app-installations", targets: ["firebase_app_installations"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift index fb9ed2a06894..eb1d365a1f7e 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/FirebaseInstallationsPlugin.swift @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseInstallations + #if canImport(FlutterMacOS) import FlutterMacOS #else @@ -13,7 +15,6 @@ #else import firebase_core_shared #endif -import FirebaseInstallations let kFLTFirebaseInstallationsChannelName = "plugins.flutter.io/firebase_app_installations" @@ -75,8 +76,10 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F /// - Parameter arguments: the arguments passed by the Dart calling method /// - Parameter result: the result instance used to send the result to Dart. /// - Parameter errorBlock: the error block used to send the error to Dart. - private func getId(arguments: NSDictionary, result: @escaping FlutterResult, - errorBlock: @escaping FLTFirebaseMethodCallErrorBlock) { + private func getId( + arguments: NSDictionary, result: @escaping FlutterResult, + errorBlock: @escaping FLTFirebaseMethodCallErrorBlock + ) { let instance = getInstallations(appName: arguments["appName"] as! String) instance.installationID { (id: String?, error: Error?) in if let error { @@ -91,8 +94,10 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F /// - Parameter arguments: the arguments passed by the Dart calling method /// - Parameter result: the result instance used to send the result to Dart. /// - Parameter errorBlock: the error block used to send the error to Dart. - private func deleteId(arguments: NSDictionary, result: @escaping FlutterResult, - errorBlock: @escaping FLTFirebaseMethodCallErrorBlock) { + private func deleteId( + arguments: NSDictionary, result: @escaping FlutterResult, + errorBlock: @escaping FLTFirebaseMethodCallErrorBlock + ) { let instance = getInstallations(appName: arguments["appName"] as! String) instance.delete { (error: Error?) in if let error { @@ -107,18 +112,23 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F /// - Parameter arguments: the arguments passed by the Dart calling method /// - Parameter result: the result instance used to send the result to Dart. /// - Parameter errorBlock: the error block used to send the error to Dart. - private func getToken(arguments: NSDictionary, result: @escaping FlutterResult, - errorBlock: @escaping FLTFirebaseMethodCallErrorBlock) { + private func getToken( + arguments: NSDictionary, result: @escaping FlutterResult, + errorBlock: @escaping FLTFirebaseMethodCallErrorBlock + ) { let instance = getInstallations(appName: arguments["appName"] as! String) let forceRefresh = arguments["forceRefresh"] as? Bool ?? false instance - .authTokenForcingRefresh(forceRefresh) { (tokenResult: InstallationsAuthTokenResult?, - error: Error?) in - if let error { - errorBlock(nil, nil, nil, error) - } else { - result(tokenResult?.authToken) - } + .authTokenForcingRefresh(forceRefresh) { + ( + tokenResult: InstallationsAuthTokenResult?, + error: Error? + ) in + if let error { + errorBlock(nil, nil, nil, error) + } else { + result(tokenResult?.authToken) + } } } @@ -126,8 +136,10 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F /// - Parameter arguments: the arguments passed by the Dart calling method /// - Parameter result: the result instance used to send the result to Dart. /// - Parameter errorBlock: the error block used to send the error to Dart. - private func registerIdChangeListener(arguments: NSDictionary, result: @escaping FlutterResult, - errorBlock: @escaping FLTFirebaseMethodCallErrorBlock) { + private func registerIdChangeListener( + arguments: NSDictionary, result: @escaping FlutterResult, + errorBlock: @escaping FLTFirebaseMethodCallErrorBlock + ) { let instance = getInstallations(appName: arguments["appName"] as! String) let appName = arguments["appName"] as! String let eventChannelName = kFLTFirebaseInstallationsChannelName + "/token/" + appName @@ -144,8 +156,10 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F } private func mapInstallationsErrorCodes(code: UInt) -> NSString { - let error = InstallationsErrorCode(InstallationsErrorCode - .Code(rawValue: Int(code)) ?? InstallationsErrorCode.unknown) + let error = InstallationsErrorCode( + InstallationsErrorCode + .Code(rawValue: Int(code)) ?? InstallationsErrorCode.unknown + ) switch error { case InstallationsErrorCode.invalidConfiguration: @@ -163,37 +177,49 @@ public class FirebaseInstallationsPlugin: NSObject, FLTFirebasePluginProtocol, F public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { guard let args = call.arguments as? NSDictionary else { - result(FlutterError( - code: "invalid-arguments", - message: "Arguments are not a dictionary", - details: nil - )) + result( + FlutterError( + code: "invalid-arguments", + message: "Arguments are not a dictionary", + details: nil + ) + ) return } - let errorBlock: FLTFirebaseMethodCallErrorBlock = { (code, message, details, - error: Error?) in - var errorDetails = [String: Any?]() - - errorDetails["code"] = code ?? self - .mapInstallationsErrorCodes(code: UInt((error! as NSError).code)) - errorDetails["message"] = message ?? error? - .localizedDescription ?? "An unknown error has occurred." - errorDetails["additionalData"] = details - - if code == "unknown" { - NSLog( - "FLTFirebaseInstallations: An error occurred while calling method %@", - call.method - ) - } + let errorBlock: FLTFirebaseMethodCallErrorBlock = { + ( + code, message, details, + error: Error? + ) in + var errorDetails = [String: Any?]() + + errorDetails["code"] = + code + ?? self + .mapInstallationsErrorCodes(code: UInt((error! as NSError).code)) + errorDetails["message"] = + message ?? error? + .localizedDescription ?? "An unknown error has occurred." + errorDetails["additionalData"] = details + + if code == "unknown" { + NSLog( + "FLTFirebaseInstallations: An error occurred while calling method %@", + call.method + ) + } - result(FLTFirebasePlugin.createFlutterError(fromCode: errorDetails["code"] as! String, - message: errorDetails["message"] as! String, - optionalDetails: errorDetails[ - "additionalData" - ] as? [AnyHashable: Any], - andOptionalNSError: error)) + result( + FLTFirebasePlugin.createFlutterError( + fromCode: errorDetails["code"] as! String, + message: errorDetails["message"] as! String, + optionalDetails: errorDetails[ + "additionalData" + ] as? [AnyHashable: Any], + andOptionalNSError: error + ) + ) } switch call.method { diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/IdChangedStreamHandler.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/IdChangedStreamHandler.swift index 6d07257dfee8..89f9cbc2e4e9 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/IdChangedStreamHandler.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/IdChangedStreamHandler.swift @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseInstallations +import Foundation + #if canImport(FlutterMacOS) import FlutterMacOS #else import Flutter #endif -import FirebaseInstallations -import Foundation - class IdChangedStreamHandler: NSObject, FlutterStreamHandler { var eventSink: FlutterEventSink? var installationIDObserver: NSObjectProtocol? @@ -33,11 +33,13 @@ class IdChangedStreamHandler: NSObject, FlutterStreamHandler { guard let self else { return } if let error { - self.eventSink?(FlutterError( - code: "unknown", - message: error.localizedDescription, - details: ["code": "unknown", "message": error.localizedDescription] - )) + self.eventSink?( + FlutterError( + code: "unknown", + message: error.localizedDescription, + details: ["code": "unknown", "message": error.localizedDescription] + ) + ) } else if let newId, newId != self.installationsId { self.installationsId = newId self.eventSink?(["token": self.installationsId]) @@ -45,8 +47,10 @@ class IdChangedStreamHandler: NSObject, FlutterStreamHandler { } } - func onListen(withArguments _: Any?, - eventSink events: @escaping FlutterEventSink) -> FlutterError? { + func onListen( + withArguments _: Any?, + eventSink events: @escaping FlutterEventSink + ) -> FlutterError? { eventSink = events installationIDObserver = NotificationCenter.default.addObserver( diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift index aa19a3f19e9a..325e24d74976 100644 --- a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_app_installations", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-app-installations", targets: ["firebase_app_installations"]), + .library(name: "firebase-app-installations", targets: ["firebase_app_installations"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java index 890fbca4c32d..a122221c601c 100755 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPlugin.java @@ -142,7 +142,8 @@ static FirebaseAuth getAuthFromPigeon( auth.setCustomAuthDomain(customDomain); } - // Auth's `getCustomAuthDomain` supersedes value from `customAuthDomain` map set by `initializeApp` + // Auth's `getCustomAuthDomain` supersedes value from `customAuthDomain` map set by + // `initializeApp` if (pigeonApp.getCustomAuthDomain() != null) { auth.setCustomAuthDomain(pigeonApp.getCustomAuthDomain()); } diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java index 7d8ef4338065..a42bcb56956d 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/FlutterFirebaseAuthPluginException.java @@ -70,7 +70,8 @@ static GeneratedAndroidFirebaseAuth.FlutterError parserExceptionToFlutter( && nativeException.getCause() instanceof FirebaseNetworkException)) { return new GeneratedAndroidFirebaseAuth.FlutterError( "network-request-failed", - "A network error (such as timeout, interrupted connection or unreachable host) has occurred.", + "A network error (such as timeout, interrupted connection or unreachable host) has" + + " occurred.", null); } diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java index ee16c9973a33..5aaa168b70e8 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/GeneratedAndroidFirebaseAuth.java @@ -3234,6 +3234,7 @@ public interface Result { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Asynchronous error handling return type for nullable API method returns. */ public interface NullableResult { /** Success case callback method for handling returns. */ @@ -3242,6 +3243,7 @@ public interface NullableResult { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Asynchronous error handling return type for void API method returns. */ public interface VoidResult { /** Success case callback method for handling returns. */ @@ -3250,6 +3252,7 @@ public interface VoidResult { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseAuthHostApi { @@ -3368,6 +3371,7 @@ void revokeAccessToken( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `FirebaseAuthHostApi` to handle messages through the * `binaryMessenger`. @@ -4181,6 +4185,7 @@ public void error(Throwable error) { } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseAuthUserHostApi { @@ -4253,6 +4258,7 @@ void verifyBeforeUpdateEmail( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `FirebaseAuthUserHostApi` to handle messages through the * `binaryMessenger`. @@ -4733,6 +4739,7 @@ public void error(Throwable error) { } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface MultiFactorUserHostApi { @@ -4761,6 +4768,7 @@ void getEnrolledFactors( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `MultiFactorUserHostApi` to handle messages through the * `binaryMessenger`. @@ -4943,6 +4951,7 @@ public void error(Throwable error) { } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface MultiFactoResolverHostApi { @@ -4956,6 +4965,7 @@ void resolveSignIn( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `MultiFactoResolverHostApi` to handle messages through the * `binaryMessenger`. @@ -5007,6 +5017,7 @@ public void error(Throwable error) { } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface MultiFactorTotpHostApi { @@ -5024,6 +5035,7 @@ void getAssertionForSignIn( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `MultiFactorTotpHostApi` to handle messages through the * `binaryMessenger`. @@ -5138,6 +5150,7 @@ public void error(Throwable error) { } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface MultiFactorTotpSecretHostApi { @@ -5154,6 +5167,7 @@ void openInOtpApp( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `MultiFactorTotpSecretHostApi` to handle messages through the * `binaryMessenger`. @@ -5237,6 +5251,7 @@ public void error(Throwable error) { } } } + /** * Only used to generate the object interface that are use outside of the Pigeon interface * @@ -5250,6 +5265,7 @@ public interface GenerateInterfaces { static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `GenerateInterfaces` to handle messages through the `binaryMessenger`. */ diff --git a/packages/firebase_auth/firebase_auth/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/auth/example/MainActivity.kt b/packages/firebase_auth/firebase_auth/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/auth/example/MainActivity.kt index e8ca8519f78f..2b88c507db23 100644 --- a/packages/firebase_auth/firebase_auth/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/auth/example/MainActivity.kt +++ b/packages/firebase_auth/firebase_auth/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/auth/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.auth.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_auth/firebase_auth/example/ios/Runner/AppDelegate.swift b/packages/firebase_auth/firebase_auth/example/ios/Runner/AppDelegate.swift index b6363034812b..626664468b89 100644 --- a/packages/firebase_auth/firebase_auth/example/ios/Runner/AppDelegate.swift +++ b/packages/firebase_auth/firebase_auth/example/ios/Runner/AppDelegate.swift @@ -1,5 +1,5 @@ -import UIKit import Flutter +import UIKit @main @objc class AppDelegate: FlutterAppDelegate { diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index 4f5d3dff67bc..21e7c1442de5 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "6.5.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "6.5.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_auth", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-auth", targets: ["firebase_auth"]), + .library(name: "firebase-auth", targets: ["firebase_auth"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,14 +30,14 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include/Private"), .headerSearchPath("include/Public"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-auth\""), ] - ), + ) ] ) diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index 6097c54e634a..8ecc7b9db7ec 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "6.5.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "6.5.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_auth", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-auth", targets: ["firebase_auth"]), + .library(name: "firebase-auth", targets: ["firebase_auth"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,14 +30,14 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include/Private"), .headerSearchPath("include/Public"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-auth\""), ] - ), + ) ] ) diff --git a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java index 53b7e6356457..a1fed94439e3 100644 --- a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java +++ b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java @@ -151,8 +151,10 @@ public void initializeApp( .setGaTrackingId(initializeAppRequest.getTrackingId()) .build(); // TODO(Salakar) hacky workaround a bug with FirebaseInAppMessaging causing the error: - // Can't create handler inside thread Thread[pool-3-thread-1,5,main] that has not called Looper.prepare() - // at com.google.firebase.inappmessaging.internal.ForegroundNotifier.(ForegroundNotifier.java:61) + // Can't create handler inside thread Thread[pool-3-thread-1,5,main] that has not + // called Looper.prepare() + // at + // com.google.firebase.inappmessaging.internal.ForegroundNotifier.(ForegroundNotifier.java:61) try { Looper.prepare(); } catch (Exception e) { @@ -221,7 +223,8 @@ public void optionsFromResource( if (options == null) { taskCompletionSource.setException( new Exception( - "Failed to load FirebaseOptions from resource. Check that you have defined values.xml correctly.")); + "Failed to load FirebaseOptions from resource. Check that you have defined" + + " values.xml correctly.")); return; } taskCompletionSource.setResult(firebaseOptionsToMap(options)); diff --git a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java index 8a5db2e48066..b0a698faf51c 100644 --- a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java +++ b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java @@ -802,6 +802,7 @@ public interface Result { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Asynchronous error handling return type for nullable API method returns. */ public interface NullableResult { /** Success case callback method for handling returns. */ @@ -810,6 +811,7 @@ public interface NullableResult { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Asynchronous error handling return type for void API method returns. */ public interface VoidResult { /** Success case callback method for handling returns. */ @@ -818,6 +820,7 @@ public interface VoidResult { /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseCoreHostApi { @@ -834,6 +837,7 @@ void initializeApp( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `FirebaseCoreHostApi` to handle messages through the * `binaryMessenger`. @@ -942,6 +946,7 @@ public void error(Throwable error) { } } } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FirebaseAppHostApi { @@ -957,6 +962,7 @@ void setAutomaticResourceManagementEnabled( static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } + /** * Sets up an instance of `FirebaseAppHostApi` to handle messages through the `binaryMessenger`. */ diff --git a/packages/firebase_core/firebase_core/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecoreexample/MainActivity.kt b/packages/firebase_core/firebase_core/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecoreexample/MainActivity.kt index 8757d9f10dbd..2416ea61ea9d 100644 --- a/packages/firebase_core/firebase_core/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecoreexample/MainActivity.kt +++ b/packages/firebase_core/firebase_core/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecoreexample/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebasecoreexample import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index ee5b08632f51..28085699c8cb 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -7,35 +7,35 @@ import PackageDescription -let library_version_string = "4.9.0" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersionString = "4.9.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_core", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-core", targets: ["firebase_core"]), + .library(name: "firebase-core", targets: ["firebase_core"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion) ], targets: [ .target( name: "firebase_core", dependencies: [ // No product for firebase-core so we pull in the smallest one - .product(name: "FirebaseInstallations", package: "firebase-ios-sdk"), + .product(name: "FirebaseInstallations", package: "firebase-ios-sdk") ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include/firebase_core"), - .define("LIBRARY_VERSION", to: "\"\(library_version_string)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersionString)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-core\""), ] - ), + ) ] ) diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index 278b94b9dc21..74c925e5baa6 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -7,35 +7,35 @@ import PackageDescription -let library_version_string = "4.9.0" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersionString = "4.9.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_core", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-core", targets: ["firebase_core"]), + .library(name: "firebase-core", targets: ["firebase_core"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion) ], targets: [ .target( name: "firebase_core", dependencies: [ // No product for firebase-core so we pull in the smallest one - .product(name: "FirebaseInstallations", package: "firebase-ios-sdk"), + .product(name: "FirebaseInstallations", package: "firebase-ios-sdk") ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include/firebase_core"), - .define("LIBRARY_VERSION", to: "\"\(library_version_string)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersionString)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-core\""), ] - ), + ) ] ) diff --git a/packages/firebase_crashlytics/firebase_crashlytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecrashlyticsexample/MainActivity.kt b/packages/firebase_crashlytics/firebase_crashlytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecrashlyticsexample/MainActivity.kt index 2fb355214b7b..87963034f34b 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecrashlyticsexample/MainActivity.kt +++ b/packages/firebase_crashlytics/firebase_crashlytics/example/android/app/src/main/kotlin/io/flutter/plugins/firebasecrashlyticsexample/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebasecrashlyticsexample import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index c334113d34ad..08be6e33616b 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "5.2.2" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "5.2.2" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_crashlytics", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-crashlytics", targets: ["firebase_crashlytics"]), + .library(name: "firebase-crashlytics", targets: ["firebase_crashlytics"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-cls\""), ] - ), + ) ] ) diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index 5a5a02b868c0..21044f98b44f 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "5.2.2" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "5.2.2" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_crashlytics", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-crashlytics", targets: ["firebase_crashlytics"]), + .library(name: "firebase-crashlytics", targets: ["firebase_crashlytics"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-cls\""), ] - ), + ) ] ) diff --git a/packages/firebase_data_connect/firebase_data_connect/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/dataconnect/example/MainActivity.kt b/packages/firebase_data_connect/firebase_data_connect/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/dataconnect/example/MainActivity.kt index edca5bed7fed..5f6a78ea469a 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/dataconnect/example/MainActivity.kt +++ b/packages/firebase_data_connect/firebase_data_connect/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/dataconnect/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.dataconnect.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ChildEventsProxy.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ChildEventsProxy.kt index 707b8b8b5e5a..82de31ae09a0 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ChildEventsProxy.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ChildEventsProxy.kt @@ -14,43 +14,42 @@ import com.google.firebase.database.DatabaseError import io.flutter.plugin.common.EventChannel.EventSink class ChildEventsProxy - @JvmOverloads - constructor( +@JvmOverloads +constructor( @NonNull eventSink: EventSink, @NonNull eventType: String, - ) : EventsProxy(eventSink, eventType), - ChildEventListener { - override fun onChildAdded( +) : EventsProxy(eventSink, eventType), ChildEventListener { + override fun onChildAdded( @NonNull snapshot: DataSnapshot, @Nullable previousChildName: String?, - ) { - sendEvent(Constants.EVENT_TYPE_CHILD_ADDED, snapshot, previousChildName) - } + ) { + sendEvent(Constants.EVENT_TYPE_CHILD_ADDED, snapshot, previousChildName) + } - override fun onChildChanged( + override fun onChildChanged( @NonNull snapshot: DataSnapshot, @Nullable previousChildName: String?, - ) { - sendEvent(Constants.EVENT_TYPE_CHILD_CHANGED, snapshot, previousChildName) - } + ) { + sendEvent(Constants.EVENT_TYPE_CHILD_CHANGED, snapshot, previousChildName) + } - override fun onChildRemoved( + override fun onChildRemoved( @NonNull snapshot: DataSnapshot, - ) { - sendEvent(Constants.EVENT_TYPE_CHILD_REMOVED, snapshot, null) - } + ) { + sendEvent(Constants.EVENT_TYPE_CHILD_REMOVED, snapshot, null) + } - override fun onChildMoved( + override fun onChildMoved( @NonNull snapshot: DataSnapshot, @Nullable previousChildName: String?, - ) { - sendEvent(Constants.EVENT_TYPE_CHILD_MOVED, snapshot, previousChildName) - } + ) { + sendEvent(Constants.EVENT_TYPE_CHILD_MOVED, snapshot, previousChildName) + } - override fun onCancelled( + override fun onCancelled( @NonNull error: DatabaseError, - ) { - val e = FlutterFirebaseDatabaseException.fromDatabaseError(error) - eventSink.error(e.code, e.message, e.additionalData) - } + ) { + val e = FlutterFirebaseDatabaseException.fromDatabaseError(error) + eventSink.error(e.code, e.message, e.additionalData) } +} diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/Constants.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/Constants.kt index 474bf2fd83ca..43f8e2cf316c 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/Constants.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/Constants.kt @@ -49,8 +49,7 @@ object Constants { const val CHILD_KEYS = "childKeys" const val PREVIOUS_CHILD_NAME = "previousChildKey" - const val METHOD_CALL_TRANSACTION_HANDLER = - "FirebaseDatabase#callTransactionHandler" + const val METHOD_CALL_TRANSACTION_HANDLER = "FirebaseDatabase#callTransactionHandler" const val TRANSACTION_KEY = "transactionKey" const val TRANSACTION_APPLY_LOCALLY = "transactionApplyLocally" diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventStreamHandler.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventStreamHandler.kt index 7a2fd171fd70..54cf8f23e932 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventStreamHandler.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventStreamHandler.kt @@ -18,53 +18,53 @@ interface OnDispose { } class EventStreamHandler - @JvmOverloads - constructor( +@JvmOverloads +constructor( private val query: Query, private val onDispose: OnDispose, - ) : StreamHandler { - private var valueEventListener: ValueEventListener? = null - private var childEventListener: ChildEventListener? = null +) : StreamHandler { + private var valueEventListener: ValueEventListener? = null + private var childEventListener: ChildEventListener? = null - @Suppress("UNCHECKED_CAST") - override fun onListen( + @Suppress("UNCHECKED_CAST") + override fun onListen( arguments: Any?, events: EventChannel.EventSink?, - ) { - val args = arguments as Map - val eventType = args[Constants.EVENT_TYPE] as String + ) { + val args = arguments as Map + val eventType = args[Constants.EVENT_TYPE] as String - if (Constants.EVENT_TYPE_VALUE == eventType) { - events?.let { eventSink -> - valueEventListener = ValueEventsProxy(eventSink) - query.addValueEventListener(valueEventListener!!) - } - } else { - events?.let { eventSink -> - childEventListener = ChildEventsProxy(eventSink, eventType) - query.addChildEventListener(childEventListener!!) - } + if (Constants.EVENT_TYPE_VALUE == eventType) { + events?.let { eventSink -> + valueEventListener = ValueEventsProxy(eventSink) + query.addValueEventListener(valueEventListener!!) + } + } else { + events?.let { eventSink -> + childEventListener = ChildEventsProxy(eventSink, eventType) + query.addChildEventListener(childEventListener!!) } } + } - override fun onCancel(arguments: Any?) { - try { - // Remove listeners first to prevent any new events - valueEventListener?.let { - query.removeEventListener(it) - valueEventListener = null - } - - childEventListener?.let { - query.removeEventListener(it) - childEventListener = null - } + override fun onCancel(arguments: Any?) { + try { + // Remove listeners first to prevent any new events + valueEventListener?.let { + query.removeEventListener(it) + valueEventListener = null + } - // Then run the dispose callback - onDispose.run() - } catch (e: Exception) { - // Log any cleanup errors but don't throw - android.util.Log.w("EventStreamHandler", "Error during cleanup: ${e.message}") + childEventListener?.let { + query.removeEventListener(it) + childEventListener = null } + + // Then run the dispose callback + onDispose.run() + } catch (e: Exception) { + // Log any cleanup errors but don't throw + android.util.Log.w("EventStreamHandler", "Error during cleanup: ${e.message}") } } +} diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventsProxy.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventsProxy.kt index b58ca737f333..40e4735f87cb 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventsProxy.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/EventsProxy.kt @@ -15,35 +15,35 @@ import java.util.* @RestrictTo(RestrictTo.Scope.LIBRARY) abstract class EventsProxy - @JvmOverloads - constructor( +@JvmOverloads +constructor( protected val eventSink: EventChannel.EventSink, private val eventType: String, - ) { - fun buildAdditionalParams( +) { + fun buildAdditionalParams( @NonNull eventType: String, @Nullable previousChildName: String?, - ): Map { - val params = mutableMapOf() - params[Constants.EVENT_TYPE] = eventType - - if (previousChildName != null) { - params[Constants.PREVIOUS_CHILD_NAME] = previousChildName - } + ): Map { + val params = mutableMapOf() + params[Constants.EVENT_TYPE] = eventType - return params + if (previousChildName != null) { + params[Constants.PREVIOUS_CHILD_NAME] = previousChildName } - protected fun sendEvent( + return params + } + + protected fun sendEvent( @NonNull eventType: String, snapshot: DataSnapshot, @Nullable previousChildName: String?, - ) { - if (this.eventType != eventType) return + ) { + if (this.eventType != eventType) return - val payload = FlutterDataSnapshotPayload(snapshot) - val additionalParams = buildAdditionalParams(eventType, previousChildName) + val payload = FlutterDataSnapshotPayload(snapshot) + val additionalParams = buildAdditionalParams(eventType, previousChildName) - eventSink.success(payload.withAdditionalParams(additionalParams).toMap()) - } + eventSink.success(payload.withAdditionalParams(additionalParams).toMap()) } +} diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt index 9e31c6bf6137..0654954d2c81 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FirebaseDatabasePlugin.kt @@ -14,16 +14,13 @@ import com.google.firebase.database.DatabaseException import com.google.firebase.database.DatabaseReference import com.google.firebase.database.FirebaseDatabase import com.google.firebase.database.Logger -import com.google.firebase.database.OnDisconnect import com.google.firebase.database.Query import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.EventChannel.StreamHandler -import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result import io.flutter.plugins.firebase.core.FlutterFirebasePlugin import io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry @@ -32,10 +29,7 @@ import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import kotlin.Result as KotlinResult -class FirebaseDatabasePlugin : - FlutterFirebasePlugin, - FlutterPlugin, - FirebaseDatabaseHostApi { +class FirebaseDatabasePlugin : FlutterFirebasePlugin, FlutterPlugin, FirebaseDatabaseHostApi { companion object { private const val METHOD_CHANNEL_NAME = "plugins.flutter.io/firebase_database" private val databaseInstanceCache = HashMap() @@ -55,8 +49,8 @@ class FirebaseDatabasePlugin : } private fun setCachedFirebaseDatabaseInstanceForKey( - database: FirebaseDatabase, - key: String, + database: FirebaseDatabase, + key: String, ) { synchronized(databaseInstanceCache) { val existingInstance = databaseInstanceCache[key] @@ -89,11 +83,11 @@ class FirebaseDatabasePlugin : val app = FirebaseApp.getInstance(appName) val database = - if (databaseURL.isNotEmpty()) { - FirebaseDatabase.getInstance(app, databaseURL) - } else { - FirebaseDatabase.getInstance(app) - } + if (databaseURL.isNotEmpty()) { + FirebaseDatabase.getInstance(app, databaseURL) + } else { + FirebaseDatabase.getInstance(app) + } val loggingEnabled = arguments[Constants.DATABASE_LOGGING_ENABLED] as Boolean? val persistenceEnabled = arguments[Constants.DATABASE_PERSISTENCE_ENABLED] as Boolean? @@ -110,9 +104,7 @@ class FirebaseDatabasePlugin : database.useEmulator(emulatorHost, emulatorPort) } - persistenceEnabled?.let { enabled -> - database.setPersistenceEnabled(enabled) - } + persistenceEnabled?.let { enabled -> database.setPersistenceEnabled(enabled) } cacheSizeBytes?.let { size -> when (size) { @@ -122,7 +114,8 @@ class FirebaseDatabasePlugin : } } catch (e: DatabaseException) { val message = e.message - if (message != null && !message.contains("must be made before any other usage of FirebaseDatabase")) { + if (message != null && + !message.contains("must be made before any other usage of FirebaseDatabase")) { throw e } } @@ -146,8 +139,8 @@ class FirebaseDatabasePlugin : /** Applies [modifiers]. */ private fun queryFromModifiers( - reference: DatabaseReference, - modifiers: List>, + reference: DatabaseReference, + modifiers: List>, ): Query = QueryBuilder(reference, modifiers).build() private fun goOnline(arguments: Map): Task { @@ -240,10 +233,9 @@ class FirebaseDatabasePlugin : try { val ref = getReference(arguments) - @Suppress("UNCHECKED_CAST") - val value = arguments[Constants.VALUE] as Map + @Suppress("UNCHECKED_CAST") val value = arguments[Constants.VALUE] as Map Tasks.await(ref.updateChildren(value)) - taskCompletionSource.setResult(null) + taskCompletionSource.setResult(null) } catch (e: Exception) { taskCompletionSource.setException(e) } @@ -336,14 +328,14 @@ class FirebaseDatabasePlugin : val eventChannel = EventChannel(messenger, eventChannelName) val streamHandler = - EventStreamHandler( - query, - object : OnDispose { - override fun run() { - eventChannel.setStreamHandler(null) - } - }, - ) + EventStreamHandler( + query, + object : OnDispose { + override fun run() { + eventChannel.setStreamHandler(null) + } + }, + ) eventChannel.setStreamHandler(streamHandler) streamHandlers[eventChannel] = streamHandler @@ -384,12 +376,12 @@ class FirebaseDatabasePlugin : val onDisconnect = getReference(arguments).onDisconnect() val onDisconnectTask = - when (priority) { - is Double -> onDisconnect.setValue(value, priority) - is String -> onDisconnect.setValue(value, priority) - null -> onDisconnect.setValue(value, null as String?) - else -> throw Exception("Invalid priority value for OnDisconnect.setWithPriority") - } + when (priority) { + is Double -> onDisconnect.setValue(value, priority) + is String -> onDisconnect.setValue(value, priority) + null -> onDisconnect.setValue(value, null as String?) + else -> throw Exception("Invalid priority value for OnDisconnect.setWithPriority") + } Tasks.await(onDisconnectTask) taskCompletionSource.setResult(null) @@ -408,8 +400,7 @@ class FirebaseDatabasePlugin : try { val ref = getReference(arguments) - @Suppress("UNCHECKED_CAST") - val value = arguments[Constants.VALUE] as Map + @Suppress("UNCHECKED_CAST") val value = arguments[Constants.VALUE] as Map val task = ref.onDisconnect().updateChildren(value) Tasks.await(task) taskCompletionSource.setResult(null) @@ -442,7 +433,7 @@ class FirebaseDatabasePlugin : } override fun onDetachedFromEngine( - @NonNull binding: FlutterPluginBinding, + @NonNull binding: FlutterPluginBinding, ) { methodChannel.setMethodCallHandler(null) cleanup() @@ -512,7 +503,11 @@ class FirebaseDatabasePlugin : } } - override fun setPersistenceEnabled(app: DatabasePigeonFirebaseApp, enabled: Boolean, callback: (KotlinResult) -> Unit) { + override fun setPersistenceEnabled( + app: DatabasePigeonFirebaseApp, + enabled: Boolean, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) if (app.settings.persistenceEnabled == null) { @@ -524,7 +519,11 @@ class FirebaseDatabasePlugin : } } - override fun setPersistenceCacheSizeBytes(app: DatabasePigeonFirebaseApp, cacheSize: Long, callback: (KotlinResult) -> Unit) { + override fun setPersistenceCacheSizeBytes( + app: DatabasePigeonFirebaseApp, + cacheSize: Long, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) if (app.settings.cacheSizeBytes == null) { @@ -536,7 +535,11 @@ class FirebaseDatabasePlugin : } } - override fun setLoggingEnabled(app: DatabasePigeonFirebaseApp, enabled: Boolean, callback: (KotlinResult) -> Unit) { + override fun setLoggingEnabled( + app: DatabasePigeonFirebaseApp, + enabled: Boolean, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) database.setLogLevel(if (enabled) Logger.Level.DEBUG else Logger.Level.NONE) @@ -546,7 +549,12 @@ class FirebaseDatabasePlugin : } } - override fun useDatabaseEmulator(app: DatabasePigeonFirebaseApp, host: String, port: Long, callback: (KotlinResult) -> Unit) { + override fun useDatabaseEmulator( + app: DatabasePigeonFirebaseApp, + host: String, + port: Long, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) database.useEmulator(host, port.toInt()) @@ -556,7 +564,11 @@ class FirebaseDatabasePlugin : } } - override fun ref(app: DatabasePigeonFirebaseApp, path: String?, callback: (KotlinResult) -> Unit) { + override fun ref( + app: DatabasePigeonFirebaseApp, + path: String?, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = if (path.isNullOrEmpty()) database.reference else database.getReference(path) @@ -567,7 +579,11 @@ class FirebaseDatabasePlugin : } } - override fun refFromURL(app: DatabasePigeonFirebaseApp, url: String, callback: (KotlinResult) -> Unit) { + override fun refFromURL( + app: DatabasePigeonFirebaseApp, + url: String, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReferenceFromUrl(url) @@ -578,7 +594,10 @@ class FirebaseDatabasePlugin : } } - override fun purgeOutstandingWrites(app: DatabasePigeonFirebaseApp, callback: (KotlinResult) -> Unit) { + override fun purgeOutstandingWrites( + app: DatabasePigeonFirebaseApp, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) database.purgeOutstandingWrites() @@ -588,7 +607,11 @@ class FirebaseDatabasePlugin : } } - override fun databaseReferenceSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (KotlinResult) -> Unit) { + override fun databaseReferenceSet( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) @@ -601,7 +624,8 @@ class FirebaseDatabasePlugin : callback(KotlinResult.success(Unit)) } else { val exception = completedTask.exception ?: Exception("Unknown error setting value") - callback(KotlinResult.failure(FlutterError("firebase_database", exception.message, null))) + callback( + KotlinResult.failure(FlutterError("firebase_database", exception.message, null))) } } } @@ -610,22 +634,28 @@ class FirebaseDatabasePlugin : } } - override fun databaseReferenceSetWithPriority(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (KotlinResult) -> Unit) { + override fun databaseReferenceSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) // Handle priority type conversion - Firebase Database expects Any? but Pigeon sends Object? - val priority = when (request.priority) { - is String -> request.priority - is Number -> request.priority - null -> null - else -> { - // Log the unexpected type for debugging - println("Warning: Unexpected priority type: ${request.priority?.javaClass?.simpleName}, value: $request.priority") - request.priority.toString() - } - } + val priority = + when (request.priority) { + is String -> request.priority + is Number -> request.priority + null -> null + else -> { + // Log the unexpected type for debugging + println( + "Warning: Unexpected priority type: ${request.priority?.javaClass?.simpleName}, value: $request.priority") + request.priority.toString() + } + } val task = reference.setValue(request.value, priority) var callbackCalled = false @@ -635,8 +665,10 @@ class FirebaseDatabasePlugin : if (completedTask.isSuccessful) { callback(KotlinResult.success(Unit)) } else { - val exception = completedTask.exception ?: Exception("Unknown error setting value with priority") - callback(KotlinResult.failure(FlutterError("firebase_database", exception.message, null))) + val exception = + completedTask.exception ?: Exception("Unknown error setting value with priority") + callback( + KotlinResult.failure(FlutterError("firebase_database", exception.message, null))) } } } @@ -648,37 +680,46 @@ class FirebaseDatabasePlugin : } } - override fun databaseReferenceUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, callback: (KotlinResult) -> Unit) { - val database = getDatabaseFromPigeonApp(app) - val reference = database.getReference(request.path) - reference.updateChildren(request.value).addOnCompleteListener { task-> - if(task.isSuccessful){ - callback(KotlinResult.success(Unit)) - } - else { - val exception = task.exception - callback(KotlinResult.failure(FlutterError("firebase_database", exception?.message, null))) - } + override fun databaseReferenceUpdate( + app: DatabasePigeonFirebaseApp, + request: UpdateRequest, + callback: (KotlinResult) -> Unit + ) { + val database = getDatabaseFromPigeonApp(app) + val reference = database.getReference(request.path) + reference.updateChildren(request.value).addOnCompleteListener { task -> + if (task.isSuccessful) { + callback(KotlinResult.success(Unit)) + } else { + val exception = task.exception + callback(KotlinResult.failure(FlutterError("firebase_database", exception?.message, null))) } + } } - override fun databaseReferenceSetPriority(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (KotlinResult) -> Unit) { + override fun databaseReferenceSetPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) // Handle priority type conversion - Firebase Database expects Any? but Pigeon sends Object? // Convert the priority to the appropriate type for Firebase - val priority = when (request.priority) { - is String -> request.priority - is Number -> request.priority - null -> null - else -> { - // Log the unexpected type for debugging - println("Warning: Unexpected priority type: ${request.priority?.javaClass?.simpleName}, value: $request.priority") - request.priority.toString() - } - } + val priority = + when (request.priority) { + is String -> request.priority + is Number -> request.priority + null -> null + else -> { + // Log the unexpected type for debugging + println( + "Warning: Unexpected priority type: ${request.priority?.javaClass?.simpleName}, value: $request.priority") + request.priority.toString() + } + } val task = reference.setPriority(priority) var callbackCalled = false @@ -697,13 +738,17 @@ class FirebaseDatabasePlugin : } // Fallback timeout to ensure callback is always called - android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({ - if (!callbackCalled && !task.isComplete) { - callbackCalled = true - println("Firebase Database setPriority timeout - calling callback anyway") - callback(KotlinResult.success(Unit)) - } - }, 3000) // 3 second timeout + android.os + .Handler(android.os.Looper.getMainLooper()) + .postDelayed( + { + if (!callbackCalled && !task.isComplete) { + callbackCalled = true + println("Firebase Database setPriority timeout - calling callback anyway") + callback(KotlinResult.success(Unit)) + } + }, + 3000) // 3 second timeout } catch (e: Exception) { // Log the exception for debugging println("Firebase Database setPriority error: ${e.message}") @@ -712,7 +757,11 @@ class FirebaseDatabasePlugin : } } - override fun databaseReferenceRunTransaction(app: DatabasePigeonFirebaseApp, request: TransactionRequest, callback: (KotlinResult) -> Unit) { + override fun databaseReferenceRunTransaction( + app: DatabasePigeonFirebaseApp, + request: TransactionRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) @@ -721,67 +770,88 @@ class FirebaseDatabasePlugin : transactionRequests[request.transactionKey] = request // Start the transaction - simplified approach like iOS - reference.runTransaction(object : com.google.firebase.database.Transaction.Handler { - override fun doTransaction(mutableData: com.google.firebase.database.MutableData): com.google.firebase.database.Transaction.Result { - val semaphore = java.util.concurrent.CountDownLatch(1) - var transactionResult: TransactionHandlerResult? = null - - // Call the Flutter transaction handler on the main thread (required by FlutterJNI) - val mainHandler = android.os.Handler(android.os.Looper.getMainLooper()) - mainHandler.post { - val flutterApi = FirebaseDatabaseFlutterApi(messenger) - flutterApi.callTransactionHandler(request.transactionKey, mutableData.value) { result -> - result.fold( - onSuccess = { transactionResult = it }, - onFailure = { - transactionResult = TransactionHandlerResult(value = null, aborted = true, exception = true) + reference.runTransaction( + object : com.google.firebase.database.Transaction.Handler { + override fun doTransaction( + mutableData: com.google.firebase.database.MutableData + ): com.google.firebase.database.Transaction.Result { + val semaphore = java.util.concurrent.CountDownLatch(1) + var transactionResult: TransactionHandlerResult? = null + + // Call the Flutter transaction handler on the main thread (required by FlutterJNI) + val mainHandler = android.os.Handler(android.os.Looper.getMainLooper()) + mainHandler.post { + val flutterApi = FirebaseDatabaseFlutterApi(messenger) + flutterApi.callTransactionHandler(request.transactionKey, mutableData.value) { + result -> + result.fold( + onSuccess = { transactionResult = it }, + onFailure = { + transactionResult = + TransactionHandlerResult(value = null, aborted = true, exception = true) + }) + semaphore.countDown() } - ) - semaphore.countDown() - } - } + } - semaphore.await() + semaphore.await() - val result = transactionResult ?: return com.google.firebase.database.Transaction.abort() + val result = + transactionResult ?: return com.google.firebase.database.Transaction.abort() - if (result.aborted || result.exception) { - return com.google.firebase.database.Transaction.abort() - } - - mutableData.value = result.value - return com.google.firebase.database.Transaction.success(mutableData) - } + if (result.aborted || result.exception) { + return com.google.firebase.database.Transaction.abort() + } - override fun onComplete(error: com.google.firebase.database.DatabaseError?, committed: Boolean, currentData: com.google.firebase.database.DataSnapshot?) { - // Store the transaction result for later retrieval - val result = mapOf( - "committed" to committed, - "snapshot" to mapOf( - "value" to currentData?.value, - "key" to currentData?.key, - "exists" to currentData?.exists() - ) - ) - transactionResults[request.transactionKey] = result + mutableData.value = result.value + return com.google.firebase.database.Transaction.success(mutableData) + } - // Complete the transaction - simplified like iOS - if (error != null) { - val ex = FlutterFirebaseDatabaseException.fromDatabaseError(error) - callback(KotlinResult.failure(FlutterError("firebase_database", ex.message, ex.additionalData))) - } else { - callback(KotlinResult.success(Unit)) - } - } - }, request.applyLocally) + override fun onComplete( + error: com.google.firebase.database.DatabaseError?, + committed: Boolean, + currentData: com.google.firebase.database.DataSnapshot? + ) { + // Store the transaction result for later retrieval + val result = + mapOf( + "committed" to committed, + "snapshot" to + mapOf( + "value" to currentData?.value, + "key" to currentData?.key, + "exists" to currentData?.exists())) + transactionResults[request.transactionKey] = result + + // Complete the transaction - simplified like iOS + if (error != null) { + val ex = FlutterFirebaseDatabaseException.fromDatabaseError(error) + callback( + KotlinResult.failure( + FlutterError("firebase_database", ex.message, ex.additionalData))) + } else { + callback(KotlinResult.success(Unit)) + } + } + }, + request.applyLocally) } catch (e: Exception) { // Convert generic exceptions to FlutterFirebaseDatabaseException for proper error handling - val flutterException = if (e is FlutterFirebaseDatabaseException) e else FlutterFirebaseDatabaseException.unknown(e.message ?: "Unknown transaction error") - callback(KotlinResult.failure(FlutterError("firebase_database", flutterException.message, flutterException.additionalData))) + val flutterException = + if (e is FlutterFirebaseDatabaseException) e + else FlutterFirebaseDatabaseException.unknown(e.message ?: "Unknown transaction error") + callback( + KotlinResult.failure( + FlutterError( + "firebase_database", flutterException.message, flutterException.additionalData))) } } - override fun databaseReferenceGetTransactionResult(app: DatabasePigeonFirebaseApp, transactionKey: Long, callback: (KotlinResult>) -> Unit) { + override fun databaseReferenceGetTransactionResult( + app: DatabasePigeonFirebaseApp, + transactionKey: Long, + callback: (KotlinResult>) -> Unit + ) { try { // Return the stored transaction result val result = transactionResults[transactionKey] @@ -789,10 +859,7 @@ class FirebaseDatabasePlugin : callback(KotlinResult.success(result)) } else { // If no result is available yet, return a default result - val defaultResult = mapOf( - "committed" to false, - "snapshot" to mapOf("value" to null) - ) + val defaultResult = mapOf("committed" to false, "snapshot" to mapOf("value" to null)) callback(KotlinResult.success(defaultResult)) } } catch (e: Exception) { @@ -800,7 +867,11 @@ class FirebaseDatabasePlugin : } } - override fun onDisconnectSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (KotlinResult) -> Unit) { + override fun onDisconnectSet( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) @@ -812,7 +883,11 @@ class FirebaseDatabasePlugin : } } - override fun onDisconnectSetWithPriority(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (KotlinResult) -> Unit) { + override fun onDisconnectSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) @@ -824,7 +899,11 @@ class FirebaseDatabasePlugin : } } - override fun onDisconnectUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, callback: (KotlinResult) -> Unit) { + override fun onDisconnectUpdate( + app: DatabasePigeonFirebaseApp, + request: UpdateRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) @@ -836,7 +915,11 @@ class FirebaseDatabasePlugin : } } - override fun onDisconnectCancel(app: DatabasePigeonFirebaseApp, path: String, callback: (KotlinResult) -> Unit) { + override fun onDisconnectCancel( + app: DatabasePigeonFirebaseApp, + path: String, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(path) @@ -848,25 +931,31 @@ class FirebaseDatabasePlugin : } } - override fun queryObserve(app: DatabasePigeonFirebaseApp, request: QueryRequest, callback: (KotlinResult) -> Unit) { + override fun queryObserve( + app: DatabasePigeonFirebaseApp, + request: QueryRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) val query = queryFromModifiers(reference, request.modifiers) // Generate a unique channel name - val channelName = - synchronized(this) { "firebase_database_query_${listenerCount++}" } + val channelName = synchronized(this) { "firebase_database_query_${listenerCount++}" } // Set up the event channel val eventChannel = EventChannel(messenger, channelName) - val streamHandler = EventStreamHandler(query, object : OnDispose { - override fun run() { - // Clean up when the stream is disposed - eventChannel.setStreamHandler(null) - streamHandlers.remove(eventChannel) - } - }) + val streamHandler = + EventStreamHandler( + query, + object : OnDispose { + override fun run() { + // Clean up when the stream is disposed + eventChannel.setStreamHandler(null) + streamHandlers.remove(eventChannel) + } + }) eventChannel.setStreamHandler(streamHandler) streamHandlers[eventChannel] = streamHandler @@ -876,7 +965,11 @@ class FirebaseDatabasePlugin : } } - override fun queryKeepSynced(app: DatabasePigeonFirebaseApp, request: QueryRequest, callback: (KotlinResult) -> Unit) { + override fun queryKeepSynced( + app: DatabasePigeonFirebaseApp, + request: QueryRequest, + callback: (KotlinResult) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) @@ -890,7 +983,11 @@ class FirebaseDatabasePlugin : } } - override fun queryGet(app: DatabasePigeonFirebaseApp, request: QueryRequest, callback: (KotlinResult>) -> Unit) { + override fun queryGet( + app: DatabasePigeonFirebaseApp, + request: QueryRequest, + callback: (KotlinResult>) -> Unit + ) { try { val database = getDatabaseFromPigeonApp(app) val reference = database.getReference(request.path) @@ -914,11 +1011,12 @@ class FirebaseDatabasePlugin : // Helper method to get FirebaseDatabase from Pigeon app private fun getDatabaseFromPigeonApp(app: DatabasePigeonFirebaseApp): FirebaseDatabase { val firebaseApp = FirebaseApp.getInstance(app.appName) - val database = if (app.databaseURL != null) { - FirebaseDatabase.getInstance(firebaseApp, app.databaseURL) - } else { - FirebaseDatabase.getInstance(firebaseApp) - } + val database = + if (app.databaseURL != null) { + FirebaseDatabase.getInstance(firebaseApp, app.databaseURL) + } else { + FirebaseDatabase.getInstance(firebaseApp) + } // Apply settings carried on the Pigeon app object (idempotent across calls) try { @@ -933,13 +1031,9 @@ class FirebaseDatabasePlugin : database.useEmulator(emulatorHost, emulatorPort.toInt()) } - app.settings.persistenceEnabled?.let { enabled -> - database.setPersistenceEnabled(enabled) - } + app.settings.persistenceEnabled?.let { enabled -> database.setPersistenceEnabled(enabled) } - app.settings.cacheSizeBytes?.let { size -> - database.setPersistenceCacheSizeBytes(size) - } + app.settings.cacheSizeBytes?.let { size -> database.setPersistenceCacheSizeBytes(size) } } catch (e: DatabaseException) { // Ignore ordering errors if the instance was already used; settings that require // pre-use configuration would have no effect and should not crash tests. diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterDataSnapshotPayload.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterDataSnapshotPayload.kt index 3687ebabeb3c..c95bc304ad64 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterDataSnapshotPayload.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterDataSnapshotPayload.kt @@ -10,7 +10,7 @@ import com.google.firebase.database.DataSnapshot import java.util.* class FlutterDataSnapshotPayload( - snapshot: DataSnapshot, + snapshot: DataSnapshot, ) { private var payloadMap: MutableMap = mutableMapOf() diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseAppRegistrar.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseAppRegistrar.kt index a78fd2044ecb..2c74d47c57eb 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseAppRegistrar.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseAppRegistrar.kt @@ -12,7 +12,7 @@ import com.google.firebase.platforminfo.LibraryVersionComponent @Keep class FlutterFirebaseAppRegistrar : ComponentRegistrar { override fun getComponents(): List> = - listOf( - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION), - ) + listOf( + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION), + ) } diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseDatabaseException.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseDatabaseException.kt index 573a760f072e..c2f1a2f9915d 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseDatabaseException.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/FlutterFirebaseDatabaseException.kt @@ -13,91 +13,100 @@ import com.google.firebase.database.DatabaseException import java.util.* class FlutterFirebaseDatabaseException - @JvmOverloads - constructor( +@JvmOverloads +constructor( @NonNull val code: String, @NonNull val errorMessage: String, @Nullable additionalData: Map? = null, - ) : Exception(errorMessage) { - companion object { - const val UNKNOWN_ERROR_CODE = "unknown" - const val UNKNOWN_ERROR_MESSAGE = "An unknown error occurred" - private const val MODULE = "firebase_database" +) : Exception(errorMessage) { + companion object { + const val UNKNOWN_ERROR_CODE = "unknown" + const val UNKNOWN_ERROR_MESSAGE = "An unknown error occurred" + private const val MODULE = "firebase_database" - fun fromDatabaseError(e: DatabaseError): FlutterFirebaseDatabaseException { - val errorCode = e.code + fun fromDatabaseError(e: DatabaseError): FlutterFirebaseDatabaseException { + val errorCode = e.code - val (code, message) = + val (code, message) = when (errorCode) { - DatabaseError.DATA_STALE -> "data-stale" to "The transaction needs to be run again with current data." - DatabaseError.OPERATION_FAILED -> "failure" to "The server indicated that this operation failed." - DatabaseError.PERMISSION_DENIED -> "permission-denied" to "Client doesn't have permission to access the desired data." - DatabaseError.DISCONNECTED -> "disconnected" to "The operation had to be aborted due to a network disconnect." + DatabaseError.DATA_STALE -> + "data-stale" to "The transaction needs to be run again with current data." + DatabaseError.OPERATION_FAILED -> + "failure" to "The server indicated that this operation failed." + DatabaseError.PERMISSION_DENIED -> + "permission-denied" to "Client doesn't have permission to access the desired data." + DatabaseError.DISCONNECTED -> + "disconnected" to "The operation had to be aborted due to a network disconnect." DatabaseError.EXPIRED_TOKEN -> "expired-token" to "The supplied auth token has expired." DatabaseError.INVALID_TOKEN -> "invalid-token" to "The supplied auth token was invalid." DatabaseError.MAX_RETRIES -> "max-retries" to "The transaction had too many retries." - DatabaseError.OVERRIDDEN_BY_SET -> "overridden-by-set" to "The transaction was overridden by a subsequent set." + DatabaseError.OVERRIDDEN_BY_SET -> + "overridden-by-set" to "The transaction was overridden by a subsequent set." DatabaseError.UNAVAILABLE -> "unavailable" to "The service is unavailable." - DatabaseError.NETWORK_ERROR -> "network-error" to "The operation could not be performed due to a network error." - DatabaseError.WRITE_CANCELED -> "write-cancelled" to "The write was canceled by the user." + DatabaseError.NETWORK_ERROR -> + "network-error" to "The operation could not be performed due to a network error." + DatabaseError.WRITE_CANCELED -> + "write-cancelled" to "The write was canceled by the user." else -> UNKNOWN_ERROR_CODE to UNKNOWN_ERROR_MESSAGE } - if (code == UNKNOWN_ERROR_CODE) { - return unknown(e.message ?: UNKNOWN_ERROR_MESSAGE) - } - - val additionalData = mutableMapOf() - val errorDetails = e.details - additionalData[Constants.ERROR_DETAILS] = errorDetails - return FlutterFirebaseDatabaseException(code, message, additionalData) + if (code == UNKNOWN_ERROR_CODE) { + return unknown(e.message ?: UNKNOWN_ERROR_MESSAGE) } - fun fromDatabaseException(e: DatabaseException): FlutterFirebaseDatabaseException { - val error = DatabaseError.fromException(e) - return fromDatabaseError(error) - } + val additionalData = mutableMapOf() + val errorDetails = e.details + additionalData[Constants.ERROR_DETAILS] = errorDetails + return FlutterFirebaseDatabaseException(code, message, additionalData) + } - fun fromException(e: Exception?): FlutterFirebaseDatabaseException = + fun fromDatabaseException(e: DatabaseException): FlutterFirebaseDatabaseException { + val error = DatabaseError.fromException(e) + return fromDatabaseError(error) + } + + fun fromException(e: Exception?): FlutterFirebaseDatabaseException = if (e == null) unknown() else unknown(e.message ?: UNKNOWN_ERROR_MESSAGE) - fun unknown(): FlutterFirebaseDatabaseException = unknown(null) + fun unknown(): FlutterFirebaseDatabaseException = unknown(null) - fun unknown(errorMessage: String?): FlutterFirebaseDatabaseException { - val details = mutableMapOf() - var code = UNKNOWN_ERROR_CODE + fun unknown(errorMessage: String?): FlutterFirebaseDatabaseException { + val details = mutableMapOf() + var code = UNKNOWN_ERROR_CODE - var message = errorMessage + var message = errorMessage - if (errorMessage == null) { - message = UNKNOWN_ERROR_MESSAGE - } + if (errorMessage == null) { + message = UNKNOWN_ERROR_MESSAGE + } - when { - message?.contains("Index not defined, add \".indexOn\"") == true -> { - // No known error code for this in DatabaseError, so we manually have to - // detect it. - code = "index-not-defined" - message = message?.replaceFirst("java.lang.Exception: ", "") ?: UNKNOWN_ERROR_MESSAGE - } - message?.contains("Permission denied") == true || message?.contains("Client doesn't have permission") == true -> { - // Permission denied when using Firebase emulator does not correctly come - // through as a DatabaseError. - code = "permission-denied" - message = "Client doesn't have permission to access the desired data." - } + when { + message?.contains("Index not defined, add \".indexOn\"") == true -> { + // No known error code for this in DatabaseError, so we manually have to + // detect it. + code = "index-not-defined" + message = message?.replaceFirst("java.lang.Exception: ", "") ?: UNKNOWN_ERROR_MESSAGE + } + message?.contains("Permission denied") == true || + message?.contains("Client doesn't have permission") == true -> { + // Permission denied when using Firebase emulator does not correctly come + // through as a DatabaseError. + code = "permission-denied" + message = "Client doesn't have permission to access the desired data." } - - return FlutterFirebaseDatabaseException(code, message ?: UNKNOWN_ERROR_MESSAGE, details) } + + return FlutterFirebaseDatabaseException(code, message ?: UNKNOWN_ERROR_MESSAGE, details) } + } - val additionalData: Map = + val additionalData: Map = additionalData?.toMutableMap()?.apply { put(Constants.ERROR_CODE, code) put(Constants.ERROR_MESSAGE, errorMessage) - } ?: mutableMapOf().apply { - put(Constants.ERROR_CODE, code) - put(Constants.ERROR_MESSAGE, errorMessage) } - } + ?: mutableMapOf().apply { + put(Constants.ERROR_CODE, code) + put(Constants.ERROR_MESSAGE, errorMessage) + } +} diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt index 1d8dd75cfbb5..dd778f34ea6b 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/GeneratedAndroidFirebaseDatabase.g.kt @@ -10,16 +10,17 @@ package io.flutter.plugins.firebase.database import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object GeneratedAndroidFirebaseDatabasePigeonUtils { fun createConnectionError(channelName: String): FlutterError { - return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } + return FlutterError( + "channel-error", "Unable to establish connection on channel: '$channelName'.", "") + } fun wrapResult(result: Any?): List { return listOf(result) @@ -27,19 +28,15 @@ private object GeneratedAndroidFirebaseDatabasePigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } + fun doubleEquals(a: Double, b: Double): Boolean { // Normalize -0.0 to 0.0 and handle NaN equality. return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) @@ -183,30 +180,29 @@ private object GeneratedAndroidFirebaseDatabasePigeonUtils { else -> value.hashCode() } } - } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : RuntimeException() /** Generated class from Pigeon that represents data sent in messages. */ -data class DatabasePigeonSettings ( - val persistenceEnabled: Boolean? = null, - val cacheSizeBytes: Long? = null, - val loggingEnabled: Boolean? = null, - val emulatorHost: String? = null, - val emulatorPort: Long? = null -) - { +data class DatabasePigeonSettings( + val persistenceEnabled: Boolean? = null, + val cacheSizeBytes: Long? = null, + val loggingEnabled: Boolean? = null, + val emulatorHost: String? = null, + val emulatorPort: Long? = null +) { companion object { fun fromList(pigeonVar_list: List): DatabasePigeonSettings { val persistenceEnabled = pigeonVar_list[0] as Boolean? @@ -214,18 +210,21 @@ data class DatabasePigeonSettings ( val loggingEnabled = pigeonVar_list[2] as Boolean? val emulatorHost = pigeonVar_list[3] as String? val emulatorPort = pigeonVar_list[4] as Long? - return DatabasePigeonSettings(persistenceEnabled, cacheSizeBytes, loggingEnabled, emulatorHost, emulatorPort) + return DatabasePigeonSettings( + persistenceEnabled, cacheSizeBytes, loggingEnabled, emulatorHost, emulatorPort) } } + fun toList(): List { return listOf( - persistenceEnabled, - cacheSizeBytes, - loggingEnabled, - emulatorHost, - emulatorPort, + persistenceEnabled, + cacheSizeBytes, + loggingEnabled, + emulatorHost, + emulatorPort, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -234,12 +233,22 @@ data class DatabasePigeonSettings ( return true } val other = other as DatabasePigeonSettings - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.persistenceEnabled, other.persistenceEnabled) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.cacheSizeBytes, other.cacheSizeBytes) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.loggingEnabled, other.loggingEnabled) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.emulatorHost, other.emulatorHost) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.emulatorPort, other.emulatorPort) + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.persistenceEnabled, other.persistenceEnabled) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.cacheSizeBytes, other.cacheSizeBytes) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.loggingEnabled, other.loggingEnabled) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.emulatorHost, other.emulatorHost) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.emulatorPort, other.emulatorPort) } override fun hashCode(): Int { var result = javaClass.hashCode() - result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.persistenceEnabled) + result = + 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.persistenceEnabled) result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.cacheSizeBytes) result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.loggingEnabled) result = 31 * result + GeneratedAndroidFirebaseDatabasePigeonUtils.deepHash(this.emulatorHost) @@ -249,12 +258,11 @@ data class DatabasePigeonSettings ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class DatabasePigeonFirebaseApp ( - val appName: String, - val databaseURL: String? = null, - val settings: DatabasePigeonSettings -) - { +data class DatabasePigeonFirebaseApp( + val appName: String, + val databaseURL: String? = null, + val settings: DatabasePigeonSettings +) { companion object { fun fromList(pigeonVar_list: List): DatabasePigeonFirebaseApp { val appName = pigeonVar_list[0] as String @@ -263,13 +271,15 @@ data class DatabasePigeonFirebaseApp ( return DatabasePigeonFirebaseApp(appName, databaseURL, settings) } } + fun toList(): List { return listOf( - appName, - databaseURL, - settings, + appName, + databaseURL, + settings, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -278,7 +288,10 @@ data class DatabasePigeonFirebaseApp ( return true } val other = other as DatabasePigeonFirebaseApp - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.appName, other.appName) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.databaseURL, other.databaseURL) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.settings, other.settings) + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.appName, other.appName) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.databaseURL, other.databaseURL) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.settings, other.settings) } override fun hashCode(): Int { @@ -291,21 +304,20 @@ data class DatabasePigeonFirebaseApp ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class DatabaseReferencePlatform ( - val path: String -) - { +data class DatabaseReferencePlatform(val path: String) { companion object { fun fromList(pigeonVar_list: List): DatabaseReferencePlatform { val path = pigeonVar_list[0] as String return DatabaseReferencePlatform(path) } } + fun toList(): List { return listOf( - path, + path, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -325,12 +337,11 @@ data class DatabaseReferencePlatform ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class DatabaseReferenceRequest ( - val path: String, - val value: Any? = null, - val priority: Any? = null -) - { +data class DatabaseReferenceRequest( + val path: String, + val value: Any? = null, + val priority: Any? = null +) { companion object { fun fromList(pigeonVar_list: List): DatabaseReferenceRequest { val path = pigeonVar_list[0] as String @@ -339,13 +350,15 @@ data class DatabaseReferenceRequest ( return DatabaseReferenceRequest(path, value, priority) } } + fun toList(): List { return listOf( - path, - value, - priority, + path, + value, + priority, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -354,7 +367,9 @@ data class DatabaseReferenceRequest ( return true } val other = other as DatabaseReferenceRequest - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.priority, other.priority) + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.priority, other.priority) } override fun hashCode(): Int { @@ -367,11 +382,7 @@ data class DatabaseReferenceRequest ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class UpdateRequest ( - val path: String, - val value: Map -) - { +data class UpdateRequest(val path: String, val value: Map) { companion object { fun fromList(pigeonVar_list: List): UpdateRequest { val path = pigeonVar_list[0] as String @@ -379,12 +390,14 @@ data class UpdateRequest ( return UpdateRequest(path, value) } } + fun toList(): List { return listOf( - path, - value, + path, + value, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -393,7 +406,8 @@ data class UpdateRequest ( return true } val other = other as UpdateRequest - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) } override fun hashCode(): Int { @@ -405,12 +419,11 @@ data class UpdateRequest ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class TransactionRequest ( - val path: String, - val transactionKey: Long, - val applyLocally: Boolean -) - { +data class TransactionRequest( + val path: String, + val transactionKey: Long, + val applyLocally: Boolean +) { companion object { fun fromList(pigeonVar_list: List): TransactionRequest { val path = pigeonVar_list[0] as String @@ -419,13 +432,15 @@ data class TransactionRequest ( return TransactionRequest(path, transactionKey, applyLocally) } } + fun toList(): List { return listOf( - path, - transactionKey, - applyLocally, + path, + transactionKey, + applyLocally, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -434,7 +449,11 @@ data class TransactionRequest ( return true } val other = other as TransactionRequest - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.transactionKey, other.transactionKey) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.applyLocally, other.applyLocally) + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.transactionKey, other.transactionKey) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals( + this.applyLocally, other.applyLocally) } override fun hashCode(): Int { @@ -447,12 +466,11 @@ data class TransactionRequest ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class QueryRequest ( - val path: String, - val modifiers: List>, - val value: Boolean? = null -) - { +data class QueryRequest( + val path: String, + val modifiers: List>, + val value: Boolean? = null +) { companion object { fun fromList(pigeonVar_list: List): QueryRequest { val path = pigeonVar_list[0] as String @@ -461,13 +479,15 @@ data class QueryRequest ( return QueryRequest(path, modifiers, value) } } + fun toList(): List { return listOf( - path, - modifiers, - value, + path, + modifiers, + value, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -476,7 +496,9 @@ data class QueryRequest ( return true } val other = other as QueryRequest - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.modifiers, other.modifiers) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.path, other.path) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.modifiers, other.modifiers) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) } override fun hashCode(): Int { @@ -489,12 +511,11 @@ data class QueryRequest ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class TransactionHandlerResult ( - val value: Any? = null, - val aborted: Boolean, - val exception: Boolean -) - { +data class TransactionHandlerResult( + val value: Any? = null, + val aborted: Boolean, + val exception: Boolean +) { companion object { fun fromList(pigeonVar_list: List): TransactionHandlerResult { val value = pigeonVar_list[0] @@ -503,13 +524,15 @@ data class TransactionHandlerResult ( return TransactionHandlerResult(value, aborted, exception) } } + fun toList(): List { return listOf( - value, - aborted, - exception, + value, + aborted, + exception, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -518,7 +541,9 @@ data class TransactionHandlerResult ( return true } val other = other as TransactionHandlerResult - return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.aborted, other.aborted) && GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.exception, other.exception) + return GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.value, other.value) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.aborted, other.aborted) && + GeneratedAndroidFirebaseDatabasePigeonUtils.deepEquals(this.exception, other.exception) } override fun hashCode(): Int { @@ -529,53 +554,39 @@ data class TransactionHandlerResult ( return result } } + private open class GeneratedAndroidFirebaseDatabasePigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 129.toByte() -> { - return (readValue(buffer) as? List)?.let { - DatabasePigeonSettings.fromList(it) - } + return (readValue(buffer) as? List)?.let { DatabasePigeonSettings.fromList(it) } } 130.toByte() -> { - return (readValue(buffer) as? List)?.let { - DatabasePigeonFirebaseApp.fromList(it) - } + return (readValue(buffer) as? List)?.let { DatabasePigeonFirebaseApp.fromList(it) } } 131.toByte() -> { - return (readValue(buffer) as? List)?.let { - DatabaseReferencePlatform.fromList(it) - } + return (readValue(buffer) as? List)?.let { DatabaseReferencePlatform.fromList(it) } } 132.toByte() -> { - return (readValue(buffer) as? List)?.let { - DatabaseReferenceRequest.fromList(it) - } + return (readValue(buffer) as? List)?.let { DatabaseReferenceRequest.fromList(it) } } 133.toByte() -> { - return (readValue(buffer) as? List)?.let { - UpdateRequest.fromList(it) - } + return (readValue(buffer) as? List)?.let { UpdateRequest.fromList(it) } } 134.toByte() -> { - return (readValue(buffer) as? List)?.let { - TransactionRequest.fromList(it) - } + return (readValue(buffer) as? List)?.let { TransactionRequest.fromList(it) } } 135.toByte() -> { - return (readValue(buffer) as? List)?.let { - QueryRequest.fromList(it) - } + return (readValue(buffer) as? List)?.let { QueryRequest.fromList(it) } } 136.toByte() -> { - return (readValue(buffer) as? List)?.let { - TransactionHandlerResult.fromList(it) - } + return (readValue(buffer) as? List)?.let { TransactionHandlerResult.fromList(it) } } else -> super.readValueOfType(type, buffer) } } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { when (value) { is DatabasePigeonSettings -> { stream.write(129) @@ -614,43 +625,150 @@ private open class GeneratedAndroidFirebaseDatabasePigeonCodec : StandardMessage } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseDatabaseHostApi { fun goOnline(app: DatabasePigeonFirebaseApp, callback: (Result) -> Unit) + fun goOffline(app: DatabasePigeonFirebaseApp, callback: (Result) -> Unit) - fun setPersistenceEnabled(app: DatabasePigeonFirebaseApp, enabled: Boolean, callback: (Result) -> Unit) - fun setPersistenceCacheSizeBytes(app: DatabasePigeonFirebaseApp, cacheSize: Long, callback: (Result) -> Unit) - fun setLoggingEnabled(app: DatabasePigeonFirebaseApp, enabled: Boolean, callback: (Result) -> Unit) - fun useDatabaseEmulator(app: DatabasePigeonFirebaseApp, host: String, port: Long, callback: (Result) -> Unit) - fun ref(app: DatabasePigeonFirebaseApp, path: String?, callback: (Result) -> Unit) - fun refFromURL(app: DatabasePigeonFirebaseApp, url: String, callback: (Result) -> Unit) + + fun setPersistenceEnabled( + app: DatabasePigeonFirebaseApp, + enabled: Boolean, + callback: (Result) -> Unit + ) + + fun setPersistenceCacheSizeBytes( + app: DatabasePigeonFirebaseApp, + cacheSize: Long, + callback: (Result) -> Unit + ) + + fun setLoggingEnabled( + app: DatabasePigeonFirebaseApp, + enabled: Boolean, + callback: (Result) -> Unit + ) + + fun useDatabaseEmulator( + app: DatabasePigeonFirebaseApp, + host: String, + port: Long, + callback: (Result) -> Unit + ) + + fun ref( + app: DatabasePigeonFirebaseApp, + path: String?, + callback: (Result) -> Unit + ) + + fun refFromURL( + app: DatabasePigeonFirebaseApp, + url: String, + callback: (Result) -> Unit + ) + fun purgeOutstandingWrites(app: DatabasePigeonFirebaseApp, callback: (Result) -> Unit) - fun databaseReferenceSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (Result) -> Unit) - fun databaseReferenceSetWithPriority(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (Result) -> Unit) - fun databaseReferenceUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, callback: (Result) -> Unit) - fun databaseReferenceSetPriority(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (Result) -> Unit) - fun databaseReferenceRunTransaction(app: DatabasePigeonFirebaseApp, request: TransactionRequest, callback: (Result) -> Unit) - fun databaseReferenceGetTransactionResult(app: DatabasePigeonFirebaseApp, transactionKey: Long, callback: (Result>) -> Unit) - fun onDisconnectSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (Result) -> Unit) - fun onDisconnectSetWithPriority(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, callback: (Result) -> Unit) - fun onDisconnectUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, callback: (Result) -> Unit) - fun onDisconnectCancel(app: DatabasePigeonFirebaseApp, path: String, callback: (Result) -> Unit) - fun queryObserve(app: DatabasePigeonFirebaseApp, request: QueryRequest, callback: (Result) -> Unit) - fun queryKeepSynced(app: DatabasePigeonFirebaseApp, request: QueryRequest, callback: (Result) -> Unit) - fun queryGet(app: DatabasePigeonFirebaseApp, request: QueryRequest, callback: (Result>) -> Unit) + + fun databaseReferenceSet( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (Result) -> Unit + ) + + fun databaseReferenceSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (Result) -> Unit + ) + + fun databaseReferenceUpdate( + app: DatabasePigeonFirebaseApp, + request: UpdateRequest, + callback: (Result) -> Unit + ) + + fun databaseReferenceSetPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (Result) -> Unit + ) + + fun databaseReferenceRunTransaction( + app: DatabasePigeonFirebaseApp, + request: TransactionRequest, + callback: (Result) -> Unit + ) + + fun databaseReferenceGetTransactionResult( + app: DatabasePigeonFirebaseApp, + transactionKey: Long, + callback: (Result>) -> Unit + ) + + fun onDisconnectSet( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (Result) -> Unit + ) + + fun onDisconnectSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + callback: (Result) -> Unit + ) + + fun onDisconnectUpdate( + app: DatabasePigeonFirebaseApp, + request: UpdateRequest, + callback: (Result) -> Unit + ) + + fun onDisconnectCancel( + app: DatabasePigeonFirebaseApp, + path: String, + callback: (Result) -> Unit + ) + + fun queryObserve( + app: DatabasePigeonFirebaseApp, + request: QueryRequest, + callback: (Result) -> Unit + ) + + fun queryKeepSynced( + app: DatabasePigeonFirebaseApp, + request: QueryRequest, + callback: (Result) -> Unit + ) + + fun queryGet( + app: DatabasePigeonFirebaseApp, + request: QueryRequest, + callback: (Result>) -> Unit + ) companion object { /** The codec used by FirebaseDatabaseHostApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidFirebaseDatabasePigeonCodec() - } - /** Sets up an instance of `FirebaseDatabaseHostApi` to handle messages through the `binaryMessenger`. */ + val codec: MessageCodec by lazy { GeneratedAndroidFirebaseDatabasePigeonCodec() } + /** + * Sets up an instance of `FirebaseDatabaseHostApi` to handle messages through the + * `binaryMessenger`. + */ @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseDatabaseHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp( + binaryMessenger: BinaryMessenger, + api: FirebaseDatabaseHostApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -669,7 +787,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -688,7 +810,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -708,7 +834,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -728,7 +858,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -748,7 +882,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -769,7 +907,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -790,7 +932,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -811,7 +957,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -830,7 +980,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -850,7 +1004,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -870,7 +1028,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -890,7 +1052,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -910,7 +1076,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -930,13 +1100,18 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val appArg = args[0] as DatabasePigeonFirebaseApp val transactionKeyArg = args[1] as Long - api.databaseReferenceGetTransactionResult(appArg, transactionKeyArg) { result: Result> -> + api.databaseReferenceGetTransactionResult(appArg, transactionKeyArg) { + result: Result> -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseDatabasePigeonUtils.wrapError(error)) @@ -951,7 +1126,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -971,7 +1150,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -991,7 +1174,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -1011,7 +1198,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -1031,7 +1222,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -1052,7 +1247,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -1072,7 +1271,11 @@ interface FirebaseDatabaseHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -1096,31 +1299,45 @@ interface FirebaseDatabaseHostApi { } } /** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */ -class FirebaseDatabaseFlutterApi(private val binaryMessenger: BinaryMessenger, private val messageChannelSuffix: String = "") { +class FirebaseDatabaseFlutterApi( + private val binaryMessenger: BinaryMessenger, + private val messageChannelSuffix: String = "" +) { companion object { /** The codec used by FirebaseDatabaseFlutterApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidFirebaseDatabasePigeonCodec() - } + val codec: MessageCodec by lazy { GeneratedAndroidFirebaseDatabasePigeonCodec() } } - fun callTransactionHandler(transactionKeyArg: Long, snapshotValueArg: Any?, callback: (Result) -> Unit) -{ - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" - val channelName = "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler$separatedMessageChannelSuffix" + + fun callTransactionHandler( + transactionKeyArg: Long, + snapshotValueArg: Any?, + callback: (Result) -> Unit + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + val channelName = + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler$separatedMessageChannelSuffix" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(transactionKeyArg, snapshotValueArg)) { if (it is List<*>) { if (it.size > 1) { callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else if (it[0] == null) { - callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""))) + callback( + Result.failure( + FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) } else { val output = it[0] as TransactionHandlerResult callback(Result.success(output)) } } else { - callback(Result.failure(GeneratedAndroidFirebaseDatabasePigeonUtils.createConnectionError(channelName))) - } + callback( + Result.failure( + GeneratedAndroidFirebaseDatabasePigeonUtils.createConnectionError(channelName))) + } } } } diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt index ebb84e4edc4b..9e8a97bd4f70 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/QueryBuilder.kt @@ -11,50 +11,50 @@ import com.google.firebase.database.DatabaseReference import com.google.firebase.database.Query class QueryBuilder - @JvmOverloads - constructor( +@JvmOverloads +constructor( @NonNull ref: DatabaseReference, @NonNull private val modifiers: List>, - ) { - private var query: Query = ref +) { + private var query: Query = ref - fun build(): Query { - if (modifiers.isEmpty()) return query + fun build(): Query { + if (modifiers.isEmpty()) return query - for (modifier in modifiers) { - val type = modifier["type"] as String + for (modifier in modifiers) { + val type = modifier["type"] as String - when (type) { - Constants.LIMIT -> limit(modifier) - Constants.CURSOR -> cursor(modifier) - Constants.ORDER_BY -> orderBy(modifier) - } + when (type) { + Constants.LIMIT -> limit(modifier) + Constants.CURSOR -> cursor(modifier) + Constants.ORDER_BY -> orderBy(modifier) } - - return query } - private fun limit(modifier: Map) { - val name = modifier["name"] as String - val value = + return query + } + + private fun limit(modifier: Map) { + val name = modifier["name"] as String + val value = when (val limit = modifier["limit"]) { is Int -> limit is Number -> limit.toInt() else -> throw IllegalArgumentException("Invalid limit value: $limit") } - query = + query = when (name) { Constants.LIMIT_TO_FIRST -> query.limitToFirst(value) Constants.LIMIT_TO_LAST -> query.limitToLast(value) else -> query } - } + } - private fun orderBy(modifier: Map) { - val name = modifier["name"] as String + private fun orderBy(modifier: Map) { + val name = modifier["name"] as String - query = + query = when (name) { "orderByKey" -> query.orderByKey() "orderByValue" -> query.orderByValue() @@ -65,64 +65,78 @@ class QueryBuilder } else -> query } - } + } - private fun cursor(modifier: Map) { - val name = modifier["name"] as String + private fun cursor(modifier: Map) { + val name = modifier["name"] as String - when (name) { - Constants.START_AT -> startAt(modifier) - Constants.START_AFTER -> startAfter(modifier) - Constants.END_AT -> endAt(modifier) - Constants.END_BEFORE -> endBefore(modifier) - } + when (name) { + Constants.START_AT -> startAt(modifier) + Constants.START_AFTER -> startAfter(modifier) + Constants.END_AT -> endAt(modifier) + Constants.END_BEFORE -> endBefore(modifier) } + } - private fun startAt(modifier: Map) { - val value = modifier["value"] - val key = modifier["key"] as String? + private fun startAt(modifier: Map) { + val value = modifier["value"] + val key = modifier["key"] as String? - query = + query = when (value) { is Boolean -> if (key == null) query.startAt(value) else query.startAt(value, key) - is Number -> if (key == null) query.startAt(value.toDouble()) else query.startAt(value.toDouble(), key) - else -> if (key == null) query.startAt(value.toString()) else query.startAt(value.toString(), key) + is Number -> + if (key == null) query.startAt(value.toDouble()) + else query.startAt(value.toDouble(), key) + else -> + if (key == null) query.startAt(value.toString()) + else query.startAt(value.toString(), key) } - } + } - private fun startAfter(modifier: Map) { - val value = modifier["value"] - val key = modifier["key"] as String? + private fun startAfter(modifier: Map) { + val value = modifier["value"] + val key = modifier["key"] as String? - query = + query = when (value) { is Boolean -> if (key == null) query.startAfter(value) else query.startAfter(value, key) - is Number -> if (key == null) query.startAfter(value.toDouble()) else query.startAfter(value.toDouble(), key) - else -> if (key == null) query.startAfter(value.toString()) else query.startAfter(value.toString(), key) + is Number -> + if (key == null) query.startAfter(value.toDouble()) + else query.startAfter(value.toDouble(), key) + else -> + if (key == null) query.startAfter(value.toString()) + else query.startAfter(value.toString(), key) } - } + } - private fun endAt(modifier: Map) { - val value = modifier["value"] - val key = modifier["key"] as String? + private fun endAt(modifier: Map) { + val value = modifier["value"] + val key = modifier["key"] as String? - query = + query = when (value) { is Boolean -> if (key == null) query.endAt(value) else query.endAt(value, key) - is Number -> if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key) - else -> if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key) + is Number -> + if (key == null) query.endAt(value.toDouble()) else query.endAt(value.toDouble(), key) + else -> + if (key == null) query.endAt(value.toString()) else query.endAt(value.toString(), key) } - } + } - private fun endBefore(modifier: Map) { - val value = modifier["value"] - val key = modifier["key"] as String? + private fun endBefore(modifier: Map) { + val value = modifier["value"] + val key = modifier["key"] as String? - query = + query = when (value) { is Boolean -> if (key == null) query.endBefore(value) else query.endBefore(value, key) - is Number -> if (key == null) query.endBefore(value.toDouble()) else query.endBefore(value.toDouble(), key) - else -> if (key == null) query.endBefore(value.toString()) else query.endBefore(value.toString(), key) + is Number -> + if (key == null) query.endBefore(value.toDouble()) + else query.endBefore(value.toDouble(), key) + else -> + if (key == null) query.endBefore(value.toString()) + else query.endBefore(value.toString(), key) } - } } +} diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionExecutor.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionExecutor.kt index 4f31edf655e2..c6be9ca7f0bd 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionExecutor.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionExecutor.kt @@ -15,8 +15,9 @@ import io.flutter.plugin.common.MethodChannel import java.util.* import java.util.concurrent.ExecutionException -class TransactionExecutor constructor( - private val channel: MethodChannel, +class TransactionExecutor +constructor( + private val channel: MethodChannel, ) { private val completion = TaskCompletionSource() @@ -24,46 +25,46 @@ class TransactionExecutor constructor( fun execute(arguments: Map): Any { Handler(Looper.getMainLooper()).post { channel.invokeMethod( - Constants.METHOD_CALL_TRANSACTION_HANDLER, - arguments, - object : MethodChannel.Result { - override fun success( - @Nullable result: Any?, - ) { - completion.setResult(result) - } + Constants.METHOD_CALL_TRANSACTION_HANDLER, + arguments, + object : MethodChannel.Result { + override fun success( + @Nullable result: Any?, + ) { + completion.setResult(result) + } - @Suppress("UNCHECKED_CAST") - override fun error( - errorCode: String, - @Nullable errorMessage: String?, - @Nullable errorDetails: Any?, - ) { - var message = errorMessage - val additionalData = mutableMapOf() + @Suppress("UNCHECKED_CAST") + override fun error( + errorCode: String, + @Nullable errorMessage: String?, + @Nullable errorDetails: Any?, + ) { + var message = errorMessage + val additionalData = mutableMapOf() - if (message == null) { - message = FlutterFirebaseDatabaseException.UNKNOWN_ERROR_MESSAGE - } + if (message == null) { + message = FlutterFirebaseDatabaseException.UNKNOWN_ERROR_MESSAGE + } - if (errorDetails is Map<*, *>) { - additionalData.putAll(errorDetails as Map) - } + if (errorDetails is Map<*, *>) { + additionalData.putAll(errorDetails as Map) + } - val e = - FlutterFirebaseDatabaseException( - errorCode, - message, - additionalData, - ) + val e = + FlutterFirebaseDatabaseException( + errorCode, + message, + additionalData, + ) - completion.setException(e) - } + completion.setException(e) + } - override fun notImplemented() { - // never called - } - }, + override fun notImplemented() { + // never called + } + }, ) } diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionHandler.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionHandler.kt index 5bc549ba629e..675ecac3bf5c 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionHandler.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/TransactionHandler.kt @@ -19,87 +19,89 @@ import com.google.firebase.database.Transaction.Handler import io.flutter.plugin.common.MethodChannel class TransactionHandler - @JvmOverloads - constructor( +@JvmOverloads +constructor( @NonNull private val channel: MethodChannel, private val transactionKey: Int, - ) : Handler { - private val transactionCompletionSource = TaskCompletionSource>() +) : Handler { + private val transactionCompletionSource = TaskCompletionSource>() - fun getTask(): Task> = transactionCompletionSource.task + fun getTask(): Task> = transactionCompletionSource.task - @NonNull - override fun doTransaction( + @NonNull + override fun doTransaction( @NonNull currentData: MutableData, - ): Transaction.Result { - val snapshotMap = + ): Transaction.Result { + val snapshotMap = mapOf( - Constants.KEY to (currentData.key ?: ""), - Constants.VALUE to currentData.value, + Constants.KEY to (currentData.key ?: ""), + Constants.VALUE to currentData.value, ) - val transactionArgs = + val transactionArgs = mapOf( - Constants.SNAPSHOT to snapshotMap, - Constants.TRANSACTION_KEY to transactionKey, + Constants.SNAPSHOT to snapshotMap, + Constants.TRANSACTION_KEY to transactionKey, ) - return try { - val executor = TransactionExecutor(channel) - val updatedData: Any? = executor.execute(transactionArgs) + return try { + val executor = TransactionExecutor(channel) + val updatedData: Any? = executor.execute(transactionArgs) - @Suppress("UNCHECKED_CAST") - val transactionHandlerResult: Map = + @Suppress("UNCHECKED_CAST") + val transactionHandlerResult: Map = when (updatedData) { is Map<*, *> -> updatedData as Map null -> emptyMap() else -> { - Log.e("firebase_database", "Unexpected transaction result type: ${updatedData::class.java}") + Log.e( + "firebase_database", + "Unexpected transaction result type: ${updatedData::class.java}") emptyMap() } } - val aborted: Boolean = (transactionHandlerResult["aborted"] as? Boolean) ?: false - val exception: Boolean = (transactionHandlerResult["exception"] as? Boolean) ?: false + val aborted: Boolean = (transactionHandlerResult["aborted"] as? Boolean) ?: false + val exception: Boolean = (transactionHandlerResult["exception"] as? Boolean) ?: false - if (aborted || exception) { - Transaction.abort() - } else { - if (transactionHandlerResult.containsKey("value")) { - currentData.value = transactionHandlerResult["value"] - } - Transaction.success(currentData) - } - } catch (e: Exception) { - Log.e("firebase_database", "An unexpected exception occurred for a transaction.", e) + if (aborted || exception) { Transaction.abort() + } else { + if (transactionHandlerResult.containsKey("value")) { + currentData.value = transactionHandlerResult["value"] + } + Transaction.success(currentData) } + } catch (e: Exception) { + Log.e("firebase_database", "An unexpected exception occurred for a transaction.", e) + Transaction.abort() } + } - override fun onComplete( + override fun onComplete( @Nullable error: DatabaseError?, committed: Boolean, @Nullable currentData: DataSnapshot?, - ) { - when { - error != null -> { - transactionCompletionSource.setException( + ) { + when { + error != null -> { + transactionCompletionSource.setException( FlutterFirebaseDatabaseException.fromDatabaseError(error), - ) - } - currentData != null -> { - val payload = FlutterDataSnapshotPayload(currentData) - val additionalParams: MutableMap = + ) + } + currentData != null -> { + val payload = FlutterDataSnapshotPayload(currentData) + val additionalParams: MutableMap = mutableMapOf( - Constants.COMMITTED to committed, + Constants.COMMITTED to committed, ) - transactionCompletionSource.setResult( + transactionCompletionSource.setResult( payload.withAdditionalParams(additionalParams).toMap(), - ) - } - else -> { - transactionCompletionSource.setResult(emptyMap()) - } + ) + } + else -> { + transactionCompletionSource.setResult(emptyMap()) } } } +} diff --git a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ValueEventsProxy.kt b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ValueEventsProxy.kt index 299a129e86b7..41c46a6a54cd 100644 --- a/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ValueEventsProxy.kt +++ b/packages/firebase_database/firebase_database/android/src/main/kotlin/io/flutter/plugins/firebase/database/ValueEventsProxy.kt @@ -13,21 +13,20 @@ import com.google.firebase.database.ValueEventListener import io.flutter.plugin.common.EventChannel.EventSink class ValueEventsProxy - @JvmOverloads - constructor( +@JvmOverloads +constructor( @NonNull eventSink: EventSink, - ) : EventsProxy(eventSink, Constants.EVENT_TYPE_VALUE), - ValueEventListener { - override fun onDataChange( +) : EventsProxy(eventSink, Constants.EVENT_TYPE_VALUE), ValueEventListener { + override fun onDataChange( @NonNull snapshot: DataSnapshot, - ) { - sendEvent(Constants.EVENT_TYPE_VALUE, snapshot, null) - } + ) { + sendEvent(Constants.EVENT_TYPE_VALUE, snapshot, null) + } - override fun onCancelled( + override fun onCancelled( @NonNull error: DatabaseError, - ) { - val e = FlutterFirebaseDatabaseException.fromDatabaseError(error) - eventSink.error(e.code, e.message, e.additionalData) - } + ) { + val e = FlutterFirebaseDatabaseException.fromDatabaseError(error) + eventSink.error(e.code, e.message, e.additionalData) } +} diff --git a/packages/firebase_database/firebase_database/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/database/example/MainActivity.kt b/packages/firebase_database/firebase_database/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/database/example/MainActivity.kt index 8453022cc73f..0fcc054366fe 100644 --- a/packages/firebase_database/firebase_database/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/database/example/MainActivity.kt +++ b/packages/firebase_database/firebase_database/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/database/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.database.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_database/firebase_database/example/macos/Runner/AppDelegate.swift b/packages/firebase_database/firebase_database/example/macos/Runner/AppDelegate.swift index dd8f68d76ac5..b3c176141221 100644 --- a/packages/firebase_database/firebase_database/example/macos/Runner/AppDelegate.swift +++ b/packages/firebase_database/firebase_database/example/macos/Runner/AppDelegate.swift @@ -6,7 +6,7 @@ class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } - + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { return true } diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index f944075b3d48..14d652359c46 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "12.4.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "12.4.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_database", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-database", targets: ["firebase_database"]), + .library(name: "firebase-database", targets: ["firebase_database"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-rtdb\""), ] - ), + ) ] ) diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseObserveStreamHandler.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseObserveStreamHandler.swift index 4b147e49db5b..86029a6d5d39 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseObserveStreamHandler.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseObserveStreamHandler.swift @@ -22,16 +22,17 @@ import FirebaseDatabase } func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) - -> FlutterError? { + -> FlutterError? + { guard let args = arguments as? [String: Any], - let eventTypeString = args["eventType"] as? String + let eventTypeString = args["eventType"] as? String else { return nil } let observeBlock: (DataSnapshot, String?) -> Void = { [weak self] snapshot, previousChildKey in var eventDictionary: [String: Any] = [ - "eventType": eventTypeString, + "eventType": eventTypeString ] let snapshotDict = FLTFirebaseDatabaseUtils.dictionary( diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift index 1c617600deb7..d94bc937593f 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift @@ -17,14 +17,15 @@ import Foundation #else import firebase_core_shared #endif -import FirebaseDatabase /// Channel name constant to match macOS implementation +// swift-format-ignore: AlwaysUseLowerCamelCase let FLTFirebaseDatabaseChannelName = "plugins.flutter.io/firebase_database" @objc(FLTFirebaseDatabasePlugin) public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePluginProtocol, - FirebaseDatabaseHostApi { + FirebaseDatabaseHostApi +{ private var binaryMessenger: FlutterBinaryMessenger private static var cachedDatabaseInstances: [String: Database] = [:] private var streamHandlers: [String: FLTFirebaseDatabaseObserveStreamHandler] = [:] @@ -104,22 +105,28 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug // MARK: - Database Management - func goOnline(app: DatabasePigeonFirebaseApp, - completion: @escaping (Result) -> Void) { + func goOnline( + app: DatabasePigeonFirebaseApp, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) database.goOnline() completion(.success(())) } - func goOffline(app: DatabasePigeonFirebaseApp, - completion: @escaping (Result) -> Void) { + func goOffline( + app: DatabasePigeonFirebaseApp, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) database.goOffline() completion(.success(())) } - func setPersistenceEnabled(app: DatabasePigeonFirebaseApp, enabled: Bool, - completion: @escaping (Result) -> Void) { + func setPersistenceEnabled( + app: DatabasePigeonFirebaseApp, enabled: Bool, + completion: @escaping (Result) -> Void + ) { let instanceKey = app.appName + (app.databaseURL ?? "") if Self.cachedDatabaseInstances[instanceKey] != nil { completion(.success(())) @@ -131,8 +138,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug completion(.success(())) } - func setPersistenceCacheSizeBytes(app: DatabasePigeonFirebaseApp, cacheSize: Int64, - completion: @escaping (Result) -> Void) { + func setPersistenceCacheSizeBytes( + app: DatabasePigeonFirebaseApp, cacheSize: Int64, + completion: @escaping (Result) -> Void + ) { let instanceKey = app.appName + (app.databaseURL ?? "") if Self.cachedDatabaseInstances[instanceKey] != nil { completion(.success(())) @@ -148,37 +157,47 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug completion(.success(())) } - func setLoggingEnabled(app: DatabasePigeonFirebaseApp, enabled: Bool, - completion: @escaping (Result) -> Void) { + func setLoggingEnabled( + app: DatabasePigeonFirebaseApp, enabled: Bool, + completion: @escaping (Result) -> Void + ) { Database.setLoggingEnabled(enabled) completion(.success(())) } - func useDatabaseEmulator(app: DatabasePigeonFirebaseApp, host: String, port: Int64, - completion: @escaping (Result) -> Void) { + func useDatabaseEmulator( + app: DatabasePigeonFirebaseApp, host: String, port: Int64, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) database.useEmulator(withHost: host, port: Int(port)) completion(.success(())) } - func ref(app: DatabasePigeonFirebaseApp, path: String?, - completion: @escaping (Result) -> Void) { + func ref( + app: DatabasePigeonFirebaseApp, path: String?, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: path ?? "") let result = DatabaseReferencePlatform(path: reference.url) completion(.success(result)) } - func refFromURL(app: DatabasePigeonFirebaseApp, url: String, - completion: @escaping (Result) -> Void) { + func refFromURL( + app: DatabasePigeonFirebaseApp, url: String, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(fromURL: url) let result = DatabaseReferencePlatform(path: reference.url) completion(.success(result)) } - func purgeOutstandingWrites(app: DatabasePigeonFirebaseApp, - completion: @escaping (Result) -> Void) { + func purgeOutstandingWrites( + app: DatabasePigeonFirebaseApp, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) database.purgeOutstandingWrites() completion(.success(())) @@ -186,8 +205,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug // MARK: - Database Reference Operations - func databaseReferenceSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) { + func databaseReferenceSet( + app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -200,9 +221,11 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } } - func databaseReferenceSetWithPriority(app: DatabasePigeonFirebaseApp, - request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) { + func databaseReferenceSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -215,8 +238,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } } - func databaseReferenceUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, - completion: @escaping (Result) -> Void) { + func databaseReferenceUpdate( + app: DatabasePigeonFirebaseApp, request: UpdateRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -231,9 +256,11 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } } - func databaseReferenceSetPriority(app: DatabasePigeonFirebaseApp, - request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) { + func databaseReferenceSetPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -246,84 +273,98 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } } - func databaseReferenceRunTransaction(app: DatabasePigeonFirebaseApp, request: TransactionRequest, - completion: @escaping (Result) -> Void) { + func databaseReferenceRunTransaction( + app: DatabasePigeonFirebaseApp, request: TransactionRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) - reference.runTransactionBlock({ currentData in - let semaphore = DispatchSemaphore(value: 0) - var transactionResult: TransactionHandlerResult? - - DispatchQueue.main.async { - let flutterApi = FirebaseDatabaseFlutterApi(binaryMessenger: self.binaryMessenger) - flutterApi.callTransactionHandler( - transactionKey: request.transactionKey, - snapshotValue: currentData.value - ) { result in - switch result { - case let .success(handlerResult): - transactionResult = handlerResult - case let .failure(error): - print("Transaction handler error: \(error)") - transactionResult = TransactionHandlerResult(value: nil, aborted: true, exception: true) + reference.runTransactionBlock( + { currentData in + let semaphore = DispatchSemaphore(value: 0) + var transactionResult: TransactionHandlerResult? + + DispatchQueue.main.async { + let flutterApi = FirebaseDatabaseFlutterApi(binaryMessenger: self.binaryMessenger) + flutterApi.callTransactionHandler( + transactionKey: request.transactionKey, + snapshotValue: currentData.value + ) { result in + switch result { + case .success(let handlerResult): + transactionResult = handlerResult + case .failure(let error): + print("Transaction handler error: \(error)") + transactionResult = TransactionHandlerResult( + value: nil, aborted: true, exception: true + ) + } + semaphore.signal() } - semaphore.signal() } - } - semaphore.wait() + semaphore.wait() - guard let result = transactionResult else { - return TransactionResult.abort() - } + guard let result = transactionResult else { + return TransactionResult.abort() + } - if result.aborted || result.exception { - return TransactionResult.abort() - } + if result.aborted || result.exception { + return TransactionResult.abort() + } - currentData.value = result.value - return TransactionResult.success(withValue: currentData) - }, andCompletionBlock: { error, committed, snapshot in - if let error { - completion(.failure(self.createFlutterError(error))) - return - } + currentData.value = result.value + return TransactionResult.success(withValue: currentData) + }, + andCompletionBlock: { error, committed, snapshot in + if let error { + completion(.failure(self.createFlutterError(error))) + return + } - var snapshotMap: [String: Any?] - if let snapshot { - let snapshotDict = FLTFirebaseDatabaseUtils.dictionary(from: snapshot) - snapshotMap = ["snapshot": snapshotDict] - } else { - snapshotMap = ["snapshot": NSNull()] - } + var snapshotMap: [String: Any?] + if let snapshot { + let snapshotDict = FLTFirebaseDatabaseUtils.dictionary(from: snapshot) + snapshotMap = ["snapshot": snapshotDict] + } else { + snapshotMap = ["snapshot": NSNull()] + } - self.transactionResults[request.transactionKey] = [ - "committed": committed, - "snapshot": snapshotMap["snapshot"] as Any, - ] + self.transactionResults[request.transactionKey] = [ + "committed": committed, + "snapshot": snapshotMap["snapshot"] as Any, + ] - completion(.success(())) - }, withLocalEvents: request.applyLocally) + completion(.success(())) + }, withLocalEvents: request.applyLocally + ) } - func databaseReferenceGetTransactionResult(app: DatabasePigeonFirebaseApp, transactionKey: Int64, - completion: @escaping (Result<[String: Any?], Error>) - -> Void) { + func databaseReferenceGetTransactionResult( + app: DatabasePigeonFirebaseApp, transactionKey: Int64, + completion: + @escaping (Result<[String: Any?], Error>) + -> Void + ) { if let result = transactionResults.removeValue(forKey: transactionKey) { completion(.success(result)) } else { - completion(.success([ - "committed": false, - "snapshot": ["value": NSNull()], - ])) + completion( + .success([ + "committed": false, + "snapshot": ["value": NSNull()], + ]) + ) } } // MARK: - OnDisconnect Operations - func onDisconnectSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) { + func onDisconnectSet( + app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -336,9 +377,11 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } } - func onDisconnectSetWithPriority(app: DatabasePigeonFirebaseApp, - request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) { + func onDisconnectSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -351,8 +394,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } } - func onDisconnectUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, - completion: @escaping (Result) -> Void) { + func onDisconnectUpdate( + app: DatabasePigeonFirebaseApp, request: UpdateRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -367,8 +412,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } } - func onDisconnectCancel(app: DatabasePigeonFirebaseApp, path: String, - completion: @escaping (Result) -> Void) { + func onDisconnectCancel( + app: DatabasePigeonFirebaseApp, path: String, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: path) @@ -383,8 +430,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug // MARK: - Query Operations - func queryObserve(app: DatabasePigeonFirebaseApp, request: QueryRequest, - completion: @escaping (Result) -> Void) { + func queryObserve( + app: DatabasePigeonFirebaseApp, request: QueryRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -447,7 +496,8 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug case "limit": if let name = modifier["name"] as? String, - let limit = modifier["limit"] as? NSNumber { + let limit = modifier["limit"] as? NSNumber + { switch name { case "limitToFirst": query = query.queryLimited(toFirst: limit.uintValue) @@ -485,8 +535,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug completion(.success(channelName)) } - func queryKeepSynced(app: DatabasePigeonFirebaseApp, request: QueryRequest, - completion: @escaping (Result) -> Void) { + func queryKeepSynced( + app: DatabasePigeonFirebaseApp, request: QueryRequest, + completion: @escaping (Result) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -549,7 +601,8 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug case "limit": if let name = modifier["name"] as? String, - let limit = modifier["limit"] as? NSNumber { + let limit = modifier["limit"] as? NSNumber + { switch name { case "limitToFirst": query = query.queryLimited(toFirst: limit.uintValue) @@ -572,8 +625,10 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug completion(.success(())) } - func queryGet(app: DatabasePigeonFirebaseApp, request: QueryRequest, - completion: @escaping (Result<[String: Any?], Error>) -> Void) { + func queryGet( + app: DatabasePigeonFirebaseApp, request: QueryRequest, + completion: @escaping (Result<[String: Any?], Error>) -> Void + ) { let database = getDatabaseFromPigeonApp(app) let reference = database.reference(withPath: request.path) @@ -647,7 +702,8 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug case "limit": if let name = modifier["name"] as? String, - let limit = modifier["limit"] as? NSNumber { + let limit = modifier["limit"] as? NSNumber + { switch name { case "limitToFirst": query = query.queryLimited(toFirst: limit.uintValue) @@ -710,7 +766,8 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug } if let emulatorHost = app.settings.emulatorHost, - let emulatorPort = app.settings.emulatorPort { + let emulatorPort = app.settings.emulatorPort + { database.useEmulator(withHost: emulatorHost, port: Int(emulatorPort)) } diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseUtils.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseUtils.swift index 9561af721ff1..c51f5ac67a2a 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseUtils.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabaseUtils.swift @@ -55,7 +55,8 @@ import Foundation } if let emulatorHost = arguments["emulatorHost"] as? String, - let emulatorPort = arguments["emulatorPort"] as? Int { + let emulatorPort = arguments["emulatorPort"] as? Int + { database.useEmulator(withHost: emulatorHost, port: emulatorPort) } @@ -69,8 +70,10 @@ import Foundation return database.reference(withPath: path) } - private static func databaseQuery(_ query: DatabaseQuery, - applyLimitModifier modifier: [String: Any]) -> DatabaseQuery { + private static func databaseQuery( + _ query: DatabaseQuery, + applyLimitModifier modifier: [String: Any] + ) -> DatabaseQuery { let name = modifier["name"] as? String ?? "" let limit = modifier["limit"] as? UInt ?? 0 @@ -84,8 +87,10 @@ import Foundation } } - private static func databaseQuery(_ query: DatabaseQuery, - applyOrderModifier modifier: [String: Any]) -> DatabaseQuery { + private static func databaseQuery( + _ query: DatabaseQuery, + applyOrderModifier modifier: [String: Any] + ) -> DatabaseQuery { let name = modifier["name"] as? String ?? "" switch name { @@ -103,8 +108,10 @@ import Foundation } } - private static func databaseQuery(_ query: DatabaseQuery, - applyCursorModifier modifier: [String: Any]) -> DatabaseQuery { + private static func databaseQuery( + _ query: DatabaseQuery, + applyCursorModifier modifier: [String: Any] + ) -> DatabaseQuery { let name = modifier["name"] as? String ?? "" let key = modifier["key"] as? String let value = modifier["value"] @@ -161,8 +168,10 @@ import Foundation return query } - static func dictionary(from snapshot: DataSnapshot, - withPreviousChildKey previousChildKey: String?) -> [String: Any] { + static func dictionary( + from snapshot: DataSnapshot, + withPreviousChildKey previousChildKey: String? + ) -> [String: Any] { [ "snapshot": dictionary(from: snapshot), "previousChildKey": previousChildKey ?? NSNull(), diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift index 5e0d5707382d..6a0fb0d765f5 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FirebaseDatabaseMessages.g.swift @@ -97,7 +97,7 @@ func deepEqualsFirebaseDatabaseMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: return true case is (Void, Void): @@ -139,7 +139,7 @@ func deepEqualsFirebaseDatabaseMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { } return true - case let (lhs as Double, rhs as Double): + case (let lhs as Double, let rhs as Double): return doubleEqualsFirebaseDatabaseMessages(lhs, rhs) case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): @@ -222,12 +222,12 @@ struct DatabasePigeonSettings: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseDatabaseMessages(lhs.persistenceEnabled, rhs.persistenceEnabled) && - deepEqualsFirebaseDatabaseMessages( + return deepEqualsFirebaseDatabaseMessages(lhs.persistenceEnabled, rhs.persistenceEnabled) + && deepEqualsFirebaseDatabaseMessages( lhs.cacheSizeBytes, rhs.cacheSizeBytes - ) && deepEqualsFirebaseDatabaseMessages(lhs.loggingEnabled, rhs.loggingEnabled) && - deepEqualsFirebaseDatabaseMessages( + ) && deepEqualsFirebaseDatabaseMessages(lhs.loggingEnabled, rhs.loggingEnabled) + && deepEqualsFirebaseDatabaseMessages( lhs.emulatorHost, rhs.emulatorHost ) && deepEqualsFirebaseDatabaseMessages(lhs.emulatorPort, rhs.emulatorPort) @@ -274,8 +274,8 @@ struct DatabasePigeonFirebaseApp: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseDatabaseMessages(lhs.appName, rhs.appName) && - deepEqualsFirebaseDatabaseMessages( + return deepEqualsFirebaseDatabaseMessages(lhs.appName, rhs.appName) + && deepEqualsFirebaseDatabaseMessages( lhs.databaseURL, rhs.databaseURL ) && deepEqualsFirebaseDatabaseMessages(lhs.settings, rhs.settings) @@ -304,7 +304,7 @@ struct DatabaseReferencePlatform: Hashable { func toList() -> [Any?] { [ - path, + path ] } @@ -352,8 +352,8 @@ struct DatabaseReferenceRequest: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && - deepEqualsFirebaseDatabaseMessages( + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) + && deepEqualsFirebaseDatabaseMessages( lhs.value, rhs.value ) && deepEqualsFirebaseDatabaseMessages(lhs.priority, rhs.priority) @@ -394,8 +394,8 @@ struct UpdateRequest: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && - deepEqualsFirebaseDatabaseMessages( + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) + && deepEqualsFirebaseDatabaseMessages( lhs.value, rhs.value ) @@ -439,8 +439,8 @@ struct TransactionRequest: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && - deepEqualsFirebaseDatabaseMessages( + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) + && deepEqualsFirebaseDatabaseMessages( lhs.transactionKey, rhs.transactionKey ) && deepEqualsFirebaseDatabaseMessages(lhs.applyLocally, rhs.applyLocally) @@ -485,8 +485,8 @@ struct QueryRequest: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) && - deepEqualsFirebaseDatabaseMessages( + return deepEqualsFirebaseDatabaseMessages(lhs.path, rhs.path) + && deepEqualsFirebaseDatabaseMessages( lhs.modifiers, rhs.modifiers ) && deepEqualsFirebaseDatabaseMessages(lhs.value, rhs.value) @@ -531,8 +531,8 @@ struct TransactionHandlerResult: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseDatabaseMessages(lhs.value, rhs.value) && - deepEqualsFirebaseDatabaseMessages( + return deepEqualsFirebaseDatabaseMessages(lhs.value, rhs.value) + && deepEqualsFirebaseDatabaseMessages( lhs.aborted, rhs.aborted ) && deepEqualsFirebaseDatabaseMessages(lhs.exception, rhs.exception) @@ -623,52 +623,74 @@ class FirebaseDatabaseMessagesPigeonCodec: FlutterStandardMessageCodec, @uncheck /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseDatabaseHostApi { func goOnline(app: DatabasePigeonFirebaseApp, completion: @escaping (Result) -> Void) - func goOffline(app: DatabasePigeonFirebaseApp, - completion: @escaping (Result) -> Void) - func setPersistenceEnabled(app: DatabasePigeonFirebaseApp, enabled: Bool, - completion: @escaping (Result) -> Void) - func setPersistenceCacheSizeBytes(app: DatabasePigeonFirebaseApp, cacheSize: Int64, - completion: @escaping (Result) -> Void) - func setLoggingEnabled(app: DatabasePigeonFirebaseApp, enabled: Bool, - completion: @escaping (Result) -> Void) - func useDatabaseEmulator(app: DatabasePigeonFirebaseApp, host: String, port: Int64, - completion: @escaping (Result) -> Void) - func ref(app: DatabasePigeonFirebaseApp, path: String?, - completion: @escaping (Result) -> Void) - func refFromURL(app: DatabasePigeonFirebaseApp, url: String, - completion: @escaping (Result) -> Void) - func purgeOutstandingWrites(app: DatabasePigeonFirebaseApp, - completion: @escaping (Result) -> Void) - func databaseReferenceSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) - func databaseReferenceSetWithPriority(app: DatabasePigeonFirebaseApp, - request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) - func databaseReferenceUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, - completion: @escaping (Result) -> Void) - func databaseReferenceSetPriority(app: DatabasePigeonFirebaseApp, - request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) - func databaseReferenceRunTransaction(app: DatabasePigeonFirebaseApp, request: TransactionRequest, - completion: @escaping (Result) -> Void) - func databaseReferenceGetTransactionResult(app: DatabasePigeonFirebaseApp, transactionKey: Int64, - completion: @escaping (Result<[String: Any?], Error>) - -> Void) - func onDisconnectSet(app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) - func onDisconnectSetWithPriority(app: DatabasePigeonFirebaseApp, - request: DatabaseReferenceRequest, - completion: @escaping (Result) -> Void) - func onDisconnectUpdate(app: DatabasePigeonFirebaseApp, request: UpdateRequest, - completion: @escaping (Result) -> Void) - func onDisconnectCancel(app: DatabasePigeonFirebaseApp, path: String, - completion: @escaping (Result) -> Void) - func queryObserve(app: DatabasePigeonFirebaseApp, request: QueryRequest, - completion: @escaping (Result) -> Void) - func queryKeepSynced(app: DatabasePigeonFirebaseApp, request: QueryRequest, - completion: @escaping (Result) -> Void) - func queryGet(app: DatabasePigeonFirebaseApp, request: QueryRequest, - completion: @escaping (Result<[String: Any?], Error>) -> Void) + func goOffline( + app: DatabasePigeonFirebaseApp, + completion: @escaping (Result) -> Void) + func setPersistenceEnabled( + app: DatabasePigeonFirebaseApp, enabled: Bool, + completion: @escaping (Result) -> Void) + func setPersistenceCacheSizeBytes( + app: DatabasePigeonFirebaseApp, cacheSize: Int64, + completion: @escaping (Result) -> Void) + func setLoggingEnabled( + app: DatabasePigeonFirebaseApp, enabled: Bool, + completion: @escaping (Result) -> Void) + func useDatabaseEmulator( + app: DatabasePigeonFirebaseApp, host: String, port: Int64, + completion: @escaping (Result) -> Void) + func ref( + app: DatabasePigeonFirebaseApp, path: String?, + completion: @escaping (Result) -> Void) + func refFromURL( + app: DatabasePigeonFirebaseApp, url: String, + completion: @escaping (Result) -> Void) + func purgeOutstandingWrites( + app: DatabasePigeonFirebaseApp, + completion: @escaping (Result) -> Void) + func databaseReferenceSet( + app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void) + func databaseReferenceSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void) + func databaseReferenceUpdate( + app: DatabasePigeonFirebaseApp, request: UpdateRequest, + completion: @escaping (Result) -> Void) + func databaseReferenceSetPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void) + func databaseReferenceRunTransaction( + app: DatabasePigeonFirebaseApp, request: TransactionRequest, + completion: @escaping (Result) -> Void) + func databaseReferenceGetTransactionResult( + app: DatabasePigeonFirebaseApp, transactionKey: Int64, + completion: + @escaping (Result<[String: Any?], Error>) + -> Void) + func onDisconnectSet( + app: DatabasePigeonFirebaseApp, request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void) + func onDisconnectSetWithPriority( + app: DatabasePigeonFirebaseApp, + request: DatabaseReferenceRequest, + completion: @escaping (Result) -> Void) + func onDisconnectUpdate( + app: DatabasePigeonFirebaseApp, request: UpdateRequest, + completion: @escaping (Result) -> Void) + func onDisconnectCancel( + app: DatabasePigeonFirebaseApp, path: String, + completion: @escaping (Result) -> Void) + func queryObserve( + app: DatabasePigeonFirebaseApp, request: QueryRequest, + completion: @escaping (Result) -> Void) + func queryKeepSynced( + app: DatabasePigeonFirebaseApp, request: QueryRequest, + completion: @escaping (Result) -> Void) + func queryGet( + app: DatabasePigeonFirebaseApp, request: QueryRequest, + completion: @escaping (Result<[String: Any?], Error>) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -679,11 +701,14 @@ class FirebaseDatabaseHostApiSetup { /// Sets up an instance of `FirebaseDatabaseHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseDatabaseHostApi?, - messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: FirebaseDatabaseHostApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let goOnlineChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOnline\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -695,7 +720,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -704,7 +729,8 @@ class FirebaseDatabaseHostApiSetup { goOnlineChannel.setMessageHandler(nil) } let goOfflineChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.goOffline\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -716,7 +742,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -725,7 +751,8 @@ class FirebaseDatabaseHostApiSetup { goOfflineChannel.setMessageHandler(nil) } let setPersistenceEnabledChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceEnabled\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -738,7 +765,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -747,7 +774,8 @@ class FirebaseDatabaseHostApiSetup { setPersistenceEnabledChannel.setMessageHandler(nil) } let setPersistenceCacheSizeBytesChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setPersistenceCacheSizeBytes\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -760,7 +788,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -769,7 +797,8 @@ class FirebaseDatabaseHostApiSetup { setPersistenceCacheSizeBytesChannel.setMessageHandler(nil) } let setLoggingEnabledChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.setLoggingEnabled\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -782,7 +811,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -791,7 +820,8 @@ class FirebaseDatabaseHostApiSetup { setLoggingEnabledChannel.setMessageHandler(nil) } let useDatabaseEmulatorChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.useDatabaseEmulator\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -805,7 +835,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -814,7 +844,8 @@ class FirebaseDatabaseHostApiSetup { useDatabaseEmulatorChannel.setMessageHandler(nil) } let refChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.ref\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -825,9 +856,9 @@ class FirebaseDatabaseHostApiSetup { let pathArg: String? = nilOrValue(args[1]) api.ref(app: appArg, path: pathArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -836,7 +867,8 @@ class FirebaseDatabaseHostApiSetup { refChannel.setMessageHandler(nil) } let refFromURLChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.refFromURL\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -847,9 +879,9 @@ class FirebaseDatabaseHostApiSetup { let urlArg = args[1] as! String api.refFromURL(app: appArg, url: urlArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -858,7 +890,8 @@ class FirebaseDatabaseHostApiSetup { refFromURLChannel.setMessageHandler(nil) } let purgeOutstandingWritesChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.purgeOutstandingWrites\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -870,7 +903,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -879,7 +912,8 @@ class FirebaseDatabaseHostApiSetup { purgeOutstandingWritesChannel.setMessageHandler(nil) } let databaseReferenceSetChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSet\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -892,7 +926,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -901,7 +935,8 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceSetChannel.setMessageHandler(nil) } let databaseReferenceSetWithPriorityChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetWithPriority\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -914,7 +949,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -923,7 +958,8 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceSetWithPriorityChannel.setMessageHandler(nil) } let databaseReferenceUpdateChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceUpdate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -936,7 +972,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -945,7 +981,8 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceUpdateChannel.setMessageHandler(nil) } let databaseReferenceSetPriorityChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceSetPriority\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -958,7 +995,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -967,7 +1004,8 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceSetPriorityChannel.setMessageHandler(nil) } let databaseReferenceRunTransactionChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceRunTransaction\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -980,7 +1018,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -989,7 +1027,8 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceRunTransactionChannel.setMessageHandler(nil) } let databaseReferenceGetTransactionResultChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.databaseReferenceGetTransactionResult\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -999,12 +1038,14 @@ class FirebaseDatabaseHostApiSetup { let appArg = args[0] as! DatabasePigeonFirebaseApp let transactionKeyArg = args[1] as! Int64 api - .databaseReferenceGetTransactionResult(app: appArg, - transactionKey: transactionKeyArg) { result in + .databaseReferenceGetTransactionResult( + app: appArg, + transactionKey: transactionKeyArg + ) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1013,7 +1054,8 @@ class FirebaseDatabaseHostApiSetup { databaseReferenceGetTransactionResultChannel.setMessageHandler(nil) } let onDisconnectSetChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSet\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1026,7 +1068,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1035,7 +1077,8 @@ class FirebaseDatabaseHostApiSetup { onDisconnectSetChannel.setMessageHandler(nil) } let onDisconnectSetWithPriorityChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectSetWithPriority\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1048,7 +1091,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1057,7 +1100,8 @@ class FirebaseDatabaseHostApiSetup { onDisconnectSetWithPriorityChannel.setMessageHandler(nil) } let onDisconnectUpdateChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectUpdate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1070,7 +1114,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1079,7 +1123,8 @@ class FirebaseDatabaseHostApiSetup { onDisconnectUpdateChannel.setMessageHandler(nil) } let onDisconnectCancelChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.onDisconnectCancel\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1092,7 +1137,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1101,7 +1146,8 @@ class FirebaseDatabaseHostApiSetup { onDisconnectCancelChannel.setMessageHandler(nil) } let queryObserveChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryObserve\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1112,9 +1158,9 @@ class FirebaseDatabaseHostApiSetup { let requestArg = args[1] as! QueryRequest api.queryObserve(app: appArg, request: requestArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1123,7 +1169,8 @@ class FirebaseDatabaseHostApiSetup { queryObserveChannel.setMessageHandler(nil) } let queryKeepSyncedChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryKeepSynced\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1136,7 +1183,7 @@ class FirebaseDatabaseHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1145,7 +1192,8 @@ class FirebaseDatabaseHostApiSetup { queryKeepSyncedChannel.setMessageHandler(nil) } let queryGetChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseHostApi.queryGet\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1156,9 +1204,9 @@ class FirebaseDatabaseHostApiSetup { let requestArg = args[1] as! QueryRequest api.queryGet(app: appArg, request: requestArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1171,10 +1219,12 @@ class FirebaseDatabaseHostApiSetup { /// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift. protocol FirebaseDatabaseFlutterApiProtocol { - func callTransactionHandler(transactionKey transactionKeyArg: Int64, - snapshotValue snapshotValueArg: Any?, - completion: @escaping (Result) - -> Void) + func callTransactionHandler( + transactionKey transactionKeyArg: Int64, + snapshotValue snapshotValueArg: Any?, + completion: + @escaping (Result) + -> Void) } class FirebaseDatabaseFlutterApi: FirebaseDatabaseFlutterApiProtocol { @@ -1189,11 +1239,15 @@ class FirebaseDatabaseFlutterApi: FirebaseDatabaseFlutterApiProtocol { FirebaseDatabaseMessagesPigeonCodec.shared } - func callTransactionHandler(transactionKey transactionKeyArg: Int64, - snapshotValue snapshotValueArg: Any?, - completion: @escaping (Result) - -> Void) { - let channelName = "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler\(messageChannelSuffix)" + func callTransactionHandler( + transactionKey transactionKeyArg: Int64, + snapshotValue snapshotValueArg: Any?, + completion: + @escaping (Result) + -> Void + ) { + let channelName = + "dev.flutter.pigeon.firebase_database_platform_interface.FirebaseDatabaseFlutterApi.callTransactionHandler\(messageChannelSuffix)" let channel = FlutterBasicMessageChannel( name: channelName, binaryMessenger: binaryMessenger, @@ -1210,11 +1264,15 @@ class FirebaseDatabaseFlutterApi: FirebaseDatabaseFlutterApiProtocol { let details: String? = nilOrValue(listResponse[2]) completion(.failure(PigeonError(code: code, message: message, details: details))) } else if listResponse[0] == nil { - completion(.failure(PigeonError( - code: "null-error", - message: "Flutter api returned null value for non-null return value.", - details: "" - ))) + completion( + .failure( + PigeonError( + code: "null-error", + message: "Flutter api returned null value for non-null return value.", + details: "" + ) + ) + ) } else { let result = listResponse[0] as! TransactionHandlerResult completion(.success(result)) diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index 84e32568e1ad..f11a445f0fd5 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "12.4.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "12.4.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_database", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-database", targets: ["firebase_database"]), + .library(name: "firebase-database", targets: ["firebase_database"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-rtdb\""), ] - ), + ) ] ) diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt index 57b5fca33169..88c6950b89c7 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.tests import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index a36e759a869d..cf4892d53507 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "0.9.2-2" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "0.9.2-2" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_in_app_messaging", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-in-app-messaging", targets: ["firebase_in_app_messaging"]), + .library(name: "firebase-in-app-messaging", targets: ["firebase_in_app_messaging"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-fiam\""), ] - ), + ) ] ) diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundExecutor.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundExecutor.java index a920109065f6..51f48f0a6f21 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundExecutor.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundExecutor.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; + /** * An background execution abstraction which handles initializing a background isolate running a * callback dispatcher, used to invoke Dart callbacks while backgrounded. @@ -41,6 +42,7 @@ public class FlutterFirebaseMessagingBackgroundExecutor implements MethodCallHan private static final String USER_CALLBACK_HANDLE_KEY = "user_callback_handle"; private final AtomicBoolean isCallbackDispatcherReady = new AtomicBoolean(false); + /** * The {@link MethodChannel} that connects the Android side of this plugin with the background * Dart isolate that was created by this plugin. @@ -180,7 +182,8 @@ public void executeDartCallbackInBackgroundIsolate(Intent intent, final CountDow if (backgroundFlutterEngine == null) { Log.i( TAG, - "A background message could not be handled in Dart as no onBackgroundMessage handler has been registered."); + "A background message could not be handled in Dart as no onBackgroundMessage handler has" + + " been registered."); return; } @@ -190,7 +193,8 @@ public void executeDartCallbackInBackgroundIsolate(Intent intent, final CountDow new Result() { @Override public void success(Object result) { - // If another thread is waiting, then wake that thread when the callback returns a result. + // If another thread is waiting, then wake that thread when the callback returns a + // result. latch.countDown(); } diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java index 6b75fa2ad6e5..b4f3ee877b59 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingBackgroundService.java @@ -122,7 +122,8 @@ protected void onHandleWork(@NonNull final Intent intent) { if (!flutterBackgroundExecutor.isDartBackgroundHandlerRegistered()) { Log.w( TAG, - "A background message could not be handled in Dart as no onBackgroundMessage handler has been registered."); + "A background message could not be handled in Dart as no onBackgroundMessage handler has" + + " been registered."); return; } diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java index 63d1e0dfac0a..868c950899b3 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java @@ -200,6 +200,7 @@ private Task unsubscribeFromTopic(Map arguments) { return taskCompletionSource.getTask(); } + // This API will be removed in a future release. Slated to be removed by June 2024 by Firebase. // https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessaging#send @SuppressWarnings("deprecation") @@ -312,7 +313,8 @@ private Task> getInitialMessage() { FlutterFirebaseMessagingReceiver.notifications.get(messageId); Map notificationMap = null; - // If we can't find a copy of the remote message in memory then check from our persisted store. + // If we can't find a copy of the remote message in memory then check from our persisted + // store. if (remoteMessage == null) { Map messageMap = FlutterFirebaseMessagingStore.getInstance().getFirebaseMessageMap(messageId); @@ -339,7 +341,8 @@ private Task> getInitialMessage() { Map remoteMessageMap = FlutterFirebaseMessagingUtils.remoteMessageToMap(remoteMessage); - // If no notification map is available in the remote message we override with the one we got + // If no notification map is available in the remote message we override with the one we + // got if (remoteMessage.getNotification() == null && notificationMap != null) { remoteMessageMap.put("notification", notificationMap); } @@ -421,12 +424,12 @@ public void onMethodCall(final MethodCall call, @NonNull final Result result) { Task methodCallTask; switch (call.method) { - // This message is sent when the Dart side of this plugin is told to initialize. - // In response, this (native) side of the plugin needs to spin up a background - // Dart isolate by using the given pluginCallbackHandle, and then setup a background - // method channel to communicate with the new background isolate. Once completed, - // this onMethodCall() method will receive messages from both the primary and background - // method channels. + // This message is sent when the Dart side of this plugin is told to initialize. + // In response, this (native) side of the plugin needs to spin up a background + // Dart isolate by using the given pluginCallbackHandle, and then setup a background + // method channel to communicate with the new background isolate. Once completed, + // this onMethodCall() method will receive messages from both the primary and background + // method channels. case "Messaging#startBackgroundIsolate": @SuppressWarnings("unchecked") Map arguments = ((Map) call.arguments); @@ -496,7 +499,8 @@ public void onMethodCall(final MethodCall call, @NonNull final Result result) { break; case "Messaging#requestPermission": if (Build.VERSION.SDK_INT >= 33) { - // Android version >= Android 13 requires user input if notification permission not set/granted + // Android version >= Android 13 requires user input if notification permission not + // set/granted methodCallTask = requestPermissions(); } else { // Android version < Android 13 doesn't require asking for runtime permissions. diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingReceiver.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingReceiver.java index ebaeca9ffe24..f9e10df1bd1c 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingReceiver.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingReceiver.java @@ -31,7 +31,8 @@ public void onReceive(Context context, Intent intent) { if (intent.getExtras() == null) { Log.d( TAG, - "broadcast received but intent contained no extras to process RemoteMessage. Operation cancelled."); + "broadcast received but intent contained no extras to process RemoteMessage. Operation" + + " cancelled."); return; } @@ -59,7 +60,8 @@ public void onReceive(Context context, Intent intent) { Parcel parcel = Parcel.obtain(); remoteMessage.writeToParcel(parcel, 0); - // We write to parcel using RemoteMessage.writeToParcel() to pass entire RemoteMessage as array of bytes + // We write to parcel using RemoteMessage.writeToParcel() to pass entire RemoteMessage as array + // of bytes // Which can be read using RemoteMessage.createFromParcel(parcel) API onBackgroundMessageIntent.putExtra( FlutterFirebaseMessagingUtils.EXTRA_REMOTE_MESSAGE, parcel.marshall()); diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingService.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingService.java index 6f50bd40bcb2..85d557453646 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingService.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingService.java @@ -17,6 +17,7 @@ public void onNewToken(@NonNull String token) { @Override public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { // Added for commenting purposes; - // We don't handle the message here as we already handle it in the receiver and don't want to duplicate. + // We don't handle the message here as we already handle it in the receiver and don't want to + // duplicate. } } diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingStore.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingStore.java index 95573e3b43f0..1dfaf754d023 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingStore.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingStore.java @@ -55,8 +55,10 @@ public void storeFirebaseMessage(RemoteMessage remoteMessage) { setPreferencesStringValue(remoteMessage.getMessageId(), remoteMessageString); // Save new notification id. - // Note that this is using a comma delimited string to preserve ordering. We could use a String Set - // on SharedPreferences but this won't guarantee ordering when we want to remove the oldest added ids. + // Note that this is using a comma delimited string to preserve ordering. We could use a String + // Set + // on SharedPreferences but this won't guarantee ordering when we want to remove the oldest + // added ids. String notifications = getPreferencesStringValue(KEY_NOTIFICATION_IDS, ""); notifications += remoteMessage.getMessageId() + DELIMITER; // append to last diff --git a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/PluginRegistrantException.java b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/PluginRegistrantException.java index 4787b643784c..67d882312c91 100644 --- a/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/PluginRegistrantException.java +++ b/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/PluginRegistrantException.java @@ -8,7 +8,8 @@ class PluginRegistrantException extends RuntimeException { public PluginRegistrantException() { super( - "PluginRegistrantCallback is not set. Did you forget to call " - + "FlutterFirebaseMessagingBackgroundService.setPluginRegistrant? See the documentation for instructions."); + "PluginRegistrantCallback is not set. Did you forget to call" + + " FlutterFirebaseMessagingBackgroundService.setPluginRegistrant? See the" + + " documentation for instructions."); } } diff --git a/packages/firebase_messaging/firebase_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/messaging/example/MainActivity.kt b/packages/firebase_messaging/firebase_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/messaging/example/MainActivity.kt index 2be79f209e91..c5b5e08c88f8 100644 --- a/packages/firebase_messaging/firebase_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/messaging/example/MainActivity.kt +++ b/packages/firebase_messaging/firebase_messaging/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/messaging/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.messaging.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index c9ed36eff14f..edc0ddaa543b 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "16.2.2" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "16.2.2" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_messaging", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-messaging", targets: ["firebase_messaging"]), + .library(name: "firebase-messaging", targets: ["firebase_messaging"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-fcm\""), ] - ), + ) ] ) diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index 0ffc9147fdbe..fb9488cec058 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "16.2.2" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "16.2.2" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_messaging", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-messaging", targets: ["firebase_messaging"]), + .library(name: "firebase-messaging", targets: ["firebase_messaging"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-fcm\""), ] - ), + ) ] ) diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt index 57b5fca33169..88c6950b89c7 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.tests import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/ios/Runner/AppDelegate.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/ios/Runner/AppDelegate.swift index b6363034812b..626664468b89 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/ios/Runner/AppDelegate.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/ios/Runner/AppDelegate.swift @@ -1,5 +1,5 @@ -import UIKit import Flutter +import UIKit @main @objc class AppDelegate: FlutterAppDelegate { diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift index 4231c0422536..65138b30f9ec 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_ml_model_downloader", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-ml-model-downloader", targets: ["firebase_ml_model_downloader"]), + .library(name: "firebase-ml-model-downloader", targets: ["firebase_ml_model_downloader"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/FirebaseModelDownloaderPlugin.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/FirebaseModelDownloaderPlugin.swift index 3d512ac1457a..94cc55407399 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/FirebaseModelDownloaderPlugin.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/FirebaseModelDownloaderPlugin.swift @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseCore +import FirebaseMLModelDownloader + #if canImport(FlutterMacOS) import FlutterMacOS #else import Flutter #endif -import FirebaseCore -import FirebaseMLModelDownloader - #if canImport(firebase_core) import firebase_core #else @@ -85,21 +85,26 @@ public class FirebaseModelDownloaderPlugin: NSObject, FLTFirebasePluginProtocol, var errorDetails = [String: Any?]() errorDetails["code"] = code ?? self.mapErrorCodes(error: error! as NSError) - errorDetails["message"] = message ?? error? + errorDetails["message"] = + message ?? error? .localizedDescription ?? "An unknown error has occurred." - errorDetails["additionalData"] = details ?? - ["code": errorDetails["code"], "message": errorDetails["message"]] + errorDetails["additionalData"] = + details ?? ["code": errorDetails["code"], "message": errorDetails["message"]] if code == "unknown" { NSLog("FLTFirebaseModelDownloader: An error occurred while calling method %@", call.method) } - result(FLTFirebasePlugin.createFlutterError(fromCode: errorDetails["code"] as! String, - message: errorDetails["message"] as! String, - optionalDetails: errorDetails[ - "additionalData" - ] as? [AnyHashable: Any], - andOptionalNSError: nil)) + result( + FLTFirebasePlugin.createFlutterError( + fromCode: errorDetails["code"] as! String, + message: errorDetails["message"] as! String, + optionalDetails: errorDetails[ + "additionalData" + ] as? [AnyHashable: Any], + andOptionalNSError: nil + ) + ) } let result = FLTFirebaseMethodCallResult.create(success: result, andErrorBlock: errorBlock) @@ -114,13 +119,15 @@ public class FirebaseModelDownloaderPlugin: NSObject, FLTFirebasePluginProtocol, } } - func listDownloadedModels(arguments: [String: Any], - result: FLTFirebaseMethodCallResult) { + func listDownloadedModels( + arguments: [String: Any], + result: FLTFirebaseMethodCallResult + ) { let modelDownloader = modelDownloaderFromArguments(arguments: arguments) modelDownloader?.listDownloadedModels { response in switch response { - case let .success(customModel): + case .success(let customModel): let responseList: [[String: Any]] = customModel.map { [ "filePath": $0.path, @@ -130,7 +137,7 @@ public class FirebaseModelDownloaderPlugin: NSObject, FLTFirebasePluginProtocol, ] } result.success(responseList) - case let .failure(error): + case .failure(let error): result.error(nil, nil, nil, error) } } @@ -160,21 +167,23 @@ public class FirebaseModelDownloaderPlugin: NSObject, FLTFirebasePluginProtocol, conditions: modelDownloadConditions ) { response in switch response { - case let .success(customModel): + case .success(let customModel): result.success([ "filePath": customModel.path, "size": customModel.size, "hash": customModel.hash, "name": customModel.name, ]) - case let .failure(error): + case .failure(let error): result.error(nil, nil, nil, error) } } } - func deleteDownloadedModel(arguments: [String: Any], - result: FLTFirebaseMethodCallResult) { + func deleteDownloadedModel( + arguments: [String: Any], + result: FLTFirebaseMethodCallResult + ) { let modelDownloader = modelDownloaderFromArguments(arguments: arguments) let modelName = arguments["modelName"] @@ -182,7 +191,7 @@ public class FirebaseModelDownloaderPlugin: NSObject, FLTFirebasePluginProtocol, switch response { case .success(): result.success(nil) - case let .failure(error): + case .failure(let error): result.error(nil, nil, nil, error) } } diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift index 2780cfb8ccbf..d59fe67468f2 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_ml_model_downloader", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-ml-model-downloader", targets: ["firebase_ml_model_downloader"]), + .library(name: "firebase-ml-model-downloader", targets: ["firebase_ml_model_downloader"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebaseAppRegistrar.kt b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebaseAppRegistrar.kt index c4f81db754bb..e6695bbc968f 100644 --- a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebaseAppRegistrar.kt +++ b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebaseAppRegistrar.kt @@ -12,7 +12,6 @@ import com.google.firebase.platforminfo.LibraryVersionComponent class FlutterFirebaseAppRegistrar : ComponentRegistrar { override fun getComponents(): List> { return listOf( - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION) - ) + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION)) } } diff --git a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebasePerformancePlugin.kt b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebasePerformancePlugin.kt index dfc913d0700e..4353a5fa833f 100644 --- a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebasePerformancePlugin.kt +++ b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/FlutterFirebasePerformancePlugin.kt @@ -18,18 +18,14 @@ import io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry /** * Flutter plugin accessing Firebase Performance API. * - * * Instantiate this in an add to app scenario to gracefully handle activity and context changes. */ -class FlutterFirebasePerformancePlugin - : FlutterFirebasePlugin, FlutterPlugin, FirebasePerformanceHostApi { +class FlutterFirebasePerformancePlugin : + FlutterFirebasePlugin, FlutterPlugin, FirebasePerformanceHostApi { private var binaryMessenger: BinaryMessenger? = null private fun initInstance(messenger: BinaryMessenger) { - FlutterFirebasePluginRegistry.registerPlugin( - METHOD_CHANNEL_NAME, - this - ) + FlutterFirebasePluginRegistry.registerPlugin(METHOD_CHANNEL_NAME, this) binaryMessenger = messenger FirebasePerformanceHostApi.setUp(messenger, this) } @@ -79,7 +75,11 @@ class FlutterFirebasePerformancePlugin } } - override fun stopTrace(handle: Long, attributes: TraceAttributes, callback: (Result) -> Unit) { + override fun stopTrace( + handle: Long, + attributes: TraceAttributes, + callback: (Result) -> Unit + ) { FlutterFirebasePlugin.cachedThreadPool.execute { try { val trace = _traces[handle.toInt()] @@ -88,13 +88,9 @@ class FlutterFirebasePerformancePlugin return@execute } - attributes.attributes?.forEach { (key, value) -> - trace.putAttribute(key, value) - } + attributes.attributes?.forEach { (key, value) -> trace.putAttribute(key, value) } - attributes.metrics?.forEach { (key, value) -> - trace.putMetric(key, value) - } + attributes.metrics?.forEach { (key, value) -> trace.putMetric(key, value) } trace.stop() _traces.remove(handle.toInt()) @@ -109,10 +105,7 @@ class FlutterFirebasePerformancePlugin FlutterFirebasePlugin.cachedThreadPool.execute { try { val httpMethod = parseHttpMethod(options.httpMethod) - val httpMetric = FirebasePerformance.getInstance().newHttpMetric( - options.url, - httpMethod - ) + val httpMetric = FirebasePerformance.getInstance().newHttpMetric(options.url, httpMethod) httpMetric.start() val httpMetricHandle = _httpMetricHandle++ _httpMetrics[httpMetricHandle] = httpMetric @@ -123,7 +116,11 @@ class FlutterFirebasePerformancePlugin } } - override fun stopHttpMetric(handle: Long, attributes: HttpMetricAttributes, callback: (Result) -> Unit) { + override fun stopHttpMetric( + handle: Long, + attributes: HttpMetricAttributes, + callback: (Result) -> Unit + ) { FlutterFirebasePlugin.cachedThreadPool.execute { try { val httpMetric = _httpMetrics[handle.toInt()] @@ -137,9 +134,7 @@ class FlutterFirebasePerformancePlugin attributes.responseContentType?.let { httpMetric.setResponseContentType(it) } attributes.responsePayloadSize?.let { httpMetric.setResponsePayloadSize(it) } - attributes.attributes?.forEach { (key, value) -> - httpMetric.putAttribute(key, value) - } + attributes.attributes?.forEach { (key, value) -> httpMetric.putAttribute(key, value) } httpMetric.stop() _httpMetrics.remove(handle.toInt()) @@ -150,9 +145,8 @@ class FlutterFirebasePerformancePlugin } } - private fun handleFailure (callback: (Result) -> Unit, exception: Exception?) { - val message = - if (exception != null) exception.message else "An unknown error occurred" + private fun handleFailure(callback: (Result) -> Unit, exception: Exception?) { + val message = if (exception != null) exception.message else "An unknown error occurred" callback(Result.failure(FlutterError("firebase_performance", message, null))) } diff --git a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt index 666c2379ab10..ce9d86e85190 100644 --- a/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt +++ b/packages/firebase_performance/firebase_performance/android/src/main/kotlin/io/flutter/plugins/firebase/performance/GeneratedAndroidFirebasePerformance.g.kt @@ -10,12 +10,11 @@ package io.flutter.plugins.firebase.performance import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object GeneratedAndroidFirebasePerformancePigeonUtils { fun wrapResult(result: Any?): List { @@ -24,19 +23,15 @@ private object GeneratedAndroidFirebasePerformancePigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } + fun doubleEquals(a: Double, b: Double): Boolean { // Normalize -0.0 to 0.0 and handle NaN equality. return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) @@ -180,19 +175,19 @@ private object GeneratedAndroidFirebasePerformancePigeonUtils { else -> value.hashCode() } } - } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : RuntimeException() enum class HttpMethod(val raw: Int) { @@ -214,11 +209,7 @@ enum class HttpMethod(val raw: Int) { } /** Generated class from Pigeon that represents data sent in messages. */ -data class HttpMetricOptions ( - val url: String, - val httpMethod: HttpMethod -) - { +data class HttpMetricOptions(val url: String, val httpMethod: HttpMethod) { companion object { fun fromList(pigeonVar_list: List): HttpMetricOptions { val url = pigeonVar_list[0] as String @@ -226,12 +217,14 @@ data class HttpMetricOptions ( return HttpMetricOptions(url, httpMethod) } } + fun toList(): List { return listOf( - url, - httpMethod, + url, + httpMethod, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -240,7 +233,8 @@ data class HttpMetricOptions ( return true } val other = other as HttpMetricOptions - return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.url, other.url) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.httpMethod, other.httpMethod) + return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.url, other.url) && + GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.httpMethod, other.httpMethod) } override fun hashCode(): Int { @@ -252,14 +246,13 @@ data class HttpMetricOptions ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class HttpMetricAttributes ( - val httpResponseCode: Long? = null, - val requestPayloadSize: Long? = null, - val responsePayloadSize: Long? = null, - val responseContentType: String? = null, - val attributes: Map? = null -) - { +data class HttpMetricAttributes( + val httpResponseCode: Long? = null, + val requestPayloadSize: Long? = null, + val responsePayloadSize: Long? = null, + val responseContentType: String? = null, + val attributes: Map? = null +) { companion object { fun fromList(pigeonVar_list: List): HttpMetricAttributes { val httpResponseCode = pigeonVar_list[0] as Long? @@ -267,18 +260,25 @@ data class HttpMetricAttributes ( val responsePayloadSize = pigeonVar_list[2] as Long? val responseContentType = pigeonVar_list[3] as String? val attributes = pigeonVar_list[4] as Map? - return HttpMetricAttributes(httpResponseCode, requestPayloadSize, responsePayloadSize, responseContentType, attributes) + return HttpMetricAttributes( + httpResponseCode, + requestPayloadSize, + responsePayloadSize, + responseContentType, + attributes) } } + fun toList(): List { return listOf( - httpResponseCode, - requestPayloadSize, - responsePayloadSize, - responseContentType, - attributes, + httpResponseCode, + requestPayloadSize, + responsePayloadSize, + responseContentType, + attributes, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -287,26 +287,40 @@ data class HttpMetricAttributes ( return true } val other = other as HttpMetricAttributes - return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.httpResponseCode, other.httpResponseCode) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.requestPayloadSize, other.requestPayloadSize) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.responsePayloadSize, other.responsePayloadSize) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.responseContentType, other.responseContentType) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.attributes, other.attributes) + return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals( + this.httpResponseCode, other.httpResponseCode) && + GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals( + this.requestPayloadSize, other.requestPayloadSize) && + GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals( + this.responsePayloadSize, other.responsePayloadSize) && + GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals( + this.responseContentType, other.responseContentType) && + GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.attributes, other.attributes) } override fun hashCode(): Int { var result = javaClass.hashCode() - result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.httpResponseCode) - result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.requestPayloadSize) - result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.responsePayloadSize) - result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.responseContentType) + result = + 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.httpResponseCode) + result = + 31 * result + + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.requestPayloadSize) + result = + 31 * result + + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.responsePayloadSize) + result = + 31 * result + + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.responseContentType) result = 31 * result + GeneratedAndroidFirebasePerformancePigeonUtils.deepHash(this.attributes) return result } } /** Generated class from Pigeon that represents data sent in messages. */ -data class TraceAttributes ( - val metrics: Map? = null, - val attributes: Map? = null -) - { +data class TraceAttributes( + val metrics: Map? = null, + val attributes: Map? = null +) { companion object { fun fromList(pigeonVar_list: List): TraceAttributes { val metrics = pigeonVar_list[0] as Map? @@ -314,12 +328,14 @@ data class TraceAttributes ( return TraceAttributes(metrics, attributes) } } + fun toList(): List { return listOf( - metrics, - attributes, + metrics, + attributes, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -328,7 +344,8 @@ data class TraceAttributes ( return true } val other = other as TraceAttributes - return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.metrics, other.metrics) && GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.attributes, other.attributes) + return GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.metrics, other.metrics) && + GeneratedAndroidFirebasePerformancePigeonUtils.deepEquals(this.attributes, other.attributes) } override fun hashCode(): Int { @@ -338,33 +355,27 @@ data class TraceAttributes ( return result } } + private open class GeneratedAndroidFirebasePerformancePigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 129.toByte() -> { - return (readValue(buffer) as Long?)?.let { - HttpMethod.ofRaw(it.toInt()) - } + return (readValue(buffer) as Long?)?.let { HttpMethod.ofRaw(it.toInt()) } } 130.toByte() -> { - return (readValue(buffer) as? List)?.let { - HttpMetricOptions.fromList(it) - } + return (readValue(buffer) as? List)?.let { HttpMetricOptions.fromList(it) } } 131.toByte() -> { - return (readValue(buffer) as? List)?.let { - HttpMetricAttributes.fromList(it) - } + return (readValue(buffer) as? List)?.let { HttpMetricAttributes.fromList(it) } } 132.toByte() -> { - return (readValue(buffer) as? List)?.let { - TraceAttributes.fromList(it) - } + return (readValue(buffer) as? List)?.let { TraceAttributes.fromList(it) } } else -> super.readValueOfType(type, buffer) } } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { when (value) { is HttpMethod -> { stream.write(129) @@ -387,27 +398,45 @@ private open class GeneratedAndroidFirebasePerformancePigeonCodec : StandardMess } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebasePerformanceHostApi { fun setPerformanceCollectionEnabled(enabled: Boolean, callback: (Result) -> Unit) + fun isPerformanceCollectionEnabled(callback: (Result) -> Unit) + fun startTrace(name: String, callback: (Result) -> Unit) + fun stopTrace(handle: Long, attributes: TraceAttributes, callback: (Result) -> Unit) + fun startHttpMetric(options: HttpMetricOptions, callback: (Result) -> Unit) - fun stopHttpMetric(handle: Long, attributes: HttpMetricAttributes, callback: (Result) -> Unit) + + fun stopHttpMetric( + handle: Long, + attributes: HttpMetricAttributes, + callback: (Result) -> Unit + ) companion object { /** The codec used by FirebasePerformanceHostApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidFirebasePerformancePigeonCodec() - } - /** Sets up an instance of `FirebasePerformanceHostApi` to handle messages through the `binaryMessenger`. */ + val codec: MessageCodec by lazy { GeneratedAndroidFirebasePerformancePigeonCodec() } + /** + * Sets up an instance of `FirebasePerformanceHostApi` to handle messages through the + * `binaryMessenger`. + */ @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: FirebasePerformanceHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp( + binaryMessenger: BinaryMessenger, + api: FirebasePerformanceHostApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -426,10 +455,14 @@ interface FirebasePerformanceHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.isPerformanceCollectionEnabled$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.isPerformanceCollectionEnabled$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { _, reply -> - api.isPerformanceCollectionEnabled{ result: Result -> + api.isPerformanceCollectionEnabled { result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebasePerformancePigeonUtils.wrapError(error)) @@ -444,7 +477,11 @@ interface FirebasePerformanceHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -464,7 +501,11 @@ interface FirebasePerformanceHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -484,7 +525,11 @@ interface FirebasePerformanceHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -504,7 +549,11 @@ interface FirebasePerformanceHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List diff --git a/packages/firebase_performance/firebase_performance/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt b/packages/firebase_performance/firebase_performance/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt index 57b5fca33169..88c6950b89c7 100644 --- a/packages/firebase_performance/firebase_performance/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt +++ b/packages/firebase_performance/firebase_performance/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/tests/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.tests import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index ed7ec080a700..3fcf255d9868 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "0.11.4-1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "0.11.4-1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_performance", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-performance", targets: ["firebase_performance"]), + .library(name: "firebase-performance", targets: ["firebase_performance"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-perf\""), ] - ), + ) ] ) diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift index 47f32896fcb5..d0bf9252d08f 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformanceMessages.g.swift @@ -89,7 +89,7 @@ func deepEqualsFirebasePerformanceMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: return true case is (Void, Void): @@ -131,7 +131,7 @@ func deepEqualsFirebasePerformanceMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { } return true - case let (lhs as Double, rhs as Double): + case (let lhs as Double, let rhs as Double): return doubleEqualsFirebasePerformanceMessages(lhs, rhs) case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): @@ -214,8 +214,8 @@ struct HttpMetricOptions: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebasePerformanceMessages(lhs.url, rhs.url) && - deepEqualsFirebasePerformanceMessages( + return deepEqualsFirebasePerformanceMessages(lhs.url, rhs.url) + && deepEqualsFirebasePerformanceMessages( lhs.httpMethod, rhs.httpMethod ) @@ -267,15 +267,16 @@ struct HttpMetricAttributes: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebasePerformanceMessages(lhs.httpResponseCode, rhs.httpResponseCode) && - deepEqualsFirebasePerformanceMessages( + return deepEqualsFirebasePerformanceMessages(lhs.httpResponseCode, rhs.httpResponseCode) + && deepEqualsFirebasePerformanceMessages( lhs.requestPayloadSize, rhs.requestPayloadSize - ) && deepEqualsFirebasePerformanceMessages( + ) + && deepEqualsFirebasePerformanceMessages( lhs.responsePayloadSize, rhs.responsePayloadSize - ) && - deepEqualsFirebasePerformanceMessages( + ) + && deepEqualsFirebasePerformanceMessages( lhs.responseContentType, rhs.responseContentType ) && deepEqualsFirebasePerformanceMessages(lhs.attributes, rhs.attributes) @@ -318,8 +319,8 @@ struct TraceAttributes: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebasePerformanceMessages(lhs.metrics, rhs.metrics) && - deepEqualsFirebasePerformanceMessages( + return deepEqualsFirebasePerformanceMessages(lhs.metrics, rhs.metrics) + && deepEqualsFirebasePerformanceMessages( lhs.attributes, rhs.attributes ) @@ -392,16 +393,20 @@ class FirebasePerformanceMessagesPigeonCodec: FlutterStandardMessageCodec, @unch /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebasePerformanceHostApi { - func setPerformanceCollectionEnabled(enabled: Bool, - completion: @escaping (Result) -> Void) + func setPerformanceCollectionEnabled( + enabled: Bool, + completion: @escaping (Result) -> Void) func isPerformanceCollectionEnabled(completion: @escaping (Result) -> Void) func startTrace(name: String, completion: @escaping (Result) -> Void) - func stopTrace(handle: Int64, attributes: TraceAttributes, - completion: @escaping (Result) -> Void) - func startHttpMetric(options: HttpMetricOptions, - completion: @escaping (Result) -> Void) - func stopHttpMetric(handle: Int64, attributes: HttpMetricAttributes, - completion: @escaping (Result) -> Void) + func stopTrace( + handle: Int64, attributes: TraceAttributes, + completion: @escaping (Result) -> Void) + func startHttpMetric( + options: HttpMetricOptions, + completion: @escaping (Result) -> Void) + func stopHttpMetric( + handle: Int64, attributes: HttpMetricAttributes, + completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -412,11 +417,14 @@ class FirebasePerformanceHostApiSetup { /// Sets up an instance of `FirebasePerformanceHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebasePerformanceHostApi?, - messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: FirebasePerformanceHostApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let setPerformanceCollectionEnabledChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.setPerformanceCollectionEnabled\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -428,7 +436,7 @@ class FirebasePerformanceHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -437,7 +445,8 @@ class FirebasePerformanceHostApiSetup { setPerformanceCollectionEnabledChannel.setMessageHandler(nil) } let isPerformanceCollectionEnabledChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.isPerformanceCollectionEnabled\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.isPerformanceCollectionEnabled\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -445,9 +454,9 @@ class FirebasePerformanceHostApiSetup { isPerformanceCollectionEnabledChannel.setMessageHandler { _, reply in api.isPerformanceCollectionEnabled { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -456,7 +465,8 @@ class FirebasePerformanceHostApiSetup { isPerformanceCollectionEnabledChannel.setMessageHandler(nil) } let startTraceChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startTrace\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -466,9 +476,9 @@ class FirebasePerformanceHostApiSetup { let nameArg = args[0] as! String api.startTrace(name: nameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -477,7 +487,8 @@ class FirebasePerformanceHostApiSetup { startTraceChannel.setMessageHandler(nil) } let stopTraceChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopTrace\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -490,7 +501,7 @@ class FirebasePerformanceHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -499,7 +510,8 @@ class FirebasePerformanceHostApiSetup { stopTraceChannel.setMessageHandler(nil) } let startHttpMetricChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.startHttpMetric\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -509,9 +521,9 @@ class FirebasePerformanceHostApiSetup { let optionsArg = args[0] as! HttpMetricOptions api.startHttpMetric(options: optionsArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -520,7 +532,8 @@ class FirebasePerformanceHostApiSetup { startHttpMetricChannel.setMessageHandler(nil) } let stopHttpMetricChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_performance_platform_interface.FirebasePerformanceHostApi.stopHttpMetric\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -533,7 +546,7 @@ class FirebasePerformanceHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformancePlugin.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformancePlugin.swift index 6d0ac5c39979..3c7d8f50b620 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformancePlugin.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Sources/firebase_performance/FirebasePerformancePlugin.swift @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebasePerformance + #if canImport(FlutterMacOS) import FlutterMacOS #else @@ -13,14 +15,15 @@ #else import firebase_core_shared #endif -import FirebasePerformance +// swift-format-ignore: AlwaysUseLowerCamelCase let FirebasePerformanceChannelName = "plugins.flutter.io/firebase_performance" extension FlutterError: Error {} public class FirebasePerformancePlugin: NSObject, FlutterPlugin, FLTFirebasePluginProtocol, - FirebasePerformanceHostApi { + FirebasePerformanceHostApi +{ public func didReinitializeFirebaseCore(_ completion: @escaping () -> Void) { completion() } @@ -58,8 +61,10 @@ public class FirebasePerformancePlugin: NSObject, FlutterPlugin, FLTFirebasePlug FirebasePerformanceHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: instance) } - public func setPerformanceCollectionEnabled(enabled: Bool, - completion: @escaping (Result) -> Void) { + public func setPerformanceCollectionEnabled( + enabled: Bool, + completion: @escaping (Result) -> Void + ) { Performance.sharedInstance().isDataCollectionEnabled = enabled completion(.success(())) } @@ -77,8 +82,10 @@ public class FirebasePerformancePlugin: NSObject, FlutterPlugin, FLTFirebasePlug completion(.success(Int64(traceHandle))) } - func stopTrace(handle: Int64, attributes: TraceAttributes, - completion: @escaping (Result) -> Void) { + func stopTrace( + handle: Int64, attributes: TraceAttributes, + completion: @escaping (Result) -> Void + ) { guard let trace = traces[Int(handle)] else { completion(.success(())) return @@ -101,19 +108,25 @@ public class FirebasePerformancePlugin: NSObject, FlutterPlugin, FLTFirebasePlug completion(.success(())) } - func startHttpMetric(options: HttpMetricOptions, - completion: @escaping (Result) -> Void) { + func startHttpMetric( + options: HttpMetricOptions, + completion: @escaping (Result) -> Void + ) { guard let url = URL(string: options.url) else { completion(.failure(FlutterError(code: "invalid-url", message: "Invalid url", details: nil))) return } guard let httpMethod = parseHttpMethod(options.httpMethod) else { - completion(.failure(FlutterError( - code: "invalid-argument", - message: "Invalid httpMethod", - details: nil - ))) + completion( + .failure( + FlutterError( + code: "invalid-argument", + message: "Invalid httpMethod", + details: nil + ) + ) + ) return } @@ -124,8 +137,10 @@ public class FirebasePerformancePlugin: NSObject, FlutterPlugin, FLTFirebasePlug completion(.success(Int64(httpMetricHandle))) } - func stopHttpMetric(handle: Int64, attributes: HttpMetricAttributes, - completion: @escaping (Result) -> Void) { + func stopHttpMetric( + handle: Int64, attributes: HttpMetricAttributes, + completion: @escaping (Result) -> Void + ) { guard let httpMetric = httpMetrics[Int(handle)] else { completion(.success(())) return diff --git a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FirebaseRemoteConfigPlugin.kt b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FirebaseRemoteConfigPlugin.kt index 2700a45258cb..e1a3917abda3 100644 --- a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FirebaseRemoteConfigPlugin.kt +++ b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FirebaseRemoteConfigPlugin.kt @@ -20,7 +20,6 @@ import com.google.firebase.remoteconfig.FirebaseRemoteConfigFetchThrottledExcept import com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue -import io.flutter.Log import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.BinaryMessenger @@ -30,11 +29,9 @@ import io.flutter.plugins.firebase.core.FlutterFirebasePlugin import io.flutter.plugins.firebase.core.FlutterFirebasePluginRegistry import java.util.Objects -/** FirebaseRemoteConfigPlugin */ -class FirebaseRemoteConfigPlugin - - : FlutterFirebasePlugin, FlutterPlugin, - EventChannel.StreamHandler, FirebaseRemoteConfigHostApi { +/** FirebaseRemoteConfigPlugin */ +class FirebaseRemoteConfigPlugin : + FlutterFirebasePlugin, FlutterPlugin, EventChannel.StreamHandler, FirebaseRemoteConfigHostApi { private val listenersMap: MutableMap = HashMap() private var eventChannel: EventChannel? = null @@ -56,8 +53,7 @@ class FirebaseRemoteConfigPlugin try { val remoteConfig = FirebaseRemoteConfig.getInstance(firebaseApp) val configProperties = getConfigProperties(remoteConfig) - val configValues: MutableMap = - HashMap(configProperties) + val configValues: MutableMap = HashMap(configProperties) configValues["parameters"] = parseParameters(remoteConfig.all) taskCompletionSource.setResult(configValues) @@ -73,7 +69,7 @@ class FirebaseRemoteConfigPlugin val configProperties: MutableMap = HashMap() configProperties["fetchTimeout"] = remoteConfig.info.configSettings.fetchTimeoutInSeconds configProperties["minimumFetchInterval"] = - remoteConfig.info.configSettings.minimumFetchIntervalInSeconds + remoteConfig.info.configSettings.minimumFetchIntervalInSeconds configProperties["lastFetchTime"] = remoteConfig.info.fetchTimeMillis configProperties["lastFetchStatus"] = mapLastFetchStatus(remoteConfig.info.lastFetchStatus) return configProperties @@ -96,10 +92,7 @@ class FirebaseRemoteConfigPlugin private fun setupChannel(messenger: BinaryMessenger) { FirebaseRemoteConfigHostApi.setUp(messenger, this) - FlutterFirebasePluginRegistry.registerPlugin( - METHOD_CHANNEL, - this - ) + FlutterFirebasePluginRegistry.registerPlugin(METHOD_CHANNEL, this) eventChannel = EventChannel(messenger, EVENT_CHANNEL) eventChannel!!.setStreamHandler(this) @@ -122,7 +115,8 @@ class FirebaseRemoteConfigPlugin } private fun setCustomSignals( - remoteConfig: FirebaseRemoteConfig, customSignalsArguments: Map + remoteConfig: FirebaseRemoteConfig, + customSignalsArguments: Map ): Task { val taskCompletionSource = TaskCompletionSource() FlutterFirebasePlugin.cachedThreadPool.execute { @@ -150,18 +144,18 @@ class FirebaseRemoteConfigPlugin return taskCompletionSource.task } - private fun parseParameters(parameters: Map): Map { + private fun parseParameters( + parameters: Map + ): Map { val parsedParameters: MutableMap = HashMap() for (key in parameters.keys) { - parsedParameters[key] = createRemoteConfigValueMap( - parameters[key]!! - ) + parsedParameters[key] = createRemoteConfigValueMap(parameters[key]!!) } return parsedParameters } private fun createRemoteConfigValueMap( - remoteConfigValue: FirebaseRemoteConfigValue + remoteConfigValue: FirebaseRemoteConfigValue ): Map { val valueMap: MutableMap = HashMap() valueMap["value"] = remoteConfigValue.asByteArray() @@ -193,23 +187,24 @@ class FirebaseRemoteConfigPlugin val appName = Objects.requireNonNull(argumentsMap["appName"]) as String val remoteConfig = getRemoteConfig(appName) - listenersMap[appName] = remoteConfig.addOnConfigUpdateListener( - object : ConfigUpdateListener { - override fun onUpdate(configUpdate: ConfigUpdate) { - val updatedKeys = ArrayList(configUpdate.updatedKeys) - mainThreadHandler.post { events.success(updatedKeys) } - } - - override fun onError(error: FirebaseRemoteConfigException) { - events.error("firebase_remote_config", error.message, null) - } - }) + listenersMap[appName] = + remoteConfig.addOnConfigUpdateListener( + object : ConfigUpdateListener { + override fun onUpdate(configUpdate: ConfigUpdate) { + val updatedKeys = ArrayList(configUpdate.updatedKeys) + mainThreadHandler.post { events.success(updatedKeys) } + } + + override fun onError(error: FirebaseRemoteConfigException) { + events.error("firebase_remote_config", error.message, null) + } + }) } override fun onCancel(arguments: Any?) { - // arguments will be null on hot restart, so we will clean up listeners in didReinitializeFirebaseCore() - val argumentsMap = arguments as? Map - ?: return + // arguments will be null on hot restart, so we will clean up listeners in + // didReinitializeFirebaseCore() + val argumentsMap = arguments as? Map ?: return val appName = Objects.requireNonNull(argumentsMap["appName"]) as String val listener = listenersMap[appName] @@ -219,7 +214,7 @@ class FirebaseRemoteConfigPlugin } } - /** Remove all registered listeners. */ + /** Remove all registered listeners. */ private fun removeEventListeners() { for (listener in listenersMap.values) { listener.remove() @@ -227,9 +222,8 @@ class FirebaseRemoteConfigPlugin listenersMap.clear() } - private fun handleFailure (callback: (Result) -> Unit, exception: Exception?) { - val details: MutableMap = - HashMap() + private fun handleFailure(callback: (Result) -> Unit, exception: Exception?) { + val details: MutableMap = HashMap() if (exception is FirebaseRemoteConfigFetchThrottledException) { details["code"] = "throttled" details["message"] = "frequency of requests exceeds throttled limits" @@ -252,9 +246,7 @@ class FirebaseRemoteConfigPlugin details["code"] = "unknown" details["message"] = "unknown remote config error" } - callback(Result.failure(FlutterError( "firebase_remote_config", - exception?.message, - details))) + callback(Result.failure(FlutterError("firebase_remote_config", exception?.message, details))) } companion object { @@ -265,10 +257,9 @@ class FirebaseRemoteConfigPlugin override fun fetch(appName: String, callback: (Result) -> Unit) { getRemoteConfig(appName).fetch().addOnCompleteListener { task -> - if(task.isSuccessful){ + if (task.isSuccessful) { callback(Result.success(Unit)) - } - else { + } else { handleFailure(callback, task.exception) } } @@ -276,10 +267,9 @@ class FirebaseRemoteConfigPlugin override fun fetchAndActivate(appName: String, callback: (Result) -> Unit) { getRemoteConfig(appName).fetchAndActivate().addOnCompleteListener { task -> - if(task.isSuccessful){ + if (task.isSuccessful) { callback(Result.success(task.result)) - } - else { + } else { handleFailure(callback, task.exception) } } @@ -287,43 +277,42 @@ class FirebaseRemoteConfigPlugin override fun activate(appName: String, callback: (Result) -> Unit) { getRemoteConfig(appName).activate().addOnCompleteListener { task -> - if(task.isSuccessful){ + if (task.isSuccessful) { callback(Result.success(task.result)) - } - else { + } else { handleFailure(callback, task.exception) } } } override fun setConfigSettings( - appName: String, - settings: RemoteConfigPigeonSettings, - callback: (Result) -> Unit + appName: String, + settings: RemoteConfigPigeonSettings, + callback: (Result) -> Unit ) { val configSettings = - FirebaseRemoteConfigSettings.Builder() - .setFetchTimeoutInSeconds(settings.fetchTimeoutSeconds) - .setMinimumFetchIntervalInSeconds(settings.minimumFetchIntervalSeconds) - .build() + FirebaseRemoteConfigSettings.Builder() + .setFetchTimeoutInSeconds(settings.fetchTimeoutSeconds) + .setMinimumFetchIntervalInSeconds(settings.minimumFetchIntervalSeconds) + .build() getRemoteConfig(appName).setConfigSettingsAsync(configSettings).addOnCompleteListener { task -> - if(task.isSuccessful){ + if (task.isSuccessful) { callback(Result.success(Unit)) - } - else { + } else { handleFailure(callback, task.exception) } } } - override fun setDefaults(appName: String, defaultParameters: Map, callback: (Result) -> Unit) { - getRemoteConfig( - appName - ).setDefaultsAsync(defaultParameters).addOnCompleteListener { task -> - if(task.isSuccessful){ + override fun setDefaults( + appName: String, + defaultParameters: Map, + callback: (Result) -> Unit + ) { + getRemoteConfig(appName).setDefaultsAsync(defaultParameters).addOnCompleteListener { task -> + if (task.isSuccessful) { callback(Result.success(Unit)) - } - else { + } else { handleFailure(callback, task.exception) } } @@ -331,22 +320,24 @@ class FirebaseRemoteConfigPlugin override fun ensureInitialized(appName: String, callback: (Result) -> Unit) { getRemoteConfig(appName).ensureInitialized().addOnCompleteListener { task -> - if(task.isSuccessful){ + if (task.isSuccessful) { callback(Result.success(Unit)) - } - else { + } else { handleFailure(callback, task.exception) } } } - override fun setCustomSignals(appName: String, customSignals: Map, callback: (Result) -> Unit) { + override fun setCustomSignals( + appName: String, + customSignals: Map, + callback: (Result) -> Unit + ) { val remoteConfig = getRemoteConfig(appName) - setCustomSignals(remoteConfig, customSignals).addOnCompleteListener {task-> - if(task.isSuccessful){ + setCustomSignals(remoteConfig, customSignals).addOnCompleteListener { task -> + if (task.isSuccessful) { callback(Result.success(Unit)) - } - else { + } else { handleFailure(callback, task.exception) } } @@ -357,10 +348,7 @@ class FirebaseRemoteConfigPlugin callback(Result.success(parseParameters(remoteConfig.all))) } - override fun getProperties( - appName: String, - callback: (Result>) -> Unit - ) { + override fun getProperties(appName: String, callback: (Result>) -> Unit) { val remoteConfig = getRemoteConfig(appName) val configProperties = getConfigProperties(remoteConfig) callback(Result.success(configProperties)) diff --git a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FlutterFirebaseAppRegistrar.kt b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FlutterFirebaseAppRegistrar.kt index d758db99adda..e343fc60d5d1 100644 --- a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FlutterFirebaseAppRegistrar.kt +++ b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/FlutterFirebaseAppRegistrar.kt @@ -12,7 +12,6 @@ import com.google.firebase.platforminfo.LibraryVersionComponent class FlutterFirebaseAppRegistrar : ComponentRegistrar { override fun getComponents(): List> { return listOf( - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION) - ) + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION)) } } diff --git a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt index 4a3d096eafdc..840d3090a3bc 100644 --- a/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt +++ b/packages/firebase_remote_config/firebase_remote_config/android/src/main/kotlin/io/flutter/plugins/firebase/firebaseremoteconfig/GeneratedAndroidFirebaseRemoteConfig.g.kt @@ -10,12 +10,11 @@ package io.flutter.plugins.firebase.firebaseremoteconfig import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object GeneratedAndroidFirebaseRemoteConfigPigeonUtils { fun wrapResult(result: Any?): List { @@ -24,19 +23,15 @@ private object GeneratedAndroidFirebaseRemoteConfigPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } + fun doubleEquals(a: Double, b: Double): Boolean { // Normalize -0.0 to 0.0 and handle NaN equality. return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) @@ -180,27 +175,26 @@ private object GeneratedAndroidFirebaseRemoteConfigPigeonUtils { else -> value.hashCode() } } - } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : RuntimeException() /** Generated class from Pigeon that represents data sent in messages. */ -data class RemoteConfigPigeonSettings ( - val fetchTimeoutSeconds: Long, - val minimumFetchIntervalSeconds: Long -) - { +data class RemoteConfigPigeonSettings( + val fetchTimeoutSeconds: Long, + val minimumFetchIntervalSeconds: Long +) { companion object { fun fromList(pigeonVar_list: List): RemoteConfigPigeonSettings { val fetchTimeoutSeconds = pigeonVar_list[0] as Long @@ -208,12 +202,14 @@ data class RemoteConfigPigeonSettings ( return RemoteConfigPigeonSettings(fetchTimeoutSeconds, minimumFetchIntervalSeconds) } } + fun toList(): List { return listOf( - fetchTimeoutSeconds, - minimumFetchIntervalSeconds, + fetchTimeoutSeconds, + minimumFetchIntervalSeconds, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -222,28 +218,36 @@ data class RemoteConfigPigeonSettings ( return true } val other = other as RemoteConfigPigeonSettings - return GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepEquals(this.fetchTimeoutSeconds, other.fetchTimeoutSeconds) && GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepEquals(this.minimumFetchIntervalSeconds, other.minimumFetchIntervalSeconds) + return GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepEquals( + this.fetchTimeoutSeconds, other.fetchTimeoutSeconds) && + GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepEquals( + this.minimumFetchIntervalSeconds, other.minimumFetchIntervalSeconds) } override fun hashCode(): Int { var result = javaClass.hashCode() - result = 31 * result + GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepHash(this.fetchTimeoutSeconds) - result = 31 * result + GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepHash(this.minimumFetchIntervalSeconds) + result = + 31 * result + + GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepHash(this.fetchTimeoutSeconds) + result = + 31 * result + + GeneratedAndroidFirebaseRemoteConfigPigeonUtils.deepHash( + this.minimumFetchIntervalSeconds) return result } } + private open class GeneratedAndroidFirebaseRemoteConfigPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 129.toByte() -> { - return (readValue(buffer) as? List)?.let { - RemoteConfigPigeonSettings.fromList(it) - } + return (readValue(buffer) as? List)?.let { RemoteConfigPigeonSettings.fromList(it) } } else -> super.readValueOfType(type, buffer) } } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { when (value) { is RemoteConfigPigeonSettings -> { stream.write(129) @@ -254,30 +258,59 @@ private open class GeneratedAndroidFirebaseRemoteConfigPigeonCodec : StandardMes } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseRemoteConfigHostApi { fun fetch(appName: String, callback: (Result) -> Unit) + fun fetchAndActivate(appName: String, callback: (Result) -> Unit) + fun activate(appName: String, callback: (Result) -> Unit) - fun setConfigSettings(appName: String, settings: RemoteConfigPigeonSettings, callback: (Result) -> Unit) - fun setDefaults(appName: String, defaultParameters: Map, callback: (Result) -> Unit) + + fun setConfigSettings( + appName: String, + settings: RemoteConfigPigeonSettings, + callback: (Result) -> Unit + ) + + fun setDefaults( + appName: String, + defaultParameters: Map, + callback: (Result) -> Unit + ) + fun ensureInitialized(appName: String, callback: (Result) -> Unit) - fun setCustomSignals(appName: String, customSignals: Map, callback: (Result) -> Unit) + + fun setCustomSignals( + appName: String, + customSignals: Map, + callback: (Result) -> Unit + ) + fun getAll(appName: String, callback: (Result>) -> Unit) + fun getProperties(appName: String, callback: (Result>) -> Unit) companion object { /** The codec used by FirebaseRemoteConfigHostApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidFirebaseRemoteConfigPigeonCodec() - } - /** Sets up an instance of `FirebaseRemoteConfigHostApi` to handle messages through the `binaryMessenger`. */ + val codec: MessageCodec by lazy { GeneratedAndroidFirebaseRemoteConfigPigeonCodec() } + /** + * Sets up an instance of `FirebaseRemoteConfigHostApi` to handle messages through the + * `binaryMessenger`. + */ @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseRemoteConfigHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp( + binaryMessenger: BinaryMessenger, + api: FirebaseRemoteConfigHostApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetch$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetch$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -296,7 +329,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetchAndActivate$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetchAndActivate$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -316,7 +353,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.activate$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.activate$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -336,7 +377,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setConfigSettings$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setConfigSettings$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -356,7 +401,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setDefaults$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setDefaults$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -376,7 +425,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.ensureInitialized$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.ensureInitialized$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -395,7 +448,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setCustomSignals$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setCustomSignals$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -415,7 +472,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getAll$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getAll$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -435,7 +496,11 @@ interface FirebaseRemoteConfigHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getProperties$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getProperties$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List diff --git a/packages/firebase_remote_config/firebase_remote_config/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/remoteconfig/example/MainActivity.kt b/packages/firebase_remote_config/firebase_remote_config/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/remoteconfig/example/MainActivity.kt index f93b81d6fbde..30304afd1029 100644 --- a/packages/firebase_remote_config/firebase_remote_config/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/remoteconfig/example/MainActivity.kt +++ b/packages/firebase_remote_config/firebase_remote_config/example/android/app/src/main/kotlin/io/flutter/plugins/firebase/remoteconfig/example/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebase.remoteconfig.example import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift index cb2906a259c5..787668e656ef 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_remote_config", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-remote-config", targets: ["firebase_remote_config"]), + .library(name: "firebase-remote-config", targets: ["firebase_remote_config"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift index 15be7c5b33a7..f7b031c0c6e3 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigMessages.g.swift @@ -89,7 +89,7 @@ func deepEqualsFirebaseRemoteConfigMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: return true case is (Void, Void): @@ -131,7 +131,7 @@ func deepEqualsFirebaseRemoteConfigMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { } return true - case let (lhs as Double, rhs as Double): + case (let lhs as Double, let rhs as Double): return doubleEqualsFirebaseRemoteConfigMessages(lhs, rhs) case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): @@ -205,8 +205,8 @@ struct RemoteConfigPigeonSettings: Hashable { return deepEqualsFirebaseRemoteConfigMessages( lhs.fetchTimeoutSeconds, rhs.fetchTimeoutSeconds - ) && - deepEqualsFirebaseRemoteConfigMessages( + ) + && deepEqualsFirebaseRemoteConfigMessages( lhs.minimumFetchIntervalSeconds, rhs.minimumFetchIntervalSeconds ) @@ -263,13 +263,16 @@ protocol FirebaseRemoteConfigHostApi { func fetch(appName: String, completion: @escaping (Result) -> Void) func fetchAndActivate(appName: String, completion: @escaping (Result) -> Void) func activate(appName: String, completion: @escaping (Result) -> Void) - func setConfigSettings(appName: String, settings: RemoteConfigPigeonSettings, - completion: @escaping (Result) -> Void) - func setDefaults(appName: String, defaultParameters: [String: Any?], - completion: @escaping (Result) -> Void) + func setConfigSettings( + appName: String, settings: RemoteConfigPigeonSettings, + completion: @escaping (Result) -> Void) + func setDefaults( + appName: String, defaultParameters: [String: Any?], + completion: @escaping (Result) -> Void) func ensureInitialized(appName: String, completion: @escaping (Result) -> Void) - func setCustomSignals(appName: String, customSignals: [String: Any?], - completion: @escaping (Result) -> Void) + func setCustomSignals( + appName: String, customSignals: [String: Any?], + completion: @escaping (Result) -> Void) func getAll(appName: String, completion: @escaping (Result<[String: Any?], Error>) -> Void) func getProperties(appName: String, completion: @escaping (Result<[String: Any], Error>) -> Void) } @@ -282,11 +285,14 @@ class FirebaseRemoteConfigHostApiSetup { /// Sets up an instance of `FirebaseRemoteConfigHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseRemoteConfigHostApi?, - messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: FirebaseRemoteConfigHostApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let fetchChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetch\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetch\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -298,7 +304,7 @@ class FirebaseRemoteConfigHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -307,7 +313,8 @@ class FirebaseRemoteConfigHostApiSetup { fetchChannel.setMessageHandler(nil) } let fetchAndActivateChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetchAndActivate\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.fetchAndActivate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -317,9 +324,9 @@ class FirebaseRemoteConfigHostApiSetup { let appNameArg = args[0] as! String api.fetchAndActivate(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -328,7 +335,8 @@ class FirebaseRemoteConfigHostApiSetup { fetchAndActivateChannel.setMessageHandler(nil) } let activateChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.activate\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.activate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -338,9 +346,9 @@ class FirebaseRemoteConfigHostApiSetup { let appNameArg = args[0] as! String api.activate(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -349,7 +357,8 @@ class FirebaseRemoteConfigHostApiSetup { activateChannel.setMessageHandler(nil) } let setConfigSettingsChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setConfigSettings\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setConfigSettings\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -362,7 +371,7 @@ class FirebaseRemoteConfigHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -371,7 +380,8 @@ class FirebaseRemoteConfigHostApiSetup { setConfigSettingsChannel.setMessageHandler(nil) } let setDefaultsChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setDefaults\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setDefaults\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -384,7 +394,7 @@ class FirebaseRemoteConfigHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -393,7 +403,8 @@ class FirebaseRemoteConfigHostApiSetup { setDefaultsChannel.setMessageHandler(nil) } let ensureInitializedChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.ensureInitialized\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.ensureInitialized\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -405,7 +416,7 @@ class FirebaseRemoteConfigHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -414,7 +425,8 @@ class FirebaseRemoteConfigHostApiSetup { ensureInitializedChannel.setMessageHandler(nil) } let setCustomSignalsChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setCustomSignals\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.setCustomSignals\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -427,7 +439,7 @@ class FirebaseRemoteConfigHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -436,7 +448,8 @@ class FirebaseRemoteConfigHostApiSetup { setCustomSignalsChannel.setMessageHandler(nil) } let getAllChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getAll\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getAll\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -446,9 +459,9 @@ class FirebaseRemoteConfigHostApiSetup { let appNameArg = args[0] as! String api.getAll(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -457,7 +470,8 @@ class FirebaseRemoteConfigHostApiSetup { getAllChannel.setMessageHandler(nil) } let getPropertiesChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getProperties\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_remote_config_platform_interface.FirebaseRemoteConfigHostApi.getProperties\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -467,9 +481,9 @@ class FirebaseRemoteConfigHostApiSetup { let appNameArg = args[0] as! String api.getProperties(appName: appNameArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigPlugin.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigPlugin.swift index 10a80253147c..aa923738980a 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigPlugin.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigPlugin.swift @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import FirebaseRemoteConfig + #if canImport(FlutterMacOS) import FlutterMacOS #else @@ -13,7 +15,6 @@ #else import firebase_core_shared #endif -import FirebaseRemoteConfig let kFirebaseRemoteConfigChannelName = "plugins.flutter.io/firebase_remote_config" let kFirebaseRemoteConfigUpdatedChannelName = "plugins.flutter.io/firebase_remote_config_updated" @@ -21,7 +22,8 @@ let kFirebaseRemoteConfigUpdatedChannelName = "plugins.flutter.io/firebase_remot extension FlutterError: Error {} public class FirebaseRemoteConfigPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, - FLTFirebasePluginProtocol, FirebaseRemoteConfigHostApi { + FLTFirebasePluginProtocol, FirebaseRemoteConfigHostApi +{ private var listenersMap: [String: ConfigUpdateListenerRegistration] = [:] private var fetchAndActivateRetry = false @@ -106,8 +108,10 @@ public class FirebaseRemoteConfigPlugin: NSObject, FlutterPlugin, FlutterStreamH } } - func setConfigSettings(appName: String, settings: RemoteConfigPigeonSettings, - completion: @escaping (Result) -> Void) { + func setConfigSettings( + appName: String, settings: RemoteConfigPigeonSettings, + completion: @escaping (Result) -> Void + ) { let fetchTimeout = settings.fetchTimeoutSeconds let minFetchInterval = settings.minimumFetchIntervalSeconds let configSettings = RemoteConfigSettings() @@ -117,8 +121,10 @@ public class FirebaseRemoteConfigPlugin: NSObject, FlutterPlugin, FlutterStreamH completion(.success(())) } - func setDefaults(appName: String, defaultParameters: [String: Any?], - completion: @escaping (Result) -> Void) { + func setDefaults( + appName: String, defaultParameters: [String: Any?], + completion: @escaping (Result) -> Void + ) { var filtered: [String: NSObject] = [:] for (key, value) in defaultParameters { @@ -141,8 +147,10 @@ public class FirebaseRemoteConfigPlugin: NSObject, FlutterPlugin, FlutterStreamH } } - func setCustomSignals(appName: String, customSignals: [String: Any?], - completion: @escaping (Result) -> Void) { + func setCustomSignals( + appName: String, customSignals: [String: Any?], + completion: @escaping (Result) -> Void + ) { let signalValues = convertToCustomSignalValues(customSignals) Task { do { @@ -171,8 +179,10 @@ public class FirebaseRemoteConfigPlugin: NSObject, FlutterPlugin, FlutterStreamH completion(.success(parameters)) } - func getProperties(appName: String, - completion: @escaping (Result<[String: Any], any Error>) -> Void) { + func getProperties( + appName: String, + completion: @escaping (Result<[String: Any], any Error>) -> Void + ) { let config = getRemoteConfig(from: appName) completion(.success(configProperties(for: config))) } @@ -189,8 +199,10 @@ public class FirebaseRemoteConfigPlugin: NSObject, FlutterPlugin, FlutterStreamH kFirebaseRemoteConfigChannelName } - public func onListen(withArguments arguments: Any?, - eventSink events: @escaping FlutterEventSink) -> FlutterError? { + public func onListen( + withArguments arguments: Any?, + eventSink events: @escaping FlutterEventSink + ) -> FlutterError? { guard let args = arguments as? [String: Any], let appName = args["appName"] as? String else { return nil } @@ -236,7 +248,8 @@ public class FirebaseRemoteConfigPlugin: NSObject, FlutterPlugin, FlutterStreamH } private func createRemoteConfigValueDict(_ remoteConfigValue: RemoteConfigValue) - -> [String: Any] { + -> [String: Any] + { [ "value": FlutterStandardTypedData(bytes: remoteConfigValue.dataValue), "source": mapSource(remoteConfigValue.source), diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigUtils.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigUtils.swift index 983987589c41..45065769736b 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigUtils.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/FirebaseRemoteConfigUtils.swift @@ -11,7 +11,8 @@ class FLTFirebaseRemoteConfigUtils { switch error.code { case RemoteConfigError.internalError.rawValue: if let description = error.userInfo[NSLocalizedDescriptionKey] as? String, - description.contains("403") { + description.contains("403") + { // See PR for details: https://github.com/firebase/flutterfire/pull/9629 codeAndMessage["code"] = "forbidden" let updateMessage = @@ -19,7 +20,8 @@ class FLTFirebaseRemoteConfigUtils { codeAndMessage["message"] = updateMessage } else { codeAndMessage["code"] = "internal" - codeAndMessage["message"] = error + codeAndMessage["message"] = + error .userInfo[NSLocalizedDescriptionKey] as? String ?? "Internal error" } diff --git a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift index 8f7084f34b64..525d98ef693a 100644 --- a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift @@ -7,18 +7,18 @@ import PackageDescription -let firebase_sdk_version: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_remote_config", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-remote-config", targets: ["firebase_remote_config"]), + .library(name: "firebase-remote-config", targets: ["firebase_remote_config"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -29,8 +29,8 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ] - ), + ) ] ) diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseAppRegistrar.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseAppRegistrar.kt index 424f5d7c8ffb..3b59c3d7c919 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseAppRegistrar.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseAppRegistrar.kt @@ -14,9 +14,6 @@ import com.google.firebase.platforminfo.LibraryVersionComponent class FlutterFirebaseAppRegistrar : ComponentRegistrar { override fun getComponents(): List> { return listOf( - LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION) - ) + LibraryVersionComponent.create(BuildConfig.LIBRARY_NAME, BuildConfig.LIBRARY_VERSION)) } } - - diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageException.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageException.kt index db671035ee96..50cb7ce1d949 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageException.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageException.kt @@ -12,11 +12,7 @@ internal object FlutterFirebaseStorageException { @JvmStatic fun parserExceptionToFlutter(@Nullable nativeException: Exception?): FlutterError { if (nativeException == null) { - return FlutterError( - "UNKNOWN", - "An unknown error occurred", - null - ) + return FlutterError("UNKNOWN", "An unknown error occurred", null) } var code = "UNKNOWN" @@ -55,16 +51,19 @@ internal object FlutterFirebaseStorageException { StorageException.ERROR_OBJECT_NOT_FOUND -> "No object exists at the desired reference." StorageException.ERROR_BUCKET_NOT_FOUND -> "No bucket is configured for Firebase Storage." StorageException.ERROR_PROJECT_NOT_FOUND -> "No project is configured for Firebase Storage." - StorageException.ERROR_QUOTA_EXCEEDED -> "Quota on your Firebase Storage bucket has been exceeded." - StorageException.ERROR_NOT_AUTHENTICATED -> "User is unauthenticated. Authenticate and try again." - StorageException.ERROR_NOT_AUTHORIZED -> "User is not authorized to perform the desired action." - StorageException.ERROR_RETRY_LIMIT_EXCEEDED -> "The maximum time limit on an operation (upload, download, delete, etc.) has been exceeded." - StorageException.ERROR_INVALID_CHECKSUM -> "File on the client does not match the checksum of the file received by the server." + StorageException.ERROR_QUOTA_EXCEEDED -> + "Quota on your Firebase Storage bucket has been exceeded." + StorageException.ERROR_NOT_AUTHENTICATED -> + "User is unauthenticated. Authenticate and try again." + StorageException.ERROR_NOT_AUTHORIZED -> + "User is not authorized to perform the desired action." + StorageException.ERROR_RETRY_LIMIT_EXCEEDED -> + "The maximum time limit on an operation (upload, download, delete, etc.) has been exceeded." + StorageException.ERROR_INVALID_CHECKSUM -> + "File on the client does not match the checksum of the file received by the server." StorageException.ERROR_CANCELED -> "User cancelled the operation." StorageException.ERROR_UNKNOWN -> "An unknown error occurred" else -> "An unknown error occurred" } } } - - diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt index 466c44c98220..8a632ceb75f2 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStoragePlugin.kt @@ -7,8 +7,6 @@ package io.flutter.plugins.firebase.storage import android.net.Uri import android.util.Base64 -import androidx.annotation.NonNull -import androidx.annotation.Nullable import com.google.android.gms.tasks.Task import com.google.android.gms.tasks.TaskCompletionSource import com.google.firebase.FirebaseApp @@ -53,7 +51,11 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb this.messenger = messenger } - private fun registerEventChannel(prefix: String, identifier: String, handler: StreamHandler): String { + private fun registerEventChannel( + prefix: String, + identifier: String, + handler: StreamHandler + ): String { val channelName = "$prefix/$identifier" val channel = EventChannel(messenger, channelName) channel.setStreamHandler(handler) @@ -87,8 +89,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } private fun getReferenceFromPigeon( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference + app: InternalStorageFirebaseApp, + reference: InternalStorageReference ): StorageReference { val androidStorage = getStorageFromPigeon(app) return androidStorage.getReference(reference.fullPath) @@ -96,10 +98,7 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb private fun convertToPigeonReference(reference: StorageReference): InternalStorageReference { return InternalStorageReference( - bucket = reference.bucket, - fullPath = reference.path, - name = reference.name - ) + bucket = reference.bucket, fullPath = reference.path, name = reference.name) } private fun convertToPigeonMetaData(storageMetadata: StorageMetadata?): InternalFullMetaData { @@ -112,14 +111,18 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb return InternalListResult(items = items, pageToken = listResult.pageToken, prefixs = prefixes) } - private fun getMetaDataFromPigeon(pigeonSettableMetatdata: InternalSettableMetadata): StorageMetadata { + private fun getMetaDataFromPigeon( + pigeonSettableMetatdata: InternalSettableMetadata + ): StorageMetadata { val builder = StorageMetadata.Builder() pigeonSettableMetatdata.contentType?.let { builder.setContentType(it) } pigeonSettableMetatdata.cacheControl?.let { builder.setCacheControl(it) } pigeonSettableMetatdata.contentDisposition?.let { builder.setContentDisposition(it) } pigeonSettableMetatdata.contentEncoding?.let { builder.setContentEncoding(it) } pigeonSettableMetatdata.contentLanguage?.let { builder.setContentLanguage(it) } - pigeonSettableMetatdata.customMetadata?.forEach { (k, v) -> if (k != null && v != null) builder.setCustomMetadata(k, v) } + pigeonSettableMetatdata.customMetadata?.forEach { (k, v) -> + if (k != null && v != null) builder.setCustomMetadata(k, v) + } return builder.build() } @@ -132,20 +135,20 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun getReferencebyPath( - app: InternalStorageFirebaseApp, - path: String, - bucket: String?, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + path: String, + bucket: String?, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(path) callback(Result.success(convertToPigeonReference(androidReference))) } override fun useStorageEmulator( - app: InternalStorageFirebaseApp, - host: String, - port: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + host: String, + port: Long, + callback: (Result) -> Unit ) { try { val storage = getStorageFromPigeon(app) @@ -157,185 +160,223 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun referenceDelete( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.delete().addOnCompleteListener { task -> if (task.isSuccessful) callback(Result.success(Unit)) - else callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) + else + callback( + Result.failure( + FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) } } override fun referenceGetDownloadURL( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.downloadUrl.addOnCompleteListener { task -> if (task.isSuccessful) callback(Result.success(task.result.toString())) - else callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) + else + callback( + Result.failure( + FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) } } override fun referenceGetData( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - maxSize: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + maxSize: Long, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.getBytes(maxSize).addOnCompleteListener { task -> if (task.isSuccessful) callback(Result.success(task.result)) - else callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) + else + callback( + Result.failure( + FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) } } override fun referenceGetMetaData( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.metadata.addOnCompleteListener { task -> if (task.isSuccessful) callback(Result.success(convertToPigeonMetaData(task.result))) - else callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) + else + callback( + Result.failure( + FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) } } override fun referenceList( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - options: InternalListOptions, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + options: InternalListOptions, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) - val task = if (options.pageToken != null) { - androidReference.list(options.maxResults.toInt(), options.pageToken) - } else { - androidReference.list(options.maxResults.toInt()) - } + val task = + if (options.pageToken != null) { + androidReference.list(options.maxResults.toInt(), options.pageToken) + } else { + androidReference.list(options.maxResults.toInt()) + } task.addOnCompleteListener { t -> if (t.isSuccessful) callback(Result.success(convertToPigeonListResult(t.result))) - else callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(t.exception))) + else + callback( + Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(t.exception))) } } override fun referenceListAll( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.listAll().addOnCompleteListener { task -> if (task.isSuccessful) callback(Result.success(convertToPigeonListResult(task.result))) - else callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) + else + callback( + Result.failure( + FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) } } override fun referenceUpdateMetadata( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - metadata: InternalSettableMetadata, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + metadata: InternalSettableMetadata, + callback: (Result) -> Unit ) { val androidReference = getStorageFromPigeon(app).getReference(reference.fullPath) androidReference.updateMetadata(getMetaDataFromPigeon(metadata)).addOnCompleteListener { task -> if (task.isSuccessful) callback(Result.success(convertToPigeonMetaData(task.result))) - else callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) + else + callback( + Result.failure( + FlutterFirebaseStorageException.parserExceptionToFlutter(task.exception))) } } override fun referencePutData( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - data: ByteArray, - settableMetaData: InternalSettableMetadata, - handle: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + data: ByteArray, + settableMetaData: InternalSettableMetadata, + handle: Long, + callback: (Result) -> Unit ) { val androidReference = getReferenceFromPigeon(app, reference) val androidMetaData = getMetaDataFromPigeon(settableMetaData) - val storageTask = FlutterFirebaseStorageTask.uploadBytes(handle.toInt(), androidReference, data, androidMetaData) + val storageTask = + FlutterFirebaseStorageTask.uploadBytes( + handle.toInt(), androidReference, data, androidMetaData) try { val identifier = UUID.randomUUID().toString().lowercase(Locale.US) val handler = storageTask.startTaskWithMethodChannel(channel!!, identifier) - callback(Result.success(registerEventChannel("$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) + callback( + Result.success( + registerEventChannel( + "$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) } catch (e: Exception) { callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(e))) } } override fun referencePutString( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - data: String, - format: Long, - settableMetaData: InternalSettableMetadata, - handle: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + data: String, + format: Long, + settableMetaData: InternalSettableMetadata, + handle: Long, + callback: (Result) -> Unit ) { val androidReference = getReferenceFromPigeon(app, reference) val androidMetaData = getMetaDataFromPigeon(settableMetaData) val bytes = stringToByteData(data, format.toInt()) - val storageTask = FlutterFirebaseStorageTask.uploadBytes(handle.toInt(), androidReference, bytes!!, androidMetaData) + val storageTask = + FlutterFirebaseStorageTask.uploadBytes( + handle.toInt(), androidReference, bytes!!, androidMetaData) try { val identifier = UUID.randomUUID().toString().lowercase(Locale.US) val handler = storageTask.startTaskWithMethodChannel(channel!!, identifier) - callback(Result.success(registerEventChannel("$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) + callback( + Result.success( + registerEventChannel( + "$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) } catch (e: Exception) { callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(e))) } } override fun referencePutFile( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - filePath: String, - settableMetaData: InternalSettableMetadata?, - handle: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + filePath: String, + settableMetaData: InternalSettableMetadata?, + handle: Long, + callback: (Result) -> Unit ) { val androidReference = getReferenceFromPigeon(app, reference) - val storageTask = FlutterFirebaseStorageTask.uploadFile( - handle.toInt(), - androidReference, - Uri.fromFile(File(filePath)), - settableMetaData?.let { getMetaDataFromPigeon(it) } - ) + val storageTask = + FlutterFirebaseStorageTask.uploadFile( + handle.toInt(), + androidReference, + Uri.fromFile(File(filePath)), + settableMetaData?.let { getMetaDataFromPigeon(it) }) try { val identifier = UUID.randomUUID().toString().lowercase(Locale.US) val handler = storageTask.startTaskWithMethodChannel(channel!!, identifier) - callback(Result.success(registerEventChannel("$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) + callback( + Result.success( + registerEventChannel( + "$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) } catch (e: Exception) { callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(e))) } } override fun referenceDownloadFile( - app: InternalStorageFirebaseApp, - reference: InternalStorageReference, - filePath: String, - handle: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + filePath: String, + handle: Long, + callback: (Result) -> Unit ) { val androidReference = getReferenceFromPigeon(app, reference) - val storageTask = FlutterFirebaseStorageTask.downloadFile(handle.toInt(), androidReference, File(filePath)) + val storageTask = + FlutterFirebaseStorageTask.downloadFile(handle.toInt(), androidReference, File(filePath)) try { val identifier = UUID.randomUUID().toString().lowercase(Locale.US) val handler = storageTask.startTaskWithMethodChannel(channel!!, identifier) - callback(Result.success(registerEventChannel("$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) + callback( + Result.success( + registerEventChannel( + "$STORAGE_METHOD_CHANNEL_NAME/$STORAGE_TASK_EVENT_NAME", identifier, handler))) } catch (e: Exception) { callback(Result.failure(FlutterFirebaseStorageException.parserExceptionToFlutter(e))) } } override fun taskPause( - app: InternalStorageFirebaseApp, - handle: Long, - callback: (Result>) -> Unit + app: InternalStorageFirebaseApp, + handle: Long, + callback: (Result>) -> Unit ) { val storageTask = FlutterFirebaseStorageTask.getInProgressTaskForHandle(handle.toInt()) if (storageTask == null) { @@ -352,7 +393,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb val statusMap = HashMap() statusMap["status"] = paused if (paused) { - statusMap["snapshot"] = FlutterFirebaseStorageTask.parseTaskSnapshot(storageTask.getSnapshot()) + statusMap["snapshot"] = + FlutterFirebaseStorageTask.parseTaskSnapshot(storageTask.getSnapshot()) } callback(Result.success(statusMap)) } catch (e: Exception) { @@ -361,9 +403,9 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun taskResume( - app: InternalStorageFirebaseApp, - handle: Long, - callback: (Result>) -> Unit + app: InternalStorageFirebaseApp, + handle: Long, + callback: (Result>) -> Unit ) { val storageTask = FlutterFirebaseStorageTask.getInProgressTaskForHandle(handle.toInt()) if (storageTask == null) { @@ -380,7 +422,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb val statusMap = HashMap() statusMap["status"] = resumed if (resumed) { - statusMap["snapshot"] = FlutterFirebaseStorageTask.parseTaskSnapshot(storageTask.getSnapshot()) + statusMap["snapshot"] = + FlutterFirebaseStorageTask.parseTaskSnapshot(storageTask.getSnapshot()) } callback(Result.success(statusMap)) } catch (e: Exception) { @@ -389,9 +432,9 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun taskCancel( - app: InternalStorageFirebaseApp, - handle: Long, - callback: (Result>) -> Unit + app: InternalStorageFirebaseApp, + handle: Long, + callback: (Result>) -> Unit ) { val storageTask = FlutterFirebaseStorageTask.getInProgressTaskForHandle(handle.toInt()) if (storageTask == null) { @@ -405,7 +448,8 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb val statusMap = HashMap() statusMap["status"] = canceled if (canceled) { - statusMap["snapshot"] = FlutterFirebaseStorageTask.parseTaskSnapshot(storageTask.getSnapshot()) + statusMap["snapshot"] = + FlutterFirebaseStorageTask.parseTaskSnapshot(storageTask.getSnapshot()) } callback(Result.success(statusMap)) } catch (e: Exception) { @@ -414,9 +458,9 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun setMaxOperationRetryTime( - app: InternalStorageFirebaseApp, - time: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + time: Long, + callback: (Result) -> Unit ) { val storage = getStorageFromPigeon(app) storage.maxOperationRetryTimeMillis = time @@ -424,9 +468,9 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun setMaxUploadRetryTime( - app: InternalStorageFirebaseApp, - time: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + time: Long, + callback: (Result) -> Unit ) { val storage = getStorageFromPigeon(app) storage.maxUploadRetryTimeMillis = time @@ -434,16 +478,18 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } override fun setMaxDownloadRetryTime( - app: InternalStorageFirebaseApp, - time: Long, - callback: (Result) -> Unit + app: InternalStorageFirebaseApp, + time: Long, + callback: (Result) -> Unit ) { val storage = getStorageFromPigeon(app) storage.maxDownloadRetryTimeMillis = time callback(Result.success(Unit)) } - override fun getPluginConstantsForFirebaseApp(firebaseApp: FirebaseApp?): Task> { + override fun getPluginConstantsForFirebaseApp( + firebaseApp: FirebaseApp? + ): Task> { val taskCompletionSource = TaskCompletionSource>() cachedThreadPool.execute { val obj = HashMap() @@ -504,5 +550,3 @@ class FlutterFirebaseStoragePlugin : FlutterFirebasePlugin, FlutterPlugin, Fireb } } } - - diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt index 21b6453191f2..f8cd77d739a8 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/FlutterFirebaseStorageTask.kt @@ -8,7 +8,6 @@ package io.flutter.plugins.firebase.storage import android.net.Uri import android.util.SparseArray import androidx.annotation.NonNull -import androidx.annotation.Nullable import com.google.firebase.storage.FileDownloadTask import com.google.firebase.storage.StorageMetadata import com.google.firebase.storage.StorageReference @@ -18,13 +17,14 @@ import io.flutter.plugin.common.MethodChannel import java.io.File import java.util.HashMap -internal class FlutterFirebaseStorageTask private constructor( - private val type: FlutterFirebaseStorageTaskType, - private val handle: Int, - private val reference: StorageReference, - private val bytes: ByteArray?, - private val fileUri: Uri?, - private val metadata: StorageMetadata? +internal class FlutterFirebaseStorageTask +private constructor( + private val type: FlutterFirebaseStorageTaskType, + private val handle: Int, + private val reference: StorageReference, + private val bytes: ByteArray?, + private val fileUri: Uri?, + private val metadata: StorageMetadata? ) { private val pauseSyncObject = Object() private val resumeSyncObject = Object() @@ -36,12 +36,20 @@ internal class FlutterFirebaseStorageTask private constructor( synchronized(inProgressTasks) { inProgressTasks.put(handle, this) } } - fun startTaskWithMethodChannel(@NonNull channel: MethodChannel, @NonNull identifier: String): TaskStateChannelStreamHandler { - storageTask = when (type) { - FlutterFirebaseStorageTaskType.BYTES -> if (metadata == null) reference.putBytes(bytes!!) else reference.putBytes(bytes!!, metadata) - FlutterFirebaseStorageTaskType.FILE -> if (metadata == null) reference.putFile(fileUri!!) else reference.putFile(fileUri!!, metadata) - FlutterFirebaseStorageTaskType.DOWNLOAD -> reference.getFile(fileUri!!) - } + fun startTaskWithMethodChannel( + @NonNull channel: MethodChannel, + @NonNull identifier: String + ): TaskStateChannelStreamHandler { + storageTask = + when (type) { + FlutterFirebaseStorageTaskType.BYTES -> + if (metadata == null) reference.putBytes(bytes!!) + else reference.putBytes(bytes!!, metadata) + FlutterFirebaseStorageTaskType.FILE -> + if (metadata == null) reference.putFile(fileUri!!) + else reference.putFile(fileUri!!, metadata) + FlutterFirebaseStorageTaskType.DOWNLOAD -> reference.getFile(fileUri!!) + } return TaskStateChannelStreamHandler(this, reference.storage, storageTask as Any, identifier) } @@ -62,9 +70,17 @@ internal class FlutterFirebaseStorageTask private constructor( fun isDestroyed(): Boolean = destroyed - fun notifyResumeObjects() { synchronized(resumeSyncObject) { resumeSyncObject.notifyAll() } } - fun notifyCancelObjects() { synchronized(cancelSyncObject) { cancelSyncObject.notifyAll() } } - fun notifyPauseObjects() { synchronized(pauseSyncObject) { pauseSyncObject.notifyAll() } } + fun notifyResumeObjects() { + synchronized(resumeSyncObject) { resumeSyncObject.notifyAll() } + } + + fun notifyCancelObjects() { + synchronized(cancelSyncObject) { cancelSyncObject.notifyAll() } + } + + fun notifyPauseObjects() { + synchronized(pauseSyncObject) { pauseSyncObject.notifyAll() } + } // Intentionally do not expose the StorageTask generic type outside this class @@ -89,7 +105,9 @@ internal class FlutterFirebaseStorageTask private constructor( @JvmStatic fun getInProgressTaskForHandle(handle: Int): FlutterFirebaseStorageTask? { - synchronized(inProgressTasks) { return inProgressTasks.get(handle) } + synchronized(inProgressTasks) { + return inProgressTasks.get(handle) + } } @JvmStatic @@ -106,18 +124,40 @@ internal class FlutterFirebaseStorageTask private constructor( } @JvmStatic - fun uploadBytes(handle: Int, reference: StorageReference, data: ByteArray, metadata: StorageMetadata?): FlutterFirebaseStorageTask { - return FlutterFirebaseStorageTask(FlutterFirebaseStorageTaskType.BYTES, handle, reference, data, null, metadata) + fun uploadBytes( + handle: Int, + reference: StorageReference, + data: ByteArray, + metadata: StorageMetadata? + ): FlutterFirebaseStorageTask { + return FlutterFirebaseStorageTask( + FlutterFirebaseStorageTaskType.BYTES, handle, reference, data, null, metadata) } @JvmStatic - fun uploadFile(handle: Int, reference: StorageReference, fileUri: Uri, metadata: StorageMetadata?): FlutterFirebaseStorageTask { - return FlutterFirebaseStorageTask(FlutterFirebaseStorageTaskType.FILE, handle, reference, null, fileUri, metadata) + fun uploadFile( + handle: Int, + reference: StorageReference, + fileUri: Uri, + metadata: StorageMetadata? + ): FlutterFirebaseStorageTask { + return FlutterFirebaseStorageTask( + FlutterFirebaseStorageTaskType.FILE, handle, reference, null, fileUri, metadata) } @JvmStatic - fun downloadFile(handle: Int, reference: StorageReference, file: File): FlutterFirebaseStorageTask { - return FlutterFirebaseStorageTask(FlutterFirebaseStorageTaskType.DOWNLOAD, handle, reference, null, Uri.fromFile(file), null) + fun downloadFile( + handle: Int, + reference: StorageReference, + file: File + ): FlutterFirebaseStorageTask { + return FlutterFirebaseStorageTask( + FlutterFirebaseStorageTaskType.DOWNLOAD, + handle, + reference, + null, + Uri.fromFile(file), + null) } @JvmStatic @@ -137,7 +177,8 @@ internal class FlutterFirebaseStorageTask private constructor( val out: MutableMap = HashMap() out["path"] = snapshot.storage.path // Workaround: sometimes getBytesTransferred != getTotalByteCount when completed - out["bytesTransferred"] = if (snapshot.task.isSuccessful) snapshot.totalByteCount else snapshot.bytesTransferred + out["bytesTransferred"] = + if (snapshot.task.isSuccessful) snapshot.totalByteCount else snapshot.bytesTransferred out["totalBytes"] = snapshot.totalByteCount return out } @@ -158,5 +199,3 @@ internal class FlutterFirebaseStorageTask private constructor( DOWNLOAD } } - - diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt index ffd0cf5a58d8..3e2741a89caa 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/GeneratedAndroidFirebaseStorage.g.kt @@ -10,12 +10,11 @@ package io.flutter.plugins.firebase.storage import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object GeneratedAndroidFirebaseStoragePigeonUtils { fun wrapResult(result: Any?): List { @@ -24,19 +23,15 @@ private object GeneratedAndroidFirebaseStoragePigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } + fun doubleEquals(a: Double, b: Double): Boolean { // Normalize -0.0 to 0.0 and handle NaN equality. return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN()) @@ -180,25 +175,22 @@ private object GeneratedAndroidFirebaseStoragePigeonUtils { else -> value.hashCode() } } - } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : RuntimeException() -/** - * The type of operation that generated the action code from calling - * [TaskState]. - */ +/** The type of operation that generated the action code from calling [TaskState]. */ enum class InternalStorageTaskState(val raw: Int) { /** Indicates the task has been paused by the user. */ PAUSED(0), @@ -219,12 +211,11 @@ enum class InternalStorageTaskState(val raw: Int) { } /** Generated class from Pigeon that represents data sent in messages. */ -data class InternalStorageFirebaseApp ( - val appName: String, - val tenantId: String? = null, - val bucket: String -) - { +data class InternalStorageFirebaseApp( + val appName: String, + val tenantId: String? = null, + val bucket: String +) { companion object { fun fromList(pigeonVar_list: List): InternalStorageFirebaseApp { val appName = pigeonVar_list[0] as String @@ -233,13 +224,15 @@ data class InternalStorageFirebaseApp ( return InternalStorageFirebaseApp(appName, tenantId, bucket) } } + fun toList(): List { return listOf( - appName, - tenantId, - bucket, + appName, + tenantId, + bucket, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -248,7 +241,9 @@ data class InternalStorageFirebaseApp ( return true } val other = other as InternalStorageFirebaseApp - return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.appName, other.appName) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.tenantId, other.tenantId) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bucket, other.bucket) + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.appName, other.appName) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.tenantId, other.tenantId) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bucket, other.bucket) } override fun hashCode(): Int { @@ -261,12 +256,7 @@ data class InternalStorageFirebaseApp ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class InternalStorageReference ( - val bucket: String, - val fullPath: String, - val name: String -) - { +data class InternalStorageReference(val bucket: String, val fullPath: String, val name: String) { companion object { fun fromList(pigeonVar_list: List): InternalStorageReference { val bucket = pigeonVar_list[0] as String @@ -275,13 +265,15 @@ data class InternalStorageReference ( return InternalStorageReference(bucket, fullPath, name) } } + fun toList(): List { return listOf( - bucket, - fullPath, - name, + bucket, + fullPath, + name, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -290,7 +282,9 @@ data class InternalStorageReference ( return true } val other = other as InternalStorageReference - return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bucket, other.bucket) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.fullPath, other.fullPath) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.name, other.name) + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bucket, other.bucket) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.fullPath, other.fullPath) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.name, other.name) } override fun hashCode(): Int { @@ -303,21 +297,20 @@ data class InternalStorageReference ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class InternalFullMetaData ( - val metadata: Map? = null -) - { +data class InternalFullMetaData(val metadata: Map? = null) { companion object { fun fromList(pigeonVar_list: List): InternalFullMetaData { val metadata = pigeonVar_list[0] as Map? return InternalFullMetaData(metadata) } } + fun toList(): List { return listOf( - metadata, + metadata, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -337,21 +330,20 @@ data class InternalFullMetaData ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class InternalListOptions ( - /** - * If set, limits the total number of `prefixes` and `items` to return. - * - * The default and maximum maxResults is 1000. - */ - val maxResults: Long, - /** - * The nextPageToken from a previous call to list(). - * - * If provided, listing is resumed from the previous position. - */ - val pageToken: String? = null -) - { +data class InternalListOptions( + /** + * If set, limits the total number of `prefixes` and `items` to return. + * + * The default and maximum maxResults is 1000. + */ + val maxResults: Long, + /** + * The nextPageToken from a previous call to list(). + * + * If provided, listing is resumed from the previous position. + */ + val pageToken: String? = null +) { companion object { fun fromList(pigeonVar_list: List): InternalListOptions { val maxResults = pigeonVar_list[0] as Long @@ -359,12 +351,14 @@ data class InternalListOptions ( return InternalListOptions(maxResults, pageToken) } } + fun toList(): List { return listOf( - maxResults, - pageToken, + maxResults, + pageToken, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -373,7 +367,9 @@ data class InternalListOptions ( return true } val other = other as InternalListOptions - return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.maxResults, other.maxResults) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.pageToken, other.pageToken) + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.maxResults, other.maxResults) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.pageToken, other.pageToken) } override fun hashCode(): Int { @@ -385,41 +381,40 @@ data class InternalListOptions ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class InternalSettableMetadata ( - /** - * Served as the 'Cache-Control' header on object download. - * - * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control. - */ - val cacheControl: String? = null, - /** - * Served as the 'Content-Disposition' header on object download. - * - * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition. - */ - val contentDisposition: String? = null, - /** - * Served as the 'Content-Encoding' header on object download. - * - * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding. - */ - val contentEncoding: String? = null, - /** - * Served as the 'Content-Language' header on object download. - * - * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language. - */ - val contentLanguage: String? = null, - /** - * Served as the 'Content-Type' header on object download. - * - * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type. - */ - val contentType: String? = null, - /** Additional user-defined custom metadata. */ - val customMetadata: Map? = null -) - { +data class InternalSettableMetadata( + /** + * Served as the 'Cache-Control' header on object download. + * + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control. + */ + val cacheControl: String? = null, + /** + * Served as the 'Content-Disposition' header on object download. + * + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition. + */ + val contentDisposition: String? = null, + /** + * Served as the 'Content-Encoding' header on object download. + * + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding. + */ + val contentEncoding: String? = null, + /** + * Served as the 'Content-Language' header on object download. + * + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Language. + */ + val contentLanguage: String? = null, + /** + * Served as the 'Content-Type' header on object download. + * + * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type. + */ + val contentType: String? = null, + /** Additional user-defined custom metadata. */ + val customMetadata: Map? = null +) { companion object { fun fromList(pigeonVar_list: List): InternalSettableMetadata { val cacheControl = pigeonVar_list[0] as String? @@ -428,19 +423,27 @@ data class InternalSettableMetadata ( val contentLanguage = pigeonVar_list[3] as String? val contentType = pigeonVar_list[4] as String? val customMetadata = pigeonVar_list[5] as Map? - return InternalSettableMetadata(cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType, customMetadata) + return InternalSettableMetadata( + cacheControl, + contentDisposition, + contentEncoding, + contentLanguage, + contentType, + customMetadata) } } + fun toList(): List { return listOf( - cacheControl, - contentDisposition, - contentEncoding, - contentLanguage, - contentType, - customMetadata, + cacheControl, + contentDisposition, + contentEncoding, + contentLanguage, + contentType, + customMetadata, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -449,13 +452,25 @@ data class InternalSettableMetadata ( return true } val other = other as InternalSettableMetadata - return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.cacheControl, other.cacheControl) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentDisposition, other.contentDisposition) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentEncoding, other.contentEncoding) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentLanguage, other.contentLanguage) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.contentType, other.contentType) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.customMetadata, other.customMetadata) + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.cacheControl, other.cacheControl) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.contentDisposition, other.contentDisposition) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.contentEncoding, other.contentEncoding) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.contentLanguage, other.contentLanguage) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.contentType, other.contentType) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.customMetadata, other.customMetadata) } override fun hashCode(): Int { var result = javaClass.hashCode() result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.cacheControl) - result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentDisposition) + result = + 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentDisposition) result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentEncoding) result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentLanguage) result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.contentType) @@ -465,13 +480,12 @@ data class InternalSettableMetadata ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class InternalStorageTaskSnapShot ( - val bytesTransferred: Long, - val metadata: InternalFullMetaData? = null, - val state: InternalStorageTaskState, - val totalBytes: Long -) - { +data class InternalStorageTaskSnapShot( + val bytesTransferred: Long, + val metadata: InternalFullMetaData? = null, + val state: InternalStorageTaskState, + val totalBytes: Long +) { companion object { fun fromList(pigeonVar_list: List): InternalStorageTaskSnapShot { val bytesTransferred = pigeonVar_list[0] as Long @@ -481,14 +495,16 @@ data class InternalStorageTaskSnapShot ( return InternalStorageTaskSnapShot(bytesTransferred, metadata, state, totalBytes) } } + fun toList(): List { return listOf( - bytesTransferred, - metadata, - state, - totalBytes, + bytesTransferred, + metadata, + state, + totalBytes, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -497,12 +513,17 @@ data class InternalStorageTaskSnapShot ( return true } val other = other as InternalStorageTaskSnapShot - return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.bytesTransferred, other.bytesTransferred) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.metadata, other.metadata) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.state, other.state) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.totalBytes, other.totalBytes) + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals( + this.bytesTransferred, other.bytesTransferred) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.metadata, other.metadata) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.state, other.state) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.totalBytes, other.totalBytes) } override fun hashCode(): Int { var result = javaClass.hashCode() - result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.bytesTransferred) + result = + 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.bytesTransferred) result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.metadata) result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.state) result = 31 * result + GeneratedAndroidFirebaseStoragePigeonUtils.deepHash(this.totalBytes) @@ -511,12 +532,11 @@ data class InternalStorageTaskSnapShot ( } /** Generated class from Pigeon that represents data sent in messages. */ -data class InternalListResult ( - val items: List, - val pageToken: String? = null, - val prefixs: List -) - { +data class InternalListResult( + val items: List, + val pageToken: String? = null, + val prefixs: List +) { companion object { fun fromList(pigeonVar_list: List): InternalListResult { val items = pigeonVar_list[0] as List @@ -525,13 +545,15 @@ data class InternalListResult ( return InternalListResult(items, pageToken, prefixs) } } + fun toList(): List { return listOf( - items, - pageToken, - prefixs, + items, + pageToken, + prefixs, ) } + override fun equals(other: Any?): Boolean { if (other == null || other.javaClass != javaClass) { return false @@ -540,7 +562,9 @@ data class InternalListResult ( return true } val other = other as InternalListResult - return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.items, other.items) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.pageToken, other.pageToken) && GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.prefixs, other.prefixs) + return GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.items, other.items) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.pageToken, other.pageToken) && + GeneratedAndroidFirebaseStoragePigeonUtils.deepEquals(this.prefixs, other.prefixs) } override fun hashCode(): Int { @@ -551,53 +575,39 @@ data class InternalListResult ( return result } } + private open class GeneratedAndroidFirebaseStoragePigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 129.toByte() -> { - return (readValue(buffer) as Long?)?.let { - InternalStorageTaskState.ofRaw(it.toInt()) - } + return (readValue(buffer) as Long?)?.let { InternalStorageTaskState.ofRaw(it.toInt()) } } 130.toByte() -> { - return (readValue(buffer) as? List)?.let { - InternalStorageFirebaseApp.fromList(it) - } + return (readValue(buffer) as? List)?.let { InternalStorageFirebaseApp.fromList(it) } } 131.toByte() -> { - return (readValue(buffer) as? List)?.let { - InternalStorageReference.fromList(it) - } + return (readValue(buffer) as? List)?.let { InternalStorageReference.fromList(it) } } 132.toByte() -> { - return (readValue(buffer) as? List)?.let { - InternalFullMetaData.fromList(it) - } + return (readValue(buffer) as? List)?.let { InternalFullMetaData.fromList(it) } } 133.toByte() -> { - return (readValue(buffer) as? List)?.let { - InternalListOptions.fromList(it) - } + return (readValue(buffer) as? List)?.let { InternalListOptions.fromList(it) } } 134.toByte() -> { - return (readValue(buffer) as? List)?.let { - InternalSettableMetadata.fromList(it) - } + return (readValue(buffer) as? List)?.let { InternalSettableMetadata.fromList(it) } } 135.toByte() -> { - return (readValue(buffer) as? List)?.let { - InternalStorageTaskSnapShot.fromList(it) - } + return (readValue(buffer) as? List)?.let { InternalStorageTaskSnapShot.fromList(it) } } 136.toByte() -> { - return (readValue(buffer) as? List)?.let { - InternalListResult.fromList(it) - } + return (readValue(buffer) as? List)?.let { InternalListResult.fromList(it) } } else -> super.readValueOfType(type, buffer) } } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { when (value) { is InternalStorageTaskState -> { stream.write(129) @@ -636,47 +646,168 @@ private open class GeneratedAndroidFirebaseStoragePigeonCodec : StandardMessageC } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ interface FirebaseStorageHostApi { - fun getReferencebyPath(app: InternalStorageFirebaseApp, path: String, bucket: String?, callback: (Result) -> Unit) - fun setMaxOperationRetryTime(app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit) - fun setMaxUploadRetryTime(app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit) - fun setMaxDownloadRetryTime(app: InternalStorageFirebaseApp, time: Long, callback: (Result) -> Unit) - fun useStorageEmulator(app: InternalStorageFirebaseApp, host: String, port: Long, callback: (Result) -> Unit) - fun referenceDelete(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) - fun referenceGetDownloadURL(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) - fun referenceGetMetaData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) - fun referenceList(app: InternalStorageFirebaseApp, reference: InternalStorageReference, options: InternalListOptions, callback: (Result) -> Unit) - fun referenceListAll(app: InternalStorageFirebaseApp, reference: InternalStorageReference, callback: (Result) -> Unit) - fun referenceGetData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, maxSize: Long, callback: (Result) -> Unit) - fun referencePutData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, data: ByteArray, settableMetaData: InternalSettableMetadata, handle: Long, callback: (Result) -> Unit) - fun referencePutString(app: InternalStorageFirebaseApp, reference: InternalStorageReference, data: String, format: Long, settableMetaData: InternalSettableMetadata, handle: Long, callback: (Result) -> Unit) - fun referencePutFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, filePath: String, settableMetaData: InternalSettableMetadata?, handle: Long, callback: (Result) -> Unit) - fun referenceDownloadFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, filePath: String, handle: Long, callback: (Result) -> Unit) - fun referenceUpdateMetadata(app: InternalStorageFirebaseApp, reference: InternalStorageReference, metadata: InternalSettableMetadata, callback: (Result) -> Unit) - fun taskPause(app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) - fun taskResume(app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) - fun taskCancel(app: InternalStorageFirebaseApp, handle: Long, callback: (Result>) -> Unit) + fun getReferencebyPath( + app: InternalStorageFirebaseApp, + path: String, + bucket: String?, + callback: (Result) -> Unit + ) + + fun setMaxOperationRetryTime( + app: InternalStorageFirebaseApp, + time: Long, + callback: (Result) -> Unit + ) + + fun setMaxUploadRetryTime( + app: InternalStorageFirebaseApp, + time: Long, + callback: (Result) -> Unit + ) + + fun setMaxDownloadRetryTime( + app: InternalStorageFirebaseApp, + time: Long, + callback: (Result) -> Unit + ) + + fun useStorageEmulator( + app: InternalStorageFirebaseApp, + host: String, + port: Long, + callback: (Result) -> Unit + ) + + fun referenceDelete( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit + ) + + fun referenceGetDownloadURL( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit + ) + + fun referenceGetMetaData( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit + ) + + fun referenceList( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + options: InternalListOptions, + callback: (Result) -> Unit + ) + + fun referenceListAll( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + callback: (Result) -> Unit + ) + + fun referenceGetData( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + maxSize: Long, + callback: (Result) -> Unit + ) + + fun referencePutData( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + data: ByteArray, + settableMetaData: InternalSettableMetadata, + handle: Long, + callback: (Result) -> Unit + ) + + fun referencePutString( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + data: String, + format: Long, + settableMetaData: InternalSettableMetadata, + handle: Long, + callback: (Result) -> Unit + ) + + fun referencePutFile( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + filePath: String, + settableMetaData: InternalSettableMetadata?, + handle: Long, + callback: (Result) -> Unit + ) + + fun referenceDownloadFile( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + filePath: String, + handle: Long, + callback: (Result) -> Unit + ) + + fun referenceUpdateMetadata( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference, + metadata: InternalSettableMetadata, + callback: (Result) -> Unit + ) + + fun taskPause( + app: InternalStorageFirebaseApp, + handle: Long, + callback: (Result>) -> Unit + ) + + fun taskResume( + app: InternalStorageFirebaseApp, + handle: Long, + callback: (Result>) -> Unit + ) + + fun taskCancel( + app: InternalStorageFirebaseApp, + handle: Long, + callback: (Result>) -> Unit + ) companion object { /** The codec used by FirebaseStorageHostApi. */ - val codec: MessageCodec by lazy { - GeneratedAndroidFirebaseStoragePigeonCodec() - } - /** Sets up an instance of `FirebaseStorageHostApi` to handle messages through the `binaryMessenger`. */ + val codec: MessageCodec by lazy { GeneratedAndroidFirebaseStoragePigeonCodec() } + /** + * Sets up an instance of `FirebaseStorageHostApi` to handle messages through the + * `binaryMessenger`. + */ @JvmOverloads - fun setUp(binaryMessenger: BinaryMessenger, api: FirebaseStorageHostApi?, messageChannelSuffix: String = "") { - val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" + fun setUp( + binaryMessenger: BinaryMessenger, + api: FirebaseStorageHostApi?, + messageChannelSuffix: String = "" + ) { + val separatedMessageChannelSuffix = + if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else "" run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val appArg = args[0] as InternalStorageFirebaseApp val pathArg = args[1] as String val bucketArg = args[2] as String? - api.getReferencebyPath(appArg, pathArg, bucketArg) { result: Result -> + api.getReferencebyPath(appArg, pathArg, bucketArg) { + result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) @@ -691,7 +822,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -711,7 +846,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -731,7 +870,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -751,7 +894,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -772,7 +919,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -792,7 +943,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -813,7 +968,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -834,14 +993,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val appArg = args[0] as InternalStorageFirebaseApp val referenceArg = args[1] as InternalStorageReference val optionsArg = args[2] as InternalListOptions - api.referenceList(appArg, referenceArg, optionsArg) { result: Result -> + api.referenceList(appArg, referenceArg, optionsArg) { result: Result + -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) @@ -856,7 +1020,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -877,7 +1045,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -899,7 +1071,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -908,7 +1084,8 @@ interface FirebaseStorageHostApi { val dataArg = args[2] as ByteArray val settableMetaDataArg = args[3] as InternalSettableMetadata val handleArg = args[4] as Long - api.referencePutData(appArg, referenceArg, dataArg, settableMetaDataArg, handleArg) { result: Result -> + api.referencePutData(appArg, referenceArg, dataArg, settableMetaDataArg, handleArg) { + result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) @@ -923,7 +1100,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -933,22 +1114,28 @@ interface FirebaseStorageHostApi { val formatArg = args[3] as Long val settableMetaDataArg = args[4] as InternalSettableMetadata val handleArg = args[5] as Long - api.referencePutString(appArg, referenceArg, dataArg, formatArg, settableMetaDataArg, handleArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) - } - } + api.referencePutString( + appArg, referenceArg, dataArg, formatArg, settableMetaDataArg, handleArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) + } + } } } else { channel.setMessageHandler(null) } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -957,22 +1144,28 @@ interface FirebaseStorageHostApi { val filePathArg = args[2] as String val settableMetaDataArg = args[3] as InternalSettableMetadata? val handleArg = args[4] as Long - api.referencePutFile(appArg, referenceArg, filePathArg, settableMetaDataArg, handleArg) { result: Result -> - val error = result.exceptionOrNull() - if (error != null) { - reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) - } else { - val data = result.getOrNull() - reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) - } - } + api.referencePutFile( + appArg, referenceArg, filePathArg, settableMetaDataArg, handleArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapResult(data)) + } + } } } else { channel.setMessageHandler(null) } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -980,7 +1173,8 @@ interface FirebaseStorageHostApi { val referenceArg = args[1] as InternalStorageReference val filePathArg = args[2] as String val handleArg = args[3] as Long - api.referenceDownloadFile(appArg, referenceArg, filePathArg, handleArg) { result: Result -> + api.referenceDownloadFile(appArg, referenceArg, filePathArg, handleArg) { + result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) @@ -995,14 +1189,19 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val appArg = args[0] as InternalStorageFirebaseApp val referenceArg = args[1] as InternalStorageReference val metadataArg = args[2] as InternalSettableMetadata - api.referenceUpdateMetadata(appArg, referenceArg, metadataArg) { result: Result -> + api.referenceUpdateMetadata(appArg, referenceArg, metadataArg) { + result: Result -> val error = result.exceptionOrNull() if (error != null) { reply.reply(GeneratedAndroidFirebaseStoragePigeonUtils.wrapError(error)) @@ -1017,7 +1216,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -1038,7 +1241,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List @@ -1059,7 +1266,11 @@ interface FirebaseStorageHostApi { } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel$separatedMessageChannelSuffix", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel$separatedMessageChannelSuffix", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List diff --git a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt index 5efa6415dae7..396b525d116b 100644 --- a/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt +++ b/packages/firebase_storage/firebase_storage/android/src/main/kotlin/io/flutter/plugins/firebase/storage/TaskStateChannelStreamHandler.kt @@ -8,16 +8,15 @@ import androidx.annotation.Nullable import com.google.firebase.storage.FirebaseStorage import com.google.firebase.storage.StorageException import com.google.firebase.storage.StorageTask -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.EventChannel.EventSink import io.flutter.plugin.common.EventChannel.StreamHandler import java.util.HashMap internal class TaskStateChannelStreamHandler( - private val flutterTask: FlutterFirebaseStorageTask, - private val androidStorage: FirebaseStorage, - task: Any, - private val identifier: String + private val flutterTask: FlutterFirebaseStorageTask, + private val androidStorage: FirebaseStorage, + task: Any, + private val identifier: String ) : StreamHandler { private val androidTask: StorageTask<*> = task as StorageTask<*> @@ -57,8 +56,10 @@ internal class TaskStateChannelStreamHandler( val event = getTaskEventMap(null, null) event[TASK_STATE_NAME] = InternalStorageTaskState.ERROR.raw val syntheticException: MutableMap = HashMap() - syntheticException["code"] = FlutterFirebaseStorageException.getCode(StorageException.ERROR_CANCELED) - syntheticException["message"] = FlutterFirebaseStorageException.getMessage(StorageException.ERROR_CANCELED) + syntheticException["code"] = + FlutterFirebaseStorageException.getCode(StorageException.ERROR_CANCELED) + syntheticException["message"] = + FlutterFirebaseStorageException.getMessage(StorageException.ERROR_CANCELED) event[TASK_ERROR] = syntheticException events.success(event) flutterTask.notifyCancelObjects() @@ -87,7 +88,10 @@ internal class TaskStateChannelStreamHandler( } } - private fun getTaskEventMap(@Nullable snapshot: Any?, @Nullable exception: Exception?): MutableMap { + private fun getTaskEventMap( + @Nullable snapshot: Any?, + @Nullable exception: Exception? + ): MutableMap { val arguments: MutableMap = HashMap() arguments[TASK_APP_NAME] = androidStorage.app.name if (snapshot != null) { @@ -99,5 +103,3 @@ internal class TaskStateChannelStreamHandler( return arguments } } - - diff --git a/packages/firebase_storage/firebase_storage/example/android/app/src/main/kotlin/io/flutter/plugins/firebasestorageexample/MainActivity.kt b/packages/firebase_storage/firebase_storage/example/android/app/src/main/kotlin/io/flutter/plugins/firebasestorageexample/MainActivity.kt index 7391f3a97ef9..4e41f73c96ae 100644 --- a/packages/firebase_storage/firebase_storage/example/android/app/src/main/kotlin/io/flutter/plugins/firebasestorageexample/MainActivity.kt +++ b/packages/firebase_storage/firebase_storage/example/android/app/src/main/kotlin/io/flutter/plugins/firebasestorageexample/MainActivity.kt @@ -2,4 +2,4 @@ package io.flutter.plugins.firebasestorageexample import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index cbd515861729..3bb7839d5742 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "13.4.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "13.4.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_storage", platforms: [ - .iOS("15.0"), + .iOS("15.0") ], products: [ - .library(name: "firebase-storage", targets: ["firebase_storage"]), + .library(name: "firebase-storage", targets: ["firebase_storage"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-gcs\""), ] - ), + ) ] ) diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift index 9b7693378a7a..ef81f56e31da 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FLTFirebaseStoragePlugin.swift @@ -63,8 +63,10 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt return Storage.storage(app: firApp, url: base) } - private func ref(app: InternalStorageFirebaseApp, - reference: InternalStorageReference) -> StorageReference { + private func ref( + app: InternalStorageFirebaseApp, + reference: InternalStorageReference + ) -> StorageReference { storage(app: app).reference(withPath: reference.fullPath) } @@ -72,36 +74,50 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt InternalStorageReference(bucket: ref.bucket, fullPath: ref.fullPath, name: ref.name) } - func getReferencebyPath(app: InternalStorageFirebaseApp, path: String, bucket: String?, - completion: @escaping (Result) -> Void) { + func getReferencebyPath( + app: InternalStorageFirebaseApp, path: String, bucket: String?, + completion: @escaping (Result) -> Void + ) { let r = storage(app: app).reference(withPath: path) - completion(.success(InternalStorageReference( - bucket: r.bucket, - fullPath: r.fullPath, - name: r.name - ))) - } - - func setMaxOperationRetryTime(app: InternalStorageFirebaseApp, time: Int64, - completion: @escaping (Result) -> Void) { + completion( + .success( + InternalStorageReference( + bucket: r.bucket, + fullPath: r.fullPath, + name: r.name + ) + ) + ) + } + + func setMaxOperationRetryTime( + app: InternalStorageFirebaseApp, time: Int64, + completion: @escaping (Result) -> Void + ) { storage(app: app).maxOperationRetryTime = TimeInterval(Double(time) / 1000.0) completion(.success(())) } - func setMaxUploadRetryTime(app: InternalStorageFirebaseApp, time: Int64, - completion: @escaping (Result) -> Void) { + func setMaxUploadRetryTime( + app: InternalStorageFirebaseApp, time: Int64, + completion: @escaping (Result) -> Void + ) { storage(app: app).maxUploadRetryTime = TimeInterval(Double(time) / 1000.0) completion(.success(())) } - func setMaxDownloadRetryTime(app: InternalStorageFirebaseApp, time: Int64, - completion: @escaping (Result) -> Void) { + func setMaxDownloadRetryTime( + app: InternalStorageFirebaseApp, time: Int64, + completion: @escaping (Result) -> Void + ) { storage(app: app).maxDownloadRetryTime = TimeInterval(Double(time) / 1000.0) completion(.success(())) } - func useStorageEmulator(app: InternalStorageFirebaseApp, host: String, port: Int64, - completion: @escaping (Result) -> Void) { + func useStorageEmulator( + app: InternalStorageFirebaseApp, host: String, port: Int64, + completion: @escaping (Result) -> Void + ) { guard emulatorBooted[app.bucket] == nil else { completion(.success(())) return @@ -112,40 +128,62 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt completion(.success(())) } - func referenceDelete(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) { + func referenceDelete( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void + ) { ref(app: app, reference: reference).delete { error in - if let e = error { completion(.failure(self.toFlutterError(e))) } - else { completion(.success(())) } + if let e = error { + completion(.failure(self.toFlutterError(e))) + } else { + completion(.success(())) + } } } - func referenceGetDownloadURL(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) { + func referenceGetDownloadURL( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void + ) { ref(app: app, reference: reference).downloadURL { url, error in - if let e = error { completion(.failure(self.toFlutterError(e))) } - else { completion(.success(url!.absoluteString.replacingOccurrences( - of: ":443", - with: "" - ))) } + if let e = error { + completion(.failure(self.toFlutterError(e))) + } else { + completion( + .success( + url!.absoluteString.replacingOccurrences( + of: ":443", + with: "" + ) + ) + ) + } } } - func referenceGetMetaData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) { + func referenceGetMetaData( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void + ) { ref(app: app, reference: reference).getMetadata { md, error in - if let e = error { completion(.failure(self.toFlutterError(e))) } else { + if let e = error { + completion(.failure(self.toFlutterError(e))) + } else { completion(.success(InternalFullMetaData(metadata: self.metaToDict(md)))) } } } - func referenceList(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - options: InternalListOptions, - completion: @escaping (Result) -> Void) { + func referenceList( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + options: InternalListOptions, + completion: @escaping (Result) -> Void + ) { let r = ref(app: app, reference: reference) let block: (StorageListResult?, Error?) -> Void = { list, error in - if let e = error { completion(.failure(self.toFlutterError(e))) } else { + if let e = error { + completion(.failure(self.toFlutterError(e))) + } else { completion(.success(self.listToPigeon(list!))) } } @@ -156,17 +194,24 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func referenceListAll(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) { + func referenceListAll( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void + ) { ref(app: app, reference: reference).listAll { list, error in - if let e = error { completion(.failure(self.toFlutterError(e))) } - else { completion(.success(self.listToPigeon(list!))) } + if let e = error { + completion(.failure(self.toFlutterError(e))) + } else { + completion(.success(self.listToPigeon(list!))) + } } } - func referenceGetData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - maxSize: Int64, - completion: @escaping (Result) -> Void) { + func referenceGetData( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + maxSize: Int64, + completion: @escaping (Result) -> Void + ) { ref(app: app, reference: reference).getData(maxSize: maxSize) { data, error in if let e = error { completion(.failure(self.toFlutterError(e))) @@ -178,83 +223,123 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func referencePutData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - data: FlutterStandardTypedData, settableMetaData: InternalSettableMetadata, - handle: Int64, completion: @escaping (Result) -> Void) { + func referencePutData( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: FlutterStandardTypedData, settableMetaData: InternalSettableMetadata, + handle: Int64, completion: @escaping (Result) -> Void + ) { let r = ref(app: app, reference: reference) let task = r.putData(data.data, metadata: toMeta(settableMetaData)) - completion(.success(registerTask( - task: task, - appName: r.storage.app.name, - handle: handle, - path: r.fullPath - ))) - } - - func referencePutString(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - data: String, format: Int64, settableMetaData: InternalSettableMetadata, - handle: Int64, completion: @escaping (Result) -> Void) { + completion( + .success( + registerTask( + task: task, + appName: r.storage.app.name, + handle: handle, + path: r.fullPath + ) + ) + ) + } + + func referencePutString( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: String, format: Int64, settableMetaData: InternalSettableMetadata, + handle: Int64, completion: @escaping (Result) -> Void + ) { let r = ref(app: app, reference: reference) let d: Data - if format == 1 { d = Data(base64Encoded: data) ?? Data() } - else if format == - 2 { - d = Data(base64Encoded: data.replacingOccurrences(of: "-", with: "+") - .replacingOccurrences(of: "_", with: "/") - .padding(toLength: ((data.count + 3) / 4) * 4, withPad: "=", startingAt: 0)) ?? Data() - } else { d = Data() } + if format == 1 { + d = Data(base64Encoded: data) ?? Data() + } else if format == 2 { + d = + Data( + base64Encoded: data.replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + .padding(toLength: ((data.count + 3) / 4) * 4, withPad: "=", startingAt: 0) + ) ?? Data() + } else { + d = Data() + } let task = r.putData(d, metadata: toMeta(settableMetaData)) - completion(.success(registerTask( - task: task, - appName: r.storage.app.name, - handle: handle, - path: r.fullPath - ))) - } - - func referencePutFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - filePath: String, settableMetaData: InternalSettableMetadata?, - handle: Int64, - completion: @escaping (Result) -> Void) { + completion( + .success( + registerTask( + task: task, + appName: r.storage.app.name, + handle: handle, + path: r.fullPath + ) + ) + ) + } + + func referencePutFile( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + filePath: String, settableMetaData: InternalSettableMetadata?, + handle: Int64, + completion: @escaping (Result) -> Void + ) { let r = ref(app: app, reference: reference) let url = URL(fileURLWithPath: filePath) let task: StorageUploadTask - if let md = settableMetaData { task = r.putFile(from: url, metadata: toMeta(md)) } - else { task = r.putFile(from: url) } - completion(.success(registerTask( - task: task, - appName: r.storage.app.name, - handle: handle, - path: r.fullPath - ))) - } - - func referenceDownloadFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - filePath: String, handle: Int64, - completion: @escaping (Result) -> Void) { + if let md = settableMetaData { + task = r.putFile(from: url, metadata: toMeta(md)) + } else { + task = r.putFile(from: url) + } + completion( + .success( + registerTask( + task: task, + appName: r.storage.app.name, + handle: handle, + path: r.fullPath + ) + ) + ) + } + + func referenceDownloadFile( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + filePath: String, handle: Int64, + completion: @escaping (Result) -> Void + ) { let r = ref(app: app, reference: reference) let url = URL(fileURLWithPath: filePath) let task = r.write(toFile: url) - completion(.success(registerTask( - task: task, - appName: r.storage.app.name, - handle: handle, - path: r.fullPath - ))) - } - - func referenceUpdateMetadata(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - metadata: InternalSettableMetadata, - completion: @escaping (Result) - -> Void) { + completion( + .success( + registerTask( + task: task, + appName: r.storage.app.name, + handle: handle, + path: r.fullPath + ) + ) + ) + } + + func referenceUpdateMetadata( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + metadata: InternalSettableMetadata, + completion: + @escaping (Result) + -> Void + ) { ref(app: app, reference: reference).updateMetadata(toMeta(metadata)) { md, error in - if let e = error { completion(.failure(self.toFlutterError(e))) } - else { completion(.success(InternalFullMetaData(metadata: self.metaToDict(md)))) } + if let e = error { + completion(.failure(self.toFlutterError(e))) + } else { + completion(.success(InternalFullMetaData(metadata: self.metaToDict(md)))) + } } } - func taskPause(app: InternalStorageFirebaseApp, handle: Int64, - completion: @escaping (Result<[String: Any], Error>) -> Void) { + func taskPause( + app: InternalStorageFirebaseApp, handle: Int64, + completion: @escaping (Result<[String: Any], Error>) -> Void + ) { if let task = handleToTask[handle] as? StorageUploadTask { task.pause() completion(.success(["status": true, "snapshot": currentSnapshot(handle: handle)])) @@ -266,8 +351,10 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func taskResume(app: InternalStorageFirebaseApp, handle: Int64, - completion: @escaping (Result<[String: Any], Error>) -> Void) { + func taskResume( + app: InternalStorageFirebaseApp, handle: Int64, + completion: @escaping (Result<[String: Any], Error>) -> Void + ) { if let task = handleToTask[handle] as? StorageUploadTask { task.resume() completion(.success(["status": true, "snapshot": currentSnapshot(handle: handle)])) @@ -279,8 +366,10 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt } } - func taskCancel(app: InternalStorageFirebaseApp, handle: Int64, - completion: @escaping (Result<[String: Any], Error>) -> Void) { + func taskCancel( + app: InternalStorageFirebaseApp, handle: Int64, + completion: @escaping (Result<[String: Any], Error>) -> Void + ) { if let task = handleToTask[handle] as? StorageUploadTask { task.cancel() if let id = handleToIdentifier[handle] { @@ -338,17 +427,21 @@ public final class FLTFirebaseStoragePlugin: NSObject, FlutterPlugin, FirebaseSt return InternalListResult(items: itemsOpt, pageToken: list.pageToken, prefixs: prefixesOpt) } - private func registerTask(task: StorageObservableTask, appName: String, handle: Int64, - path: String) -> String { + private func registerTask( + task: StorageObservableTask, appName: String, handle: Int64, + path: String + ) -> String { let uuid = UUID().uuidString let channelName = "plugins.flutter.io/firebase_storage/taskEvent/\(uuid)" let channel = FlutterEventChannel(name: channelName, binaryMessenger: messenger!) let storageInstance = Storage.storage(app: FLTFirebasePlugin.firebaseAppNamed(appName)!) - channel.setStreamHandler(TaskStateChannelStreamHandler( - task: task, - storage: storageInstance, - identifier: channelName - )) + channel.setStreamHandler( + TaskStateChannelStreamHandler( + task: task, + storage: storageInstance, + identifier: channelName + ) + ) eventChannels[channelName] = channel handleToTask[handle] = task as AnyObject handleToPath[handle] = path diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift index 71d157a36414..8012456b979d 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/FirebaseStorageMessages.g.swift @@ -89,7 +89,7 @@ func deepEqualsFirebaseStorageMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { case (nil, _), (_, nil): return false - case let (lhs as AnyObject, rhs as AnyObject) where lhs === rhs: + case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs: return true case is (Void, Void): @@ -131,7 +131,7 @@ func deepEqualsFirebaseStorageMessages(_ lhs: Any?, _ rhs: Any?) -> Bool { } return true - case let (lhs as Double, rhs as Double): + case (let lhs as Double, let rhs as Double): return doubleEqualsFirebaseStorageMessages(lhs, rhs) case let (lhsHashable, rhsHashable) as (AnyHashable, AnyHashable): @@ -221,8 +221,8 @@ struct InternalStorageFirebaseApp: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseStorageMessages(lhs.appName, rhs.appName) && - deepEqualsFirebaseStorageMessages( + return deepEqualsFirebaseStorageMessages(lhs.appName, rhs.appName) + && deepEqualsFirebaseStorageMessages( lhs.tenantId, rhs.tenantId ) && deepEqualsFirebaseStorageMessages(lhs.bucket, rhs.bucket) @@ -267,8 +267,8 @@ struct InternalStorageReference: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseStorageMessages(lhs.bucket, rhs.bucket) && - deepEqualsFirebaseStorageMessages( + return deepEqualsFirebaseStorageMessages(lhs.bucket, rhs.bucket) + && deepEqualsFirebaseStorageMessages( lhs.fullPath, rhs.fullPath ) && deepEqualsFirebaseStorageMessages(lhs.name, rhs.name) @@ -297,7 +297,7 @@ struct InternalFullMetaData: Hashable { func toList() -> [Any?] { [ - metadata, + metadata ] } @@ -347,8 +347,8 @@ struct InternalListOptions: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseStorageMessages(lhs.maxResults, rhs.maxResults) && - deepEqualsFirebaseStorageMessages( + return deepEqualsFirebaseStorageMessages(lhs.maxResults, rhs.maxResults) + && deepEqualsFirebaseStorageMessages( lhs.pageToken, rhs.pageToken ) @@ -420,16 +420,16 @@ struct InternalSettableMetadata: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseStorageMessages(lhs.cacheControl, rhs.cacheControl) && - deepEqualsFirebaseStorageMessages( + return deepEqualsFirebaseStorageMessages(lhs.cacheControl, rhs.cacheControl) + && deepEqualsFirebaseStorageMessages( lhs.contentDisposition, rhs.contentDisposition - ) && deepEqualsFirebaseStorageMessages(lhs.contentEncoding, rhs.contentEncoding) && - deepEqualsFirebaseStorageMessages( + ) && deepEqualsFirebaseStorageMessages(lhs.contentEncoding, rhs.contentEncoding) + && deepEqualsFirebaseStorageMessages( lhs.contentLanguage, rhs.contentLanguage - ) && deepEqualsFirebaseStorageMessages(lhs.contentType, rhs.contentType) && - deepEqualsFirebaseStorageMessages( + ) && deepEqualsFirebaseStorageMessages(lhs.contentType, rhs.contentType) + && deepEqualsFirebaseStorageMessages( lhs.customMetadata, rhs.customMetadata ) @@ -481,12 +481,12 @@ struct InternalStorageTaskSnapShot: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseStorageMessages(lhs.bytesTransferred, rhs.bytesTransferred) && - deepEqualsFirebaseStorageMessages( + return deepEqualsFirebaseStorageMessages(lhs.bytesTransferred, rhs.bytesTransferred) + && deepEqualsFirebaseStorageMessages( lhs.metadata, rhs.metadata - ) && deepEqualsFirebaseStorageMessages(lhs.state, rhs.state) && - deepEqualsFirebaseStorageMessages( + ) && deepEqualsFirebaseStorageMessages(lhs.state, rhs.state) + && deepEqualsFirebaseStorageMessages( lhs.totalBytes, rhs.totalBytes ) @@ -532,8 +532,8 @@ struct InternalListResult: Hashable { if Swift.type(of: lhs) != Swift.type(of: rhs) { return false } - return deepEqualsFirebaseStorageMessages(lhs.items, rhs.items) && - deepEqualsFirebaseStorageMessages( + return deepEqualsFirebaseStorageMessages(lhs.items, rhs.items) + && deepEqualsFirebaseStorageMessages( lhs.pageToken, rhs.pageToken ) && deepEqualsFirebaseStorageMessages(lhs.prefixs, rhs.prefixs) @@ -627,51 +627,70 @@ class FirebaseStorageMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecke /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseStorageHostApi { - func getReferencebyPath(app: InternalStorageFirebaseApp, path: String, bucket: String?, - completion: @escaping (Result) -> Void) - func setMaxOperationRetryTime(app: InternalStorageFirebaseApp, time: Int64, - completion: @escaping (Result) -> Void) - func setMaxUploadRetryTime(app: InternalStorageFirebaseApp, time: Int64, - completion: @escaping (Result) -> Void) - func setMaxDownloadRetryTime(app: InternalStorageFirebaseApp, time: Int64, - completion: @escaping (Result) -> Void) - func useStorageEmulator(app: InternalStorageFirebaseApp, host: String, port: Int64, - completion: @escaping (Result) -> Void) - func referenceDelete(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) - func referenceGetDownloadURL(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) - func referenceGetMetaData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) - func referenceList(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - options: InternalListOptions, - completion: @escaping (Result) -> Void) - func referenceListAll(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - completion: @escaping (Result) -> Void) - func referenceGetData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - maxSize: Int64, - completion: @escaping (Result) -> Void) - func referencePutData(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - data: FlutterStandardTypedData, settableMetaData: InternalSettableMetadata, - handle: Int64, completion: @escaping (Result) -> Void) - func referencePutString(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - data: String, format: Int64, settableMetaData: InternalSettableMetadata, - handle: Int64, completion: @escaping (Result) -> Void) - func referencePutFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - filePath: String, settableMetaData: InternalSettableMetadata?, - handle: Int64, completion: @escaping (Result) -> Void) - func referenceDownloadFile(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - filePath: String, handle: Int64, - completion: @escaping (Result) -> Void) - func referenceUpdateMetadata(app: InternalStorageFirebaseApp, reference: InternalStorageReference, - metadata: InternalSettableMetadata, - completion: @escaping (Result) -> Void) - func taskPause(app: InternalStorageFirebaseApp, handle: Int64, - completion: @escaping (Result<[String: Any], Error>) -> Void) - func taskResume(app: InternalStorageFirebaseApp, handle: Int64, - completion: @escaping (Result<[String: Any], Error>) -> Void) - func taskCancel(app: InternalStorageFirebaseApp, handle: Int64, - completion: @escaping (Result<[String: Any], Error>) -> Void) + func getReferencebyPath( + app: InternalStorageFirebaseApp, path: String, bucket: String?, + completion: @escaping (Result) -> Void) + func setMaxOperationRetryTime( + app: InternalStorageFirebaseApp, time: Int64, + completion: @escaping (Result) -> Void) + func setMaxUploadRetryTime( + app: InternalStorageFirebaseApp, time: Int64, + completion: @escaping (Result) -> Void) + func setMaxDownloadRetryTime( + app: InternalStorageFirebaseApp, time: Int64, + completion: @escaping (Result) -> Void) + func useStorageEmulator( + app: InternalStorageFirebaseApp, host: String, port: Int64, + completion: @escaping (Result) -> Void) + func referenceDelete( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) + func referenceGetDownloadURL( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) + func referenceGetMetaData( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) + func referenceList( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + options: InternalListOptions, + completion: @escaping (Result) -> Void) + func referenceListAll( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + completion: @escaping (Result) -> Void) + func referenceGetData( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + maxSize: Int64, + completion: @escaping (Result) -> Void) + func referencePutData( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: FlutterStandardTypedData, settableMetaData: InternalSettableMetadata, + handle: Int64, completion: @escaping (Result) -> Void) + func referencePutString( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + data: String, format: Int64, settableMetaData: InternalSettableMetadata, + handle: Int64, completion: @escaping (Result) -> Void) + func referencePutFile( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + filePath: String, settableMetaData: InternalSettableMetadata?, + handle: Int64, completion: @escaping (Result) -> Void) + func referenceDownloadFile( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + filePath: String, handle: Int64, + completion: @escaping (Result) -> Void) + func referenceUpdateMetadata( + app: InternalStorageFirebaseApp, reference: InternalStorageReference, + metadata: InternalSettableMetadata, + completion: @escaping (Result) -> Void) + func taskPause( + app: InternalStorageFirebaseApp, handle: Int64, + completion: @escaping (Result<[String: Any], Error>) -> Void) + func taskResume( + app: InternalStorageFirebaseApp, handle: Int64, + completion: @escaping (Result<[String: Any], Error>) -> Void) + func taskCancel( + app: InternalStorageFirebaseApp, handle: Int64, + completion: @escaping (Result<[String: Any], Error>) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -682,11 +701,14 @@ class FirebaseStorageHostApiSetup { /// Sets up an instance of `FirebaseStorageHostApi` to handle messages through the /// `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FirebaseStorageHostApi?, - messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: FirebaseStorageHostApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" let getReferencebyPathChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.getReferencebyPath\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -698,9 +720,9 @@ class FirebaseStorageHostApiSetup { let bucketArg: String? = nilOrValue(args[2]) api.getReferencebyPath(app: appArg, path: pathArg, bucket: bucketArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -709,7 +731,8 @@ class FirebaseStorageHostApiSetup { getReferencebyPathChannel.setMessageHandler(nil) } let setMaxOperationRetryTimeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxOperationRetryTime\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -722,7 +745,7 @@ class FirebaseStorageHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -731,7 +754,8 @@ class FirebaseStorageHostApiSetup { setMaxOperationRetryTimeChannel.setMessageHandler(nil) } let setMaxUploadRetryTimeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxUploadRetryTime\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -744,7 +768,7 @@ class FirebaseStorageHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -753,7 +777,8 @@ class FirebaseStorageHostApiSetup { setMaxUploadRetryTimeChannel.setMessageHandler(nil) } let setMaxDownloadRetryTimeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.setMaxDownloadRetryTime\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -766,7 +791,7 @@ class FirebaseStorageHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -775,7 +800,8 @@ class FirebaseStorageHostApiSetup { setMaxDownloadRetryTimeChannel.setMessageHandler(nil) } let useStorageEmulatorChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.useStorageEmulator\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -789,7 +815,7 @@ class FirebaseStorageHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -798,7 +824,8 @@ class FirebaseStorageHostApiSetup { useStorageEmulatorChannel.setMessageHandler(nil) } let referenceDeleteChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDelete\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -811,7 +838,7 @@ class FirebaseStorageHostApiSetup { switch result { case .success: reply(wrapResult(nil)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -820,7 +847,8 @@ class FirebaseStorageHostApiSetup { referenceDeleteChannel.setMessageHandler(nil) } let referenceGetDownloadURLChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetDownloadURL\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -831,9 +859,9 @@ class FirebaseStorageHostApiSetup { let referenceArg = args[1] as! InternalStorageReference api.referenceGetDownloadURL(app: appArg, reference: referenceArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -842,7 +870,8 @@ class FirebaseStorageHostApiSetup { referenceGetDownloadURLChannel.setMessageHandler(nil) } let referenceGetMetaDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetMetaData\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -853,9 +882,9 @@ class FirebaseStorageHostApiSetup { let referenceArg = args[1] as! InternalStorageReference api.referenceGetMetaData(app: appArg, reference: referenceArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -864,7 +893,8 @@ class FirebaseStorageHostApiSetup { referenceGetMetaDataChannel.setMessageHandler(nil) } let referenceListChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceList\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -876,9 +906,9 @@ class FirebaseStorageHostApiSetup { let optionsArg = args[2] as! InternalListOptions api.referenceList(app: appArg, reference: referenceArg, options: optionsArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -887,7 +917,8 @@ class FirebaseStorageHostApiSetup { referenceListChannel.setMessageHandler(nil) } let referenceListAllChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceListAll\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -898,9 +929,9 @@ class FirebaseStorageHostApiSetup { let referenceArg = args[1] as! InternalStorageReference api.referenceListAll(app: appArg, reference: referenceArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -909,7 +940,8 @@ class FirebaseStorageHostApiSetup { referenceListAllChannel.setMessageHandler(nil) } let referenceGetDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceGetData\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -921,9 +953,9 @@ class FirebaseStorageHostApiSetup { let maxSizeArg = args[2] as! Int64 api.referenceGetData(app: appArg, reference: referenceArg, maxSize: maxSizeArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -932,7 +964,8 @@ class FirebaseStorageHostApiSetup { referenceGetDataChannel.setMessageHandler(nil) } let referencePutDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutData\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -952,9 +985,9 @@ class FirebaseStorageHostApiSetup { handle: handleArg ) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -963,7 +996,8 @@ class FirebaseStorageHostApiSetup { referencePutDataChannel.setMessageHandler(nil) } let referencePutStringChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutString\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -985,9 +1019,9 @@ class FirebaseStorageHostApiSetup { handle: handleArg ) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -996,7 +1030,8 @@ class FirebaseStorageHostApiSetup { referencePutStringChannel.setMessageHandler(nil) } let referencePutFileChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referencePutFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1016,9 +1051,9 @@ class FirebaseStorageHostApiSetup { handle: handleArg ) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1027,7 +1062,8 @@ class FirebaseStorageHostApiSetup { referencePutFileChannel.setMessageHandler(nil) } let referenceDownloadFileChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceDownloadFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1045,9 +1081,9 @@ class FirebaseStorageHostApiSetup { handle: handleArg ) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1056,7 +1092,8 @@ class FirebaseStorageHostApiSetup { referenceDownloadFileChannel.setMessageHandler(nil) } let referenceUpdateMetadataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.referenceUpdateMetadata\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1067,12 +1104,14 @@ class FirebaseStorageHostApiSetup { let referenceArg = args[1] as! InternalStorageReference let metadataArg = args[2] as! InternalSettableMetadata api - .referenceUpdateMetadata(app: appArg, reference: referenceArg, - metadata: metadataArg) { result in + .referenceUpdateMetadata( + app: appArg, reference: referenceArg, + metadata: metadataArg + ) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1081,7 +1120,8 @@ class FirebaseStorageHostApiSetup { referenceUpdateMetadataChannel.setMessageHandler(nil) } let taskPauseChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskPause\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1092,9 +1132,9 @@ class FirebaseStorageHostApiSetup { let handleArg = args[1] as! Int64 api.taskPause(app: appArg, handle: handleArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1103,7 +1143,8 @@ class FirebaseStorageHostApiSetup { taskPauseChannel.setMessageHandler(nil) } let taskResumeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskResume\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1114,9 +1155,9 @@ class FirebaseStorageHostApiSetup { let handleArg = args[1] as! Int64 api.taskResume(app: appArg, handle: handleArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } @@ -1125,7 +1166,8 @@ class FirebaseStorageHostApiSetup { taskResumeChannel.setMessageHandler(nil) } let taskCancelChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel\(channelSuffix)", + name: + "dev.flutter.pigeon.firebase_storage_platform_interface.FirebaseStorageHostApi.taskCancel\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec ) @@ -1136,9 +1178,9 @@ class FirebaseStorageHostApiSetup { let handleArg = args[1] as! Int64 api.taskCancel(app: appArg, handle: handleArg) { result in switch result { - case let .success(res): + case .success(let res): reply(wrapResult(res)) - case let .failure(error): + case .failure(let error): reply(wrapError(error)) } } diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/TaskStateChannelStreamHandler.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/TaskStateChannelStreamHandler.swift index 9cc69b046a25..21acfcbe6f32 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/TaskStateChannelStreamHandler.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Sources/firebase_storage/TaskStateChannelStreamHandler.swift @@ -27,11 +27,13 @@ final class TaskStateChannelStreamHandler: NSObject, FlutterStreamHandler { self.identifier = identifier } - func onListen(withArguments arguments: Any?, - eventSink events: @escaping FlutterEventSink) -> FlutterError? { + func onListen( + withArguments arguments: Any?, + eventSink events: @escaping FlutterEventSink + ) -> FlutterError? { successHandle = task.observe(.success) { snapshot in events([ - "taskState": 2, // success + "taskState": 2, // success "appName": self.storage.app.name, "snapshot": self.parseTaskSnapshot(snapshot), ]) @@ -41,7 +43,7 @@ final class TaskStateChannelStreamHandler: NSObject, FlutterStreamHandler { let err = snapshot.error as NSError? let errorDict: [String: Any] = self.errorDict(err) events([ - "taskState": 4, // error (including cancellations as errors per platform contract) + "taskState": 4, // error (including cancellations as errors per platform contract) "appName": self.storage.app.name, "error": errorDict, ]) @@ -49,14 +51,14 @@ final class TaskStateChannelStreamHandler: NSObject, FlutterStreamHandler { } pausedHandle = task.observe(.pause) { snapshot in events([ - "taskState": 0, // paused + "taskState": 0, // paused "appName": self.storage.app.name, "snapshot": self.parseTaskSnapshot(snapshot), ]) } progressHandle = task.observe(.progress) { snapshot in events([ - "taskState": 1, // running + "taskState": 1, // running "appName": self.storage.app.name, "snapshot": self.parseTaskSnapshot(snapshot), ]) @@ -105,7 +107,8 @@ final class TaskStateChannelStreamHandler: NSObject, FlutterStreamHandler { } let code: String if error.domain == StorageErrorDomain, - let storageCode = StorageErrorCode(rawValue: error.code) { + let storageCode = StorageErrorCode(rawValue: error.code) + { switch storageCode { case .objectNotFound: code = "object-not-found" case .bucketNotFound: code = "bucket-not-found" diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index 37f3c0dd99a3..a37ec5f226b2 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -7,19 +7,19 @@ import PackageDescription -let library_version = "13.4.1" -let firebase_sdk_version: Version = "12.13.0" +let libraryVersion = "13.4.1" +let firebaseSdkVersion: Version = "12.13.0" let package = Package( name: "firebase_storage", platforms: [ - .macOS("10.15"), + .macOS("10.15") ], products: [ - .library(name: "firebase-storage", targets: ["firebase_storage"]), + .library(name: "firebase-storage", targets: ["firebase_storage"]) ], dependencies: [ - .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebase_sdk_version), + .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -30,13 +30,13 @@ let package = Package( .product(name: "firebase-core", package: "firebase_core"), ], resources: [ - .process("Resources"), + .process("Resources") ], cSettings: [ .headerSearchPath("include"), - .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_VERSION", to: "\"\(libraryVersion)\""), .define("LIBRARY_NAME", to: "\"flutter-fire-gcs\""), ] - ), + ) ] ) From a780d9fed78f9c5690d45972009b66abe0ffd2d0 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 06:47:04 +0000 Subject: [PATCH 088/137] ci: unpin Flutter version for web e2e pipeline (#18314) * ci: update flutter version to 3.41.9 in CI workflows * Trigger CI * ci: update flutter drive command to use --release flag in CI workflows * ci: remove --release flag from flutter drive command in CI workflows * ci: add --verbose flag to flutter drive command in CI workflows for detailed output * ci: remove --verbose flag from flutter drive command in CI workflows and add version checks for chromedriver and Chrome * ci: downgrade flutter version to 3.41.6 in CI workflows and add Chrome installation for testing * ci: add flutter version check in CI workflows for better debugging * ci: add flutter version output to CI workflows for improved debugging * ci: remove Chrome installation step from CI workflows to streamline testing process * ci: remove flutter version specification and version checks from CI workflows to simplify setup --- .github/workflows/e2e_tests_pipeline.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index dc72a114b741..a70f6ef5c6a6 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -123,7 +123,6 @@ jobs: - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff with: channel: 'stable' - flutter-version: '3.41.9' cache: true cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" From 2293dee00767cc6eebd57a340eb2b72bdab41d52 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 07:36:06 +0000 Subject: [PATCH 089/137] feat(firestore): add support for new array expressions (#18283) * fix(core, iOS): use namespaced iOS Pigeon header import * feat(firestore): add support for new array expressions * refactor(firestore): remove Variable class and update array expression aliases * refactor(firestore): update pipeline expressions test to use arraySlice and remove unused expressions * refactor(firestore): remove variable expression handling from multiple platforms --- .../firestore/utils/ExpressionParsers.java | 45 ++++- .../cloud_firestore/FLTPipelineParser.m | 80 +++++++++ .../lib/src/pipeline_expression.dart | 167 ++++++++++++++++++ .../pipeline/pipeline_expressions_e2e.dart | 18 ++ .../test/pipeline_expression_test.dart | 70 ++++++++ .../lib/src/interop/firestore_interop.dart | 6 + .../src/pipeline_expression_parser_web.dart | 35 ++++ 7 files changed, 419 insertions(+), 2 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java index f27d5fd2a42b..9aeb352a9785 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java @@ -274,8 +274,49 @@ Expression parseExpression(@NonNull Map expressionMap) { case "array_sum": return Expression.arraySum(parseChild(args, "expression")); case "array_slice": - throw new UnsupportedOperationException( - "Expression type 'array_slice' is not supported on Android Firestore pipeline API"); + { + Expression array = parseChild(args, "expression"); + Expression offset = parseChild(args, "offset"); + Map lengthMap = (Map) args.get("length"); + if (lengthMap == null) { + return array.arraySliceToEnd(offset); + } + return array.arraySlice(offset, parseExpression(lengthMap)); + } + case "array_filter": + { + Expression array = parseChild(args, "expression"); + String alias = (String) args.get("alias"); + Map filterMap = (Map) args.get("filter"); + if (alias == null || filterMap == null) { + throw new IllegalArgumentException("array_filter requires alias and filter"); + } + return array.arrayFilter(alias, parseBooleanExpression(filterMap)); + } + case "array_transform": + { + Expression array = parseChild(args, "expression"); + String elementAlias = (String) args.get("element_alias"); + Map transformMap = (Map) args.get("transform"); + if (elementAlias == null || transformMap == null) { + throw new IllegalArgumentException( + "array_transform requires element_alias and transform"); + } + return array.arrayTransform(elementAlias, parseExpression(transformMap)); + } + case "array_transform_with_index": + { + Expression array = parseChild(args, "expression"); + String elementAlias = (String) args.get("element_alias"); + String indexAlias = (String) args.get("index_alias"); + Map transformMap = (Map) args.get("transform"); + if (elementAlias == null || indexAlias == null || transformMap == null) { + throw new IllegalArgumentException( + "array_transform_with_index requires element_alias, index_alias, and transform"); + } + return array.arrayTransformWithIndex( + elementAlias, indexAlias, parseExpression(transformMap)); + } case "if_absent": { Map exprMap = (Map) args.get("expression"); diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m index cc3d36f510dd..22449aaf96bf 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m @@ -486,6 +486,86 @@ - (FIRExprBridge *)parseExpression:(NSDictionary *)map error:(NS return FLTNewFunctionExprBridge(@"array_concat", all); } + // ------------------------------------------------------------------------- + // expression + offset (+ optional length): array_slice + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array_slice"]) { + id exprMap = args[@"expression"]; + id offsetMap = args[@"offset"]; + id lengthMap = args[@"length"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || + ![offsetMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"array_slice requires expression and offset"); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *offset = [self parseExpression:offsetMap error:error]; + if (!expr || !offset) return nil; + NSMutableArray *sliceArgs = + [NSMutableArray arrayWithObjects:expr, offset, nil]; + if ([lengthMap isKindOfClass:[NSDictionary class]]) { + FIRExprBridge *length = [self parseExpression:lengthMap error:error]; + if (!length) return nil; + [sliceArgs addObject:length]; + } + return FLTNewFunctionExprBridge(@"array_slice", sliceArgs); + } + + // ------------------------------------------------------------------------- + // expression + alias + filter: array_filter + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array_filter"]) { + id exprMap = args[@"expression"]; + NSString *alias = args[@"alias"]; + id filterMap = args[@"filter"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || ![alias isKindOfClass:[NSString class]] || + ![filterMap isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"array_filter requires expression, alias, and filter"); + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *filter = [self parseBooleanExpression:filterMap error:error]; + if (!expr || !filter) return nil; + return FLTNewFunctionExprBridge(@"array_filter", + @[ expr, [[FIRConstantBridge alloc] init:alias], filter ]); + } + + // ------------------------------------------------------------------------- + // expression + aliases + transform: array_transform / array_transform_with_index + // ------------------------------------------------------------------------- + if ([name isEqualToString:@"array_transform"] || + [name isEqualToString:@"array_transform_with_index"]) { + id exprMap = args[@"expression"]; + NSString *elementAlias = args[@"element_alias"]; + NSString *indexAlias = args[@"index_alias"]; + id transformMap = args[@"transform"]; + BOOL withIndex = [name isEqualToString:@"array_transform_with_index"]; + if (![exprMap isKindOfClass:[NSDictionary class]] || + ![elementAlias isKindOfClass:[NSString class]] || + (withIndex && ![indexAlias isKindOfClass:[NSString class]]) || + ![transformMap isKindOfClass:[NSDictionary class]]) { + if (error) { + NSString *message = + withIndex + ? @"array_transform_with_index requires expression, element_alias, index_alias, " + @"and transform" + : @"array_transform requires expression, element_alias, and transform"; + *error = parseError(message); + } + return nil; + } + FIRExprBridge *expr = [self parseExpression:exprMap error:error]; + FIRExprBridge *transform = [self parseExpression:transformMap error:error]; + if (!expr || !transform) return nil; + NSMutableArray *transformArgs = + [NSMutableArray arrayWithObjects:expr, [[FIRConstantBridge alloc] init:elementAlias], nil]; + if (withIndex) { + [transformArgs addObject:[[FIRConstantBridge alloc] init:indexAlias]]; + } + [transformArgs addObject:transform]; + return FLTNewFunctionExprBridge(name, transformArgs); + } + // ------------------------------------------------------------------------- // elements[]: array (construct) — Expression.array([...]) from Dart // ------------------------------------------------------------------------- diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart index 4f8f85e49c1e..0690924f2011 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart @@ -701,6 +701,41 @@ abstract class Expression implements PipelineSerializable { return _ArrayIndexOfAllExpression(this, _toExpression(element)); } + /// Returns a slice of this array starting at [offset]. + /// + /// When [length] is provided, at most [length] elements are returned. + Expression arraySlice(Object? offset, [Object? length]) { + return _ArraySliceExpression( + this, + _toExpression(offset), + length == null ? null : _toExpression(length), + ); + } + + /// Filters this array by evaluating [filter] for each element bound to [alias]. + Expression arrayFilter(String alias, BooleanExpression filter) { + return _ArrayFilterExpression(this, alias, filter); + } + + /// Transforms each element of this array bound to [elementAlias]. + Expression arrayTransform(String elementAlias, Expression transform) { + return _ArrayTransformExpression(this, elementAlias, null, transform); + } + + /// Transforms each element of this array with both element and index aliases. + Expression arrayTransformWithIndex( + String elementAlias, + String indexAlias, + Expression transform, + ) { + return _ArrayTransformExpression( + this, + elementAlias, + indexAlias, + transform, + ); + } + // ============================================================================ // AGGREGATE FUNCTIONS // ============================================================================ @@ -1596,6 +1631,52 @@ abstract class Expression implements PipelineSerializable { ); } + /// Returns a slice of [array] starting at [offset]. + static Expression arraySliceStatic( + Expression array, + Object? offset, [ + Object? length, + ]) { + return _ArraySliceExpression( + array, + _toExpression(offset), + length == null ? null : _toExpression(length), + ); + } + + /// Filters [array] by evaluating [filter] for each element bound to [alias]. + static Expression arrayFilterStatic( + Expression array, + String alias, + BooleanExpression filter, + ) { + return _ArrayFilterExpression(array, alias, filter); + } + + /// Transforms each element of [array] bound to [elementAlias]. + static Expression arrayTransformStatic( + Expression array, + String elementAlias, + Expression transform, + ) { + return _ArrayTransformExpression(array, elementAlias, null, transform); + } + + /// Transforms each element of [array] with both element and index aliases. + static Expression arrayTransformWithIndexStatic( + Expression array, + String elementAlias, + String indexAlias, + Expression transform, + ) { + return _ArrayTransformExpression( + array, + elementAlias, + indexAlias, + transform, + ); + } + /// Creates a raw/custom function expression static Expression rawFunction( String name, @@ -2423,6 +2504,92 @@ class _ArraySumExpression extends FunctionExpression { } } +/// Represents an array slice expression. +class _ArraySliceExpression extends FunctionExpression { + final Expression expression; + final Expression offset; + final Expression? sliceLength; + + _ArraySliceExpression(this.expression, this.offset, this.sliceLength); + + @override + String get name => 'array_slice'; + + @override + Map toMap() { + final args = { + 'expression': expression.toMap(), + 'offset': offset.toMap(), + }; + if (sliceLength != null) { + args['length'] = sliceLength!.toMap(); + } + return { + 'name': name, + 'args': args, + }; + } +} + +/// Represents an array filter expression. +class _ArrayFilterExpression extends FunctionExpression { + final Expression expression; + final String elementAlias; + final BooleanExpression filter; + + _ArrayFilterExpression(this.expression, this.elementAlias, this.filter); + + @override + String get name => 'array_filter'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'expression': expression.toMap(), + 'alias': elementAlias, + 'filter': filter.toMap(), + }, + }; + } +} + +/// Represents an array transform expression. +class _ArrayTransformExpression extends FunctionExpression { + final Expression expression; + final String elementAlias; + final String? indexAlias; + final Expression transform; + + _ArrayTransformExpression( + this.expression, + this.elementAlias, + this.indexAlias, + this.transform, + ); + + @override + String get name => + indexAlias == null ? 'array_transform' : 'array_transform_with_index'; + + @override + Map toMap() { + final args = { + 'expression': expression.toMap(), + 'element_alias': elementAlias, + 'transform': transform.toMap(), + }; + if (indexAlias != null) { + args['index_alias'] = indexAlias; + } + return { + 'name': name, + 'args': args, + }; + } +} + // ============================================================================ // CONDITIONAL / LOGIC OPERATION EXPRESSION CLASSES // ============================================================================ diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart index e67e2fbdf0f5..4835839efb89 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_expressions_e2e.dart @@ -820,6 +820,24 @@ void runPipelineExpressionsTests() { expect(snapshot.result[0].data()!['tags_rev'], ['q', 'p']); }); + test('addFields with arraySlice returns sliced array', () async { + final snapshot = await firestore + .pipeline() + .collection('pipeline-e2e') + .where(Expression.field('test').equalValue('expressions')) + .where(Expression.field('score').equalValue(50)) + .addFields(Expression.field('arr').arraySlice(1, 2).as('arr_slice')) + .limit(1) + .execute(); + + expectResultCount(snapshot, 1); + expectResultsData(snapshot, [ + { + 'arr_slice': [4, 6], + }, + ]); + }); + test( 'arraySum addFields succeeds on Android', () async { diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart index dbd4f1729424..067efa4d1cb7 100644 --- a/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart @@ -660,6 +660,76 @@ void main() { expect(expr.toMap()['name'], 'array_reverse'); expect(expr.toMap()['args']['expression']['args']['field'], 'order'); }); + + test('arraySlice serializes correctly', () { + final expr = Field('items').arraySlice(1, Field('count')); + expect(expr.toMap(), { + 'name': 'array_slice', + 'args': { + 'expression': Field('items').toMap(), + 'offset': Constant(1).toMap(), + 'length': Field('count').toMap(), + }, + }); + }); + + test('arraySlice without length serializes correctly', () { + final expr = Field('items').arraySlice(1); + expect(expr.toMap(), { + 'name': 'array_slice', + 'args': { + 'expression': Field('items').toMap(), + 'offset': Constant(1).toMap(), + }, + }); + }); + + test('arrayFilter serializes correctly', () { + final expr = Field('scores').arrayFilter( + 'item', + Field('item').greaterThanValue(10), + ); + expect(expr.toMap(), { + 'name': 'array_filter', + 'args': { + 'expression': Field('scores').toMap(), + 'alias': 'item', + 'filter': Field('item').greaterThanValue(10).toMap(), + }, + }); + }); + + test('arrayTransform serializes correctly', () { + final expr = Field('scores').arrayTransform( + 'score', + Field('score').multiplyNumber(10), + ); + expect(expr.toMap(), { + 'name': 'array_transform', + 'args': { + 'expression': Field('scores').toMap(), + 'element_alias': 'score', + 'transform': Field('score').multiplyNumber(10).toMap(), + }, + }); + }); + + test('arrayTransformWithIndex serializes correctly', () { + final expr = Field('scores').arrayTransformWithIndex( + 'score', + 'i', + Field('score').add(Field('i')), + ); + expect(expr.toMap(), { + 'name': 'array_transform_with_index', + 'args': { + 'expression': Field('scores').toMap(), + 'element_alias': 'score', + 'index_alias': 'i', + 'transform': Field('score').add(Field('i')).toMap(), + }, + }); + }); }); group('Numeric expressions', () { diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart index a4069ebab335..cd4ee712c568 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart @@ -483,6 +483,12 @@ extension type ExpressionJsImpl._(JSObject _) implements JSObject { external ExpressionJsImpl arrayIndexOf(JSAny element); external ExpressionJsImpl arrayLastIndexOf(JSAny element); external ExpressionJsImpl arrayIndexOfAll(JSAny element); + external ExpressionJsImpl arraySlice(JSAny offset, [JSAny? length]); + external ExpressionJsImpl arrayFilter(JSString alias, JSAny filter); + external ExpressionJsImpl arrayTransform( + JSString elementAlias, JSAny transform); + external ExpressionJsImpl arrayTransformWithIndex( + JSString elementAlias, JSString indexAlias, JSAny transform); external ExpressionJsImpl mapSet(JSAny key, JSAny value); external ExpressionJsImpl mapEntries(); } diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart index 722c28095d02..3460778faba9 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart @@ -360,6 +360,41 @@ class PipelineExpressionParserWeb { case 'array_index_of_all': return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) .arrayIndexOfAll(_expr(argsMap, 'element')); + case 'array_slice': + { + final base = _expr(argsMap, _kExpression) as interop.ExpressionJsImpl; + final length = argsMap['length']; + if (length == null) { + return base.arraySlice(_expr(argsMap, 'offset')); + } + return base.arraySlice( + _expr(argsMap, 'offset'), + toExpression(length as Map), + ); + } + case 'array_filter': + { + final filter = + toBooleanExpression(argsMap['filter'] as Map); + if (filter == null) { + throw UnsupportedError('array_filter requires a boolean filter'); + } + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayFilter((argsMap['alias'] as String).toJS, filter); + } + case 'array_transform': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayTransform( + (argsMap['element_alias'] as String).toJS, + _expr(argsMap, 'transform'), + ); + case 'array_transform_with_index': + return (_expr(argsMap, _kExpression) as interop.ExpressionJsImpl) + .arrayTransformWithIndex( + (argsMap['element_alias'] as String).toJS, + (argsMap['index_alias'] as String).toJS, + _expr(argsMap, 'transform'), + ); default: throw FirebaseException( plugin: 'cloud_firestore', From 3b77147bc00bb19af5f4821436a1a4cdd8ff6791 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 08:51:09 +0000 Subject: [PATCH 090/137] fix(auth, android): update token retrieval in PigeonParser to handle Number type correctly (#18328) --- .../java/io/flutter/plugins/firebase/auth/PigeonParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java index 8c510f912e9d..4c9e102a54ae 100644 --- a/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java +++ b/packages/firebase_auth/firebase_auth/android/src/main/java/io/flutter/plugins/firebase/auth/PigeonParser.java @@ -179,7 +179,7 @@ private static String parsePhotoUrl(Uri photoUri) { static AuthCredential getCredential(Map credentialMap) { // If the credential map contains a token, it means a native one has been stored if (credentialMap.get(Constants.TOKEN) != null) { - int token = (int) credentialMap.get(Constants.TOKEN); + int token = ((Number) credentialMap.get(Constants.TOKEN)).intValue(); AuthCredential credential = FlutterFirebaseAuthPlugin.authCredentials.get(token); if (credential == null) { From b37722db13548aca57b3a24ba0f27b5de021be02 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 08:51:36 +0000 Subject: [PATCH 091/137] feat(messaging, web): add support for custom service worker script path in `getToken` method (#18290) --- .../firebase_messaging/lib/src/messaging.dart | 6 ++++ .../test/firebase_messaging_test.dart | 29 +++++++++++++++++-- .../firebase_messaging/test/mock.dart | 7 +++-- .../method_channel_messaging.dart | 1 + .../platform_interface_messaging.dart | 1 + .../lib/firebase_messaging_web.dart | 6 ++-- .../lib/src/interop/messaging.dart | 22 ++++++++++---- .../lib/src/interop/messaging_interop.dart | 3 ++ 8 files changed, 63 insertions(+), 12 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart b/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart index 4205bdd61bc1..de82a44a0dc1 100644 --- a/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart +++ b/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart @@ -114,11 +114,17 @@ class FirebaseMessaging extends FirebasePluginPlatform { /// Returns the default FCM token for this device. /// /// On web, a [vapidKey] is required. + /// + /// On web, a custom messaging service worker can be registered with + /// [serviceWorkerScriptPath]. This must point to a JavaScript file in the + /// root of the app's `web` directory. Future getToken({ String? vapidKey, + String? serviceWorkerScriptPath, }) { return _delegate.getToken( vapidKey: vapidKey, + serviceWorkerScriptPath: serviceWorkerScriptPath, ); } diff --git a/packages/firebase_messaging/firebase_messaging/test/firebase_messaging_test.dart b/packages/firebase_messaging/firebase_messaging/test/firebase_messaging_test.dart index af53b2720741..f3e1dd4204bb 100644 --- a/packages/firebase_messaging/firebase_messaging/test/firebase_messaging_test.dart +++ b/packages/firebase_messaging/firebase_messaging/test/firebase_messaging_test.dart @@ -99,12 +99,35 @@ void main() { group('getToken', () { test('verify delegate method is called with correct args', () async { const vapidKey = 'test-vapid-key'; - when(kMockMessagingPlatform.getToken(vapidKey: anyNamed('vapidKey'))) - .thenAnswer((_) => Future.value('')); + when(kMockMessagingPlatform.getToken( + vapidKey: anyNamed('vapidKey'), + serviceWorkerScriptPath: anyNamed('serviceWorkerScriptPath'), + )).thenAnswer((_) => Future.value('')); await messaging!.getToken(vapidKey: vapidKey); - verify(kMockMessagingPlatform.getToken(vapidKey: vapidKey)); + verify(kMockMessagingPlatform.getToken( + vapidKey: vapidKey, + serviceWorkerScriptPath: null, + )); + }); + + test('verify delegate method is called with service worker path', + () async { + const serviceWorkerScriptPath = 'custom-messaging-sw.js'; + when(kMockMessagingPlatform.getToken( + vapidKey: anyNamed('vapidKey'), + serviceWorkerScriptPath: anyNamed('serviceWorkerScriptPath'), + )).thenAnswer((_) => Future.value('')); + + await messaging!.getToken( + serviceWorkerScriptPath: serviceWorkerScriptPath, + ); + + verify(kMockMessagingPlatform.getToken( + vapidKey: null, + serviceWorkerScriptPath: serviceWorkerScriptPath, + )); }); }); diff --git a/packages/firebase_messaging/firebase_messaging/test/mock.dart b/packages/firebase_messaging/firebase_messaging/test/mock.dart index 2493e87ee85b..4555c8d77d30 100644 --- a/packages/firebase_messaging/firebase_messaging/test/mock.dart +++ b/packages/firebase_messaging/firebase_messaging/test/mock.dart @@ -96,9 +96,12 @@ class MockFirebaseMessaging extends Mock } @override - Future getToken({String? vapidKey}) { + Future getToken({String? vapidKey, String? serviceWorkerScriptPath}) { return super.noSuchMethod( - Invocation.method(#getToken, [], {#vapidKey: vapidKey}), + Invocation.method(#getToken, [], { + #vapidKey: vapidKey, + #serviceWorkerScriptPath: serviceWorkerScriptPath + }), returnValue: Future.value(''), returnValueForMissingStub: Future.value('')); } diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/method_channel/method_channel_messaging.dart b/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/method_channel/method_channel_messaging.dart index ffaac715c5b2..73788d05c3de 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/method_channel/method_channel_messaging.dart +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/method_channel/method_channel_messaging.dart @@ -240,6 +240,7 @@ class MethodChannelFirebaseMessaging extends FirebaseMessagingPlatform { @override Future getToken({ String? vapidKey, // not used yet; web only property + String? serviceWorkerScriptPath, // web only property }) async { await _APNSTokenCheck(); diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/platform_interface/platform_interface_messaging.dart b/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/platform_interface/platform_interface_messaging.dart index 3e0ffa7d90d8..44d20d32ed5b 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/platform_interface/platform_interface_messaging.dart +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/platform_interface/platform_interface_messaging.dart @@ -173,6 +173,7 @@ abstract class FirebaseMessagingPlatform extends PlatformInterface { /// Returns the default FCM token for this device and optionally [senderId]. Future getToken({ String? vapidKey, + String? serviceWorkerScriptPath, }) { throw UnimplementedError('getToken() is not implemented'); } diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/firebase_messaging_web.dart b/packages/firebase_messaging/firebase_messaging_web/lib/firebase_messaging_web.dart index 1443a65d2fbd..7825b227fa1c 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/firebase_messaging_web.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/firebase_messaging_web.dart @@ -112,7 +112,8 @@ class FirebaseMessagingWeb extends FirebaseMessagingPlatform { } @override - Future getToken({String? vapidKey}) async { + Future getToken( + {String? vapidKey, String? serviceWorkerScriptPath}) async { _delegate; if (!_initialized) { @@ -121,7 +122,8 @@ class FirebaseMessagingWeb extends FirebaseMessagingPlatform { } return convertWebExceptions( - () => _delegate.getToken(vapidKey: vapidKey), + () => _delegate.getToken( + vapidKey: vapidKey, serviceWorkerScriptPath: serviceWorkerScriptPath), ); } diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging.dart index d3a0e2673b4a..265724c2c288 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging.dart @@ -9,7 +9,7 @@ import 'dart:async'; import 'dart:js_interop'; import 'package:firebase_core_web/firebase_core_web_interop.dart'; - +import 'package:web/web.dart' as web; import 'messaging_interop.dart' as messaging_interop; export 'messaging_interop.dart'; @@ -43,15 +43,24 @@ class Messaging extends JsObjectWrapper { /// After calling [requestPermission] you can call this method to get an FCM registration token /// that can be used to send push messages to this user. - Future getToken({String? vapidKey}) async { + Future getToken( + {String? vapidKey, String? serviceWorkerScriptPath}) async { try { + web.ServiceWorkerRegistration? serviceWorkerRegistration; + if (serviceWorkerScriptPath != null) { + serviceWorkerRegistration = await web.window.navigator.serviceWorker + .register(serviceWorkerScriptPath.toJS) + .toDart; + } final token = (await messaging_interop .getToken( jsObject, - vapidKey == null + vapidKey == null && serviceWorkerRegistration == null ? null : messaging_interop.GetTokenOptions( - vapidKey: vapidKey.toJS)) + vapidKey: vapidKey?.toJS, + serviceWorkerRegistration: serviceWorkerRegistration, + )) .toDart) .toDart; return token; @@ -62,7 +71,10 @@ class Messaging extends JsObjectWrapper { if (err.toString().toLowerCase().contains('no active service worker') && firstGetTokenCall) { firstGetTokenCall = false; - return getToken(vapidKey: vapidKey); + return getToken( + vapidKey: vapidKey, + serviceWorkerScriptPath: serviceWorkerScriptPath, + ); } rethrow; } diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging_interop.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging_interop.dart index 66e1fe87e49e..9603e421c961 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging_interop.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/interop/messaging_interop.dart @@ -9,6 +9,7 @@ library; import 'dart:js_interop'; +import 'package:web/web.dart' as web; import 'package:firebase_core_web/firebase_core_web_interop.dart'; @@ -50,8 +51,10 @@ extension type GetTokenOptions._(JSObject _) implements JSObject { external factory GetTokenOptions({ JSString? vapidKey, /*dynamic serviceWorkerRegistration */ + web.ServiceWorkerRegistration? serviceWorkerRegistration, }); external JSString get vapidKey; + external web.ServiceWorkerRegistration get serviceWorkerRegistration; } extension type NotificationPayloadJsImpl._(JSObject _) implements JSObject { From 8bca9657c5f1009c429755b78b5a141065c23c68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:59:07 +0200 Subject: [PATCH 092/137] chore(deps): bump @protobufjs/utf8 (#18276) Bumps [@protobufjs/utf8](https://github.com/dcodeIO/protobuf.js) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/dcodeIO/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md) - [Commits](https://github.com/dcodeIO/protobuf.js/compare/protobufjs-cli-v1.1.0...protobufjs-cli-v1.1.1) --- updated-dependencies: - dependency-name: "@protobufjs/utf8" dependency-version: 1.1.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> From 0bcce87a17830797dae6ff3c1a8ba4ce210c2c0d Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:02:54 +0000 Subject: [PATCH 093/137] docs(auth): clarify behavior of password reset email with email enumeration protection enabled (#18296) --- docs/auth/manage-users.md | 5 +++++ .../firebase_auth/lib/src/firebase_auth.dart | 7 ++++++- .../platform_interface_firebase_auth.dart | 8 ++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/docs/auth/manage-users.md b/docs/auth/manage-users.md index 9584abf35454..5b52742175fa 100644 --- a/docs/auth/manage-users.md +++ b/docs/auth/manage-users.md @@ -162,6 +162,11 @@ await FirebaseAuth.instance .sendPasswordResetEmail(email: "user@example.com"); ``` +Note: If +[email enumeration protection](https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection) +is enabled for your Firebase project, `sendPasswordResetEmail()` may complete +without throwing an error even when the email address is not registered. This is +expected Firebase Auth behavior to prevent revealing whether an email exists. You can customize the email template that is used in Authentication section of the [Firebase console](https://console.firebase.google.com/), on the Email Templates page. See [Email Templates](https://support.google.com/firebase/answer/7000714) in diff --git a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart index 109b31adba51..2f4ebe4258f4 100644 --- a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart @@ -297,6 +297,10 @@ class FirebaseAuth extends FirebasePluginPlatform implements FirebaseService { /// To complete the password reset, call [confirmPasswordReset] with the code supplied /// in the email sent to the user, along with the new password specified by the user. /// + /// If email enumeration protection is enabled for the Firebase project, this + /// method may complete successfully even when the email does not correspond + /// to an existing user. + /// /// May throw a [FirebaseAuthException] with the following error codes: /// /// - **auth/invalid-email**\ @@ -312,7 +316,8 @@ class FirebaseAuth extends FirebasePluginPlatform implements FirebaseService { /// - **auth/unauthorized-continue-uri**\ /// The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. /// - **auth/user-not-found**\ - /// Thrown if there is no user corresponding to the email address. Note: This exception is no longer thrown when enabling email enumeration protection. + /// Thrown if there is no user corresponding to the email address. Note: This + /// exception is not thrown when email enumeration protection is enabled. Future sendPasswordResetEmail({ required String email, ActionCodeSettings? actionCodeSettings, diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart index ab9062fb57ba..60377db69238 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/platform_interface/platform_interface_firebase_auth.dart @@ -313,8 +313,12 @@ abstract class FirebaseAuthPlatform extends PlatformInterface { } /// Triggers the Firebase Authentication backend to send a password-reset - /// email to the given email address, which must correspond to an existing - /// user of your app. + /// email to the given email address. + /// + /// If email enumeration protection is enabled for the Firebase project, this + /// method may complete successfully even when the email does not correspond + /// to an existing user. This prevents apps from using password reset requests + /// to discover registered email addresses. Future sendPasswordResetEmail( String email, [ ActionCodeSettings? actionCodeSettings, From 3f31a88ab6ad96914f427e292b919b6465cf4996 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:03:15 +0000 Subject: [PATCH 094/137] feat(core): bump Firebase web SDK to 12.14.0 (#18331) --- .../firebase_core_web/lib/src/firebase_sdk_version.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart index 8c12876e746e..c3eca6802c29 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart @@ -6,4 +6,4 @@ part of '../firebase_core_web.dart'; /// The currently supported Firebase JS SDK version. -const String supportedFirebaseJsSdkVersion = '12.13.0'; +const String supportedFirebaseJsSdkVersion = '12.14.0'; From 1562eace5196227ad0058df9b5426950b0094f83 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:03:36 +0000 Subject: [PATCH 095/137] feat(core): bump Firebase android SDK to 34.14.0 (#18329) --- packages/firebase_core/firebase_core/android/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/android/gradle.properties b/packages/firebase_core/firebase_core/android/gradle.properties index 106ae63448c0..5bb4c09aee2f 100644 --- a/packages/firebase_core/firebase_core/android/gradle.properties +++ b/packages/firebase_core/firebase_core/android/gradle.properties @@ -1,2 +1,2 @@ # https://firebase.google.com/support/release-notes/android -FirebaseSDKVersion=34.13.0 +FirebaseSDKVersion=34.14.0 From b1cfe745d221f09665943762c83cdd64684c6e6c Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:04:07 +0000 Subject: [PATCH 096/137] feat(core): bump Firebase ios SDK to 12.14.0 (#18330) --- .../firebase_core/firebase_core/ios/firebase_sdk_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb index 3a861fb77b73..ee689042b0d1 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb +++ b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb @@ -1,4 +1,4 @@ # https://firebase.google.com/support/release-notes/ios def firebase_sdk_version!() - '12.13.0' + '12.14.0' end From 1bf50d2f5bbdcac29797268632e2ed8b7e344c7d Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 1 Jun 2026 10:43:16 +0000 Subject: [PATCH 097/137] fix(firestore, ios): add forceIndex parameter to collection source stage initializations (#18332) --- .../Sources/cloud_firestore/FLTPipelineParser.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m index 22449aaf96bf..a84369c64e88 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m @@ -942,14 +942,17 @@ + (NSString *)keyForExpressionMap:(NSDictionary *)em error:(NSError **)error { return nil; } FIRCollectionReference *ref = [firestore collectionWithPath:path]; - stage = [[FIRCollectionSourceStageBridge alloc] initWithRef:ref firestore:firestore]; + stage = [[FIRCollectionSourceStageBridge alloc] initWithRef:ref + firestore:firestore + forceIndex:nil]; } else if ([stageName isEqualToString:@"collection_group"]) { NSString *path = args[@"path"]; if (!path) { if (error) *error = parseError(@"collection_group requires 'path'"); return nil; } - stage = [[FIRCollectionGroupSourceStageBridge alloc] initWithCollectionId:path]; + stage = [[FIRCollectionGroupSourceStageBridge alloc] initWithCollectionId:path + forceIndex:nil]; } else if ([stageName isEqualToString:@"database"]) { stage = [[FIRDatabaseSourceStageBridge alloc] init]; } else if ([stageName isEqualToString:@"documents"]) { From a800e22a5f3a34db64c418b193a3606849f368e0 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 1 Jun 2026 16:12:14 +0200 Subject: [PATCH 098/137] chore(release): publish packages (#18333) * chore(release): publish packages - cloud_firestore@6.5.0 - cloud_firestore_web@5.5.0 - firebase_auth@6.5.2 - firebase_auth_platform_interface@9.0.2 - firebase_core@4.10.0 - firebase_core_web@3.8.0 - firebase_messaging@16.3.0 - firebase_messaging_platform_interface@4.8.0 - firebase_messaging_web@4.2.0 - firebase_ai@3.12.2 - firebase_data_connect@0.3.0+3 - firebase_auth_web@6.2.2 - _flutterfire_internals@1.3.72 - cloud_firestore_platform_interface@8.0.2 - cloud_functions@6.3.2 - cloud_functions_platform_interface@6.0.2 - cloud_functions_web@5.1.8 - firebase_analytics@12.4.2 - firebase_analytics_platform_interface@6.0.2 - firebase_analytics_web@0.6.1+8 - firebase_app_check@0.4.4+2 - firebase_app_check_platform_interface@0.4.0+2 - firebase_app_check_web@0.2.4+3 - firebase_app_installations@0.4.2+3 - firebase_app_installations_platform_interface@0.1.4+71 - firebase_app_installations_web@0.1.7+8 - firebase_crashlytics@5.2.3 - firebase_crashlytics_platform_interface@3.8.23 - firebase_database@12.4.2 - firebase_database_platform_interface@0.4.0+2 - firebase_database_web@0.2.7+9 - firebase_in_app_messaging@0.9.2+3 - firebase_in_app_messaging_platform_interface@0.2.5+23 - firebase_ml_model_downloader@0.4.2+3 - firebase_ml_model_downloader_platform_interface@0.1.5+23 - firebase_performance@0.11.4+2 - firebase_performance_platform_interface@0.2.0+2 - firebase_performance_web@0.1.8+8 - firebase_remote_config@6.5.2 - firebase_remote_config_platform_interface@3.0.2 - firebase_remote_config_web@1.10.9 - firebase_storage@13.4.2 - firebase_storage_platform_interface@6.0.2 - firebase_storage_web@3.11.8 * chore: BoM Version 4.15.0 * firebase ai * updating Packages.swift --- CHANGELOG.md | 139 ++++++++++++++++++ VERSIONS.md | 38 +++++ packages/_flutterfire_internals/CHANGELOG.md | 4 + packages/_flutterfire_internals/pubspec.yaml | 4 +- .../cloud_firestore/CHANGELOG.md | 5 + .../cloud_firestore/example/pubspec.yaml | 4 +- .../ios/cloud_firestore/Package.swift | 2 +- .../macos/cloud_firestore/Package.swift | 2 +- .../pipeline_example/pubspec.yaml | 2 +- .../cloud_firestore/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../cloud_firestore_web/CHANGELOG.md | 4 + .../lib/src/cloud_firestore_version.dart | 2 +- .../cloud_firestore_web/pubspec.yaml | 10 +- .../cloud_functions/CHANGELOG.md | 4 + .../cloud_functions/example/pubspec.yaml | 4 +- .../ios/cloud_functions/Package.swift | 2 +- .../Sources/cloud_functions/Constants.swift | 2 +- .../macos/cloud_functions/Package.swift | 2 +- .../cloud_functions/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 4 +- .../cloud_functions_web/CHANGELOG.md | 4 + .../lib/src/cloud_functions_version.dart | 2 +- .../cloud_functions_web/pubspec.yaml | 8 +- packages/firebase_ai/firebase_ai/CHANGELOG.md | 4 + .../firebase_ai/example/pubspec.yaml | 6 +- .../lib/src/firebaseai_version.dart | 2 +- packages/firebase_ai/firebase_ai/pubspec.yaml | 8 +- .../firebase_analytics/CHANGELOG.md | 4 + .../firebase_analytics/example/pubspec.yaml | 4 +- .../ios/firebase_analytics/Package.swift | 2 +- .../macos/firebase_analytics/Package.swift | 2 +- .../firebase_analytics/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_analytics_web/CHANGELOG.md | 4 + .../lib/src/firebase_analytics_version.dart | 2 +- .../firebase_analytics_web/pubspec.yaml | 10 +- .../firebase_app_check/CHANGELOG.md | 4 + .../firebase_app_check/example/pubspec.yaml | 6 +- .../ios/firebase_app_check/Package.swift | 2 +- .../firebase_app_check/Constants.swift | 2 +- .../macos/firebase_app_check/Package.swift | 2 +- .../firebase_app_check/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_app_check_web/CHANGELOG.md | 4 + .../lib/src/firebase_app_check_version.dart | 2 +- .../firebase_app_check_web/pubspec.yaml | 10 +- .../firebase_app_installations/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../firebase_app_installations/Package.swift | 2 +- .../Constants.swift | 2 +- .../firebase_app_installations/Package.swift | 2 +- .../firebase_app_installations/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../firebase_app_installations_version.dart | 2 +- .../pubspec.yaml | 10 +- .../firebase_auth/firebase_auth/CHANGELOG.md | 5 + .../firebase_auth/example/pubspec.yaml | 6 +- .../ios/firebase_auth/Package.swift | 2 +- .../macos/firebase_auth/Package.swift | 2 +- .../firebase_auth/firebase_auth/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_auth_web/CHANGELOG.md | 4 + .../lib/src/firebase_auth_version.dart | 2 +- .../firebase_auth_web/pubspec.yaml | 8 +- .../firebase_core/firebase_core/CHANGELOG.md | 5 + .../firebase_core/example/pubspec.yaml | 2 +- .../ios/firebase_core/Package.swift | 2 +- .../macos/firebase_core/Package.swift | 2 +- .../firebase_core/firebase_core/pubspec.yaml | 4 +- .../firebase_core_web/CHANGELOG.md | 4 + .../lib/src/firebase_core_version.dart | 2 +- .../firebase_core_web/pubspec.yaml | 2 +- .../firebase_crashlytics/CHANGELOG.md | 4 + .../firebase_crashlytics/example/pubspec.yaml | 6 +- .../ios/firebase_crashlytics/Package.swift | 2 +- .../macos/firebase_crashlytics/Package.swift | 2 +- .../firebase_crashlytics/pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_data_connect/CHANGELOG.md | 4 + .../example/pubspec.yaml | 6 +- .../lib/src/dataconnect_version.dart | 2 +- .../firebase_data_connect/pubspec.yaml | 12 +- .../firebase_database/CHANGELOG.md | 4 + .../firebase_database/example/pubspec.yaml | 4 +- .../ios/firebase_database/Package.swift | 2 +- .../macos/firebase_database/Package.swift | 2 +- .../firebase_database/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_database_web/CHANGELOG.md | 4 + .../lib/src/firebase_database_version.dart | 2 +- .../firebase_database_web/pubspec.yaml | 8 +- .../firebase_in_app_messaging/CHANGELOG.md | 4 + .../example/pubspec.yaml | 8 +- .../firebase_in_app_messaging/Package.swift | 2 +- .../firebase_in_app_messaging/pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_messaging/CHANGELOG.md | 4 + .../firebase_messaging/example/pubspec.yaml | 4 +- .../ios/firebase_messaging/Package.swift | 2 +- .../macos/firebase_messaging/Package.swift | 2 +- .../firebase_messaging/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_messaging_web/CHANGELOG.md | 4 + .../lib/src/firebase_messaging_version.dart | 2 +- .../firebase_messaging_web/pubspec.yaml | 10 +- .../firebase_ml_model_downloader/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../Package.swift | 2 +- .../Constants.swift | 2 +- .../Package.swift | 2 +- .../firebase_ml_model_downloader/pubspec.yaml | 6 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 4 +- .../firebase_performance/CHANGELOG.md | 4 + .../firebase_performance/example/pubspec.yaml | 4 +- .../ios/firebase_performance/Package.swift | 2 +- .../firebase_performance/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_performance_web/CHANGELOG.md | 4 + .../lib/src/firebase_performance_version.dart | 2 +- .../firebase_performance_web/pubspec.yaml | 10 +- .../firebase_remote_config/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../ios/firebase_remote_config/Package.swift | 2 +- .../firebase_remote_config/Constants.swift | 2 +- .../firebase_remote_config/Package.swift | 2 +- .../firebase_remote_config/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_remote_config_web/CHANGELOG.md | 4 + .../src/firebase_remote_config_version.dart | 2 +- .../firebase_remote_config_web/pubspec.yaml | 10 +- .../firebase_storage/CHANGELOG.md | 4 + .../firebase_storage/example/pubspec.yaml | 4 +- .../ios/firebase_storage/Package.swift | 2 +- .../macos/firebase_storage/Package.swift | 2 +- .../firebase_storage/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_storage_web/CHANGELOG.md | 4 + .../lib/src/firebase_storage_version.dart | 2 +- .../firebase_storage_web/pubspec.yaml | 10 +- scripts/versions.json | 28 ++++ tests/pubspec.yaml | 70 ++++----- 157 files changed, 667 insertions(+), 283 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6874659af312..b09d164ca4c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,145 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2026-06-01 - [BoM 4.15.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4150-2026-06-01) + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`cloud_firestore` - `v6.5.0`](#cloud_firestore---v650) + - [`cloud_firestore_web` - `v5.5.0`](#cloud_firestore_web---v550) + - [`firebase_auth` - `v6.5.2`](#firebase_auth---v652) + - [`firebase_auth_platform_interface` - `v9.0.2`](#firebase_auth_platform_interface---v902) + - [`firebase_core` - `v4.10.0`](#firebase_core---v4100) + - [`firebase_core_web` - `v3.8.0`](#firebase_core_web---v380) + - [`firebase_messaging` - `v16.3.0`](#firebase_messaging---v1630) + - [`firebase_messaging_platform_interface` - `v4.8.0`](#firebase_messaging_platform_interface---v480) + - [`firebase_messaging_web` - `v4.2.0`](#firebase_messaging_web---v420) + - [`firebase_ai` - `v3.12.2`](#firebase_ai---v3122) + - [`firebase_data_connect` - `v0.3.0+3`](#firebase_data_connect---v0303) + - [`firebase_auth_web` - `v6.2.2`](#firebase_auth_web---v622) + - [`_flutterfire_internals` - `v1.3.72`](#_flutterfire_internals---v1372) + - [`cloud_firestore_platform_interface` - `v8.0.2`](#cloud_firestore_platform_interface---v802) + - [`cloud_functions` - `v6.3.2`](#cloud_functions---v632) + - [`cloud_functions_platform_interface` - `v6.0.2`](#cloud_functions_platform_interface---v602) + - [`cloud_functions_web` - `v5.1.8`](#cloud_functions_web---v518) + - [`firebase_analytics` - `v12.4.2`](#firebase_analytics---v1242) + - [`firebase_analytics_platform_interface` - `v6.0.2`](#firebase_analytics_platform_interface---v602) + - [`firebase_analytics_web` - `v0.6.1+8`](#firebase_analytics_web---v0618) + - [`firebase_app_check` - `v0.4.4+2`](#firebase_app_check---v0442) + - [`firebase_app_check_platform_interface` - `v0.4.0+2`](#firebase_app_check_platform_interface---v0402) + - [`firebase_app_check_web` - `v0.2.4+3`](#firebase_app_check_web---v0243) + - [`firebase_app_installations` - `v0.4.2+3`](#firebase_app_installations---v0423) + - [`firebase_app_installations_platform_interface` - `v0.1.4+71`](#firebase_app_installations_platform_interface---v01471) + - [`firebase_app_installations_web` - `v0.1.7+8`](#firebase_app_installations_web---v0178) + - [`firebase_crashlytics` - `v5.2.3`](#firebase_crashlytics---v523) + - [`firebase_crashlytics_platform_interface` - `v3.8.23`](#firebase_crashlytics_platform_interface---v3823) + - [`firebase_database` - `v12.4.2`](#firebase_database---v1242) + - [`firebase_database_platform_interface` - `v0.4.0+2`](#firebase_database_platform_interface---v0402) + - [`firebase_database_web` - `v0.2.7+9`](#firebase_database_web---v0279) + - [`firebase_in_app_messaging` - `v0.9.2+3`](#firebase_in_app_messaging---v0923) + - [`firebase_in_app_messaging_platform_interface` - `v0.2.5+23`](#firebase_in_app_messaging_platform_interface---v02523) + - [`firebase_ml_model_downloader` - `v0.4.2+3`](#firebase_ml_model_downloader---v0423) + - [`firebase_ml_model_downloader_platform_interface` - `v0.1.5+23`](#firebase_ml_model_downloader_platform_interface---v01523) + - [`firebase_performance` - `v0.11.4+2`](#firebase_performance---v01142) + - [`firebase_performance_platform_interface` - `v0.2.0+2`](#firebase_performance_platform_interface---v0202) + - [`firebase_performance_web` - `v0.1.8+8`](#firebase_performance_web---v0188) + - [`firebase_remote_config` - `v6.5.2`](#firebase_remote_config---v652) + - [`firebase_remote_config_platform_interface` - `v3.0.2`](#firebase_remote_config_platform_interface---v302) + - [`firebase_remote_config_web` - `v1.10.9`](#firebase_remote_config_web---v1109) + - [`firebase_storage` - `v13.4.2`](#firebase_storage---v1342) + - [`firebase_storage_platform_interface` - `v6.0.2`](#firebase_storage_platform_interface---v602) + - [`firebase_storage_web` - `v3.11.8`](#firebase_storage_web---v3118) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `firebase_ai` - `v3.12.2` + - `firebase_data_connect` - `v0.3.0+3` + - `firebase_auth_web` - `v6.2.2` + - `_flutterfire_internals` - `v1.3.72` + - `cloud_firestore_platform_interface` - `v8.0.2` + - `cloud_functions` - `v6.3.2` + - `cloud_functions_platform_interface` - `v6.0.2` + - `cloud_functions_web` - `v5.1.8` + - `firebase_analytics` - `v12.4.2` + - `firebase_analytics_platform_interface` - `v6.0.2` + - `firebase_analytics_web` - `v0.6.1+8` + - `firebase_app_check` - `v0.4.4+2` + - `firebase_app_check_platform_interface` - `v0.4.0+2` + - `firebase_app_check_web` - `v0.2.4+3` + - `firebase_app_installations` - `v0.4.2+3` + - `firebase_app_installations_platform_interface` - `v0.1.4+71` + - `firebase_app_installations_web` - `v0.1.7+8` + - `firebase_crashlytics` - `v5.2.3` + - `firebase_crashlytics_platform_interface` - `v3.8.23` + - `firebase_database` - `v12.4.2` + - `firebase_database_platform_interface` - `v0.4.0+2` + - `firebase_database_web` - `v0.2.7+9` + - `firebase_in_app_messaging` - `v0.9.2+3` + - `firebase_in_app_messaging_platform_interface` - `v0.2.5+23` + - `firebase_ml_model_downloader` - `v0.4.2+3` + - `firebase_ml_model_downloader_platform_interface` - `v0.1.5+23` + - `firebase_performance` - `v0.11.4+2` + - `firebase_performance_platform_interface` - `v0.2.0+2` + - `firebase_performance_web` - `v0.1.8+8` + - `firebase_remote_config` - `v6.5.2` + - `firebase_remote_config_platform_interface` - `v3.0.2` + - `firebase_remote_config_web` - `v1.10.9` + - `firebase_storage` - `v13.4.2` + - `firebase_storage_platform_interface` - `v6.0.2` + - `firebase_storage_web` - `v3.11.8` + +--- + +#### `cloud_firestore` - `v6.5.0` + + - **FIX**(firestore,ios): add forceIndex parameter to collection source stage initializations ([#18332](https://github.com/firebase/flutterfire/issues/18332)). ([1bf50d2f](https://github.com/firebase/flutterfire/commit/1bf50d2f5bbdcac29797268632e2ed8b7e344c7d)) + - **FEAT**(firestore): add support for new array expressions ([#18283](https://github.com/firebase/flutterfire/issues/18283)). ([2293dee0](https://github.com/firebase/flutterfire/commit/2293dee00767cc6eebd57a340eb2b72bdab41d52)) + +#### `cloud_firestore_web` - `v5.5.0` + + - **FEAT**(firestore): add support for new array expressions ([#18283](https://github.com/firebase/flutterfire/issues/18283)). ([2293dee0](https://github.com/firebase/flutterfire/commit/2293dee00767cc6eebd57a340eb2b72bdab41d52)) + +#### `firebase_auth` - `v6.5.2` + + - **FIX**(auth,android): update token retrieval in PigeonParser to handle Number type correctly ([#18328](https://github.com/firebase/flutterfire/issues/18328)). ([3b77147b](https://github.com/firebase/flutterfire/commit/3b77147bc00bb19af5f4821436a1a4cdd8ff6791)) + - **DOCS**(auth): clarify behavior of password reset email with email enumeration protection enabled ([#18296](https://github.com/firebase/flutterfire/issues/18296)). ([0bcce87a](https://github.com/firebase/flutterfire/commit/0bcce87a17830797dae6ff3c1a8ba4ce210c2c0d)) + +#### `firebase_auth_platform_interface` - `v9.0.2` + + - **DOCS**(auth): clarify behavior of password reset email with email enumeration protection enabled ([#18296](https://github.com/firebase/flutterfire/issues/18296)). ([0bcce87a](https://github.com/firebase/flutterfire/commit/0bcce87a17830797dae6ff3c1a8ba4ce210c2c0d)) + +#### `firebase_core` - `v4.10.0` + + - **FEAT**(core): bump Firebase ios SDK to 12.14.0 ([#18330](https://github.com/firebase/flutterfire/issues/18330)). ([b1cfe745](https://github.com/firebase/flutterfire/commit/b1cfe745d221f09665943762c83cdd64684c6e6c)) + - **FEAT**(core): bump Firebase android SDK to 34.14.0 ([#18329](https://github.com/firebase/flutterfire/issues/18329)). ([1562eace](https://github.com/firebase/flutterfire/commit/1562eace5196227ad0058df9b5426950b0094f83)) + +#### `firebase_core_web` - `v3.8.0` + + - **FEAT**(core): bump Firebase web SDK to 12.14.0 ([#18331](https://github.com/firebase/flutterfire/issues/18331)). ([3f31a88a](https://github.com/firebase/flutterfire/commit/3f31a88ab6ad96914f427e292b919b6465cf4996)) + +#### `firebase_messaging` - `v16.3.0` + + - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) + +#### `firebase_messaging_platform_interface` - `v4.8.0` + + - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) + +#### `firebase_messaging_web` - `v4.2.0` + + - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) + + ## 2026-05-14 - [BoM 4.14.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4140-2026-05-14) ### Changes diff --git a/VERSIONS.md b/VERSIONS.md index 2c6c10aca845..db11f40769e8 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -4,6 +4,44 @@ This document is listing all the compatible versions of the FlutterFire plugins. # Versions +## [Flutter BoM 4.15.0 (2026-06-01)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-06-01) + +Install this version using FlutterFire CLI + +```bash +flutterfire install 4.15.0 +``` + +### Included Native Firebase SDK Versions +| Firebase SDK | Version | Link | +|--------------|---------|------| +| Android SDK | 34.14.0 | [Release Notes](https://firebase.google.com/support/release-notes/android) | +| iOS SDK | 12.14.0 | [Release Notes](https://firebase.google.com/support/release-notes/ios) | +| Web SDK | 12.14.0 | [Release Notes](https://firebase.google.com/support/release-notes/js) | +| Windows SDK | 13.5.0 | [Release Notes](https://firebase.google.com/support/release-notes/cpp-relnotes) | + +### FlutterFire Plugin Versions +| Plugin | Version | Dart Version | Flutter Version | +|--------|---------|--------------|-----------------| +| [cloud_firestore](https://pub.dev/packages/cloud_firestore/versions/6.5.0) | 6.5.0 | ^3.6.0 | >=3.27.0 | +| [cloud_functions](https://pub.dev/packages/cloud_functions/versions/6.3.2) | 6.3.2 | ^3.6.0 | >=3.27.0 | +| [firebase_ai](https://pub.dev/packages/firebase_ai/versions/3.12.2) | 3.12.2 | ^3.6.0 | >=3.16.0 | +| [firebase_analytics](https://pub.dev/packages/firebase_analytics/versions/12.4.2) | 12.4.2 | ^3.6.0 | >=3.27.0 | +| [firebase_app_check](https://pub.dev/packages/firebase_app_check/versions/0.4.4+2) | 0.4.4+2 | ^3.6.0 | >=3.27.0 | +| [firebase_app_installations](https://pub.dev/packages/firebase_app_installations/versions/0.4.2+3) | 0.4.2+3 | ^3.6.0 | >=3.27.0 | +| [firebase_auth](https://pub.dev/packages/firebase_auth/versions/6.5.2) | 6.5.2 | ^3.6.0 | >=3.16.0 | +| [firebase_core](https://pub.dev/packages/firebase_core/versions/4.10.0) | 4.10.0 | ^3.6.0 | >=3.27.0 | +| [firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics/versions/5.2.3) | 5.2.3 | ^3.6.0 | >=3.27.0 | +| [firebase_data_connect](https://pub.dev/packages/firebase_data_connect/versions/0.3.0+3) | 0.3.0+3 | ^3.6.0 | >=3.27.0 | +| [firebase_database](https://pub.dev/packages/firebase_database/versions/12.4.2) | 12.4.2 | ^3.6.0 | >=3.27.0 | +| [firebase_in_app_messaging](https://pub.dev/packages/firebase_in_app_messaging/versions/0.9.2+3) | 0.9.2+3 | ^3.6.0 | >=3.27.0 | +| [firebase_messaging](https://pub.dev/packages/firebase_messaging/versions/16.3.0) | 16.3.0 | ^3.6.0 | >=3.27.0 | +| [firebase_ml_model_downloader](https://pub.dev/packages/firebase_ml_model_downloader/versions/0.4.2+3) | 0.4.2+3 | ^3.6.0 | >=3.27.0 | +| [firebase_performance](https://pub.dev/packages/firebase_performance/versions/0.11.4+2) | 0.11.4+2 | ^3.6.0 | >=3.27.0 | +| [firebase_remote_config](https://pub.dev/packages/firebase_remote_config/versions/6.5.2) | 6.5.2 | ^3.6.0 | >=3.27.0 | +| [firebase_storage](https://pub.dev/packages/firebase_storage/versions/13.4.2) | 13.4.2 | ^3.6.0 | >=3.27.0 | + + ## [Flutter BoM 4.14.0 (2026-05-14)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-05-14) Install this version using FlutterFire CLI diff --git a/packages/_flutterfire_internals/CHANGELOG.md b/packages/_flutterfire_internals/CHANGELOG.md index ceeacaf470d1..254758ebbfe1 100644 --- a/packages/_flutterfire_internals/CHANGELOG.md +++ b/packages/_flutterfire_internals/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.72 + + - Update a dependency to the latest release. + ## 1.3.71 - Update a dependency to the latest release. diff --git a/packages/_flutterfire_internals/pubspec.yaml b/packages/_flutterfire_internals/pubspec.yaml index bc71795d13df..bce4b217cd37 100755 --- a/packages/_flutterfire_internals/pubspec.yaml +++ b/packages/_flutterfire_internals/pubspec.yaml @@ -2,7 +2,7 @@ name: _flutterfire_internals description: A package hosting Dart code shared between FlutterFire plugins. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/_flutterfire_internals -version: 1.3.71 +version: 1.3.72 resolution: workspace environment: @@ -11,7 +11,7 @@ environment: dependencies: collection: ^1.0.0 - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md index e146a0db9bb0..508b326b3129 100644 --- a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.5.0 + + - **FIX**(firestore,ios): add forceIndex parameter to collection source stage initializations ([#18332](https://github.com/firebase/flutterfire/issues/18332)). ([1bf50d2f](https://github.com/firebase/flutterfire/commit/1bf50d2f5bbdcac29797268632e2ed8b7e344c7d)) + - **FEAT**(firestore): add support for new array expressions ([#18283](https://github.com/firebase/flutterfire/issues/18283)). ([2293dee0](https://github.com/firebase/flutterfire/commit/2293dee00767cc6eebd57a340eb2b72bdab41d52)) + ## 6.4.1 - Update a dependency to the latest release. diff --git a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml index 0b2a473bfd79..9dcba518072c 100755 --- a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.4.1 - firebase_core: ^4.9.0 + cloud_firestore: ^6.5.0 + firebase_core: ^4.10.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index a2bc598d3be6..427e6eba2b86 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "6.4.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index 2438d85b6a6a..5bd2446dda51 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "6.4.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml index ff6da42a48e5..5bb006b6195c 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -31,7 +31,7 @@ environment: dependencies: cloud_firestore: path: .. - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pubspec.yaml index 14a0e0e024d1..f5a18b6741cf 100755 --- a/packages/cloud_firestore/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pubspec.yaml @@ -4,7 +4,7 @@ description: live synchronization and offline support on Android and iOS. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore -version: 6.4.1 +version: 6.5.0 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore_platform_interface: ^8.0.1 - cloud_firestore_web: ^5.4.1 + cloud_firestore_platform_interface: ^8.0.2 + cloud_firestore_web: ^5.5.0 collection: ^1.0.0 - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md index bb5cefd3c8b1..fbaf07c6dfdd 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 8.0.2 + + - Update a dependency to the latest release. + ## 8.0.1 - Update a dependency to the latest release. diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml index 6614f788eb69..0b4dd4487be0 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_firestore_platform_interface description: A common platform interface for the cloud_firestore plugin. -version: 8.0.1 +version: 8.0.2 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface @@ -10,9 +10,9 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 + _flutterfire_internals: ^1.3.72 collection: ^1.15.0 - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md index da9d0233bdbc..9e9a4f0b0f13 100644 --- a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.5.0 + + - **FEAT**(firestore): add support for new array expressions ([#18283](https://github.com/firebase/flutterfire/issues/18283)). ([2293dee0](https://github.com/firebase/flutterfire/commit/2293dee00767cc6eebd57a340eb2b72bdab41d52)) + ## 5.4.1 - Update a dependency to the latest release. diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart index 291be50d8be3..200e74209d4f 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.4.1'; +const packageVersion = '6.5.0'; diff --git a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml index 93b5d2f3376b..38c3a8e4db89 100644 --- a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_firestore homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web -version: 5.4.1 +version: 5.5.0 resolution: workspace environment: @@ -11,11 +11,11 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 - cloud_firestore_platform_interface: ^8.0.1 + _flutterfire_internals: ^1.3.72 + cloud_firestore_platform_interface: ^8.0.2 collection: ^1.0.0 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/cloud_functions/cloud_functions/CHANGELOG.md b/packages/cloud_functions/cloud_functions/CHANGELOG.md index dd77e23d82e3..b9c498844f5f 100644 --- a/packages/cloud_functions/cloud_functions/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.3.2 + + - Update a dependency to the latest release. + ## 6.3.1 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions/example/pubspec.yaml b/packages/cloud_functions/cloud_functions/example/pubspec.yaml index 3433f3a75dea..267ecca8fc47 100644 --- a/packages/cloud_functions/cloud_functions/example/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions: ^6.3.1 - firebase_core: ^4.9.0 + cloud_functions: ^6.3.2 + firebase_core: ^4.10.0 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift index 63d9adeac566..cd030b08914f 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "cloud_functions", diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift index f7f26c52d223..37927a798850 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.3.1" +public let versionNumber = "6.3.2" diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift index 8be5bb283b31..df1ccce51ab8 100644 --- a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "cloud_functions", diff --git a/packages/cloud_functions/cloud_functions/pubspec.yaml b/packages/cloud_functions/cloud_functions/pubspec.yaml index dc994b934e5e..01dc55e8ad0e 100644 --- a/packages/cloud_functions/cloud_functions/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_functions description: A Flutter plugin allowing you to use Firebase Cloud Functions. -version: 6.3.1 +version: 6.3.2 resolution: workspace homepage: https://firebase.google.com/docs/functions repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions_platform_interface: ^6.0.1 - cloud_functions_web: ^5.1.7 - firebase_core: ^4.9.0 + cloud_functions_platform_interface: ^6.0.2 + cloud_functions_web: ^5.1.8 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md index 6b6e0e083f49..8238e18b3c1e 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.2 + + - Update a dependency to the latest release. + ## 6.0.1 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml index 4a2b39171f69..4c7df1baa665 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_fun # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 6.0.1 +version: 6.0.2 resolution: workspace environment: @@ -13,7 +13,7 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md index f823d39aee51..38e93f128498 100644 --- a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.8 + + - Update a dependency to the latest release. + ## 5.1.7 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart index 955ddd8f8c5d..c4cc8e8cb6af 100644 --- a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart +++ b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.3.1'; +const packageVersion = '6.3.2'; diff --git a/packages/cloud_functions/cloud_functions_web/pubspec.yaml b/packages/cloud_functions/cloud_functions_web/pubspec.yaml index 8964f8228cb1..3135d2a2e580 100644 --- a/packages/cloud_functions/cloud_functions_web/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_functions homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web -version: 5.1.7 +version: 5.1.8 resolution: workspace environment: @@ -11,9 +11,9 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions_platform_interface: ^6.0.1 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 + cloud_functions_platform_interface: ^6.0.2 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index 39582a4ad66a..6150180a2058 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.12.2 + + - Update a dependency to the latest release. + ## 3.12.1 - Update a dependency to the latest release. diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index d87320464c2c..54c54a17901a 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -23,9 +23,9 @@ dependencies: camera: ^0.12.0+1 cupertino_icons: ^1.0.6 - firebase_ai: ^3.12.1 - firebase_core: ^4.9.0 - firebase_storage: ^13.4.1 + firebase_ai: ^3.12.2 + firebase_core: ^4.10.0 + firebase_storage: ^13.4.2 flutter: sdk: flutter flutter_animate: ^4.5.2 diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart index 251b4d38fbdf..f22c6b444513 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.3.0+2'; +const packageVersion = '0.3.0+3'; diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index fada966d9c5d..7e7cb3731c59 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI Logic SDK. -version: 3.12.1 +version: 3.12.2 resolution: workspace homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: @@ -21,9 +21,9 @@ environment: flutter: ">=3.16.0" dependencies: - firebase_app_check: ^0.4.4+1 - firebase_auth: ^6.5.1 - firebase_core: ^4.9.0 + firebase_app_check: ^0.4.4+2 + firebase_auth: ^6.5.2 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md index 3582750b0a39..14388f20e359 100644 --- a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.4.2 + + - Update a dependency to the latest release. + ## 12.4.1 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml index 29c38d8b1acd..8cf3373a2454 100755 --- a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.1 - firebase_core: ^4.9.0 + firebase_analytics: ^12.4.2 + firebase_core: ^4.10.0 flutter: sdk: flutter in_app_purchase: ^3.2.3 diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift index 16f26c8d379b..526bf50bab01 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift @@ -8,7 +8,7 @@ import Foundation import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" // Set FIREBASE_ANALYTICS_WITHOUT_ADID=true to use FirebaseAnalyticsWithoutAdIdSupport // e.g. FIREBASE_ANALYTICS_WITHOUT_ADID=true flutter build ios diff --git a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift index 040ad2c7df89..d547defc1ed5 100644 --- a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_analytics", diff --git a/packages/firebase_analytics/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/pubspec.yaml index b0b3b0b6c0d9..b9c1dbaf1d2e 100755 --- a/packages/firebase_analytics/firebase_analytics/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/pubspec.yaml @@ -4,7 +4,7 @@ description: solution that provides insight on app usage and user engagement on Android and iOS. homepage: https://firebase.google.com/docs/analytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics -version: 12.4.1 +version: 12.4.2 resolution: workspace topics: - firebase @@ -20,9 +20,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics_platform_interface: ^6.0.1 - firebase_analytics_web: ^0.6.1+7 - firebase_core: ^4.9.0 + firebase_analytics_platform_interface: ^6.0.2 + firebase_analytics_web: ^0.6.1+8 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md index b21df9014774..6e3bd6bbec3f 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.2 + + - Update a dependency to the latest release. + ## 6.0.1 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml index 6fb274a88cb5..a2943142e0f3 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_platform_interface description: A common platform interface for the firebase_analytics plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface -version: 6.0.1 +version: 6.0.2 resolution: workspace environment: @@ -10,8 +10,8 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md index bc4555b575e0..0a45170f90d5 100644 --- a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.1+8 + + - Update a dependency to the latest release. + ## 0.6.1+7 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart index bcbf9e02507e..ef292c6ef4f2 100644 --- a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart +++ b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.4.1'; +const packageVersion = '12.4.2'; diff --git a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml index dce76acc4130..1c4ed3660da5 100644 --- a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_web description: The web implementation of firebase_analytics homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web -version: 0.6.1+7 +version: 0.6.1+8 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_analytics_platform_interface: ^6.0.1 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 + _flutterfire_internals: ^1.3.72 + firebase_analytics_platform_interface: ^6.0.2 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md index 2fa6e746d5d0..91b6517e88c3 100644 --- a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.4+2 + + - Update a dependency to the latest release. + ## 0.4.4+1 - Update a dependency to the latest release. diff --git a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml index 905c8df05552..72614cde959d 100644 --- a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml @@ -11,9 +11,9 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.4.1 - firebase_app_check: ^0.4.4+1 - firebase_core: ^4.9.0 + cloud_firestore: ^6.5.0 + firebase_app_check: ^0.4.4+2 + firebase_core: ^4.10.0 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index bbb503de342b..8b543e4b1358 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_app_check", diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift index a2e723833932..b11b6dfc1d0e 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.4+1" +public let versionNumber = "0.4.4+2" diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift index 0b49a74eb477..5e18628c4123 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_app_check", diff --git a/packages/firebase_app_check/firebase_app_check/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/pubspec.yaml index 522f6bae042b..3def275e7ff9 100644 --- a/packages/firebase_app_check/firebase_app_check/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_app_check description: App Check works alongside other Firebase services to help protect your backend resources from abuse, such as billing fraud or phishing. homepage: https://firebase.google.com/docs/app-check repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check -version: 0.4.4+1 +version: 0.4.4+2 resolution: workspace topics: - firebase @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_check_platform_interface: ^0.4.0+1 - firebase_app_check_web: ^0.2.4+2 - firebase_core: ^4.9.0 + firebase_app_check_platform_interface: ^0.4.0+2 + firebase_app_check_web: ^0.2.4+3 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md index c8c2b2290802..2de79fe09408 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+2 + + - Update a dependency to the latest release. + ## 0.4.0+1 - Update a dependency to the latest release. diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 85f42f933400..263db479caa7 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_platform_interface description: A common platform interface for the firebase_app_check plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_platform_interface -version: 0.4.0+1 +version: 0.4.0+2 resolution: workspace environment: @@ -9,8 +9,8 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md index 75d0872f461d..6d7350e574cc 100644 --- a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.4+3 + + - Update a dependency to the latest release. + ## 0.2.4+2 - Update a dependency to the latest release. diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart index 6f543de27ef2..e143129de7ca 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.4+1'; +const packageVersion = '0.4.4+2'; diff --git a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml index 295aef48b899..52417bf7fa33 100644 --- a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_web description: The web implementation of firebase_app_check homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_web -version: 0.2.4+2 +version: 0.2.4+3 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_app_check_platform_interface: ^0.4.0+1 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 + _flutterfire_internals: ^1.3.72 + firebase_app_check_platform_interface: ^0.4.0+2 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md index 142d39936663..33ede781c342 100644 --- a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+3 + + - Update a dependency to the latest release. + ## 0.4.2+2 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml index 41494e6492c2..95832dbeffa3 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 - firebase_app_installations: ^0.4.2+2 + firebase_core: ^4.10.0 + firebase_app_installations: ^0.4.2+3 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift index 2d43d4e4781f..7427d6bc97d7 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift index a1317a947b5b..fc15ead900f2 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2+2" +public let versionNumber = "0.4.2+3" diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift index 325e24d74976..16b1f01b9764 100644 --- a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml index c12a7ed85c5a..6299d7967809 100644 --- a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations description: A Flutter plugin allowing you to use Firebase Installations. -version: 0.4.2+2 +version: 0.4.2+3 resolution: workspace homepage: https://firebase.google.com/docs/projects/manage-installations#flutter repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_installations_platform_interface: ^0.1.4+70 - firebase_app_installations_web: ^0.1.7+7 - firebase_core: ^4.9.0 + firebase_app_installations_platform_interface: ^0.1.4+71 + firebase_app_installations_web: ^0.1.7+8 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md index 8e98454d92c4..21683e87b2e3 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+71 + + - Update a dependency to the latest release. + ## 0.1.4+70 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 3eb6c03420e8..64d10dd9bbdc 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_platform_interface description: A common platform interface for the firebase_app_installations plugin. -version: 0.1.4+70 +version: 0.1.4+71 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface @@ -10,8 +10,8 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md index 74a2c95bf9ee..80e0d4b48ab1 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.7+8 + + - Update a dependency to the latest release. + ## 0.1.7+7 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart index 493b9b698ac8..4bcc9cc38b98 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart +++ b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.2+2'; +const packageVersion = '0.4.2+3'; diff --git a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml index 449a382ab258..7fa7cf26ab51 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_web description: The web implementation of firebase_app_installations. -version: 0.1.7+7 +version: 0.1.7+8 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_app_installations_platform_interface: ^0.1.4+70 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 + _flutterfire_internals: ^1.3.72 + firebase_app_installations_platform_interface: ^0.1.4+71 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_auth/firebase_auth/CHANGELOG.md b/packages/firebase_auth/firebase_auth/CHANGELOG.md index 64ab30e9d2f9..2018745da16f 100644 --- a/packages/firebase_auth/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.5.2 + + - **FIX**(auth,android): update token retrieval in PigeonParser to handle Number type correctly ([#18328](https://github.com/firebase/flutterfire/issues/18328)). ([3b77147b](https://github.com/firebase/flutterfire/commit/3b77147bc00bb19af5f4821436a1a4cdd8ff6791)) + - **DOCS**(auth): clarify behavior of password reset email with email enumeration protection enabled ([#18296](https://github.com/firebase/flutterfire/issues/18296)). ([0bcce87a](https://github.com/firebase/flutterfire/commit/0bcce87a17830797dae6ff3c1a8ba4ce210c2c0d)) + ## 6.5.1 - Update a dependency to the latest release. diff --git a/packages/firebase_auth/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/firebase_auth/example/pubspec.yaml index 13404244d4e5..d4945ff996a9 100644 --- a/packages/firebase_auth/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/example/pubspec.yaml @@ -8,9 +8,9 @@ environment: dependencies: barcode_widget: ^2.0.4 - firebase_auth: ^6.5.1 - firebase_core: ^4.9.0 - firebase_messaging: ^16.2.2 + firebase_auth: ^6.5.2 + firebase_core: ^4.10.0 + firebase_messaging: ^16.3.0 flutter: sdk: flutter flutter_facebook_auth: ^7.1.5 diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index 21e7c1442de5..fb20508740d9 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "6.5.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index 8ecc7b9db7ec..2f0c6134c574 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "6.5.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_auth/firebase_auth/pubspec.yaml b/packages/firebase_auth/firebase_auth/pubspec.yaml index 4a1dd3635817..d559a058e9fa 100755 --- a/packages/firebase_auth/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling like Google, Facebook and Twitter. homepage: https://firebase.google.com/docs/auth repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth -version: 6.5.1 +version: 6.5.2 resolution: workspace topics: - firebase @@ -21,9 +21,9 @@ environment: flutter: '>=3.16.0' dependencies: - firebase_auth_platform_interface: ^9.0.1 - firebase_auth_web: ^6.2.1 - firebase_core: ^4.9.0 + firebase_auth_platform_interface: ^9.0.2 + firebase_auth_web: ^6.2.2 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 flutter: sdk: flutter diff --git a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md index e81681fa4bf1..28e508b89d1e 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 9.0.2 + + - **DOCS**(auth): clarify behavior of password reset email with email enumeration protection enabled ([#18296](https://github.com/firebase/flutterfire/issues/18296)). ([0bcce87a](https://github.com/firebase/flutterfire/commit/0bcce87a17830797dae6ff3c1a8ba4ce210c2c0d)) + ## 9.0.1 - Update a dependency to the latest release. diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml index fc6be3ec1007..778b1ce6d0aa 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_au repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 9.0.1 +version: 9.0.2 resolution: workspace environment: @@ -12,9 +12,9 @@ environment: flutter: '>=3.16.0' dependencies: - _flutterfire_internals: ^1.3.71 + _flutterfire_internals: ^1.3.72 collection: ^1.16.0 - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter http: ^1.1.0 diff --git a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md index 6e96695e1a3d..0538fc7ce19c 100644 --- a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.2.2 + + - Update a dependency to the latest release. + ## 6.2.1 - Update a dependency to the latest release. diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart index ddd128c14de6..5351a5a16546 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.1'; +const packageVersion = '6.5.2'; diff --git a/packages/firebase_auth/firebase_auth_web/pubspec.yaml b/packages/firebase_auth/firebase_auth_web/pubspec.yaml index 6be8765b4927..ec422dd434b5 100644 --- a/packages/firebase_auth/firebase_auth_web/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_auth_web description: The web implementation of firebase_auth homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web -version: 6.2.1 +version: 6.2.2 resolution: workspace environment: @@ -10,9 +10,9 @@ environment: flutter: '>=3.22.0' dependencies: - firebase_auth_platform_interface: ^9.0.1 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 + firebase_auth_platform_interface: ^9.0.2 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_core/firebase_core/CHANGELOG.md b/packages/firebase_core/firebase_core/CHANGELOG.md index 62cfa0de813c..e8fcbe2a2d90 100644 --- a/packages/firebase_core/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/firebase_core/CHANGELOG.md @@ -1,3 +1,8 @@ +## 4.10.0 + + - **FEAT**(core): bump Firebase ios SDK to 12.14.0 ([#18330](https://github.com/firebase/flutterfire/issues/18330)). ([b1cfe745](https://github.com/firebase/flutterfire/commit/b1cfe745d221f09665943762c83cdd64684c6e6c)) + - **FEAT**(core): bump Firebase android SDK to 34.14.0 ([#18329](https://github.com/firebase/flutterfire/issues/18329)). ([1562eace](https://github.com/firebase/flutterfire/commit/1562eace5196227ad0058df9b5426950b0094f83)) + ## 4.9.0 - **FIX**(core,iOS): use namespaced iOS Pigeon header import ([#18281](https://github.com/firebase/flutterfire/issues/18281)). ([7c1257e7](https://github.com/firebase/flutterfire/commit/7c1257e7295f9ba67f3f5820493f105a14d34d52)) diff --git a/packages/firebase_core/firebase_core/example/pubspec.yaml b/packages/firebase_core/firebase_core/example/pubspec.yaml index 31c8d0c83ffa..a5489ddbd498 100644 --- a/packages/firebase_core/firebase_core/example/pubspec.yaml +++ b/packages/firebase_core/firebase_core/example/pubspec.yaml @@ -7,7 +7,7 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index 28085699c8cb..2564661516ae 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersionString = "4.9.0" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index 74c925e5baa6..03cdee9a4167 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersionString = "4.9.0" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index 2cf60e9921b3..ec426a170d59 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. homepage: https://firebase.google.com/docs/flutter/setup repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core -version: 4.9.0 +version: 4.10.0 resolution: workspace topics: - firebase @@ -18,7 +18,7 @@ environment: dependencies: firebase_core_platform_interface: ^7.0.1 - firebase_core_web: ^3.7.0 + firebase_core_web: ^3.8.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_core/firebase_core_web/CHANGELOG.md b/packages/firebase_core/firebase_core_web/CHANGELOG.md index 1619cef530f8..6b75c49b7dd0 100644 --- a/packages/firebase_core/firebase_core_web/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.8.0 + + - **FEAT**(core): bump Firebase web SDK to 12.14.0 ([#18331](https://github.com/firebase/flutterfire/issues/18331)). ([3f31a88a](https://github.com/firebase/flutterfire/commit/3f31a88ab6ad96914f427e292b919b6465cf4996)) + ## 3.7.0 - **FEAT**: bump Firebase JS SDK to 12.13.0 ([#18274](https://github.com/firebase/flutterfire/issues/18274)). ([bb8ad546](https://github.com/firebase/flutterfire/commit/bb8ad546f114146b6e1cd26c3296825e2964745d)) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart index 1b529f1f2e5b..eda9aff3d0fc 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '4.9.0'; +const packageVersion = '4.10.0'; diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index a0ca677a4965..8cc5a1448f0f 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_core_web description: The web implementation of firebase_core homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web -version: 3.7.0 +version: 3.8.0 resolution: workspace environment: diff --git a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md index 57740532b490..4c5828d063e0 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.2.3 + + - Update a dependency to the latest release. + ## 5.2.2 - Update a dependency to the latest release. diff --git a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml index 37d7bd4c9633..f10713cc4179 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml @@ -7,9 +7,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.1 - firebase_core: ^4.9.0 - firebase_crashlytics: ^5.2.2 + firebase_analytics: ^12.4.2 + firebase_core: ^4.10.0 + firebase_crashlytics: ^5.2.3 flutter: sdk: flutter diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index 08be6e33616b..4a0a87574f4e 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "5.2.2" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index 21044f98b44f..619e14e93216 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "5.2.2" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml index 51a5775b8d96..bbfc54d297c2 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 5.2.2 +version: 5.2.3 resolution: workspace homepage: https://firebase.google.com/docs/crashlytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics @@ -20,9 +20,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_crashlytics_platform_interface: ^3.8.22 + firebase_crashlytics_platform_interface: ^3.8.23 flutter: sdk: flutter stack_trace: ^1.10.0 diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md index 0a1250c76fc4..71491658215c 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.8.23 + + - Update a dependency to the latest release. + ## 3.8.22 - Update a dependency to the latest release. diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml index bcad65ccbcff..64a89fdc4234 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_crashlytics_platform_interface description: A common platform interface for the firebase_crashlytics plugin. -version: 3.8.22 +version: 3.8.23 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface @@ -10,9 +10,9 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 + _flutterfire_internals: ^1.3.72 collection: ^1.15.0 - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md index 6fe6548cb63e..e8f2eae2e258 100644 --- a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md +++ b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+3 + + - Update a dependency to the latest release. + ## 0.3.0+2 - Update a dependency to the latest release. diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index 0da5baea0842..6968fe1eb773 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -13,16 +13,16 @@ environment: dependencies: flutter: sdk: flutter - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 google_sign_in: ^6.1.0 - firebase_auth: ^6.5.1 + firebase_auth: ^6.5.2 firebase_data_connect: path: ../ cupertino_icons: ^1.0.6 flutter_rating_bar: ^4.0.1 protobuf: ^3.1.0 - firebase_app_check: ^0.4.4+1 + firebase_app_check: ^0.4.4+2 dev_dependencies: build_runner: ^2.3.3 diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart index 30cec7491ed7..15f614400c2f 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// version number for the package, should be align with pubspec.yaml. -const packageVersion = '0.3.0+2'; +const packageVersion = '0.3.0+3'; diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index 694bfc257fbd..34df0b12dd1e 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_data_connect description: 'Flutter plugin for Firebase Data Connect, a relational database service that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL.' -version: 0.3.0+2 +version: 0.3.0+3 resolution: workspace homepage: https://firebase.google.com/docs/data-connect/quickstart?platform=flutter false_secrets: @@ -13,9 +13,9 @@ environment: dependencies: crypto: ^3.0.6 - firebase_app_check: ^0.4.4+1 - firebase_auth: ^6.5.1 - firebase_core: ^4.9.0 + firebase_app_check: ^0.4.4+2 + firebase_auth: ^6.5.2 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 fixnum: ^1.1.1 flutter: @@ -31,8 +31,8 @@ dependencies: dev_dependencies: build_runner: ^2.4.12 - firebase_app_check_platform_interface: ^0.4.0+1 - firebase_auth_platform_interface: ^9.0.1 + firebase_app_check_platform_interface: ^0.4.0+2 + firebase_auth_platform_interface: ^9.0.2 flutter_lints: ^6.0.0 flutter_test: sdk: flutter diff --git a/packages/firebase_database/firebase_database/CHANGELOG.md b/packages/firebase_database/firebase_database/CHANGELOG.md index 2b79a94c4330..3e112c5c8d10 100644 --- a/packages/firebase_database/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/firebase_database/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.4.2 + + - Update a dependency to the latest release. + ## 12.4.1 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database/example/pubspec.yaml b/packages/firebase_database/firebase_database/example/pubspec.yaml index 8aad45158e06..495579667ce3 100755 --- a/packages/firebase_database/firebase_database/example/pubspec.yaml +++ b/packages/firebase_database/firebase_database/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 - firebase_database: ^12.4.1 + firebase_core: ^4.10.0 + firebase_database: ^12.4.2 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index 14d652359c46..d961803fe9fa 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "12.4.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index f11a445f0fd5..d322efdf7030 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "12.4.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index 8c3fd7cadbb0..d5a57955f1ff 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. homepage: https://firebase.google.com/docs/database repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database -version: 12.4.1 +version: 12.4.2 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_database_platform_interface: ^0.4.0+1 - firebase_database_web: ^0.2.7+8 + firebase_database_platform_interface: ^0.4.0+2 + firebase_database_web: ^0.2.7+9 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md index e1e0b56d7185..de01cef222b3 100755 --- a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+2 + + - Update a dependency to the latest release. + ## 0.4.0+1 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml index cc84a592f7b1..e8a36dfbaa96 100755 --- a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml +++ b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_platform_interface description: A common platform interface for the firebase_database plugin. -version: 0.4.0+1 +version: 0.4.0+2 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_platform_interface @@ -9,9 +9,9 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 + _flutterfire_internals: ^1.3.72 collection: ^1.14.3 - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_database/firebase_database_web/CHANGELOG.md b/packages/firebase_database/firebase_database_web/CHANGELOG.md index a9aed47ad6b4..47761d5d87bd 100644 --- a/packages/firebase_database/firebase_database_web/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.7+9 + + - Update a dependency to the latest release. + ## 0.2.7+8 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart index bcbf9e02507e..ef292c6ef4f2 100644 --- a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.4.1'; +const packageVersion = '12.4.2'; diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index a42292d9c735..517f77c419dc 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_web description: The web implementation of firebase_database -version: 0.2.7+8 +version: 0.2.7+9 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_web @@ -10,9 +10,9 @@ environment: dependencies: collection: ^1.18.0 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 - firebase_database_platform_interface: ^0.4.0+1 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 + firebase_database_platform_interface: ^0.4.0+2 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md index ccb5e0323550..e4616da45bb5 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2+3 + + - Update a dependency to the latest release. + ## 0.9.2+2 - Update a dependency to the latest release. diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml index 272c0a0b1d71..71f63d2126f3 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml @@ -8,10 +8,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.1 - firebase_core: ^4.9.0 - firebase_in_app_messaging: ^0.9.2+2 - firebase_in_app_messaging_platform_interface: ^0.2.5+22 + firebase_analytics: ^12.4.2 + firebase_core: ^4.10.0 + firebase_in_app_messaging: ^0.9.2+3 + firebase_in_app_messaging_platform_interface: ^0.2.5+23 flutter: sdk: flutter diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index cf4892d53507..b389528c60ee 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "0.9.2-2" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_in_app_messaging", diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml index 66edec353aa0..88bd5d6b871d 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_in_app_messaging description: Flutter plugin for Firebase In-App Messaging. -version: 0.9.2+2 +version: 0.9.2+3 resolution: workspace homepage: https://firebase.google.com/docs/in-app-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_in_app_messaging_platform_interface: ^0.2.5+22 + firebase_in_app_messaging_platform_interface: ^0.2.5+23 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md index 6dd23cb59354..199f096d87de 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.5+23 + + - Update a dependency to the latest release. + ## 0.2.5+22 - Update a dependency to the latest release. diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml index fddd18e8373c..b136ddc599bc 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the firebase_in_app_messaging plugi homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface -version: 0.2.5+22 +version: 0.2.5+23 resolution: workspace environment: @@ -11,8 +11,8 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md index 38d9a85d08e3..7e4f180e0d34 100644 --- a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 16.3.0 + + - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) + ## 16.2.2 - Update a dependency to the latest release. diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index fe4f3af5e042..d9d7fa996837 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 - firebase_messaging: ^16.2.2 + firebase_core: ^4.10.0 + firebase_messaging: ^16.3.0 flutter: sdk: flutter flutter_local_notifications: ^21.0.0 diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index edc0ddaa543b..74d6a74e26b3 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "16.2.2" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index fb9488cec058..820f2875e68a 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "16.2.2" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/pubspec.yaml index 15a85d950c8f..6837ec856e4e 100644 --- a/packages/firebase_messaging/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. homepage: https://firebase.google.com/docs/cloud-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging -version: 16.2.2 +version: 16.3.0 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_messaging_platform_interface: ^4.7.11 - firebase_messaging_web: ^4.1.7 + firebase_messaging_platform_interface: ^4.8.0 + firebase_messaging_web: ^4.2.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md index 1a5eb79762ef..9d3eac10bb81 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.8.0 + + - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) + ## 4.7.11 - Update a dependency to the latest release. diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml index 31d86dc23b9a..779bc3f5c651 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_messaging_platform_interface description: A common platform interface for the firebase_messaging plugin. -version: 4.7.11 +version: 4.8.0 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface @@ -10,8 +10,8 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md index c5397fae1dca..a6d684fd425a 100644 --- a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.2.0 + + - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) + ## 4.1.7 - Update a dependency to the latest release. diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart index 774c057adcb3..3094ad1dfb37 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '16.2.2'; +const packageVersion = '16.3.0'; diff --git a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml index 9d6841cbe9c6..22dc76ad722c 100644 --- a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_messaging_web description: The web implementation of firebase_messaging homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web -version: 4.1.7 +version: 4.2.0 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 - firebase_messaging_platform_interface: ^4.7.11 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 + firebase_messaging_platform_interface: ^4.8.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md index c9cdadac95bc..524d08186d64 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+3 + + - Update a dependency to the latest release. + ## 0.4.2+2 - Update a dependency to the latest release. diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml index 4391fcea0db3..4adc9fc6d2a9 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml @@ -12,8 +12,8 @@ dependencies: flutter: sdk: flutter - firebase_core: ^4.9.0 - firebase_ml_model_downloader: ^0.4.2+2 + firebase_core: ^4.10.0 + firebase_ml_model_downloader: ^0.4.2+3 dev_dependencies: flutter_lints: ^6.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift index 65138b30f9ec..739d1f6494ee 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift index a1317a947b5b..fc15ead900f2 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2+2" +public let versionNumber = "0.4.2+3" diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift index d59fe67468f2..cfdcb0d35386 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml index 2b4cd59e8de1..6546173101f4 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader description: A Flutter plugin allowing you to use Firebase Ml Model Downloader. -version: 0.4.2+2 +version: 0.4.2+3 resolution: workspace homepage: https://firebase.google.com/docs/ml/flutter/use-custom-models repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_ml_model_downloader_platform_interface: ^0.1.5+22 + firebase_ml_model_downloader_platform_interface: ^0.1.5+23 flutter: sdk: flutter diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md index 4d5009d8725d..3fa53ef8b6f5 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5+23 + + - Update a dependency to the latest release. + ## 0.1.5+22 - Update a dependency to the latest release. diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml index c6fe78920a5b..8dd1812fc071 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader_platform_interface description: A common platform interface for the firebase_ml_model_downloader plugin. -version: 0.1.5+22 +version: 0.1.5+23 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface @@ -10,7 +10,7 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_performance/firebase_performance/CHANGELOG.md b/packages/firebase_performance/firebase_performance/CHANGELOG.md index 5c02b147bab8..3fc0d4b19850 100644 --- a/packages/firebase_performance/firebase_performance/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.4+2 + + - Update a dependency to the latest release. + ## 0.11.4+1 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance/example/pubspec.yaml b/packages/firebase_performance/firebase_performance/example/pubspec.yaml index 1ad9f97442f9..2f95bb40c267 100644 --- a/packages/firebase_performance/firebase_performance/example/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 - firebase_performance: ^0.11.4+1 + firebase_core: ^4.10.0 + firebase_performance: ^0.11.4+2 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index 3fcf255d9868..9058965e7e35 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "0.11.4-1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_performance", diff --git a/packages/firebase_performance/firebase_performance/pubspec.yaml b/packages/firebase_performance/firebase_performance/pubspec.yaml index d4dc03ef07a7..f1efe47bbdca 100644 --- a/packages/firebase_performance/firebase_performance/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/pubspec.yaml @@ -5,7 +5,7 @@ description: iOS. homepage: https://firebase.google.com/docs/perf-mon repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance -version: 0.11.4+1 +version: 0.11.4+2 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_performance_platform_interface: ^0.2.0+1 - firebase_performance_web: ^0.1.8+7 + firebase_performance_platform_interface: ^0.2.0+2 + firebase_performance_web: ^0.1.8+8 flutter: sdk: flutter diff --git a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md index 9e8ea2b1d3ee..920a623d6d49 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+2 + + - Update a dependency to the latest release. + ## 0.2.0+1 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml index d83c64814f42..b2570eb69d05 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_performance_platform_interface description: A common platform interface for the firebase_performance plugin. -version: 0.2.0+1 +version: 0.2.0+2 resolution: workspace homepage: https://firebase.google.com/docs/perf-mon/flutter/get-started @@ -9,8 +9,8 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md index 56a1d2a49e25..3a89643a8c64 100644 --- a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8+8 + + - Update a dependency to the latest release. + ## 0.1.8+7 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart index 2c24da79ec6c..255778793f09 100644 --- a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart +++ b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.11.4+1'; +const packageVersion = '0.11.4+2'; diff --git a/packages/firebase_performance/firebase_performance_web/pubspec.yaml b/packages/firebase_performance/firebase_performance_web/pubspec.yaml index 5ec4d84da1fa..55b45f611c7c 100644 --- a/packages/firebase_performance/firebase_performance_web/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_performance_web description: Web implementation of Firebase Performance monitoring. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance_web -version: 0.1.8+7 +version: 0.1.8+8 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 - firebase_performance_platform_interface: ^0.2.0+1 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 + firebase_performance_platform_interface: ^0.2.0+2 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md index d1c39444a345..d0bcb89e6655 100644 --- a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.5.2 + + - Update a dependency to the latest release. + ## 6.5.1 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml index 5d28f5a41292..4587601f52c9 100644 --- a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - firebase_core: ^4.9.0 - firebase_remote_config: ^6.5.1 + firebase_core: ^4.10.0 + firebase_remote_config: ^6.5.2 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift index 787668e656ef..f932cb140ee9 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift index ff6af5e8bb10..0541cf200ad6 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.5.1" +public let versionNumber = "6.5.2" diff --git a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift index 525d98ef693a..f2bb3d72b4e3 100644 --- a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml index bdecc0810a52..148239b17b22 100644 --- a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml @@ -4,7 +4,7 @@ description: re-releasing. homepage: https://firebase.google.com/docs/remote-config repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config -version: 6.5.1 +version: 6.5.2 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_remote_config_platform_interface: ^3.0.1 - firebase_remote_config_web: ^1.10.8 + firebase_remote_config_platform_interface: ^3.0.2 + firebase_remote_config_web: ^1.10.9 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md index 1f653703ef6c..613e250aecc5 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.2 + + - Update a dependency to the latest release. + ## 3.0.1 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml index f93bdbe8d845..a4e13e30ca2e 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_re repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 3.0.1 +version: 3.0.2 resolution: workspace environment: @@ -12,8 +12,8 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md index b951559ec8c6..fbfedb61c59c 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.9 + + - Update a dependency to the latest release. + ## 1.10.8 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart index ddd128c14de6..5351a5a16546 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart +++ b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.1'; +const packageVersion = '6.5.2'; diff --git a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml index 3f97909dc814..ba8ac04ee536 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of firebase_remote_config homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web -version: 1.10.8 +version: 1.10.9 resolution: workspace environment: @@ -11,10 +11,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 - firebase_remote_config_platform_interface: ^3.0.1 + _flutterfire_internals: ^1.3.72 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 + firebase_remote_config_platform_interface: ^3.0.2 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_storage/firebase_storage/CHANGELOG.md b/packages/firebase_storage/firebase_storage/CHANGELOG.md index dff83f868080..d618e079120b 100644 --- a/packages/firebase_storage/firebase_storage/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage/CHANGELOG.md @@ -1,3 +1,7 @@ +## 13.4.2 + + - Update a dependency to the latest release. + ## 13.4.1 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage/example/pubspec.yaml b/packages/firebase_storage/firebase_storage/example/pubspec.yaml index add2b34ce64c..93cf6b6cabf9 100755 --- a/packages/firebase_storage/firebase_storage/example/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 - firebase_storage: ^13.4.1 + firebase_core: ^4.10.0 + firebase_storage: ^13.4.2 flutter: sdk: flutter image_picker: ^1.1.2 diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index 3bb7839d5742..149ea8699915 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "13.4.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_storage", diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index a37ec5f226b2..581580fc09ea 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -8,7 +8,7 @@ import PackageDescription let libraryVersion = "13.4.1" -let firebaseSdkVersion: Version = "12.13.0" +let firebaseSdkVersion: Version = "12.14.0" let package = Package( name: "firebase_storage", diff --git a/packages/firebase_storage/firebase_storage/pubspec.yaml b/packages/firebase_storage/firebase_storage/pubspec.yaml index aa7e95ddf6a0..ceffd8cb4fdf 100755 --- a/packages/firebase_storage/firebase_storage/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS. homepage: https://firebase.google.com/docs/storage/flutter/start repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage -version: 13.4.1 +version: 13.4.2 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_storage_platform_interface: ^6.0.1 - firebase_storage_web: ^3.11.7 + firebase_storage_platform_interface: ^6.0.2 + firebase_storage_web: ^3.11.8 flutter: sdk: flutter mime: ^2.0.0 diff --git a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md index 874fe6e1ada0..1ce02076f1eb 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.2 + + - Update a dependency to the latest release. + ## 6.0.1 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml index af00a3c9e543..1d91f519d7db 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_storage_platform_interface description: A common platform interface for the firebase_storage plugin. -version: 6.0.1 +version: 6.0.2 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface @@ -10,9 +10,9 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.71 + _flutterfire_internals: ^1.3.72 collection: ^1.15.0 - firebase_core: ^4.9.0 + firebase_core: ^4.10.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md index a889f580d928..f4837884ab38 100644 --- a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.11.8 + + - Update a dependency to the latest release. + ## 3.11.7 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart index 33d7d894e4ca..3e3d25ef6fcd 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '13.4.1'; +const packageVersion = '13.4.2'; diff --git a/packages/firebase_storage/firebase_storage_web/pubspec.yaml b/packages/firebase_storage/firebase_storage_web/pubspec.yaml index e3f15ed83188..cab7da4cca23 100644 --- a/packages/firebase_storage/firebase_storage_web/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_storage_web description: The web implementation of firebase_storage homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web -version: 3.11.7 +version: 3.11.8 resolution: workspace environment: @@ -10,11 +10,11 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.71 + _flutterfire_internals: ^1.3.72 async: ^2.5.0 - firebase_core: ^4.9.0 - firebase_core_web: ^3.7.0 - firebase_storage_platform_interface: ^6.0.1 + firebase_core: ^4.10.0 + firebase_core_web: ^3.8.0 + firebase_storage_platform_interface: ^6.0.2 flutter: sdk: flutter flutter_web_plugins: diff --git a/scripts/versions.json b/scripts/versions.json index b166da5bc116..2e948eeed641 100644 --- a/scripts/versions.json +++ b/scripts/versions.json @@ -1,4 +1,32 @@ { + "4.15.0": { + "date": "2026-06-01", + "firebase_sdk": { + "android": "34.14.0", + "ios": "12.14.0", + "web": "12.14.0", + "windows": "13.5.0" + }, + "packages": { + "cloud_firestore": "6.5.0", + "cloud_functions": "6.3.2", + "firebase_ai": "3.12.2", + "firebase_analytics": "12.4.2", + "firebase_app_check": "0.4.4+2", + "firebase_app_installations": "0.4.2+3", + "firebase_auth": "6.5.2", + "firebase_core": "4.10.0", + "firebase_crashlytics": "5.2.3", + "firebase_data_connect": "0.3.0+3", + "firebase_database": "12.4.2", + "firebase_in_app_messaging": "0.9.2+3", + "firebase_messaging": "16.3.0", + "firebase_ml_model_downloader": "0.4.2+3", + "firebase_performance": "0.11.4+2", + "firebase_remote_config": "6.5.2", + "firebase_storage": "13.4.2" + } + }, "4.14.0": { "date": "2026-05-14", "firebase_sdk": { diff --git a/tests/pubspec.yaml b/tests/pubspec.yaml index 523e10d067ba..004abfe9653f 100644 --- a/tests/pubspec.yaml +++ b/tests/pubspec.yaml @@ -10,43 +10,43 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions: ^6.3.1 - cloud_functions_platform_interface: ^6.0.1 - cloud_functions_web: ^5.1.7 + cloud_functions: ^6.3.2 + cloud_functions_platform_interface: ^6.0.2 + cloud_functions_web: ^5.1.8 collection: ^1.15.0 - firebase_ai: ^3.12.1 - firebase_analytics: ^12.4.1 - firebase_analytics_platform_interface: ^6.0.1 - firebase_analytics_web: ^0.6.1+7 - firebase_app_check: ^0.4.4+1 - firebase_app_check_platform_interface: ^0.4.0+1 - firebase_app_check_web: ^0.2.4+2 - firebase_app_installations: ^0.4.2+2 - firebase_app_installations_platform_interface: ^0.1.4+70 - firebase_app_installations_web: ^0.1.7+7 - firebase_auth: ^6.5.1 - firebase_auth_platform_interface: ^9.0.1 - firebase_auth_web: ^6.2.1 - firebase_core: ^4.9.0 + firebase_ai: ^3.12.2 + firebase_analytics: ^12.4.2 + firebase_analytics_platform_interface: ^6.0.2 + firebase_analytics_web: ^0.6.1+8 + firebase_app_check: ^0.4.4+2 + firebase_app_check_platform_interface: ^0.4.0+2 + firebase_app_check_web: ^0.2.4+3 + firebase_app_installations: ^0.4.2+3 + firebase_app_installations_platform_interface: ^0.1.4+71 + firebase_app_installations_web: ^0.1.7+8 + firebase_auth: ^6.5.2 + firebase_auth_platform_interface: ^9.0.2 + firebase_auth_web: ^6.2.2 + firebase_core: ^4.10.0 firebase_core_platform_interface: ^7.0.1 - firebase_core_web: ^3.7.0 - firebase_crashlytics: ^5.2.2 - firebase_crashlytics_platform_interface: ^3.8.22 - firebase_database: ^12.4.1 - firebase_database_platform_interface: ^0.4.0+1 - firebase_database_web: ^0.2.7+8 - firebase_messaging: ^16.2.2 - firebase_messaging_platform_interface: ^4.7.11 - firebase_messaging_web: ^4.1.7 - firebase_ml_model_downloader: ^0.4.2+2 - firebase_ml_model_downloader_platform_interface: ^0.1.5+22 - firebase_performance: ^0.11.4+1 - firebase_remote_config: ^6.5.1 - firebase_remote_config_platform_interface: ^3.0.1 - firebase_remote_config_web: ^1.10.8 - firebase_storage: ^13.4.1 - firebase_storage_platform_interface: ^6.0.1 - firebase_storage_web: ^3.11.7 + firebase_core_web: ^3.8.0 + firebase_crashlytics: ^5.2.3 + firebase_crashlytics_platform_interface: ^3.8.23 + firebase_database: ^12.4.2 + firebase_database_platform_interface: ^0.4.0+2 + firebase_database_web: ^0.2.7+9 + firebase_messaging: ^16.3.0 + firebase_messaging_platform_interface: ^4.8.0 + firebase_messaging_web: ^4.2.0 + firebase_ml_model_downloader: ^0.4.2+3 + firebase_ml_model_downloader_platform_interface: ^0.1.5+23 + firebase_performance: ^0.11.4+2 + firebase_remote_config: ^6.5.2 + firebase_remote_config_platform_interface: ^3.0.2 + firebase_remote_config_web: ^1.10.9 + firebase_storage: ^13.4.2 + firebase_storage_platform_interface: ^6.0.2 + firebase_storage_web: ^3.11.8 flutter: sdk: flutter http: ^1.0.0 From ec3feeb7f4d63a74f776af68fd0b41fcd760b00f Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Tue, 2 Jun 2026 09:35:58 +0000 Subject: [PATCH 099/137] fix: updated formatting script to align with new variable names and update version handling in Swift files (#18336) --- melos.yaml | 3 +-- scripts/generate_versions_spm.dart | 33 ++++++++---------------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/melos.yaml b/melos.yaml index 097dd2c48f92..c25d99b6bd86 100644 --- a/melos.yaml +++ b/melos.yaml @@ -55,8 +55,7 @@ scripts: format-ci: run: | - dart pub global run flutter_plugin_tools format && \ - swiftformat . + dart pub global run flutter_plugin_tools format description: | Formats the code of all packages (Java, Objective-C, and Dart). - Requires `flutter_plugin_tools` (`pub global activate flutter_plugin_tools`). diff --git a/scripts/generate_versions_spm.dart b/scripts/generate_versions_spm.dart index 369efb4f07a0..886da32aeff3 100644 --- a/scripts/generate_versions_spm.dart +++ b/scripts/generate_versions_spm.dart @@ -25,15 +25,7 @@ void main(List args) async { final firebaseiOSVersion = getFirebaseiOSVersion(firebaseCoreIosVersionFile); // Update hard-coded versions in all plugin Package.swift files - final firebaseCoreVersion = loadYaml( - File('${firebaseCorePackage.path}/pubspec.yaml').readAsStringSync(), - )['version'] - .toString(); - updatePluginPackageSwiftVersions( - workspace, - firebaseiOSVersion, - firebaseCoreVersion, - ); + updatePluginPackageSwiftVersions(workspace, firebaseiOSVersion); // Update plugin version in Constants.swift for pure Swift plugins. Unable to pass macros in pure Swift implementations updateLibraryVersionPureSwiftPlugins(); } @@ -75,7 +67,6 @@ String getFirebaseiOSVersion(File firebaseCoreIosSdkVersion) { void updatePluginPackageSwiftVersions( melos.MelosWorkspace workspace, String firebaseiOSVersion, - String firebaseCoreVersion, ) { for (final package in workspace.filteredPackages.values) { for (final platform in ['ios', 'macos']) { @@ -86,19 +77,13 @@ void updatePluginPackageSwiftVersions( var content = packageSwiftFile.readAsStringSync(); - // Update firebase_sdk_version - content = content.replaceAll( - RegExp('let firebase_sdk_version: Version = "[^"]+"'), - 'let firebase_sdk_version: Version = "$firebaseiOSVersion"', - ); - - // Update shared_spm_version + // Update firebaseSdkVersion (matches Package.swift naming). content = content.replaceAll( - RegExp('let shared_spm_version: Version = "[^"]+"'), - 'let shared_spm_version: Version = "$firebaseCoreVersion-firebase-core-swift"', + RegExp(r'let firebaseSdkVersion: Version = "[^"]+"'), + 'let firebaseSdkVersion: Version = "$firebaseiOSVersion"', ); - // Update library_version or library_version_string from pubspec version + // Update libraryVersion / libraryVersionString from pubspec version. final pubspecFile = File('${package.path}/pubspec.yaml'); if (pubspecFile.existsSync()) { final pubspecYaml = loadYaml(pubspecFile.readAsStringSync()); @@ -106,12 +91,12 @@ void updatePluginPackageSwiftVersions( if (version != null) { final spmVersion = version.replaceAll('+', '-'); content = content.replaceAll( - RegExp('let library_version_string = "[^"]+"'), - 'let library_version_string = "$spmVersion"', + RegExp(r'let libraryVersionString = "[^"]+"'), + 'let libraryVersionString = "$spmVersion"', ); content = content.replaceAll( - RegExp('let library_version = "[^"]+"'), - 'let library_version = "$spmVersion"', + RegExp(r'let libraryVersion = "[^"]+"'), + 'let libraryVersion = "$spmVersion"', ); } } From 57be702778d34b9b7e86b40817d93acaec4c3ca4 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Tue, 2 Jun 2026 11:27:54 -0700 Subject: [PATCH 100/137] feat(core): Add Recaptcha Site Key to FirebaseOptions (#18334) * Add Recaptcha Site Key to FirebaseOptions * Add Recaptcha Site Key to FirebaseOptions * chore: regenerate and format pigeon files to resolve merge state * chore: format pigeon generated files --- .../core/FlutterFirebaseCorePlugin.java | 3 ++ .../core/GeneratedAndroidFirebaseCore.java | 34 +++++++++++++++--- .../firebase_core/FLTFirebaseCorePlugin.m | 3 ++ .../include/firebase_core/messages.g.h | 4 ++- .../Sources/firebase_core/messages.g.m | 10 ++++-- .../firebase_core/windows/messages.g.cpp | 36 ++++++++++++++++--- .../firebase_core/windows/messages.g.h | 12 ++++--- .../lib/src/firebase_options.dart | 10 +++++- .../lib/src/pigeon/messages.pigeon.dart | 8 ++++- .../pigeons/messages.dart | 3 ++ .../test/firebase_options_test.dart | 4 +++ .../lib/src/firebase_core_web.dart | 2 ++ 12 files changed, 110 insertions(+), 19 deletions(-) diff --git a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java index a1fed94439e3..fcdeb2a7f5ac 100644 --- a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java +++ b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java @@ -63,6 +63,7 @@ private GeneratedAndroidFirebaseCore.CoreFirebaseOptions firebaseOptionsToMap( firebaseOptions.setDatabaseURL(options.getDatabaseUrl()); firebaseOptions.setStorageBucket(options.getStorageBucket()); firebaseOptions.setTrackingId(options.getGaTrackingId()); + // TODO(recaptchaSiteKey): Map recaptchaSiteKey if stored. return firebaseOptions.build(); } @@ -165,6 +166,8 @@ public void initializeApp( customAuthDomain.put(appName, initializeAppRequest.getAuthDomain()); } + // TODO(recaptchaSiteKey): Store or use recaptchaSiteKey if needed. + FirebaseApp firebaseApp = FirebaseApp.initializeApp(applicationContext, options, appName); taskCompletionSource.setResult(Tasks.await(firebaseAppToMap(firebaseApp))); diff --git a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java index b0a698faf51c..fdae685adbd8 100644 --- a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java +++ b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/GeneratedAndroidFirebaseCore.java @@ -377,6 +377,16 @@ public void setAppGroupId(@Nullable String setterArg) { this.appGroupId = setterArg; } + private @Nullable String recaptchaSiteKey; + + public @Nullable String getRecaptchaSiteKey() { + return recaptchaSiteKey; + } + + public void setRecaptchaSiteKey(@Nullable String setterArg) { + this.recaptchaSiteKey = setterArg; + } + /** Constructor is non-public to enforce null safety; use Builder. */ CoreFirebaseOptions() {} @@ -402,7 +412,8 @@ && pigeonDeepEquals(deepLinkURLScheme, that.deepLinkURLScheme) && pigeonDeepEquals(androidClientId, that.androidClientId) && pigeonDeepEquals(iosClientId, that.iosClientId) && pigeonDeepEquals(iosBundleId, that.iosBundleId) - && pigeonDeepEquals(appGroupId, that.appGroupId); + && pigeonDeepEquals(appGroupId, that.appGroupId) + && pigeonDeepEquals(recaptchaSiteKey, that.recaptchaSiteKey); } @Override @@ -423,7 +434,8 @@ public int hashCode() { androidClientId, iosClientId, iosBundleId, - appGroupId + appGroupId, + recaptchaSiteKey }; return pigeonDeepHashCode(fields); } @@ -542,6 +554,14 @@ public static final class Builder { return this; } + private @Nullable String recaptchaSiteKey; + + @CanIgnoreReturnValue + public @NonNull Builder setRecaptchaSiteKey(@Nullable String setterArg) { + this.recaptchaSiteKey = setterArg; + return this; + } + public @NonNull CoreFirebaseOptions build() { CoreFirebaseOptions pigeonReturn = new CoreFirebaseOptions(); pigeonReturn.setApiKey(apiKey); @@ -558,13 +578,14 @@ public static final class Builder { pigeonReturn.setIosClientId(iosClientId); pigeonReturn.setIosBundleId(iosBundleId); pigeonReturn.setAppGroupId(appGroupId); + pigeonReturn.setRecaptchaSiteKey(recaptchaSiteKey); return pigeonReturn; } } @NonNull - ArrayList toList() { - ArrayList toListResult = new ArrayList<>(14); + public ArrayList toList() { + ArrayList toListResult = new ArrayList<>(15); toListResult.add(apiKey); toListResult.add(appId); toListResult.add(messagingSenderId); @@ -579,6 +600,7 @@ ArrayList toList() { toListResult.add(iosClientId); toListResult.add(iosBundleId); toListResult.add(appGroupId); + toListResult.add(recaptchaSiteKey); return toListResult; } @@ -612,6 +634,8 @@ ArrayList toList() { pigeonResult.setIosBundleId((String) iosBundleId); Object appGroupId = pigeonVar_list.get(13); pigeonResult.setAppGroupId((String) appGroupId); + Object recaptchaSiteKey = pigeonVar_list.get(14); + pigeonResult.setRecaptchaSiteKey((String) recaptchaSiteKey); return pigeonResult; } } @@ -740,7 +764,7 @@ public static final class Builder { } @NonNull - ArrayList toList() { + public ArrayList toList() { ArrayList toListResult = new ArrayList<>(4); toListResult.add(name); toListResult.add(options); diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m index 23b3f7b9433b..b68d963b08c7 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m @@ -93,6 +93,7 @@ - (CoreFirebaseOptions *)optionsFromFIROptions:(FIROptions *)options { pigeonOptions.iosBundleId = (id)options.bundleID ?: [NSNull null]; pigeonOptions.iosClientId = (id)options.clientID ?: [NSNull null]; pigeonOptions.appGroupId = (id)options.appGroupID ?: [NSNull null]; + // TODO(recaptchaSiteKey): Map recaptchaSiteKey if stored. return pigeonOptions; } @@ -178,6 +179,8 @@ - (void)initializeAppAppName:(nonnull NSString *)appName options.appGroupID = initializeAppRequest.appGroupId; } + // TODO(recaptchaSiteKey): Store or use recaptchaSiteKey if needed. + if (initializeAppRequest.authDomain != nil) { customAuthDomains[appNameIos] = initializeAppRequest.authDomain; } diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h index 913fdbbd3e43..561383cc4135 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/include/firebase_core/messages.g.h @@ -32,7 +32,8 @@ NS_ASSUME_NONNULL_BEGIN androidClientId:(nullable NSString *)androidClientId iosClientId:(nullable NSString *)iosClientId iosBundleId:(nullable NSString *)iosBundleId - appGroupId:(nullable NSString *)appGroupId; + appGroupId:(nullable NSString *)appGroupId + recaptchaSiteKey:(nullable NSString *)recaptchaSiteKey; @property(nonatomic, copy) NSString *apiKey; @property(nonatomic, copy) NSString *appId; @property(nonatomic, copy) NSString *messagingSenderId; @@ -47,6 +48,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy, nullable) NSString *iosClientId; @property(nonatomic, copy, nullable) NSString *iosBundleId; @property(nonatomic, copy, nullable) NSString *appGroupId; +@property(nonatomic, copy, nullable) NSString *recaptchaSiteKey; @end @interface CoreInitializeResponse : NSObject diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m index b1a0a1e69e45..449944316866 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/messages.g.m @@ -143,7 +143,8 @@ + (instancetype)makeWithApiKey:(NSString *)apiKey androidClientId:(nullable NSString *)androidClientId iosClientId:(nullable NSString *)iosClientId iosBundleId:(nullable NSString *)iosBundleId - appGroupId:(nullable NSString *)appGroupId { + appGroupId:(nullable NSString *)appGroupId + recaptchaSiteKey:(nullable NSString *)recaptchaSiteKey { CoreFirebaseOptions *pigeonResult = [[CoreFirebaseOptions alloc] init]; pigeonResult.apiKey = apiKey; pigeonResult.appId = appId; @@ -159,6 +160,7 @@ + (instancetype)makeWithApiKey:(NSString *)apiKey pigeonResult.iosClientId = iosClientId; pigeonResult.iosBundleId = iosBundleId; pigeonResult.appGroupId = appGroupId; + pigeonResult.recaptchaSiteKey = recaptchaSiteKey; return pigeonResult; } + (CoreFirebaseOptions *)fromList:(NSArray *)list { @@ -177,6 +179,7 @@ + (CoreFirebaseOptions *)fromList:(NSArray *)list { pigeonResult.iosClientId = GetNullableObjectAtIndex(list, 11); pigeonResult.iosBundleId = GetNullableObjectAtIndex(list, 12); pigeonResult.appGroupId = GetNullableObjectAtIndex(list, 13); + pigeonResult.recaptchaSiteKey = GetNullableObjectAtIndex(list, 14); return pigeonResult; } + (nullable CoreFirebaseOptions *)nullableFromList:(NSArray *)list { @@ -198,6 +201,7 @@ + (nullable CoreFirebaseOptions *)nullableFromList:(NSArray *)list { self.iosClientId ?: [NSNull null], self.iosBundleId ?: [NSNull null], self.appGroupId ?: [NSNull null], + self.recaptchaSiteKey ?: [NSNull null], ]; } - (BOOL)isEqual:(id)object { @@ -221,7 +225,8 @@ - (BOOL)isEqual:(id)object { FLTPigeonDeepEquals(self.androidClientId, other.androidClientId) && FLTPigeonDeepEquals(self.iosClientId, other.iosClientId) && FLTPigeonDeepEquals(self.iosBundleId, other.iosBundleId) && - FLTPigeonDeepEquals(self.appGroupId, other.appGroupId); + FLTPigeonDeepEquals(self.appGroupId, other.appGroupId) && + FLTPigeonDeepEquals(self.recaptchaSiteKey, other.recaptchaSiteKey); } - (NSUInteger)hash { @@ -240,6 +245,7 @@ - (NSUInteger)hash { result = result * 31 + FLTPigeonDeepHash(self.iosClientId); result = result * 31 + FLTPigeonDeepHash(self.iosBundleId); result = result * 31 + FLTPigeonDeepHash(self.appGroupId); + result = result * 31 + FLTPigeonDeepHash(self.recaptchaSiteKey); return result; } @end diff --git a/packages/firebase_core/firebase_core/windows/messages.g.cpp b/packages/firebase_core/firebase_core/windows/messages.g.cpp index 42e8046a21e1..4bfc5dcbf9c4 100644 --- a/packages/firebase_core/firebase_core/windows/messages.g.cpp +++ b/packages/firebase_core/firebase_core/windows/messages.g.cpp @@ -257,7 +257,8 @@ CoreFirebaseOptions::CoreFirebaseOptions( const std::string* storage_bucket, const std::string* measurement_id, const std::string* tracking_id, const std::string* deep_link_u_r_l_scheme, const std::string* android_client_id, const std::string* ios_client_id, - const std::string* ios_bundle_id, const std::string* app_group_id) + const std::string* ios_bundle_id, const std::string* app_group_id, + const std::string* recaptcha_site_key) : api_key_(api_key), app_id_(app_id), messaging_sender_id_(messaging_sender_id), @@ -287,7 +288,10 @@ CoreFirebaseOptions::CoreFirebaseOptions( ios_bundle_id_(ios_bundle_id ? std::optional(*ios_bundle_id) : std::nullopt), app_group_id_(app_group_id ? std::optional(*app_group_id) - : std::nullopt) {} + : std::nullopt), + recaptcha_site_key_(recaptcha_site_key + ? std::optional(*recaptcha_site_key) + : std::nullopt) {} const std::string& CoreFirebaseOptions::api_key() const { return api_key_; } @@ -453,9 +457,23 @@ void CoreFirebaseOptions::set_app_group_id(std::string_view value_arg) { app_group_id_ = value_arg; } +const std::string* CoreFirebaseOptions::recaptcha_site_key() const { + return recaptcha_site_key_ ? &(*recaptcha_site_key_) : nullptr; +} + +void CoreFirebaseOptions::set_recaptcha_site_key( + const std::string_view* value_arg) { + recaptcha_site_key_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void CoreFirebaseOptions::set_recaptcha_site_key(std::string_view value_arg) { + recaptcha_site_key_ = value_arg; +} + EncodableList CoreFirebaseOptions::ToEncodableList() const { EncodableList list; - list.reserve(14); + list.reserve(15); list.push_back(EncodableValue(api_key_)); list.push_back(EncodableValue(app_id_)); list.push_back(EncodableValue(messaging_sender_id_)); @@ -481,6 +499,8 @@ EncodableList CoreFirebaseOptions::ToEncodableList() const { : EncodableValue()); list.push_back(app_group_id_ ? EncodableValue(*app_group_id_) : EncodableValue()); + list.push_back(recaptcha_site_key_ ? EncodableValue(*recaptcha_site_key_) + : EncodableValue()); return list; } @@ -531,6 +551,11 @@ CoreFirebaseOptions CoreFirebaseOptions::FromEncodableList( if (!encodable_app_group_id.IsNull()) { decoded.set_app_group_id(std::get(encodable_app_group_id)); } + auto& encodable_recaptcha_site_key = list[14]; + if (!encodable_recaptcha_site_key.IsNull()) { + decoded.set_recaptcha_site_key( + std::get(encodable_recaptcha_site_key)); + } return decoded; } @@ -551,7 +576,9 @@ bool CoreFirebaseOptions::operator==(const CoreFirebaseOptions& other) const { other.android_client_id_) && PigeonInternalDeepEquals(ios_client_id_, other.ios_client_id_) && PigeonInternalDeepEquals(ios_bundle_id_, other.ios_bundle_id_) && - PigeonInternalDeepEquals(app_group_id_, other.app_group_id_); + PigeonInternalDeepEquals(app_group_id_, other.app_group_id_) && + PigeonInternalDeepEquals(recaptcha_site_key_, + other.recaptcha_site_key_); } bool CoreFirebaseOptions::operator!=(const CoreFirebaseOptions& other) const { @@ -574,6 +601,7 @@ size_t CoreFirebaseOptions::Hash() const { result = result * 31 + PigeonInternalDeepHash(ios_client_id_); result = result * 31 + PigeonInternalDeepHash(ios_bundle_id_); result = result * 31 + PigeonInternalDeepHash(app_group_id_); + result = result * 31 + PigeonInternalDeepHash(recaptcha_site_key_); return result; } diff --git a/packages/firebase_core/firebase_core/windows/messages.g.h b/packages/firebase_core/firebase_core/windows/messages.g.h index bce0a6a81f24..a55996f5b067 100644 --- a/packages/firebase_core/firebase_core/windows/messages.g.h +++ b/packages/firebase_core/firebase_core/windows/messages.g.h @@ -76,7 +76,8 @@ class CoreFirebaseOptions { const std::string* storage_bucket, const std::string* measurement_id, const std::string* tracking_id, const std::string* deep_link_u_r_l_scheme, const std::string* android_client_id, const std::string* ios_client_id, - const std::string* ios_bundle_id, const std::string* app_group_id); + const std::string* ios_bundle_id, const std::string* app_group_id, + const std::string* recaptcha_site_key); const std::string& api_key() const; void set_api_key(std::string_view value_arg); @@ -130,6 +131,10 @@ class CoreFirebaseOptions { void set_app_group_id(const std::string_view* value_arg); void set_app_group_id(std::string_view value_arg); + const std::string* recaptcha_site_key() const; + void set_recaptcha_site_key(const std::string_view* value_arg); + void set_recaptcha_site_key(std::string_view value_arg); + bool operator==(const CoreFirebaseOptions& other) const; bool operator!=(const CoreFirebaseOptions& other) const; /// Returns a hash code value for the object. This method is supported for the @@ -140,11 +145,9 @@ class CoreFirebaseOptions { static CoreFirebaseOptions FromEncodableList( const ::flutter::EncodableList& list); - public: public: ::flutter::EncodableList ToEncodableList() const; - private: private: friend class CoreInitializeResponse; friend class FirebaseCoreHostApi; @@ -164,6 +167,7 @@ class CoreFirebaseOptions { std::optional ios_client_id_; std::optional ios_bundle_id_; std::optional app_group_id_; + std::optional recaptcha_site_key_; }; // Generated class from Pigeon that represents data sent in messages. @@ -209,11 +213,9 @@ class CoreInitializeResponse { static CoreInitializeResponse FromEncodableList( const ::flutter::EncodableList& list); - public: public: ::flutter::EncodableList ToEncodableList() const; - private: private: friend class FirebaseCoreHostApi; friend class FirebaseAppHostApi; diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/firebase_options.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/firebase_options.dart index ad0e580e88a8..dbc740a71ffe 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/firebase_options.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/firebase_options.dart @@ -50,6 +50,7 @@ class FirebaseOptions { this.iosClientId, this.iosBundleId, this.appGroupId, + this.recaptchaSiteKey, }); /// Named constructor to create [FirebaseOptions] from a the response of Pigeon channel. @@ -71,7 +72,8 @@ class FirebaseOptions { androidClientId = options.androidClientId, iosClientId = options.iosClientId, iosBundleId = options.iosBundleId, - appGroupId = options.appGroupId; + appGroupId = options.appGroupId, + recaptchaSiteKey = options.recaptchaSiteKey; /// Returns a copy of this FirebaseOptions with the given fields replaced with /// the new values. @@ -90,6 +92,7 @@ class FirebaseOptions { String? iosClientId, String? iosBundleId, String? appGroupId, + String? recaptchaSiteKey, }) { return FirebaseOptions( apiKey: apiKey ?? this.apiKey, @@ -106,6 +109,7 @@ class FirebaseOptions { iosClientId: iosClientId ?? this.iosClientId, iosBundleId: iosBundleId ?? this.iosBundleId, appGroupId: appGroupId ?? this.appGroupId, + recaptchaSiteKey: recaptchaSiteKey ?? this.recaptchaSiteKey, ); } @@ -174,6 +178,9 @@ class FirebaseOptions { /// This property is used on iOS only. final String? appGroupId; + /// The reCAPTCHA site key used for App Check. + final String? recaptchaSiteKey; + /// The current instance as a [Map]. Map get asMap { return { @@ -191,6 +198,7 @@ class FirebaseOptions { 'iosClientId': iosClientId, 'iosBundleId': iosBundleId, 'appGroupId': appGroupId, + 'recaptchaSiteKey': recaptchaSiteKey, }; } diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart index 6d4123a1f1cb..9bb893bb3aba 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -126,6 +126,7 @@ class CoreFirebaseOptions { this.iosClientId, this.iosBundleId, this.appGroupId, + this.recaptchaSiteKey, }); String apiKey; @@ -156,6 +157,8 @@ class CoreFirebaseOptions { String? appGroupId; + String? recaptchaSiteKey; + List _toList() { return [ apiKey, @@ -172,6 +175,7 @@ class CoreFirebaseOptions { iosClientId, iosBundleId, appGroupId, + recaptchaSiteKey, ]; } @@ -196,6 +200,7 @@ class CoreFirebaseOptions { iosClientId: result[11] as String?, iosBundleId: result[12] as String?, appGroupId: result[13] as String?, + recaptchaSiteKey: result[14] as String?, ); } @@ -221,7 +226,8 @@ class CoreFirebaseOptions { _deepEquals(androidClientId, other.androidClientId) && _deepEquals(iosClientId, other.iosClientId) && _deepEquals(iosBundleId, other.iosBundleId) && - _deepEquals(appGroupId, other.appGroupId); + _deepEquals(appGroupId, other.appGroupId) && + _deepEquals(recaptchaSiteKey, other.recaptchaSiteKey); } @override diff --git a/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart b/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart index a2286f54f1a9..a42278d0f4e7 100644 --- a/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart +++ b/packages/firebase_core/firebase_core_platform_interface/pigeons/messages.dart @@ -44,6 +44,7 @@ class CoreFirebaseOptions { required this.databaseURL, required this.storageBucket, required this.trackingId, + required this.recaptchaSiteKey, }); final String apiKey; @@ -73,6 +74,8 @@ class CoreFirebaseOptions { final String? iosBundleId; final String? appGroupId; + + final String? recaptchaSiteKey; } class CoreInitializeResponse { diff --git a/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart b/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart index 8b84f78e9525..91f66e2a03c0 100644 --- a/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart +++ b/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart @@ -91,6 +91,7 @@ void main() { iosClientId: 'newIosClientId', iosBundleId: 'newIosBundleId', appGroupId: 'newAppGroupId', + recaptchaSiteKey: 'newRecaptchaSiteKey', ); expect( @@ -110,6 +111,7 @@ void main() { iosClientId: 'newIosClientId', iosBundleId: 'newIosBundleId', appGroupId: 'newAppGroupId', + recaptchaSiteKey: 'newRecaptchaSiteKey', ), ); }); @@ -130,6 +132,7 @@ void main() { iosBundleId: 'iosBundleId', iosClientId: 'iosClientId', appGroupId: 'appGroupId', + recaptchaSiteKey: 'recaptchaSiteKey', ); expect(options.asMap, { @@ -147,6 +150,7 @@ void main() { 'iosBundleId': 'iosBundleId', 'iosClientId': 'iosClientId', 'appGroupId': 'appGroupId', + 'recaptchaSiteKey': 'recaptchaSiteKey', }); }); }); diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart index a3ae6f933db6..f649fa1a2f5e 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart @@ -334,6 +334,7 @@ class FirebaseCoreWeb extends FirebasePlatform { // At this point, there is no default app so we need to create it with // the users options. + // TODO(recaptchaSiteKey): Pass recaptchaSiteKey if supported. app = firebase.initializeApp( apiKey: options!.apiKey, authDomain: options.authDomain, @@ -355,6 +356,7 @@ class FirebaseCoreWeb extends FirebasePlatform { ); try { + // TODO(recaptchaSiteKey): Pass recaptchaSiteKey if supported. app = firebase.initializeApp( name: name, apiKey: options!.apiKey, From b8fbe6cbe271c09de71e77ddb943f9145781ee77 Mon Sep 17 00:00:00 2001 From: Morgan Chen Date: Wed, 3 Jun 2026 00:51:21 -0700 Subject: [PATCH 101/137] ci Remove synchronize trigger for title check (#18339) --- .github/workflows/pr_title.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/pr_title.yaml b/.github/workflows/pr_title.yaml index 453064704526..72b8012d8598 100644 --- a/.github/workflows/pr_title.yaml +++ b/.github/workflows/pr_title.yaml @@ -5,7 +5,6 @@ on: types: - opened - edited - - synchronize jobs: validate: From c15714f59ec7824a3b1bb4be3874a724ac5edfd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 09:51:51 +0200 Subject: [PATCH 102/137] chore(deps): bump gradle/actions from 4 to 6 (#18344) Bumps [gradle/actions](https://github.com/gradle/actions) from 4 to 6. - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/v4...v6) --- updated-dependencies: - dependency-name: gradle/actions dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/android.yaml | 2 +- .github/workflows/e2e_tests_fdc.yaml | 2 +- .github/workflows/e2e_tests_pipeline.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index e31e43764c10..77c910abd71c 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -89,7 +89,7 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - name: Gradle cache - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v6 - name: Free Disk Space (Ubuntu) uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 with: diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index ab3ab5322656..d0799e218682 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -88,7 +88,7 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - name: Gradle cache - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v6 - name: Free Disk Space (Ubuntu) uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 with: diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index a70f6ef5c6a6..d47de3e17b54 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -70,7 +70,7 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - name: Gradle cache - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@v6 - name: Free Disk Space (Ubuntu) uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 with: From fd87ebedd7f8adf2a28d62ad5595cc3e28a85e7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 09:52:03 +0200 Subject: [PATCH 103/137] chore(deps): bump hendrikmuhs/ccache-action from 1.2.20 to 1.2.23 (#18343) Bumps [hendrikmuhs/ccache-action](https://github.com/hendrikmuhs/ccache-action) from 1.2.20 to 1.2.23. - [Release notes](https://github.com/hendrikmuhs/ccache-action/releases) - [Commits](https://github.com/hendrikmuhs/ccache-action/compare/5ebbd400eff9e74630f759d94ddd7b6c26299639...d62db5f07c26379fc4b4e0916f098a92573c3b03) --- updated-dependencies: - dependency-name: hendrikmuhs/ccache-action dependency-version: 1.2.23 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/e2e_tests_fdc.yaml | 2 +- .github/workflows/ios.yaml | 2 +- .github/workflows/macos.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index d0799e218682..0a2b38067b69 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -157,7 +157,7 @@ jobs: java-version: '21' - name: Setup PostgreSQL for Linux/macOS/Windows uses: ikalnytskyi/action-setup-postgres@v8 - - uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639 + - uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 name: Xcode Compile Cache with: key: xcode-cache-${{ runner.os }} diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index e4df80563f19..a589659856a5 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -52,7 +52,7 @@ jobs: with: distribution: 'temurin' java-version: '21' - - uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639 + - uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 name: Xcode Compile Cache with: key: xcode-cache-${{ runner.os }} diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index 15385fcc6c1c..510ef5e91d3a 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -50,7 +50,7 @@ jobs: with: distribution: 'temurin' java-version: '21' - - uses: hendrikmuhs/ccache-action@5ebbd400eff9e74630f759d94ddd7b6c26299639 + - uses: hendrikmuhs/ccache-action@d62db5f07c26379fc4b4e0916f098a92573c3b03 name: Xcode Compile Cache with: key: xcode-cache-${{ runner.os }} From be74f99b3cf9e01f2b866efeb58d96d828cdcd32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 09:52:16 +0200 Subject: [PATCH 104/137] chore(deps): bump subosito/flutter-action from 2.18.0 to 2.23.0 (#18342) Bumps [subosito/flutter-action](https://github.com/subosito/flutter-action) from 2.18.0 to 2.23.0. - [Release notes](https://github.com/subosito/flutter-action/releases) - [Commits](https://github.com/subosito/flutter-action/compare/f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff...1a449444c387b1966244ae4d4f8c696479add0b2) --- updated-dependencies: - dependency-name: subosito/flutter-action dependency-version: 2.23.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/all_plugins.yaml | 16 ++++++++-------- .github/workflows/android.yaml | 2 +- .github/workflows/e2e_tests_fdc.yaml | 8 ++++---- .github/workflows/e2e_tests_pipeline.yaml | 6 +++--- .github/workflows/ios.yaml | 2 +- .github/workflows/macos.yaml | 2 +- .github/workflows/nightly.yaml | 2 +- .github/workflows/web.yaml | 6 +++--- .github/workflows/windows.yaml | 4 ++-- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 383c4e180bcb..03e1f639bdc9 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -66,7 +66,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -88,7 +88,7 @@ jobs: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 with: fetch-depth: 0 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -126,7 +126,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' flutter-version: '3.41.9' @@ -148,7 +148,7 @@ jobs: PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' flutter-version: '3.41.9' @@ -176,7 +176,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -201,7 +201,7 @@ jobs: # Go is used by addlicense command (addlicense is used in melos run # check-license-header) - run: go install github.com/google/addlicense@latest - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 77c910abd71c..188789e97e42 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -69,7 +69,7 @@ jobs: path: ~/.cache/firebase/emulators key: firebase-emulators-v3-${{ env.FIREBASE_TOOLS_VERSION }} restore-keys: firebase-emulators-v3 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 0a2b38067b69..b0e1cac592b6 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -61,7 +61,7 @@ jobs: # Must match the save path exactly path: ~/.cache/firebase/emulators key: firebase-emulators-v4-${{ runner.os }}-${{ env.FIREBASE_TOOLS_VERSION }} - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -184,7 +184,7 @@ jobs: # Must match the save path exactly path: ~/.cache/firebase/emulators key: firebase-emulators-v4-${{ runner.os }}-${{ env.FIREBASE_TOOLS_VERSION }} - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -271,7 +271,7 @@ jobs: java-version: '21' - name: Setup PostgreSQL for Linux/macOS/Windows uses: ikalnytskyi/action-setup-postgres@v8 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -346,7 +346,7 @@ jobs: java-version: '21' - name: Setup PostgreSQL for Linux/macOS/Windows uses: ikalnytskyi/action-setup-postgres@v8 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index d47de3e17b54..163ff5f9339e 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -42,7 +42,7 @@ jobs: with: distribution: 'temurin' java-version: '21' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' flutter-version: '3.41.9' @@ -120,7 +120,7 @@ jobs: name: Install Node.js 20 with: node-version: '20' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -171,7 +171,7 @@ jobs: with: distribution: 'temurin' java-version: '21' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' flutter-version: '3.41.9' diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index a589659856a5..113d40cc6663 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -82,7 +82,7 @@ jobs: path: ~/.cache/firebase/emulators key: firebase-emulators-v3-${{ env.FIREBASE_TOOLS_VERSION }} restore-keys: firebase-emulators-v3 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index 510ef5e91d3a..a9647bef1b0e 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -80,7 +80,7 @@ jobs: path: ~/.cache/firebase/emulators key: firebase-emulators-v3-${{ env.FIREBASE_TOOLS_VERSION }} restore-keys: firebase-emulators-v3 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' flutter-version: '3.41.9' diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 6a1b5967233f..1d903ca64448 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -62,7 +62,7 @@ jobs: needs: [e2e-android, e2e-ios, e2e-macos, e2e-web, e2e-windows, e2e-fdc, e2e-pipeline] steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' - name: Update Dashboard Issue diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index dd01a6bf15af..73760ef100ba 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -50,7 +50,7 @@ jobs: with: distribution: 'temurin' java-version: '21' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -120,7 +120,7 @@ jobs: with: distribution: 'temurin' java-version: '21' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -202,7 +202,7 @@ jobs: with: distribution: 'temurin' java-version: '21' - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index bb89b1d52f70..16d9df9f8581 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -43,7 +43,7 @@ jobs: name: Install Node.js 20 with: node-version: "20" - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true @@ -77,7 +77,7 @@ jobs: name: Install Node.js 20 with: node-version: "20" - - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' cache: true From 0dcc0af7699fd9528138355c0b7b858d3000bf33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 09:52:28 +0200 Subject: [PATCH 105/137] chore(deps): bump amannn/action-semantic-pull-request (#18341) Bumps [amannn/action-semantic-pull-request](https://github.com/amannn/action-semantic-pull-request) from 5.5.3 to 6.1.1. - [Release notes](https://github.com/amannn/action-semantic-pull-request/releases) - [Changelog](https://github.com/amannn/action-semantic-pull-request/blob/main/CHANGELOG.md) - [Commits](https://github.com/amannn/action-semantic-pull-request/compare/0723387faaf9b38adef4775cd42cfd5155ed6017...48f256284bd46cdaab1048c3721360e808335d50) --- updated-dependencies: - dependency-name: amannn/action-semantic-pull-request dependency-version: 6.1.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pr_title.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_title.yaml b/.github/workflows/pr_title.yaml index 72b8012d8598..76971ebc00c9 100644 --- a/.github/workflows/pr_title.yaml +++ b/.github/workflows/pr_title.yaml @@ -12,6 +12,6 @@ jobs: pull-requests: read runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 + - uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From c21fc77b68a87b9691fc1615454c5dac39dd4ed4 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Wed, 3 Jun 2026 08:22:01 +0000 Subject: [PATCH 106/137] fix(analytics, iOS): update iOS dependency instructions for IDFA-free usage (#18337) --- docs/analytics/_get-started.md | 7 ++++--- .../ios/firebase_analytics/Package.swift | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/analytics/_get-started.md b/docs/analytics/_get-started.md index 78bbe531e1e4..58bd944a7301 100644 --- a/docs/analytics/_get-started.md +++ b/docs/analytics/_get-started.md @@ -85,9 +85,10 @@ await FirebaseAnalytics.instance ## Using Analytics without Ad ID support (iOS) {:#without-ad-id} -If your app doesn't use IDFA, you can use `FirebaseAnalyticsWithoutAdIdSupport` -instead of the default `FirebaseAnalytics` iOS dependency to avoid App Store -review questions about advertising identifiers. +If your app doesn't use IDFA, use the IDFA-free Analytics iOS dependency +(`FirebaseAnalyticsCore` under SPM, or `FirebaseAnalytics/Core` under CocoaPods) +instead of the default `FirebaseAnalytics` dependency to avoid App Store review +questions about advertising identifiers. ### Swift Package Manager diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift index 526bf50bab01..23763dbc6049 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift @@ -10,10 +10,10 @@ import PackageDescription let firebaseSdkVersion: Version = "12.14.0" -// Set FIREBASE_ANALYTICS_WITHOUT_ADID=true to use FirebaseAnalyticsWithoutAdIdSupport +// Set FIREBASE_ANALYTICS_WITHOUT_ADID=true to use FirebaseAnalyticsCore. // e.g. FIREBASE_ANALYTICS_WITHOUT_ADID=true flutter build ios let useWithoutAdId = ProcessInfo.processInfo.environment["FIREBASE_ANALYTICS_WITHOUT_ADID"] != nil -let analyticsProduct = useWithoutAdId ? "FirebaseAnalyticsWithoutAdIdSupport" : "FirebaseAnalytics" +let analyticsProduct = useWithoutAdId ? "FirebaseAnalyticsCore" : "FirebaseAnalytics" let package = Package( name: "firebase_analytics", From e41634c4ba36ea98d179c75b779dbe2868c459ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jun 2026 12:44:22 +0000 Subject: [PATCH 107/137] chore(deps): bump actions/checkout from 4.2.0 to 6.0.3 (#18340) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.0 to 6.0.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/d632683dd7b4114ad314bca15554477dd762a938...df4cb1c069e1874edd31b4311f1884172cec0e10) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/all_plugins.yaml | 16 ++++++++-------- .github/workflows/android.yaml | 2 +- .github/workflows/e2e_tests_fdc.yaml | 8 ++++---- .github/workflows/e2e_tests_pipeline.yaml | 6 +++--- .github/workflows/ios.yaml | 2 +- .github/workflows/macos.yaml | 2 +- .github/workflows/nightly.yaml | 2 +- .github/workflows/ossf-scorecard.yml | 2 +- .github/workflows/web.yaml | 6 +++--- .github/workflows/windows.yaml | 4 ++-- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 03e1f639bdc9..629ce3dcb758 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -23,7 +23,7 @@ jobs: timeout-minutes: 50 runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' @@ -46,7 +46,7 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' @@ -65,7 +65,7 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' @@ -85,7 +85,7 @@ jobs: runs-on: macos-latest timeout-minutes: 40 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 with: fetch-depth: 0 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 @@ -125,7 +125,7 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' @@ -147,7 +147,7 @@ jobs: FLUTTER_DEPENDENCIES: "cloud_firestore firebase_remote_config cloud_functions firebase_database firebase_auth firebase_storage firebase_analytics firebase_messaging firebase_app_check firebase_in_app_messaging firebase_performance firebase_crashlytics firebase_ml_model_downloader firebase_app_installations firebase_ai" PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' @@ -175,7 +175,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' @@ -194,7 +194,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c with: go-version: '^1.13.1' diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 188789e97e42..8d83ed24c2dd 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -45,7 +45,7 @@ jobs: AVD_API_LEVEL: 34 AVD_TARGET: google_apis steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index b0e1cac592b6..979e715f88ca 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -40,7 +40,7 @@ jobs: AVD_API_LEVEL: 34 AVD_TARGET: google_apis steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: @@ -144,7 +144,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: @@ -260,7 +260,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: @@ -335,7 +335,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index 163ff5f9339e..4b101184499d 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -33,7 +33,7 @@ jobs: AVD_API_LEVEL: 34 AVD_TARGET: google_apis steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: @@ -115,7 +115,7 @@ jobs: runs-on: macos-latest timeout-minutes: 25 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: @@ -160,7 +160,7 @@ jobs: runs-on: macos-15 timeout-minutes: 50 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index 113d40cc6663..fa88c610490c 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -41,7 +41,7 @@ jobs: exclude: - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: diff --git a/.github/workflows/macos.yaml b/.github/workflows/macos.yaml index a9647bef1b0e..b2817c514338 100644 --- a/.github/workflows/macos.yaml +++ b/.github/workflows/macos.yaml @@ -41,7 +41,7 @@ jobs: exclude: - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 1d903ca64448..97b67dfb505a 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -61,7 +61,7 @@ jobs: if: ${{ always() && !cancelled() }} needs: [e2e-android, e2e-ios, e2e-macos, e2e-web, e2e-windows, e2e-fdc, e2e-pipeline] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: subosito/flutter-action@1a449444c387b1966244ae4d4f8c696479add0b2 with: channel: 'stable' diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 15e280ca0e96..7e633e33e267 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v3.1.0 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v3.1.0 with: persist-credentials: false diff --git a/.github/workflows/web.yaml b/.github/workflows/web.yaml index 73760ef100ba..8a9b9cd8c5af 100644 --- a/.github/workflows/web.yaml +++ b/.github/workflows/web.yaml @@ -41,7 +41,7 @@ jobs: exclude: - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: @@ -111,7 +111,7 @@ jobs: runs-on: macos-latest timeout-minutes: 15 steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: @@ -193,7 +193,7 @@ jobs: exclude: - working_directory: ${{ inputs.nightly_test_mode && 'packages/cloud_firestore/cloud_firestore/example' || 'none' }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a name: Install Node.js 20 with: diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml index 16d9df9f8581..8fdc79a80620 100644 --- a/.github/workflows/windows.yaml +++ b/.github/workflows/windows.yaml @@ -34,7 +34,7 @@ jobs: runs-on: windows-latest timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' @@ -68,7 +68,7 @@ jobs: if: ${{ !inputs.nightly_test_mode }} timeout-minutes: ${{ inputs.nightly_test_mode && 5 || 45 }} steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: distribution: 'temurin' From b3c835f7bae8684d4c98167d78a071d9ed88f980 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 8 Jun 2026 09:51:14 +0000 Subject: [PATCH 108/137] feat(firestore): add support for search in firestore pipeline (#18312) * feat(firestore): add support for search in firestore pipeline * chore: add document_matches expression for full document search * fix: correct method call for query serialization in SearchStage * chore: implement search functionality in native Android and added e2e tests * chore: add support for Pipeline's search api on web * chore: update swiftformat command to exclude specific directories in CI workflow * chore: simplify swiftformat command in CI workflow * feat(firestore): add search collection seeding and update tests for pipeline search functionality * refactor: remove addFields * skip test * Add iOS support for search * refactor: update query and retrieval depth options in FLTPipelineParser --- .../firestore/utils/ExpressionParsers.java | 12 ++ .../utils/PipelineStageHandlers.java | 82 ++++++++++++ .../cloud_firestore/FLTPipelineParser.m | 119 ++++++++++++++++++ .../cloud_firestore/lib/cloud_firestore.dart | 1 + .../cloud_firestore/lib/src/pipeline.dart | 25 ++++ .../lib/src/pipeline_expression.dart | 26 ++++ .../lib/src/pipeline_search.dart | 111 ++++++++++++++++ .../lib/src/pipeline_stage.dart | 18 +++ .../pipeline/pipeline_live_test.dart | 3 + .../pipeline/pipeline_search_e2e.dart | 114 +++++++++++++++++ .../pipeline/pipeline_seed.dart | 12 ++ .../test/pipeline_expression_test.dart | 8 ++ .../test/pipeline_stage_test.dart | 74 +++++++++++ .../lib/src/interop/firestore_interop.dart | 21 ++++ .../lib/src/pipeline_builder_web.dart | 2 + .../src/pipeline_expression_parser_web.dart | 75 +++++++++-- 16 files changed, 692 insertions(+), 11 deletions(-) create mode 100644 packages/cloud_firestore/cloud_firestore/lib/src/pipeline_search.dart create mode 100644 packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_search_e2e.dart diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java index 9aeb352a9785..836d79a39eb7 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/ExpressionParsers.java @@ -464,6 +464,8 @@ Expression parseExpression(@NonNull Map expressionMap) { return parseArrayContainsAll(args); case "array_contains_any": return parseArrayContainsAny(args); + case "document_matches": + return parseDocumentMatches(args); default: Log.w(TAG, "Unsupported expression type: " + name); throw new UnsupportedOperationException("Expression type not yet implemented: " + name); @@ -583,6 +585,8 @@ BooleanExpression parseBooleanExpression(@NonNull Map expression return parseNotEqualAny(args); case "as_boolean": return parseAsBoolean(args); + case "document_matches": + return parseDocumentMatches(args); default: Expression expr = parseExpression(expressionMap); if (expr instanceof BooleanExpression) { @@ -605,6 +609,14 @@ Selectable parseSelectable(@NonNull Map expressionMap) { return (Selectable) expr; } + private BooleanExpression parseDocumentMatches(@NonNull Map args) { + String query = (String) args.get("query"); + if (query == null) { + throw new IllegalArgumentException("document_matches requires a 'query' argument"); + } + return Expression.documentMatches(query); + } + @SuppressWarnings("unchecked") AggregateFunction parseAggregateFunction(@NonNull Map aggregateMap) { String functionName = (String) aggregateMap.get("function"); diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java index cc0e6b0c35e6..78222ecef7e9 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/utils/PipelineStageHandlers.java @@ -20,6 +20,7 @@ import com.google.firebase.firestore.pipeline.FindNearestStage; import com.google.firebase.firestore.pipeline.Ordering; import com.google.firebase.firestore.pipeline.SampleStage; +import com.google.firebase.firestore.pipeline.SearchStage; import com.google.firebase.firestore.pipeline.Selectable; import com.google.firebase.firestore.pipeline.UnnestOptions; import java.util.List; @@ -71,6 +72,8 @@ Pipeline applyStage( return handleSample(pipeline, args); case "find_nearest": return handleFindNearest(pipeline, args); + case "search": + return handleSearch(pipeline, args); default: throw new IllegalArgumentException("Unknown pipeline stage: " + stageName); } @@ -335,4 +338,83 @@ private Pipeline handleFindNearest( return pipeline.findNearest(fieldExpr, vectorArray, distanceMeasure); } } + + @SuppressWarnings("unchecked") + private Pipeline handleSearch(@NonNull Pipeline pipeline, @Nullable Map args) { + if (args == null) { + throw new IllegalArgumentException("'search' requires arguments"); + } + + String queryType = (String) args.get("query_type"); + Object query = args.get("query"); + SearchStage searchStage; + if ("string".equals(queryType)) { + searchStage = SearchStage.withQuery((String) query); + } else if ("expression".equals(queryType)) { + BooleanExpression expressionQuery = + parsers.parseBooleanExpression((Map) query); + searchStage = SearchStage.withQuery(expressionQuery); + } else { + throw new IllegalArgumentException( + "'search' requires query_type to be either 'string' or 'expression'"); + } + + List> sortMaps = (List>) args.get("sort"); + if (sortMaps != null && !sortMaps.isEmpty()) { + Ordering firstOrdering = parseOrdering(sortMaps.get(0)); + if (sortMaps.size() == 1) { + searchStage = searchStage.withSort(firstOrdering); + } else { + Ordering[] additionalOrderings = new Ordering[sortMaps.size() - 1]; + for (int i = 1; i < sortMaps.size(); i++) { + additionalOrderings[i - 1] = parseOrdering(sortMaps.get(i)); + } + searchStage = searchStage.withSort(firstOrdering, additionalOrderings); + } + } + + List> addFieldMaps = (List>) args.get("add_fields"); + if (addFieldMaps != null && !addFieldMaps.isEmpty()) { + Selectable firstField = parsers.parseSelectable(addFieldMaps.get(0)); + if (addFieldMaps.size() == 1) { + searchStage = searchStage.withAddFields(firstField); + } else { + Selectable[] additionalFields = new Selectable[addFieldMaps.size() - 1]; + for (int i = 1; i < addFieldMaps.size(); i++) { + additionalFields[i - 1] = parsers.parseSelectable(addFieldMaps.get(i)); + } + searchStage = searchStage.withAddFields(firstField, additionalFields); + } + } + + String languageCode = (String) args.get("language_code"); + if (languageCode != null) { + searchStage = searchStage.withLanguageCode(languageCode); + } + + Number limit = (Number) args.get("limit"); + if (limit != null) { + searchStage = searchStage.withLimit(limit.longValue()); + } + + Number offset = (Number) args.get("offset"); + if (offset != null) { + searchStage = searchStage.withOffset(offset.longValue()); + } + + Number retrievalDepth = (Number) args.get("retrieval_depth"); + if (retrievalDepth != null) { + searchStage = searchStage.withRetrievalDepth(retrievalDepth.longValue()); + } + + return pipeline.search(searchStage); + } + + @SuppressWarnings("unchecked") + private Ordering parseOrdering(@NonNull Map orderingMap) { + Expression expression = + parsers.parseExpression((Map) orderingMap.get("expression")); + String direction = (String) orderingMap.get("order_direction"); + return "asc".equals(direction) ? expression.ascending() : expression.descending(); + } } diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m index a84369c64e88..c0ca562b0e33 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTPipelineParser.m @@ -173,6 +173,16 @@ - (FIRExprBridge *)parseExpression:(NSDictionary *)map error:(NS return [self parseExpression:(NSDictionary *)exprMap error:error]; } + if ([name isEqualToString:@"document_matches"]) { + NSString *query = args[@"query"]; + if (![query isKindOfClass:[NSString class]]) { + if (error) *error = parseError(@"document_matches requires query"); + return nil; + } + FIRExprBridge *queryExpr = [[FIRConstantBridge alloc] init:query]; + return FLTNewFunctionExprBridge(@"document_matches", @[ queryExpr ]); + } + // Map Dart names to iOS SDK names where they differ NSString *sdkName = name; if ([name isEqualToString:@"bit_xor"]) sdkName = @"xor"; @@ -908,6 +918,112 @@ + (NSString *)keyForExpressionMap:(NSDictionary *)em error:(NSError **)error { return nil; } ++ (NSDictionary *) + parseSearchFieldsWithExpressionMaps:(NSArray *> *)exprMaps + exprParser:(FLTPipelineExpressionParser *)exprParser + error:(NSError **)error { + NSMutableDictionary *fields = [NSMutableDictionary dictionary]; + NSError *parseErr = nil; + + for (id em in exprMaps) { + if (![em isKindOfClass:[NSDictionary class]]) continue; + + FIRExprBridge *expr = [exprParser parseExpression:em error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + + NSString *key = [self keyForExpressionMap:em error:error]; + if (![key isKindOfClass:[NSString class]] || key.length == 0) return nil; + fields[key] = expr; + } + + return fields; +} + ++ (FIRStageBridge *)parseSearchStageWithArgs:(NSDictionary *)args + exprParser:(FLTPipelineExpressionParser *)exprParser + error:(NSError **)error { + NSString *queryType = args[@"query_type"]; + id query = args[@"query"]; + NSMutableDictionary *options = [NSMutableDictionary dictionary]; + NSError *parseErr = nil; + + if ([queryType isEqualToString:@"string"]) { + if (![query isKindOfClass:[NSString class]]) { + if (error) *error = parseError(@"search query_type 'string' requires string query"); + return nil; + } + FIRExprBridge *queryExpr = [[FIRConstantBridge alloc] init:query]; + options[@"query"] = FLTNewFunctionExprBridge(@"document_matches", @[ queryExpr ]); + } else if ([queryType isEqualToString:@"expression"]) { + if (![query isKindOfClass:[NSDictionary class]]) { + if (error) *error = parseError(@"search query_type 'expression' requires expression query"); + return nil; + } + FIRExprBridge *queryExpr = [exprParser parseBooleanExpression:query error:&parseErr]; + if (!queryExpr) { + if (error) *error = parseErr; + return nil; + } + options[@"query"] = queryExpr; + } else { + if (error) *error = parseError(@"search requires query_type to be 'string' or 'expression'"); + return nil; + } + + NSNumber *limit = [args[@"limit"] isKindOfClass:[NSNumber class]] ? args[@"limit"] : nil; + if (limit) options[@"limit"] = [[FIRConstantBridge alloc] init:limit]; + + NSNumber *offset = [args[@"offset"] isKindOfClass:[NSNumber class]] ? args[@"offset"] : nil; + if (offset) options[@"offset"] = [[FIRConstantBridge alloc] init:offset]; + + NSNumber *retrievalDepth = + [args[@"retrieval_depth"] isKindOfClass:[NSNumber class]] ? args[@"retrieval_depth"] : nil; + if (retrievalDepth) { + options[@"retrieval_depth"] = [[FIRConstantBridge alloc] init:retrievalDepth]; + } + + NSString *languageCode = + [args[@"language_code"] isKindOfClass:[NSString class]] ? args[@"language_code"] : nil; + if (languageCode) { + options[@"language_code"] = [[FIRConstantBridge alloc] init:languageCode]; + } + + NSMutableArray *sort = [NSMutableArray array]; + NSArray *orderingMaps = args[@"sort"]; + if ([orderingMaps isKindOfClass:[NSArray class]]) { + for (id om in orderingMaps) { + if (![om isKindOfClass:[NSDictionary class]]) continue; + id exprMap = ((NSDictionary *)om)[@"expression"]; + NSString *dir = ((NSDictionary *)om)[@"order_direction"]; + if (![exprMap isKindOfClass:[NSDictionary class]]) continue; + FIRExprBridge *expr = [exprParser parseExpression:exprMap error:&parseErr]; + if (!expr) { + if (error) *error = parseErr; + return nil; + } + NSString *direction = [dir isEqualToString:@"asc"] ? @"ascending" : @"descending"; + [sort addObject:[[FIROrderingBridge alloc] initWithExpr:expr Direction:direction]]; + } + } + + NSDictionary *addFields = @{}; + NSArray *addFieldMaps = args[@"add_fields"]; + if ([addFieldMaps isKindOfClass:[NSArray class]] && addFieldMaps.count > 0) { + addFields = [self parseSearchFieldsWithExpressionMaps:addFieldMaps + exprParser:exprParser + error:error]; + if (!addFields) return nil; + } + + return [[FIRSearchStageBridge alloc] initWithOptions:options + addFields:addFields + select:@{} + sort:sort]; +} + + (NSArray *) parseStagesWithFirestore:(FIRFirestore *)firestore stages:(NSArray *> *)stages @@ -989,6 +1105,9 @@ + (NSString *)keyForExpressionMap:(NSDictionary *)em error:(NSError **)error { return nil; } stage = [[FIRWhereStageBridge alloc] initWithExpr:expr]; + } else if ([stageName isEqualToString:@"search"]) { + stage = [self parseSearchStageWithArgs:args exprParser:exprParser error:error]; + if (!stage) return nil; } else if ([stageName isEqualToString:@"limit"]) { NSNumber *limit = args[@"limit"]; if (![limit isKindOfClass:[NSNumber class]]) { diff --git a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart index 69c3a95dce00..1fcccbee21bc 100755 --- a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart @@ -65,6 +65,7 @@ part 'src/pipeline_execute_options.dart'; part 'src/pipeline_expression.dart'; part 'src/pipeline_ordering.dart'; part 'src/pipeline_sample.dart'; +part 'src/pipeline_search.dart'; part 'src/pipeline_source.dart'; part 'src/pipeline_stage.dart'; part 'src/query.dart'; diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart index 6e54e253172c..55ca21d79f47 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline.dart @@ -433,6 +433,31 @@ class Pipeline { ); } + /// Adds a search stage to this pipeline. + /// + /// Search stages execute full-text search or geo search operations. A search + /// stage must be the first stage after the pipeline source. + /// + /// Example: + /// ```dart + /// firestore.pipeline().collection('restaurants').search( + /// SearchStage.withQuery('breakfast -diner', limit: 10), + /// ); + /// ``` + Pipeline search(SearchStage searchStage) { + if (_delegate.stages.length != 1) { + throw StateError( + 'A search stage must be the first stage after the pipeline source.', + ); + } + + final stage = _SearchStage(searchStage); + return Pipeline._( + _firestore, + _delegate.addStage(stage.toMap()), + ); + } + /// Limits the maximum number of documents returned by previous stages to /// [limit]. /// diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart index 0690924f2011..a25c14f55f34 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_expression.dart @@ -881,6 +881,12 @@ abstract class Expression implements PipelineSerializable { /// Creates a null value expression static Expression nullValue() => _NullExpression(); + /// Creates a search expression that matches the whole document against + /// [query]. + static BooleanExpression documentMatches(String query) { + return _DocumentMatchesExpression(query); + } + /// Creates a conditional (ternary) expression static Expression conditional( BooleanExpression condition, @@ -2043,6 +2049,26 @@ class _TrimExpression extends FunctionExpression { /// Base class for boolean expressions used in filtering abstract class BooleanExpression extends Expression {} +/// Represents a document_matches search expression. +class _DocumentMatchesExpression extends BooleanExpression { + final String query; + + _DocumentMatchesExpression(this.query); + + @override + String get name => 'document_matches'; + + @override + Map toMap() { + return { + 'name': name, + 'args': { + 'query': query, + }, + }; + } +} + // ============================================================================ // PATTERN DEMONSTRATION - Concrete Function Expression Classes // ============================================================================ diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_search.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_search.dart new file mode 100644 index 000000000000..fc5994a74d1b --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_search.dart @@ -0,0 +1,111 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of '../cloud_firestore.dart'; + +enum _SearchQueryType { + string, + expression, +} + +/// Specifies how a pipeline search stage is performed. +/// +/// Search stages must be the first stage after a pipeline source. +final class SearchStage implements PipelineSerializable { + final _SearchQueryType _queryType; + final Object _query; + final List? _sort; + final List? _addFields; + final String? _languageCode; + final int? _limit; + final int? _offset; + final int? _retrievalDepth; + + SearchStage._({ + required _SearchQueryType queryType, + required Object query, + List? sort, + List? addFields, + String? languageCode, + int? limit, + int? offset, + int? retrievalDepth, + }) : _queryType = queryType, + _query = query, + _sort = sort, + _addFields = addFields, + _languageCode = languageCode, + _limit = limit, + _offset = offset, + _retrievalDepth = retrievalDepth; + + /// Creates a search stage from a raw query string. + SearchStage.withQuery( + String query, { + List? sort, + List? addFields, + String? languageCode, + int? limit, + int? offset, + int? retrievalDepth, + }) : this._( + queryType: _SearchQueryType.string, + query: query, + sort: sort, + addFields: addFields, + languageCode: languageCode, + limit: limit, + offset: offset, + retrievalDepth: retrievalDepth, + ); + + /// Creates a search stage from a search query expression. + SearchStage.withQueryExpression( + BooleanExpression query, { + List? sort, + List? addFields, + String? languageCode, + int? limit, + int? offset, + int? retrievalDepth, + }) : this._( + queryType: _SearchQueryType.expression, + query: query, + sort: sort, + addFields: addFields, + languageCode: languageCode, + limit: limit, + offset: offset, + retrievalDepth: retrievalDepth, + ); + + @override + Map toMap() { + final args = { + 'query_type': _queryType.name, + 'query': _query is Expression ? _query.toMap() : _query, + }; + + if (_sort != null) { + args['sort'] = _sort.map((ordering) => ordering.toMap()).toList(); + } + if (_addFields != null) { + args['add_fields'] = _addFields.map((field) => field.toMap()).toList(); + } + if (_languageCode != null) { + args['language_code'] = _languageCode; + } + if (_limit != null) { + args['limit'] = _limit; + } + if (_offset != null) { + args['offset'] = _offset; + } + if (_retrievalDepth != null) { + args['retrieval_depth'] = _retrievalDepth; + } + + return args; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart index abc1555f8854..e6eaf8df20f5 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/pipeline_stage.dart @@ -207,6 +207,24 @@ final class _FindNearestStage extends PipelineStage { } } +/// Stage for full-text or geo search. +final class _SearchStage extends PipelineStage { + final SearchStage searchStage; + + _SearchStage(this.searchStage); + + @override + String get name => 'search'; + + @override + Map toMap() { + return { + 'stage': name, + 'args': searchStage.toMap(), + }; + } +} + /// Stage for limiting results final class _LimitStage extends PipelineStage { final int limit; diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart index b7a977b6e8ad..d3f679955d58 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_live_test.dart @@ -18,6 +18,7 @@ import 'pipeline_find_nearest_e2e.dart'; import 'pipeline_remove_fields_e2e.dart'; import 'pipeline_replace_with_e2e.dart'; import 'pipeline_sample_e2e.dart'; +import 'pipeline_search_e2e.dart'; import 'pipeline_seed.dart'; import 'pipeline_select_e2e.dart'; import 'pipeline_unnest_union_e2e.dart'; @@ -36,6 +37,7 @@ void main() { ); firestore.settings = const Settings(persistenceEnabled: true); await seedPipelineE2ECollections(firestore); + await seedPipelineSearchE2ECollection(firestore); }); runPipelineFilterSortTests(); @@ -47,6 +49,7 @@ void main() { runPipelineUnnestUnionTests(); runPipelineSampleTests(); runPipelineFindNearestTests(); + runPipelineSearchTests(); runPipelineExpressionsTests(); }); } diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_search_e2e.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_search_e2e.dart new file mode 100644 index 000000000000..5ac53182acca --- /dev/null +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_search_e2e.dart @@ -0,0 +1,114 @@ +// Copyright 2026, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter_test/flutter_test.dart'; + +const String _searchCollection = 'pipeline-search-e2e'; + +void runPipelineSearchTests() { + group('Pipeline search', () { + late FirebaseFirestore firestore; + + setUpAll(() { + firestore = FirebaseFirestore.instanceFor( + app: Firebase.app(), + databaseId: 'firestore-pipeline-test', + ); + }); + + test('withQuery returns matching search results', () async { + final snapshot = await firestore + .pipeline() + .collection(_searchCollection) + .search(SearchStage.withQuery('pancakes', limit: 10)) + .execute(); + + expect(_resultNames(snapshot), contains('Pancake House')); + }); + + test('withQuery passes options and returns expected result list', () async { + final snapshot = await firestore + .pipeline() + .collection(_searchCollection) + .search( + SearchStage.withQuery( + 'breakfast', + languageCode: 'en', + retrievalDepth: 10, + offset: 0, + limit: 10, + ), + ) + .execute(); + + expect(_sortedResultValues(snapshot, 'name'), [ + 'Coffee Bar', + 'Pancake House', + ]); + expect(_resultNames(snapshot), isNot(contains('Burger Diner'))); + }); + + test('withQueryExpression returns matching search results', () async { + final snapshot = await firestore + .pipeline() + .collection(_searchCollection) + .search( + SearchStage.withQueryExpression( + Expression.documentMatches('pancakes'), + limit: 10, + ), + ) + .execute(); + + expect(_resultNames(snapshot), contains('Pancake House')); + }); + + test( + 'withQueryExpression supports combined document match queries', + () async { + final snapshot = await firestore + .pipeline() + .collection(_searchCollection) + .search( + SearchStage.withQueryExpression( + Expression.and( + Expression.documentMatches('pancakes'), + Expression.documentMatches('breakfast'), + ), + limit: 10, + ), + ) + .execute(); + + expect(_resultNames(snapshot), contains('Pancake House')); + }, + skip: + true, // 'Native search does not support AND in query expressions yet.' + ); + + test('withQuery returns empty results when nothing matches', () async { + final snapshot = await firestore + .pipeline() + .collection(_searchCollection) + .search(SearchStage.withQuery('No match', limit: 10)) + .execute(); + + expect(snapshot.result, isEmpty); + }); + }); +} + +List _resultNames(PipelineSnapshot snapshot) { + return snapshot.result.map((result) => result.data()?['name']).toList(); +} + +List _sortedResultValues(PipelineSnapshot snapshot, String field) { + return snapshot.result + .map((result) => result.data()?[field]) + .whereType() + .toList() + ..sort(); +} diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart index 7df0783a15c4..9e4d8293ef69 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/integration_test/pipeline/pipeline_seed.dart @@ -5,6 +5,7 @@ import 'package:cloud_firestore/cloud_firestore.dart'; const String _col = 'pipeline-e2e'; +const String _searchCol = 'pipeline-search-e2e'; const int _maxBatchSize = 500; Future seedPipelineE2ECollections(FirebaseFirestore firestore) async { @@ -144,6 +145,17 @@ Future seedPipelineE2ECollections(FirebaseFirestore firestore) async { await _clearAndSeed(firestore, _col, docs); } +Future seedPipelineSearchE2ECollection( + FirebaseFirestore firestore, +) async { + final docs = >[ + {'name': 'Pancake House', 'description': 'waffles pancakes breakfast'}, + {'name': 'Burger Diner', 'description': 'burgers fries lunch'}, + {'name': 'Coffee Bar', 'description': 'coffee breakfast pastries'}, + ]; + await _clearAndSeed(firestore, _searchCol, docs); +} + List> _withTest( String test, List> maps, diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart index 067efa4d1cb7..468f373ba404 100644 --- a/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_expression_test.dart @@ -194,6 +194,14 @@ void main() { 'args': {'value': 100}, }); }); + + test('Expression.documentMatches() serializes search query', () { + final expr = Expression.documentMatches('breakfast -diner'); + expect(expr.toMap(), { + 'name': 'document_matches', + 'args': {'query': 'breakfast -diner'}, + }); + }); }); group('BooleanExpression from Field', () { diff --git a/packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart b/packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart index 876d53e368e2..41a6fba094db 100644 --- a/packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart +++ b/packages/cloud_firestore/cloud_firestore/test/pipeline_stage_test.dart @@ -398,6 +398,80 @@ void main() { }); }); + group('_SearchStage', () { + test('serializes search with string query', () { + final pipeline = firestore.pipeline().collection('restaurants').search( + SearchStage.withQuery( + 'breakfast -diner', + limit: 10, + offset: 2, + retrievalDepth: 100, + languageCode: 'en', + ), + ); + final stage = pipeline.stages.last; + expect(stage['stage'], 'search'); + expect(stage['args']['query_type'], 'string'); + expect(stage['args']['query'], 'breakfast -diner'); + expect(stage['args']['limit'], 10); + expect(stage['args']['offset'], 2); + expect(stage['args']['retrieval_depth'], 100); + expect(stage['args']['language_code'], 'en'); + }); + + test('serializes search with query expression', () { + final pipeline = firestore.pipeline().collection('restaurants').search( + SearchStage.withQueryExpression( + Expression.documentMatches('waffles OR pancakes'), + ), + ); + final stage = pipeline.stages.last; + expect(stage['stage'], 'search'); + expect(stage['args']['query_type'], 'expression'); + expect(stage['args']['query'], { + 'name': 'document_matches', + 'args': {'query': 'waffles OR pancakes'}, + }); + }); + + test('serializes search sort and add fields', () { + final pipeline = firestore.pipeline().collection('restaurants').search( + SearchStage.withQuery( + 'breakfast', + sort: [Field('rating').descending()], + addFields: [Field('name')], + ), + ); + final stage = pipeline.stages.last; + expect(stage['args']['sort'], [ + { + 'expression': { + 'name': 'field', + 'args': {'field': 'rating'}, + }, + 'order_direction': 'desc', + }, + ]); + expect(stage['args']['add_fields'], [ + { + 'name': 'field', + 'args': {'field': 'name'}, + }, + ]); + }); + + test('throws if search is not first stage after source', () { + expect( + () => firestore + .pipeline() + .collection('restaurants') + .limit(10) + .search(SearchStage.withQuery('breakfast')), + throwsStateError, + ); + }); + }); + group('_UnionStage', () { test('serializes union stage with nested pipeline stages', () { final innerPipeline = firestore.pipeline().collection('archived_users'); diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart index cd4ee712c568..c271c4ac62aa 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart @@ -366,6 +366,7 @@ extension type PipelinesJsImpl._(JSObject _) implements JSObject { external JSAny or(JSAny a, JSAny b); external JSAny xor(JSAny a, JSAny b); external JSAny not(JSAny expr); + external JSAny documentMatches(JSString query); // --- Existence / type checks --- external JSAny exists(JSAny expr); @@ -1240,6 +1241,7 @@ extension type PipelineJsImpl._(JSObject _) implements JSObject { external PipelineJsImpl removeFields(JSAny fieldOrOptions); external PipelineJsImpl replaceWith(JSAny fieldNameOrOptions); external PipelineJsImpl findNearest(JSAny options); + external PipelineJsImpl search(JSAny options); external PipelineJsImpl union(JSAny otherOrOptions); external PipelineJsImpl rawStage(JSString name, JSArray params, [JSAny? options]); @@ -1337,6 +1339,25 @@ extension type FindNearestStageOptionsJsImpl._(JSObject _) implements JSObject { external set distanceField(JSString value); } +extension type SearchStageOptionsJsImpl._(JSObject _) implements JSObject { + SearchStageOptionsJsImpl() : this._(JSObject.new()); + + // ignore: avoid_setters_without_getters + external set query(JSAny value); + // ignore: avoid_setters_without_getters + external set languageCode(JSString value); + // ignore: avoid_setters_without_getters + external set retrievalDepth(JSNumber value); + // ignore: avoid_setters_without_getters + external set sort(JSAny value); + // ignore: avoid_setters_without_getters + external set offset(JSNumber value); + // ignore: avoid_setters_without_getters + external set limit(JSNumber value); + // ignore: avoid_setters_without_getters + external set addFields(JSAny value); +} + extension type PipelineExecuteOptionsJsImpl._(JSObject _) implements JSObject { PipelineExecuteOptionsJsImpl() : this._(JSObject.new()); diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart index bc2db69e575d..81e181372491 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_builder_web.dart @@ -122,6 +122,8 @@ interop.PipelineJsImpl _applyStage( converter.toReplaceWithOptions(expression as Map)); case 'find_nearest': return pipeline.findNearest(converter.toFindNearestOptions(map)); + case 'search': + return pipeline.search(converter.toSearchOptions(map)); case 'union': final pipelineStages = map['pipeline'] as List>; final otherPipeline = diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart index 3460778faba9..8fc7ce67d944 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/pipeline_expression_parser_web.dart @@ -461,6 +461,12 @@ class PipelineExpressionParserWeb { throw UnsupportedError('not requires a boolean expression'); } return _pipelines.not(boolExpr); + case 'document_matches': + final query = argsMap['query'] as String?; + if (query == null) { + throw UnsupportedError('document_matches requires query'); + } + return _pipelines.documentMatches(query.toJS); case 'exists': return _pipelines.exists(_expr(argsMap, _kExpression)); case 'is_absent': @@ -505,17 +511,7 @@ class PipelineExpressionParserWeb { /// /// Each item shape: `{ expression: Map, order_direction: 'asc' | 'desc' }`. JSAny toSortOptions(List orderings) { - final list = []; - for (final o in orderings) { - final m = o is Map ? o : {}; - final expr = m[_kExpression]; - if (expr == null) continue; - final exprJs = toExpression(expr as Map); - final dir = m['order_direction'] as String?; - list.add(dir == 'desc' - ? _pipelines.descending(exprJs) - : _pipelines.ascending(exprJs)); - } + final list = _toOrderingList(orderings); if (list.isEmpty) { throw UnsupportedError( 'Pipeline sort() on web requires the Firebase JS pipeline expression API ' @@ -654,6 +650,48 @@ class PipelineExpressionParserWeb { return opts; } + /// Converts search stage args to JS SearchStageOptions. + interop.SearchStageOptionsJsImpl toSearchOptions(Map map) { + final queryType = map['query_type'] as String?; + final query = map['query']; + final opts = interop.SearchStageOptionsJsImpl(); + + if (queryType == 'string') { + opts.query = (query as String).toJS; + } else if (queryType == 'expression') { + opts.query = toBooleanExpression(query as Map)!; + } else { + throw UnsupportedError( + "Pipeline search() on web requires query_type 'string' or 'expression'.", + ); + } + + final languageCode = map['language_code'] as String?; + if (languageCode != null) opts.languageCode = languageCode.toJS; + + final retrievalDepth = map['retrieval_depth'] as int?; + if (retrievalDepth != null) opts.retrievalDepth = retrievalDepth.toJS; + + final offset = map['offset'] as int?; + if (offset != null) opts.offset = offset.toJS; + + final limit = map['limit'] as int?; + if (limit != null) opts.limit = limit.toJS; + + final sort = map['sort'] as List?; + if (sort != null && sort.isNotEmpty) { + final orderings = _toOrderingList(sort); + if (orderings.isNotEmpty) opts.sort = orderings.toJS; + } + + final addFields = map['add_fields'] as List?; + if (addFields != null && addFields.isNotEmpty) { + opts.addFields = _toSelectableList(addFields).toJS; + } + + return opts; + } + // ── Private helpers ─────────────────────────────────────────────────────── /// Converts a [Constant] value to the correct JS type for the pipelines API. @@ -808,6 +846,21 @@ class PipelineExpressionParserWeb { .whereType() .toList(); + List _toOrderingList(List orderings) { + final list = []; + for (final ordering in orderings) { + final orderingMap = Map.from(ordering as Map); + final expr = orderingMap[_kExpression]; + if (expr == null) continue; + final exprJs = toExpression(expr as Map); + final dir = orderingMap['order_direction'] as String?; + list.add(dir == 'desc' + ? _pipelines.descending(exprJs) + : _pipelines.ascending(exprJs)); + } + return list; + } + interop.AggregateStageOptionsJsImpl _buildAccumulators( List items, { List? groups, From 566cfed42599318cf0f24eefc5d696223e46128c Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 8 Jun 2026 14:36:53 +0200 Subject: [PATCH 109/137] feat(ai): add support for cancellable clients for in-flight requests (#18349) --- .../firebase_ai/lib/src/firebase_ai.dart | 6 ++ .../firebase_ai/lib/src/generative_model.dart | 2 + .../test/firebase_vertexai_test.dart | 76 +++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart index 40971c347362..ff7011af5bce 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart @@ -17,6 +17,7 @@ import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' show FirebasePluginPlatform; +import 'package:http/http.dart' as http; import 'package:meta/meta.dart'; import '../firebase_ai.dart'; @@ -142,6 +143,9 @@ class FirebaseAI extends FirebasePluginPlatform { /// The optional [safetySettings] and [generationConfig] can be used to /// control and guide the generation. See [SafetySetting] and /// [GenerationConfig] for details. + /// + /// The optional [httpClient] can be used to customize HTTP request handling, + /// such as adding support for cancelling in-flight requests. GenerativeModel generativeModel({ required String model, List? safetySettings, @@ -149,6 +153,7 @@ class FirebaseAI extends FirebasePluginPlatform { List? tools, ToolConfig? toolConfig, Content? systemInstruction, + http.Client? httpClient, }) { return createGenerativeModel( model: model, @@ -163,6 +168,7 @@ class FirebaseAI extends FirebasePluginPlatform { toolConfig: toolConfig, systemInstruction: systemInstruction, useLimitedUseAppCheckTokens: useLimitedUseAppCheckTokens, + httpClient: httpClient, ); } diff --git a/packages/firebase_ai/firebase_ai/lib/src/generative_model.dart b/packages/firebase_ai/firebase_ai/lib/src/generative_model.dart index 2bf58351eafe..844614583889 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/generative_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/generative_model.dart @@ -210,6 +210,7 @@ GenerativeModel createGenerativeModel({ List? tools, ToolConfig? toolConfig, Content? systemInstruction, + http.Client? httpClient, }) => GenerativeModel._( model: model, @@ -224,6 +225,7 @@ GenerativeModel createGenerativeModel({ tools: tools, toolConfig: toolConfig, systemInstruction: systemInstruction, + httpClient: httpClient, ); /// Creates a model with an overridden [ApiClient] for testing. diff --git a/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart b/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart index fe52b397a106..52fab592b2f5 100644 --- a/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart +++ b/packages/firebase_ai/firebase_ai/test/firebase_vertexai_test.dart @@ -12,11 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. +import 'dart:convert'; + import 'package:firebase_ai/firebase_ai.dart'; import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:http/http.dart' as http; import 'mock.dart'; @@ -50,6 +54,16 @@ void main() { customAppCheck = FirebaseAppCheck.instanceFor(app: customApp); limitTokenAppCheck = FirebaseAppCheck.instanceFor(app: limitTokenApp); customAuth = FirebaseAuth.instanceFor(app: customApp); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.' + 'FirebaseAppCheckHostApi.getToken', + (_) async { + return const StandardMessageCodec().encodeMessage( + ['app-check-token'], + ); + }, + ); }); test('Singleton behavior', () { @@ -129,5 +143,67 @@ void main() { expect(model, isA()); }); + + test('generativeModel uses provided HTTP client', () async { + final requests = []; + final client = _RecordingClient((request) { + requests.add(request); + + if (request.url.path.endsWith(':streamGenerateContent')) { + return http.StreamedResponse( + Stream.value(utf8.encode('data: ${jsonEncode(_response)}\n\n')), + 200, + ); + } + + return http.StreamedResponse( + Stream.value(utf8.encode(jsonEncode(_response))), + 200, + ); + }); + final ai = FirebaseAI.googleAI(app: app); + + final model = ai.generativeModel( + model: 'gemini-pro', + httpClient: client, + ); + + await model.generateContent([Content.text('prompt')]); + await model.generateContentStream([Content.text('prompt')]).drain(); + + expect(requests, hasLength(2)); + expect( + requests.first.url.path, + endsWith('/models/gemini-pro:generateContent'), + ); + expect( + requests.last.url.path, + endsWith('/models/gemini-pro:streamGenerateContent'), + ); + }); }); } + +class _RecordingClient extends http.BaseClient { + _RecordingClient(this._handler); + + final http.StreamedResponse Function(http.BaseRequest request) _handler; + + @override + Future send(http.BaseRequest request) async { + return _handler(request); + } +} + +const _response = { + 'candidates': [ + { + 'content': { + 'role': 'model', + 'parts': [ + {'text': 'Some Response'}, + ], + }, + }, + ], +}; From 77396b81ae56943a38c23b429249b0b9cbd4bc21 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 8 Jun 2026 15:18:04 +0200 Subject: [PATCH 110/137] fix(messaging,ios): fix a race condition that could happen when getting initial message (#18352) --- .../FLTFirebaseMessagingPlugin.m | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m index 2dd3f536edcb..a0eec7d0419f 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m @@ -263,17 +263,22 @@ - (void)setupNotificationHandlingWithRemoteNotification: // For scene delegates, if no notification was found in connectionOptions, // delay marking as gathered to allow didReceiveRemoteNotification to fire first // for contentAvailable notifications that caused the app to launch - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), - dispatch_get_main_queue(), ^{ - if (!self->_initialNotificationGathered) { - self->_initialNotificationGathered = YES; - [self initialNotificationCallback]; - } - }); + [self markInitialNotificationGatheredAfterDelay]; } else { - // For non-scene delegate apps, mark as gathered immediately - _initialNotificationGathered = YES; - [self initialNotificationCallback]; +#if !TARGET_OS_OSX + if (@available(iOS 13.0, *)) { + // Scene delegate launch notification responses arrive after didFinishLaunching. + // Give scene:willConnectToSession:options: a chance to provide the tapped notification + // before resolving getInitialMessage() as nil. + [self markInitialNotificationGatheredAfterDelay]; + } else { +#endif + // For non-scene delegate apps, mark as gathered immediately + _initialNotificationGathered = YES; + [self initialNotificationCallback]; +#if !TARGET_OS_OSX + } +#endif } [GULAppDelegateSwizzler registerAppDelegateInterceptor:self]; @@ -357,6 +362,16 @@ - (void)setupNotificationHandlingWithRemoteNotification: #endif } +- (void)markInitialNotificationGatheredAfterDelay { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + if (!self->_initialNotificationGathered) { + self->_initialNotificationGathered = YES; + [self initialNotificationCallback]; + } + }); +} + - (void)application_onDidFinishLaunchingNotification:(nonnull NSNotification *)notification { // Setup UIApplicationDelegate. #if TARGET_OS_OSX @@ -631,6 +646,7 @@ - (void)scene:(UIScene *)scene // User tapped the notification. remoteNotification = connectionOptions.notificationResponse.notification.request.content.userInfo; + _notificationOpenedAppID = remoteNotification[@"gcm.message_id"]; } [self setupNotificationHandlingWithRemoteNotification:remoteNotification]; From 795475692384385a17511b295640ad6f8ab625f6 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 8 Jun 2026 16:34:06 +0200 Subject: [PATCH 111/137] feat(ai): add mediaResolution parameter (#18354) --- .../firebase_ai/lib/firebase_ai.dart | 1 + .../firebase_ai/firebase_ai/lib/src/api.dart | 50 +++++++++++++++- .../firebase_ai/lib/src/content.dart | 36 ++++++++++- .../firebase_ai/lib/src/live_api.dart | 3 +- .../firebase_ai/test/api_test.dart | 19 ++++++ .../firebase_ai/test/content_test.dart | 60 +++++++++++++++++++ .../firebase_ai/test/live_test.dart | 2 + 7 files changed, 166 insertions(+), 5 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart index 9e48a0c58686..460fe5cb79e9 100644 --- a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart @@ -26,6 +26,7 @@ export 'src/api.dart' GroundingChunk, ThinkingConfig, ThinkingLevel, + MediaResolution, HarmBlockThreshold, HarmCategory, HarmProbability, diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index ac0a23209456..1d2ee8947954 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -1067,6 +1067,41 @@ enum ResponseModalities { String toJson() => _jsonString; } +/// The media resolution to use for media inputs. +enum MediaResolution { + /// Default media resolution selected by the model. + unspecified('MEDIA_RESOLUTION_UNSPECIFIED'), + + /// Lower token count, resulting in faster processing and lower cost. + low('MEDIA_RESOLUTION_LOW'), + + /// A balance between detail, cost, and latency. + medium('MEDIA_RESOLUTION_MEDIUM'), + + /// Higher token count, providing more detail for media inputs. + high('MEDIA_RESOLUTION_HIGH'), + + /// Highest token count for image inputs. + /// + /// This value is only supported on individual media parts. + ultraHigh('MEDIA_RESOLUTION_ULTRA_HIGH'); + + const MediaResolution(this._jsonString); + final String _jsonString; + + /// Parse a media resolution from a JSON value. + static MediaResolution parseValue(String value) => switch (value) { + 'MEDIA_RESOLUTION_LOW' => MediaResolution.low, + 'MEDIA_RESOLUTION_MEDIUM' => MediaResolution.medium, + 'MEDIA_RESOLUTION_HIGH' => MediaResolution.high, + 'MEDIA_RESOLUTION_ULTRA_HIGH' => MediaResolution.ultraHigh, + _ => MediaResolution.unspecified, + }; + + // ignore: public_member_api_docs + String toJson() => _jsonString; +} + /// A preset that balances the trade-off between reasoning quality and response /// speed for a model's "thinking" process. /// @@ -1170,7 +1205,9 @@ abstract class BaseGenerationConfig { this.presencePenalty, this.frequencyPenalty, this.responseModalities, - }); + this.mediaResolution, + }) : assert(mediaResolution != MediaResolution.ultraHigh, + 'MediaResolution.ultraHigh is only supported on individual media parts.'); /// Number of generated responses to return. /// @@ -1249,6 +1286,14 @@ abstract class BaseGenerationConfig { /// The list of desired response modalities. final List? responseModalities; + /// The resolution to use for media inputs. + /// + /// Higher resolutions provide more detail to the model, at the cost of + /// increased token usage, latency, and cost. + /// + /// [MediaResolution.ultraHigh] is only supported on individual media parts. + final MediaResolution? mediaResolution; + // ignore: public_member_api_docs Map toJson() => { if (candidateCount case final candidateCount?) @@ -1265,6 +1310,8 @@ abstract class BaseGenerationConfig { if (responseModalities case final responseModalities?) 'responseModalities': responseModalities.map((modality) => modality.toJson()).toList(), + if (mediaResolution case final mediaResolution?) + 'mediaResolution': mediaResolution.toJson(), }; } @@ -1281,6 +1328,7 @@ final class GenerationConfig extends BaseGenerationConfig { super.presencePenalty, super.frequencyPenalty, super.responseModalities, + super.mediaResolution, this.responseMimeType, this.responseSchema, this.responseJsonSchema, diff --git a/packages/firebase_ai/firebase_ai/lib/src/content.dart b/packages/firebase_ai/firebase_ai/lib/src/content.dart index 8fa2b7b14ad1..1cac4e3d9dd1 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/content.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/content.dart @@ -41,8 +41,10 @@ final class Content { static Content text(String text) => Content('user', [TextPart(text)]); /// Return a [Content] with [InlineDataPart]. - static Content inlineData(String mimeType, Uint8List bytes) => - Content('user', [InlineDataPart(mimeType, bytes)]); + static Content inlineData(String mimeType, Uint8List bytes, + {MediaResolution? mediaResolution}) => + Content('user', + [InlineDataPart(mimeType, bytes, mediaResolution: mediaResolution)]); /// Return a [Content] with multiple [Part]s. static Content multi(Iterable parts) => Content('user', [...parts]); @@ -100,6 +102,10 @@ Part parsePart(Object? jsonObject) { final thoughtSignature = jsonObject.containsKey('thoughtSignature') ? jsonObject['thoughtSignature']! as String : null; + final mediaResolution = switch (jsonObject['mediaResolution']) { + {'level': final String level} => MediaResolution.parseValue(level), + _ => null, + }; if (jsonObject.containsKey('functionCall')) { final functionCall = jsonObject['functionCall']; @@ -157,6 +163,7 @@ Part parsePart(Object? jsonObject) { inlineDataResult['mimeType'] as String, base64Decode(inlineDataResult['data'] as String), willContinue: inlineDataResult['willContinue'] as bool?, + mediaResolution: mediaResolution, isThought: isThought, thoughtSignature: thoughtSignature, ); @@ -174,7 +181,9 @@ Part parsePart(Object? jsonObject) { } } => FileData._(mimeType, fileUri, - isThought: isThought, thoughtSignature: thoughtSignature), + mediaResolution: mediaResolution, + isThought: isThought, + thoughtSignature: thoughtSignature), _ => () { log('unhandled part format: $jsonObject'); return UnknownPart(jsonObject); @@ -261,6 +270,7 @@ final class InlineDataPart extends Part { this.mimeType, this.bytes, { this.willContinue, + this.mediaResolution, bool? isThought, }) : super( isThought: isThought, @@ -273,6 +283,7 @@ final class InlineDataPart extends Part { this.mimeType, this.bytes, { this.willContinue, + this.mediaResolution, bool? isThought, String? thoughtSignature, }) : super( @@ -284,6 +295,7 @@ final class InlineDataPart extends Part { this.mimeType, this.bytes, { this.willContinue, + this.mediaResolution, bool? isThought, String? thoughtSignature, }) : super( @@ -300,6 +312,12 @@ final class InlineDataPart extends Part { /// Whether there's more inline data coming for streaming. final bool? willContinue; + + /// The resolution to use for this media part. + /// + /// This overrides the request-level media resolution for this part. + final MediaResolution? mediaResolution; + @override Object toJson() { final superJson = super.toJson() as Map; @@ -310,6 +328,8 @@ final class InlineDataPart extends Part { 'mimeType': mimeType, if (willContinue != null) 'willContinue': willContinue, }, + if (mediaResolution != null) + 'mediaResolution': {'level': mediaResolution!.toJson()}, }; } @@ -433,6 +453,7 @@ final class FileData extends Part { const FileData( this.mimeType, this.fileUri, { + this.mediaResolution, bool? isThought, }) : super( isThought: isThought, @@ -444,6 +465,7 @@ final class FileData extends Part { const FileData.forTest( this.mimeType, this.fileUri, { + this.mediaResolution, bool? isThought, String? thoughtSignature, }) : super( @@ -454,6 +476,7 @@ final class FileData extends Part { const FileData._( this.mimeType, this.fileUri, { + this.mediaResolution, bool? isThought, String? thoughtSignature, }) : super( @@ -468,12 +491,19 @@ final class FileData extends Part { /// The gs link for Firebase Storage reference final String fileUri; + /// The resolution to use for this media part. + /// + /// This overrides the request-level media resolution for this part. + final MediaResolution? mediaResolution; + @override Object toJson() { final superJson = super.toJson() as Map; return { ...superJson, 'file_data': {'file_uri': fileUri, 'mime_type': mimeType}, + if (mediaResolution != null) + 'mediaResolution': {'level': mediaResolution!.toJson()}, }; } } diff --git a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart index 973f4ba35b41..545aa23a4bf6 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart @@ -168,7 +168,8 @@ final class LiveGenerationConfig extends BaseGenerationConfig { super.topP, super.topK, super.presencePenalty, - super.frequencyPenalty}); + super.frequencyPenalty, + super.mediaResolution}); /// The speech configuration. final SpeechConfig? speechConfig; diff --git a/packages/firebase_ai/firebase_ai/test/api_test.dart b/packages/firebase_ai/firebase_ai/test/api_test.dart index fcac82a5ab50..a177abe5e374 100644 --- a/packages/firebase_ai/firebase_ai/test/api_test.dart +++ b/packages/firebase_ai/firebase_ai/test/api_test.dart @@ -516,6 +516,23 @@ void main() { }); group('GenerationConfig & BaseGenerationConfig', () { + test('GenerationConfig serializes mediaResolution', () { + final config = GenerationConfig( + mediaResolution: MediaResolution.high, + ); + + expect(config.toJson(), { + 'mediaResolution': 'MEDIA_RESOLUTION_HIGH', + }); + }); + + test('GenerationConfig rejects ultraHigh mediaResolution', () { + expect( + () => GenerationConfig(mediaResolution: MediaResolution.ultraHigh), + throwsA(isA()), + ); + }); + test('GenerationConfig toJson with all fields', () { final schema = Schema.object(properties: {}); final thinkingConfig = ThinkingConfig(thinkingBudget: 100); @@ -532,6 +549,7 @@ void main() { frequencyPenalty: 0.4, responseMimeType: 'application/json', responseSchema: schema, + mediaResolution: MediaResolution.medium, thinkingConfig: thinkingConfig, imageConfig: imageConfig, ); @@ -546,6 +564,7 @@ void main() { 'stopSequences': ['\n', 'stop'], 'responseMimeType': 'application/json', 'responseSchema': schema.toJson(), + 'mediaResolution': 'MEDIA_RESOLUTION_MEDIUM', 'thinkingConfig': {'thinkingBudget': 100}, 'imageConfig': { 'aspectRatio': '1:1', diff --git a/packages/firebase_ai/firebase_ai/test/content_test.dart b/packages/firebase_ai/firebase_ai/test/content_test.dart index d9c50082b1dd..281c420d1acf 100644 --- a/packages/firebase_ai/firebase_ai/test/content_test.dart +++ b/packages/firebase_ai/firebase_ai/test/content_test.dart @@ -15,6 +15,7 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:firebase_ai/src/api.dart'; import 'package:firebase_ai/src/content.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -46,6 +47,29 @@ void main() { expect(content.parts[0], isA()); }); + test('inlineData() accepts mediaResolution', () { + final content = Content.inlineData( + 'image/png', + Uint8List(0), + mediaResolution: MediaResolution.high, + ); + + expect(content.toJson(), { + 'role': 'user', + 'parts': [ + { + 'inlineData': { + 'mimeType': 'image/png', + 'data': '', + }, + 'mediaResolution': { + 'level': 'MEDIA_RESOLUTION_HIGH', + }, + } + ], + }); + }); + test('multi()', () { final content = Content('user', [const TextPart('Test'), InlineDataPart('image/png', Uint8List(0))]); @@ -125,6 +149,24 @@ void main() { expect(inlineData['willContinue'], true); }); + test('InlineDataPart serializes mediaResolution', () { + final part = InlineDataPart( + 'image/png', + Uint8List(0), + mediaResolution: MediaResolution.ultraHigh, + ); + + expect(part.toJson(), { + 'inlineData': { + 'mimeType': 'image/png', + 'data': '', + }, + 'mediaResolution': { + 'level': 'MEDIA_RESOLUTION_ULTRA_HIGH', + }, + }); + }); + test('FunctionCall with isThought and thoughtSignature toJson', () { const part = FunctionCall.forTest( 'myFunction', @@ -182,6 +224,24 @@ void main() { expect(fileData['file_uri'], 'gs://bucket-name/path'); expect(json['thought'], true); }); + + test('FileData serializes mediaResolution', () { + const part = FileData( + 'image/png', + 'gs://bucket-name/path', + mediaResolution: MediaResolution.high, + ); + + expect(part.toJson(), { + 'file_data': { + 'mime_type': 'image/png', + 'file_uri': 'gs://bucket-name/path', + }, + 'mediaResolution': { + 'level': 'MEDIA_RESOLUTION_HIGH', + }, + }); + }); }); group('parsePart', () { diff --git a/packages/firebase_ai/firebase_ai/test/live_test.dart b/packages/firebase_ai/firebase_ai/test/live_test.dart index b1b07d5ee445..c15bdbfb5ebf 100644 --- a/packages/firebase_ai/firebase_ai/test/live_test.dart +++ b/packages/firebase_ai/firebase_ai/test/live_test.dart @@ -48,6 +48,7 @@ void main() { temperature: 0.8, topP: 0.95, topK: 40, + mediaResolution: MediaResolution.low, ); expect(liveGenerationConfig.toJson(), { @@ -61,6 +62,7 @@ void main() { } }, 'responseModalities': ['TEXT', 'AUDIO'], + 'mediaResolution': 'MEDIA_RESOLUTION_LOW', }); final liveGenerationConfigWithoutOptionals = LiveGenerationConfig(); From 3471afc7ffa7bae58981683982d58d669ac71d50 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 8 Jun 2026 16:47:18 +0200 Subject: [PATCH 112/137] feat(ai): add language code support for SpeechConfig (#18353) --- .../firebase_ai/lib/src/live_api.dart | 16 +++++++++++++--- .../firebase_ai/firebase_ai/test/live_test.dart | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart index 545aa23a4bf6..7061bc94c694 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart @@ -50,13 +50,16 @@ class VoiceConfig { /// Configures speech synthesis settings. /// -/// Allows specifying the desired voice for speech synthesis. +/// Allows specifying the desired voice and language for speech synthesis. class SpeechConfig { /// Creates a [SpeechConfig] instance. /// /// [voiceName] See https://cloud.google.com/text-to-speech/docs/chirp3-hd /// for names and sound demos. - SpeechConfig({String? voiceName}) + /// + /// [languageCode] The language code (BCP-47) for speech synthesis, + /// e.g. "en-US", "fr-FR", "de-DE". + SpeechConfig({String? voiceName, this.languageCode}) : voiceConfig = voiceName != null ? VoiceConfig( prebuiltVoiceConfig: PrebuiltVoiceConfig(voiceName: voiceName)) @@ -64,10 +67,17 @@ class SpeechConfig { /// The voice config to use for speech synthesis. final VoiceConfig? voiceConfig; + + /// The language code (BCP-47) for speech synthesis, + /// e.g. "en-US", "fr-FR", "de-DE". + final String? languageCode; + // ignore: public_member_api_docs Map toJson() => { if (voiceConfig case final voiceConfig?) - 'voice_config': voiceConfig.toJson() + 'voice_config': voiceConfig.toJson(), + if (languageCode case final languageCode?) + 'language_code': languageCode, }; } diff --git a/packages/firebase_ai/firebase_ai/test/live_test.dart b/packages/firebase_ai/firebase_ai/test/live_test.dart index c15bdbfb5ebf..ed6f088aed4a 100644 --- a/packages/firebase_ai/firebase_ai/test/live_test.dart +++ b/packages/firebase_ai/firebase_ai/test/live_test.dart @@ -34,6 +34,22 @@ void main() { expect(speechConfigWithoutVoice.toJson(), {}); }); + test('SpeechConfig with languageCode toJson() returns correct JSON', () { + final speechConfigWithLanguage = + SpeechConfig(voiceName: 'Aoede', languageCode: 'en-US'); + expect(speechConfigWithLanguage.toJson(), { + 'voice_config': { + 'prebuilt_voice_config': {'voice_name': 'Aoede'} + }, + 'language_code': 'en-US', + }); + + final speechConfigLanguageOnly = SpeechConfig(languageCode: 'fr-FR'); + expect(speechConfigLanguageOnly.toJson(), { + 'language_code': 'fr-FR', + }); + }); + test('ResponseModalities enum toJson() returns correct value', () { expect(ResponseModalities.text.toJson(), 'TEXT'); expect(ResponseModalities.image.toJson(), 'IMAGE'); From f3c53792f1acf19ab1c2c7c3d157fca3a183b5d1 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 9 Jun 2026 09:05:32 +0200 Subject: [PATCH 113/137] fix(ai): firebase_ai server template image inputs passed as InlineDataPart were serialized as normal generative inlineData (#18350) --- .../firebase_ai/lib/src/base_model.dart | 27 ++++++++++++++++-- .../test/server_template_test.dart | 28 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart index f02bc723b580..96972eb5dafb 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/base_model.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/base_model.dart @@ -13,6 +13,7 @@ // limitations under the License. import 'dart:async'; +import 'dart:convert'; import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_auth/firebase_auth.dart'; @@ -375,7 +376,7 @@ abstract class BaseTemplateApiClientModel extends BaseApiClientModel { T Function(Map) parse) { Map body = {}; if (inputs != null) { - body['inputs'] = inputs; + body['inputs'] = _serializeTemplateInputs(inputs); } if (history != null) { body['history'] = history.map((c) => c.toJson()).toList(); @@ -405,7 +406,7 @@ abstract class BaseTemplateApiClientModel extends BaseApiClientModel { T Function(Map) parse) { Map body = {}; if (inputs != null) { - body['inputs'] = inputs; + body['inputs'] = _serializeTemplateInputs(inputs); } if (history != null) { body['history'] = history.map((c) => c.toJson()).toList(); @@ -428,4 +429,26 @@ abstract class BaseTemplateApiClientModel extends BaseApiClientModel { /// Returns the template name for the given [templateId]. String templateName(String templateId) => _templateUri.templateName(templateId); + + Map _serializeTemplateInputs(Map inputs) { + return inputs.map((key, value) { + return MapEntry(key, _serializeTemplateInputValue(value)); + }); + } + + Object? _serializeTemplateInputValue(Object? value) { + return switch (value) { + InlineDataPart(:final mimeType, :final bytes) => { + 'isInline': true, + 'mimeType': mimeType, + 'contents': base64Encode(bytes), + }, + Map() => value.map((key, nestedValue) { + return MapEntry(key, _serializeTemplateInputValue(nestedValue)); + }), + List() => + value.map(_serializeTemplateInputValue).toList(growable: false), + _ => value, + }; + } } diff --git a/packages/firebase_ai/firebase_ai/test/server_template_test.dart b/packages/firebase_ai/firebase_ai/test/server_template_test.dart index 71d0905a7424..1dbde35afc0c 100644 --- a/packages/firebase_ai/firebase_ai/test/server_template_test.dart +++ b/packages/firebase_ai/firebase_ai/test/server_template_test.dart @@ -13,6 +13,7 @@ // limitations under the License. import 'dart:convert'; +import 'dart:typed_data'; import 'package:firebase_ai/firebase_ai.dart'; import 'package:firebase_ai/src/base_model.dart'; @@ -86,6 +87,33 @@ void main() { expect(response.text, 'Some response'); }); + test('generateContent serializes inline image inputs', () async { + final mockHttp = MockClient((request) async { + final body = jsonDecode(request.body) as Map; + expect(body['inputs'], { + 'screenshot': { + 'isInline': true, + 'mimeType': 'image/jpeg', + 'contents': base64Encode([1, 2, 3]), + }, + }); + return http.Response(jsonEncode(_arbitraryGenerateContentResponse), 200, + headers: {'content-type': 'application/json'}); + }); + + final model = createModel(mockHttp); + final response = await model.generateContent( + templateId, + inputs: { + 'screenshot': InlineDataPart( + 'image/jpeg', + Uint8List.fromList([1, 2, 3]), + ), + }, + ); + expect(response.text, 'Some response'); + }); + test('generateContent with TemplateToolConfig passes retrievalConfig', () async { final mockHttp = MockClient((request) async { From 121b83a04980498db779081497df1f24adac184b Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 9 Jun 2026 10:39:44 +0200 Subject: [PATCH 114/137] ci: add AGP9 compatibility checks in CI (#18235) * ci: add AGP9 compatibility checks in CI * update * update --- .github/workflows/android.yaml | 26 +++++++++++ .../workflows/scripts/agp9-compatibility.sh | 44 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .github/workflows/scripts/agp9-compatibility.sh diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 8d83ed24c2dd..58bd4d22398e 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -143,3 +143,29 @@ jobs: path: | ~/.android/avd/* ~/.android/adb* + + agp9-compatibility: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b + with: + distribution: 'temurin' + java-version: '21' + - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff + with: + channel: 'stable' + cache: true + cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" + pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" + - uses: bluefireteam/melos-action@705015c3d2bc4ab94201ac24accb2bbe070cf533 + with: + run-bootstrap: false + melos-version: '5.3.0' + - name: 'Bootstrap tests package' + run: melos bootstrap --scope tests + - name: Gradle cache + uses: gradle/actions/setup-gradle@v4 + - name: 'Build tests app with AGP 9' + run: bash ./.github/workflows/scripts/agp9-compatibility.sh diff --git a/.github/workflows/scripts/agp9-compatibility.sh b/.github/workflows/scripts/agp9-compatibility.sh new file mode 100644 index 000000000000..9cf19d2c40ea --- /dev/null +++ b/.github/workflows/scripts/agp9-compatibility.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -euo pipefail + +AGP_VERSION="${AGP_VERSION:-9.0.1}" +GRADLE_VERSION="${GRADLE_VERSION:-9.1.0}" + +TEST_ANDROID_DIR="tests/android" + +perl -0pi -e "s/id \"com\.android\.application\" version \"[^\"]+\" apply false/id \"com.android.application\" version \"$AGP_VERSION\" apply false/" \ + "$TEST_ANDROID_DIR/settings.gradle" + +perl -0pi -e "s#distributionUrl=https\\\\://services.gradle.org/distributions/gradle-[^-]+-all.zip#distributionUrl=https\\\\://services.gradle.org/distributions/gradle-$GRADLE_VERSION-all.zip#" \ + "$TEST_ANDROID_DIR/gradle/wrapper/gradle-wrapper.properties" + +# Flutter's Gradle plugin does not fully support AGP 9's new DSL yet. Opt out in +# this CI-only checkout so the job validates FlutterFire plugin compatibility. +# https://docs.flutter.cn/release/breaking-changes/migrate-to-agp-9/ +grep -q '^android.newDsl=false$' "$TEST_ANDROID_DIR/gradle.properties" || \ + printf '\nandroid.newDsl=false\n' >> "$TEST_ANDROID_DIR/gradle.properties" + +# AGP 9 has built-in Kotlin support. Keep the compatibility check focused on +# FlutterFire plugins by applying the same migration to the test app at runtime. +perl -0pi -e 's/\n\s*id "kotlin-android"\n/\n/' "$TEST_ANDROID_DIR/app/build.gradle" +perl -0pi -e 's/\n\s*kotlinOptions \{\n\s*jvmTarget = JavaVersion\.VERSION_17\n\s*\}\n/\n/' "$TEST_ANDROID_DIR/app/build.gradle" + +# AGP 9 rejects older Espresso artifacts that share the same namespace. +grep -q 'androidx.test.espresso:espresso-core:3.7.0' "$TEST_ANDROID_DIR/app/build.gradle" || cat <<'EOF' >> "$TEST_ANDROID_DIR/app/build.gradle" + +dependencies { + debugImplementation 'androidx.test.espresso:espresso-core:3.7.0' + debugImplementation 'androidx.test.espresso:espresso-idling-resource:3.7.0' +} +EOF + +grep -q "id \"com.android.application\" version \"$AGP_VERSION\" apply false" "$TEST_ANDROID_DIR/settings.gradle" +grep -q "gradle-$GRADLE_VERSION-all.zip" "$TEST_ANDROID_DIR/gradle/wrapper/gradle-wrapper.properties" +grep -q '^android.newDsl=false$' "$TEST_ANDROID_DIR/gradle.properties" +! grep -q 'id "kotlin-android"' "$TEST_ANDROID_DIR/app/build.gradle" +! grep -q 'kotlinOptions' "$TEST_ANDROID_DIR/app/build.gradle" +grep -q 'androidx.test.espresso:espresso-core:3.7.0' "$TEST_ANDROID_DIR/app/build.gradle" +grep -q 'androidx.test.espresso:espresso-idling-resource:3.7.0' "$TEST_ANDROID_DIR/app/build.gradle" + +cd tests +flutter build apk --debug --dart-define=CI=true --no-android-gradle-daemon From d60af4d9e1345c113490e875c85bd9ac62dad935 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 9 Jun 2026 10:49:25 +0200 Subject: [PATCH 115/137] feat(messaging,ios): add support for actionIdentifier on iOS devices (#18357) --- .../FLTFirebaseMessagingPlugin.m | 38 ++++++++++++++++--- .../lib/src/remote_message.dart | 6 +++ .../test/remote_message_test.dart | 12 ++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m index a0eec7d0419f..77f2078991c6 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/FLTFirebaseMessagingPlugin.m @@ -226,6 +226,11 @@ - (void)messaging:(nonnull FIRMessaging *)messaging - (void)setupNotificationHandlingWithRemoteNotification: (nullable NSDictionary *)remoteNotification { + [self setupNotificationHandlingWithRemoteNotification:remoteNotification actionIdentifier:nil]; +} + +- (void)setupNotificationHandlingWithRemoteNotification:(nullable NSDictionary *)remoteNotification + actionIdentifier:(nullable NSString *)actionIdentifier { // If notification handling was already set up (e.g. from // application_onDidFinishLaunchingNotification) and we're called again (e.g. from // scene:willConnectToSession:), only process the notification but skip delegate/swizzler @@ -234,7 +239,8 @@ - (void)setupNotificationHandlingWithRemoteNotification: if (_notificationHandlingSetup) { if (remoteNotification != nil) { _initialNotification = - [FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification]; + [FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification + withActionIdentifier:actionIdentifier]; _initialNotificationID = remoteNotification[@"gcm.message_id"]; _initialNotificationGathered = YES; [self initialNotificationCallback]; @@ -255,7 +261,8 @@ - (void)setupNotificationHandlingWithRemoteNotification: if (remoteNotification != nil) { // If remoteNotification exists, it is the notification that opened the app. _initialNotification = - [FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification]; + [FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification + withActionIdentifier:actionIdentifier]; _initialNotificationID = remoteNotification[@"gcm.message_id"]; _initialNotificationGathered = YES; [self initialNotificationCallback]; @@ -458,12 +465,20 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center API_AVAILABLE(macos(10.14), ios(10.0)) { NSDictionary *remoteNotification = response.notification.request.content.userInfo; _notificationOpenedAppID = remoteNotification[@"gcm.message_id"]; + NSDictionary *notificationDict = + [FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification + withActionIdentifier:response.actionIdentifier]; + + if (_initialNotification != nil && + [_initialNotificationID isEqualToString:_notificationOpenedAppID]) { + _initialNotification = notificationDict; + [self initialNotificationCallback]; + } + // We only want to handle FCM notifications and stop firing `onMessageOpenedApp()` when app is // coming from a terminated state. if (_notificationOpenedAppID != nil && ![_initialNotificationID isEqualToString:_notificationOpenedAppID]) { - NSDictionary *notificationDict = - [FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:remoteNotification]; [_channel invokeMethod:@"Messaging#onMessageOpenedApp" arguments:notificationDict]; } @@ -642,14 +657,17 @@ - (void)scene:(UIScene *)scene _sceneDidConnect = YES; NSDictionary *remoteNotification = nil; + NSString *actionIdentifier = nil; if (connectionOptions.notificationResponse != nil) { // User tapped the notification. remoteNotification = connectionOptions.notificationResponse.notification.request.content.userInfo; + actionIdentifier = connectionOptions.notificationResponse.actionIdentifier; _notificationOpenedAppID = remoteNotification[@"gcm.message_id"]; } - [self setupNotificationHandlingWithRemoteNotification:remoteNotification]; + [self setupNotificationHandlingWithRemoteNotification:remoteNotification + actionIdentifier:actionIdentifier]; } #endif @@ -960,11 +978,21 @@ + (NSDictionary *)NSDictionaryFromUNNotification:(UNNotification *)notification } + (NSDictionary *)remoteMessageUserInfoToDict:(NSDictionary *)userInfo { + return [self remoteMessageUserInfoToDict:userInfo withActionIdentifier:nil]; +} + ++ (NSDictionary *)remoteMessageUserInfoToDict:(NSDictionary *)userInfo + withActionIdentifier:(nullable NSString *)actionIdentifier { NSMutableDictionary *message = [[NSMutableDictionary alloc] init]; NSMutableDictionary *data = [[NSMutableDictionary alloc] init]; NSMutableDictionary *notification = [[NSMutableDictionary alloc] init]; NSMutableDictionary *notificationIOS = [[NSMutableDictionary alloc] init]; + // message.actionIdentifier + if (actionIdentifier != nil) { + message[@"actionIdentifier"] = actionIdentifier; + } + // message.data for (id key in userInfo) { // message.messageId diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/remote_message.dart b/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/remote_message.dart index cc596a496ba0..1b39fad8d387 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/remote_message.dart +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/lib/src/remote_message.dart @@ -11,6 +11,7 @@ class RemoteMessage { const RemoteMessage( {this.senderId, this.category, + this.actionIdentifier, this.collapseKey, this.contentAvailable = false, this.data = const {}, @@ -28,6 +29,7 @@ class RemoteMessage { return RemoteMessage( senderId: map['senderId'], category: map['category'], + actionIdentifier: map['actionIdentifier'], collapseKey: map['collapseKey'], contentAvailable: map['contentAvailable'] ?? false, data: map['data'] == null @@ -57,6 +59,7 @@ class RemoteMessage { return { 'senderId': senderId, 'category': category, + 'actionIdentifier': actionIdentifier, 'collapseKey': collapseKey, 'contentAvailable': contentAvailable, 'data': data, @@ -77,6 +80,9 @@ class RemoteMessage { /// The iOS category this notification is assigned to. final String? category; + /// The Apple notification action identifier used to open the app. + final String? actionIdentifier; + /// The collapse key a message was sent with. Used to override existing messages with the same key. final String? collapseKey; diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/test/remote_message_test.dart b/packages/firebase_messaging/firebase_messaging_platform_interface/test/remote_message_test.dart index 0868d2eab3dd..b676e3c1ea0a 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/test/remote_message_test.dart +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/test/remote_message_test.dart @@ -16,6 +16,7 @@ void main() { mockMessageMap = { 'senderId': 'senderId', 'category': 'category', + 'actionIdentifier': 'actionIdentifier', 'collapseKey': 'collapseKey', 'contentAvailable': true, 'data': { @@ -38,6 +39,7 @@ void main() { mockNullableMessageMap = { 'senderId': null, 'category': null, + 'actionIdentifier': null, 'collapseKey': null, 'data': null, 'from': null, @@ -55,6 +57,7 @@ void main() { expect(message.senderId, mockMessageMap!['senderId']); expect(message.category, mockMessageMap!['category']); + expect(message.actionIdentifier, mockMessageMap!['actionIdentifier']); expect(message.collapseKey, mockMessageMap!['collapseKey']); expect(message.contentAvailable, mockMessageMap!['contentAvailable']); expect(message.data, mockMessageMap!['data']); @@ -85,6 +88,8 @@ void main() { expect(message.senderId, mockNullableMessageMap['senderId']); expect(message.category, mockNullableMessageMap['category']); + expect( + message.actionIdentifier, mockNullableMessageMap['actionIdentifier']); expect(message.collapseKey, mockNullableMessageMap['collapseKey']); expect(message.contentAvailable, false); expect(message.data, {}); @@ -105,6 +110,7 @@ void main() { final message = RemoteMessage( senderId: mockMessageMap!['senderId'], category: mockMessageMap!['category'], + actionIdentifier: mockMessageMap!['actionIdentifier'], collapseKey: mockMessageMap!['collapseKey'], contentAvailable: mockMessageMap!['contentAvailable'], data: mockMessageMap!['data'], @@ -120,6 +126,7 @@ void main() { expect(message.senderId, mockMessageMap!['senderId']); expect(message.category, mockMessageMap!['category']); + expect(message.actionIdentifier, mockMessageMap!['actionIdentifier']); expect(message.collapseKey, mockMessageMap!['collapseKey']); expect(message.contentAvailable, mockMessageMap!['contentAvailable']); expect(message.data, mockMessageMap!['data']); @@ -141,6 +148,7 @@ void main() { mockNullableMessageMap = { 'senderId': null, 'category': null, + 'actionIdentifier': null, 'collapseKey': null, 'data': null, 'from': null, @@ -156,6 +164,8 @@ void main() { expect(message.senderId, mockNullableMessageMap['senderId']); expect(message.category, mockNullableMessageMap['category']); + expect( + message.actionIdentifier, mockNullableMessageMap['actionIdentifier']); expect(message.collapseKey, mockNullableMessageMap['collapseKey']); expect(message.contentAvailable, false); expect(message.data, {}); @@ -173,6 +183,7 @@ void main() { final RemoteMessage remoteMessage = RemoteMessage( senderId: 'senderId', category: 'category', + actionIdentifier: 'actionIdentifier', collapseKey: 'collapseKey', contentAvailable: true, data: {}, @@ -193,6 +204,7 @@ void main() { expect(map['senderId'], remoteMessage.senderId); expect(map['category'], remoteMessage.category); + expect(map['actionIdentifier'], remoteMessage.actionIdentifier); expect(map['collapseKey'], remoteMessage.collapseKey); expect(map['contentAvailable'], remoteMessage.contentAvailable); expect(map['data'], remoteMessage.data); From 5e48ee791da0edd792286e4112674b07563574b8 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Wed, 10 Jun 2026 14:17:16 +0000 Subject: [PATCH 116/137] fix(android): tweak Android test `build.gradle` to support AGP 9 (#18360) --- tests/android/app/build.gradle | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/android/app/build.gradle b/tests/android/app/build.gradle index b26d90633bf5..fc3d9adc9b24 100644 --- a/tests/android/app/build.gradle +++ b/tests/android/app/build.gradle @@ -1,7 +1,6 @@ plugins { id "com.android.application" - id "kotlin-android" - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + // The Flutter Gradle Plugin must be applied after the Android Gradle plugin. id "dev.flutter.flutter-gradle-plugin" } @@ -34,10 +33,6 @@ android { coreLibraryDesugaringEnabled true } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17 - } - defaultConfig { applicationId = "io.flutter.plugins.firebase.tests" // auth requires minSdk 23 @@ -63,3 +58,9 @@ flutter { dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' } + +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} From 0af51b501603a611c7c6800efd9d98c478abab4d Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 10 Jun 2026 08:42:14 -0700 Subject: [PATCH 117/137] feat(firebaseai): Add speech config and TTS sample page (#18358) * speech config init * add test page for TTS * fix analyzer * format --- .../firebase_ai/example/lib/main.dart | 13 + .../example/lib/pages/chat_page.dart | 5 +- .../example/lib/pages/tts_page.dart | 448 ++++++++++++++++++ .../example/lib/utils/audio_output.dart | 7 + .../firebase_ai/lib/firebase_ai.dart | 3 +- .../firebase_ai/firebase_ai/lib/src/api.dart | 8 + .../firebase_ai/lib/src/live_api.dart | 73 +-- .../firebase_ai/lib/src/speech_config.dart | 112 +++++ .../firebase_ai/test/live_test.dart | 74 +++ 9 files changed, 666 insertions(+), 77 deletions(-) create mode 100644 packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart create mode 100644 packages/firebase_ai/firebase_ai/lib/src/speech_config.dart diff --git a/packages/firebase_ai/firebase_ai/example/lib/main.dart b/packages/firebase_ai/firebase_ai/example/lib/main.dart index 296fbbc79a91..01a68ff9506a 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/main.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/main.dart @@ -32,6 +32,7 @@ import 'pages/schema_page.dart'; import 'pages/server_template_page.dart'; import 'pages/grounding_page.dart'; import 'pages/token_count_page.dart'; +import 'pages/tts_page.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); @@ -180,6 +181,11 @@ class _HomeScreenState extends State { title: 'Grounding', useVertexBackend: useVertexBackend, ); + case 11: + return TTSPage( + title: 'TTS Test', + useVertexBackend: useVertexBackend, + ); default: // Fallback to the first page in case of an unexpected index @@ -314,6 +320,13 @@ class _HomeScreenState extends State { label: 'Grounding', tooltip: 'Search & Maps Grounding', ), + BottomNavigationBarItem( + icon: Icon( + Icons.record_voice_over, + ), + label: 'TTS', + tooltip: 'Text to Speech', + ), ], currentIndex: _selectedIndex, onTap: _onItemTapped, diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart index 5eb1ee91a4a8..6562420bbdc4 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/chat_page.dart @@ -49,10 +49,7 @@ class _ChatPageState extends State { void _initializeChat() { final generationConfig = GenerationConfig( thinkingConfig: _enableThinking - ? ThinkingConfig.withThinkingBudget( - null, - includeThoughts: true, - ) // Using thinkingBudget since we are testing with gemini 2.5 + ? ThinkingConfig.withThinkingLevel(ThinkingLevel.medium) : null, ); if (widget.useVertexBackend) { diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart new file mode 100644 index 000000000000..06ba3a63a9a0 --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart @@ -0,0 +1,448 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:async'; +import 'dart:math'; +import 'dart:typed_data'; +import 'package:flutter/material.dart'; +import 'package:firebase_ai/firebase_ai.dart'; +import 'package:waveform_flutter/waveform_flutter.dart'; +import '../utils/audio_output.dart'; +import '../widgets/audio_visualizer.dart'; + +class TTSPage extends StatefulWidget { + const TTSPage({ + super.key, + required this.title, + required this.useVertexBackend, + }); + + final String title; + final bool useVertexBackend; + + @override + State createState() => _TTSPageState(); +} + +class _TTSPageState extends State { + final AudioOutput _audioOutput = AudioOutput(); + final MockAmplitudeGenerator _mockAmpGen = MockAmplitudeGenerator(); + + bool _isMultiSpeaker = false; + bool _loading = false; + bool _isPlaying = false; + String? _responseText; + + // Single Speaker Controller + final TextEditingController _singlePromptController = TextEditingController( + text: 'Say cheerfully: Have a wonderful day!', + ); + String _selectedVoice = 'Kore'; + + // Multi Speaker Controllers + final TextEditingController _multiScriptController = TextEditingController( + text: "Joe: How's it going today Jane?\nJane: Not too bad, how about you?", + ); + final TextEditingController _speaker1NameController = + TextEditingController(text: 'Joe'); + String _speaker1Voice = 'Kore'; + final TextEditingController _speaker2NameController = + TextEditingController(text: 'Jane'); + String _speaker2Voice = 'Puck'; + + final List _availableVoices = [ + 'Kore', + 'Puck', + 'Fenrir', + 'Aoede', + 'Charon', + 'Leda', + ]; + + Stream? _amplitudeStream; + Timer? _playbackTimer; + + @override + void initState() { + super.initState(); + _audioOutput.init(); + } + + @override + void dispose() { + _audioOutput.dispose(); + _mockAmpGen.stop(); + _playbackTimer?.cancel(); + _singlePromptController.dispose(); + _multiScriptController.dispose(); + _speaker1NameController.dispose(); + _speaker2NameController.dispose(); + super.dispose(); + } + + void _showError(String message) { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('Something went wrong'), + content: SingleChildScrollView( + child: SelectableText(message), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: const Text('OK'), + ), + ], + ); + }, + ); + } + + Future _generateAndPlay() async { + setState(() { + _loading = true; + _responseText = null; + }); + + try { + final GenerationConfig config; + final String prompt; + + if (_isMultiSpeaker) { + prompt = _multiScriptController.text; + config = GenerationConfig( + responseModalities: [ResponseModalities.audio], + speechConfig: SpeechConfig.multiSpeaker( + multiSpeakerVoiceConfig: MultiSpeakerVoiceConfig( + speakerVoiceConfigs: [ + SpeakerVoiceConfig( + speaker: _speaker1NameController.text, + voiceName: _speaker1Voice, + ), + SpeakerVoiceConfig( + speaker: _speaker2NameController.text, + voiceName: _speaker2Voice, + ), + ], + ), + ), + ); + } else { + prompt = _singlePromptController.text; + config = GenerationConfig( + responseModalities: [ResponseModalities.audio], + speechConfig: SpeechConfig( + voiceName: _selectedVoice, + languageCode: 'en-US', + ), + ); + } + + // Use the preview model for TTS + final modelName = widget.useVertexBackend + ? 'gemini-2.5-flash-tts' + : 'gemini-3.1-flash-tts-preview'; + final GenerativeModel model; + if (widget.useVertexBackend) { + model = FirebaseAI.vertexAI(location: 'global').generativeModel( + model: modelName, + generationConfig: config, + ); + } else { + model = FirebaseAI.googleAI().generativeModel( + model: modelName, + generationConfig: config, + ); + } + + final response = await model.generateContent([Content.text(prompt)]); + + // Extract text response + _responseText = response.text; + + // Find audio bytes + Uint8List? audioBytes; + for (final candidate in response.candidates) { + for (final part in candidate.content.parts) { + if (part is InlineDataPart && part.mimeType.startsWith('audio/')) { + audioBytes = part.bytes; + break; + } + } + if (audioBytes != null) break; + } + + if (audioBytes == null || audioBytes.isEmpty) { + throw Exception('No audio received from the model.'); + } + + // Play audio and start visualizer + await _audioOutput.playStream(); + _audioOutput.addDataToAudioStream(audioBytes); + _audioOutput.finishStream(); + + // Calculate duration: 24000 Hz, 1 channel, 16-bit (2 bytes) = 48000 bytes/sec + final durationMs = (audioBytes.length / 48.0).round(); + final duration = Duration(milliseconds: durationMs); + + setState(() { + _loading = false; + _isPlaying = true; + _amplitudeStream = _mockAmpGen.start(duration); + }); + + _playbackTimer = Timer(duration, () { + setState(() { + _isPlaying = false; + _amplitudeStream = null; + }); + }); + } catch (e) { + setState(() { + _loading = false; + }); + _showError(e.toString()); + } + } + + void _stopPlayback() { + _audioOutput.stopStream(); + _mockAmpGen.stop(); + _playbackTimer?.cancel(); + setState(() { + _isPlaying = false; + _amplitudeStream = null; + }); + } + + Widget _buildSingleSpeakerForm() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + controller: _singlePromptController, + decoration: const InputDecoration( + labelText: 'Prompt', + hintText: 'Enter text to generate speech from', + border: OutlineInputBorder(), + ), + maxLines: 3, + ), + const SizedBox(height: 16), + DropdownButtonFormField( + initialValue: _selectedVoice, + decoration: const InputDecoration( + labelText: 'Voice Name', + border: OutlineInputBorder(), + ), + items: _availableVoices.map((voice) { + return DropdownMenuItem( + value: voice, + child: Text(voice), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + setState(() { + _selectedVoice = value; + }); + } + }, + ), + ], + ); + } + + Widget _buildMultiSpeakerForm() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + controller: _multiScriptController, + decoration: const InputDecoration( + labelText: 'Script', + hintText: 'Format: Name: text to say', + border: OutlineInputBorder(), + ), + maxLines: 5, + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: TextField( + controller: _speaker1NameController, + decoration: const InputDecoration( + labelText: 'Speaker 1 Name', + border: OutlineInputBorder(), + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: DropdownButtonFormField( + initialValue: _speaker1Voice, + decoration: const InputDecoration( + labelText: 'Speaker 1 Voice', + border: OutlineInputBorder(), + ), + items: _availableVoices.map((voice) { + return DropdownMenuItem( + value: voice, + child: Text(voice), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + setState(() { + _speaker1Voice = value; + }); + } + }, + ), + ), + ], + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: TextField( + controller: _speaker2NameController, + decoration: const InputDecoration( + labelText: 'Speaker 2 Name', + border: OutlineInputBorder(), + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: DropdownButtonFormField( + initialValue: _speaker2Voice, + decoration: const InputDecoration( + labelText: 'Speaker 2 Voice', + border: OutlineInputBorder(), + ), + items: _availableVoices.map((voice) { + return DropdownMenuItem( + value: voice, + child: Text(voice), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + setState(() { + _speaker2Voice = value; + }); + } + }, + ), + ), + ], + ), + ], + ); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + SegmentedButton( + segments: const [ + ButtonSegment(value: false, label: Text('Single Speaker')), + ButtonSegment(value: true, label: Text('Multi Speaker')), + ], + selected: {_isMultiSpeaker}, + onSelectionChanged: (value) { + setState(() { + _isMultiSpeaker = value.first; + }); + }, + ), + const SizedBox(height: 16), + Expanded( + child: SingleChildScrollView( + child: _isMultiSpeaker + ? _buildMultiSpeakerForm() + : _buildSingleSpeakerForm(), + ), + ), + const Divider(), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8), + child: Row( + children: [ + if (_loading) + const CircularProgressIndicator() + else + IconButton( + icon: Icon(_isPlaying ? Icons.stop : Icons.play_arrow), + iconSize: 36, + color: Theme.of(context).colorScheme.primary, + onPressed: _isPlaying ? _stopPlayback : _generateAndPlay, + ), + const SizedBox(width: 16), + AudioVisualizer( + audioStreamIsActive: _isPlaying, + amplitudeStream: _amplitudeStream, + ), + if (!_isPlaying && !_loading && _responseText != null) + Expanded( + child: Text( + _responseText!, + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyMedium, + ), + ), + ], + ), + ), + ], + ), + ); + } +} + +class MockAmplitudeGenerator { + StreamController? _controller; + Timer? _timer; + final Random _random = Random(); + + Stream start(Duration duration) { + stop(); + _controller = StreamController.broadcast(); + + _timer = Timer.periodic(const Duration(milliseconds: 100), (timer) { + double current = -60.0 + _random.nextDouble() * 60.0; + _controller?.add(Amplitude(current: current, max: 0)); + }); + + return _controller!.stream; + } + + void stop() { + _timer?.cancel(); + _timer = null; + _controller?.close(); + _controller = null; + } +} diff --git a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart index 4ec2a1a4911d..d1cfc988b453 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/utils/audio_output.dart @@ -94,4 +94,11 @@ class AudioOutput { SoLoud.instance.setDataIsEnded(currentStream); await SoLoud.instance.stop(currentHandle); } + + void finishStream() { + var currentStream = stream; + if (currentStream != null) { + SoLoud.instance.setDataIsEnded(currentStream); + } + } } diff --git a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart index 460fe5cb79e9..06eeaaa1195f 100644 --- a/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/firebase_ai.dart @@ -116,7 +116,6 @@ export 'src/live_api.dart' SessionResumptionConfig, SessionResumptionUpdate, SlidingWindow, - SpeechConfig, Transcription; export 'src/live_session.dart' show LiveSession; export 'src/schema.dart' show JSONSchema, Schema, SchemaType; @@ -128,6 +127,8 @@ export 'src/server_template/template_tool.dart' TemplateFunctionDeclaration, TemplateTool, TemplateToolConfig; +export 'src/speech_config.dart' + show SpeechConfig, MultiSpeakerVoiceConfig, SpeakerVoiceConfig; export 'src/tool.dart' show AutoFunctionDeclaration, diff --git a/packages/firebase_ai/firebase_ai/lib/src/api.dart b/packages/firebase_ai/firebase_ai/lib/src/api.dart index 1d2ee8947954..d2c2c7c9b3e9 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/api.dart @@ -16,6 +16,7 @@ import 'content.dart'; import 'error.dart'; import 'image_config.dart'; import 'schema.dart'; +import 'speech_config.dart'; import 'tool.dart' show Tool, ToolConfig; /// Response for Count Tokens @@ -1206,6 +1207,7 @@ abstract class BaseGenerationConfig { this.frequencyPenalty, this.responseModalities, this.mediaResolution, + this.speechConfig, }) : assert(mediaResolution != MediaResolution.ultraHigh, 'MediaResolution.ultraHigh is only supported on individual media parts.'); @@ -1294,6 +1296,9 @@ abstract class BaseGenerationConfig { /// [MediaResolution.ultraHigh] is only supported on individual media parts. final MediaResolution? mediaResolution; + /// The configuration parameters controlling the model's speech and audio generation. + final SpeechConfig? speechConfig; + // ignore: public_member_api_docs Map toJson() => { if (candidateCount case final candidateCount?) @@ -1312,6 +1317,8 @@ abstract class BaseGenerationConfig { responseModalities.map((modality) => modality.toJson()).toList(), if (mediaResolution case final mediaResolution?) 'mediaResolution': mediaResolution.toJson(), + if (speechConfig case final speechConfig?) + 'speechConfig': speechConfig.toJson(), }; } @@ -1329,6 +1336,7 @@ final class GenerationConfig extends BaseGenerationConfig { super.frequencyPenalty, super.responseModalities, super.mediaResolution, + super.speechConfig, this.responseMimeType, this.responseSchema, this.responseJsonSchema, diff --git a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart index 7061bc94c694..b961d5348786 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/live_api.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/live_api.dart @@ -15,72 +15,6 @@ import 'api.dart'; import 'content.dart'; import 'error.dart'; -/// Configuration for a prebuilt voice. -/// -/// This class allows specifying a voice by its name. -class PrebuiltVoiceConfig { - // ignore: public_member_api_docs - const PrebuiltVoiceConfig({this.voiceName}); - - /// The voice name to use for speech synthesis. - /// - /// See https://cloud.google.com/text-to-speech/docs/chirp3-hd for names and - /// sound demos. - final String? voiceName; - // ignore: public_member_api_docs - Map toJson() => - {if (voiceName case final voiceName?) 'voice_name': voiceName}; -} - -/// Configuration for the voice to be used in speech synthesis. -/// -/// This class currently supports using a prebuilt voice configuration. -class VoiceConfig { - // ignore: public_member_api_docs - VoiceConfig({this.prebuiltVoiceConfig}); - - // ignore: public_member_api_docs - final PrebuiltVoiceConfig? prebuiltVoiceConfig; - // ignore: public_member_api_docs - Map toJson() => { - if (prebuiltVoiceConfig case final prebuiltVoiceConfig?) - 'prebuilt_voice_config': prebuiltVoiceConfig.toJson() - }; -} - -/// Configures speech synthesis settings. -/// -/// Allows specifying the desired voice and language for speech synthesis. -class SpeechConfig { - /// Creates a [SpeechConfig] instance. - /// - /// [voiceName] See https://cloud.google.com/text-to-speech/docs/chirp3-hd - /// for names and sound demos. - /// - /// [languageCode] The language code (BCP-47) for speech synthesis, - /// e.g. "en-US", "fr-FR", "de-DE". - SpeechConfig({String? voiceName, this.languageCode}) - : voiceConfig = voiceName != null - ? VoiceConfig( - prebuiltVoiceConfig: PrebuiltVoiceConfig(voiceName: voiceName)) - : null; - - /// The voice config to use for speech synthesis. - final VoiceConfig? voiceConfig; - - /// The language code (BCP-47) for speech synthesis, - /// e.g. "en-US", "fr-FR", "de-DE". - final String? languageCode; - - // ignore: public_member_api_docs - Map toJson() => { - if (voiceConfig case final voiceConfig?) - 'voice_config': voiceConfig.toJson(), - if (languageCode case final languageCode?) - 'language_code': languageCode, - }; -} - /// The audio transcription configuration. class AudioTranscriptionConfig { // ignore: public_member_api_docs @@ -168,7 +102,7 @@ class SessionResumptionConfig { final class LiveGenerationConfig extends BaseGenerationConfig { // ignore: public_member_api_docs LiveGenerationConfig( - {this.speechConfig, + {super.speechConfig, this.inputAudioTranscription, this.outputAudioTranscription, this.contextWindowCompression, @@ -181,9 +115,6 @@ final class LiveGenerationConfig extends BaseGenerationConfig { super.frequencyPenalty, super.mediaResolution}); - /// The speech configuration. - final SpeechConfig? speechConfig; - /// The transcription of the input aligns with the input audio language. final AudioTranscriptionConfig? inputAudioTranscription; @@ -197,8 +128,6 @@ final class LiveGenerationConfig extends BaseGenerationConfig { @override Map toJson() => { ...super.toJson(), - if (speechConfig case final speechConfig?) - 'speechConfig': speechConfig.toJson(), }; } diff --git a/packages/firebase_ai/firebase_ai/lib/src/speech_config.dart b/packages/firebase_ai/firebase_ai/lib/src/speech_config.dart new file mode 100644 index 000000000000..1196ac05b92a --- /dev/null +++ b/packages/firebase_ai/firebase_ai/lib/src/speech_config.dart @@ -0,0 +1,112 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'package:meta/meta.dart'; + +/// Speech configuration class for controlling the model's speech and audio generation behaviors. +class SpeechConfig { + /// Constructs a [SpeechConfig] for a single-speaker setup. + SpeechConfig({this.voiceName, this.languageCode}) + : multiSpeakerVoiceConfig = null; + + /// Constructs a [SpeechConfig] for a multi-speaker setup. + SpeechConfig.multiSpeaker( + {required this.multiSpeakerVoiceConfig, this.languageCode}) + : voiceName = null; + + /// The voice name to use for a single-speaker setup. + final String? voiceName; + + /// The multi-speaker configuration. + final MultiSpeakerVoiceConfig? multiSpeakerVoiceConfig; + + /// The optional IETF BCP-47 language code. + final String? languageCode; + + /// Convert to json format. + @internal + Map toJson() => { + if (voiceName != null) + 'voice_config': VoiceConfig( + prebuiltVoiceConfig: PrebuiltVoiceConfig(voiceName: voiceName), + ).toJson(), + if (multiSpeakerVoiceConfig case final multiSpeakerVoiceConfig?) + 'multi_speaker_voice_config': multiSpeakerVoiceConfig.toJson(), + if (languageCode case final languageCode?) + 'language_code': languageCode, + }; +} + +/// Configuration for a multi-speaker audio generation setup. +class MultiSpeakerVoiceConfig { + /// Constructor + MultiSpeakerVoiceConfig({required this.speakerVoiceConfigs}); + + /// A list of voice configurations for the participating speakers. + final List speakerVoiceConfigs; + + /// Convert to json format. + Map toJson() => { + 'speaker_voice_configs': + speakerVoiceConfigs.map((e) => e.toJson()).toList(), + }; +} + +/// Configures a participating speaker within a multi-speaker setup. +class SpeakerVoiceConfig { + /// Constructor + SpeakerVoiceConfig({required this.speaker, required this.voiceName}); + + /// The unique name/identifier of the speaker. + final String speaker; + + /// The specific voice assigned to this speaker. + final String voiceName; + + /// Convert to json format. + Map toJson() => { + 'speaker': speaker, + 'voice_config': VoiceConfig( + prebuiltVoiceConfig: PrebuiltVoiceConfig(voiceName: voiceName), + ).toJson(), + }; +} + +/// Configuration for a prebuilt voice. +class PrebuiltVoiceConfig { + /// Constructor + const PrebuiltVoiceConfig({this.voiceName}); + + /// The voice name to use for speech synthesis. + final String? voiceName; + + /// Convert to json format. + Map toJson() => + {if (voiceName case final voiceName?) 'voice_name': voiceName}; +} + +/// Configuration for the voice to be used in speech synthesis. +class VoiceConfig { + /// Constructor + VoiceConfig({this.prebuiltVoiceConfig}); + + /// The prebuilt voice configuration. + final PrebuiltVoiceConfig? prebuiltVoiceConfig; + + /// Convert to json format. + Map toJson() => { + if (prebuiltVoiceConfig case final prebuiltVoiceConfig?) + 'prebuilt_voice_config': prebuiltVoiceConfig.toJson() + }; +} diff --git a/packages/firebase_ai/firebase_ai/test/live_test.dart b/packages/firebase_ai/firebase_ai/test/live_test.dart index ed6f088aed4a..9965c59ca46b 100644 --- a/packages/firebase_ai/firebase_ai/test/live_test.dart +++ b/packages/firebase_ai/firebase_ai/test/live_test.dart @@ -18,6 +18,7 @@ import 'package:firebase_ai/src/api.dart'; import 'package:firebase_ai/src/content.dart'; import 'package:firebase_ai/src/error.dart'; import 'package:firebase_ai/src/live_api.dart'; +import 'package:firebase_ai/src/speech_config.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { @@ -50,6 +51,38 @@ void main() { }); }); + test('SpeechConfig.multiSpeaker toJson() returns correct JSON', () { + final multiSpeechConfig = SpeechConfig.multiSpeaker( + multiSpeakerVoiceConfig: MultiSpeakerVoiceConfig( + speakerVoiceConfigs: [ + SpeakerVoiceConfig(speaker: 'Joe', voiceName: 'Kore'), + SpeakerVoiceConfig(speaker: 'Jane', voiceName: 'Puck'), + ], + ), + languageCode: 'en-US', + ); + + expect(multiSpeechConfig.toJson(), { + 'multi_speaker_voice_config': { + 'speaker_voice_configs': [ + { + 'speaker': 'Joe', + 'voice_config': { + 'prebuilt_voice_config': {'voice_name': 'Kore'} + } + }, + { + 'speaker': 'Jane', + 'voice_config': { + 'prebuilt_voice_config': {'voice_name': 'Puck'} + } + } + ] + }, + 'language_code': 'en-US', + }); + }); + test('ResponseModalities enum toJson() returns correct value', () { expect(ResponseModalities.text.toJson(), 'TEXT'); expect(ResponseModalities.image.toJson(), 'IMAGE'); @@ -85,6 +118,47 @@ void main() { expect(liveGenerationConfigWithoutOptionals.toJson(), {}); }); + test('GenerationConfig with SpeechConfig toJson() returns correct JSON', + () { + final config = GenerationConfig( + speechConfig: SpeechConfig(voiceName: 'Aoede', languageCode: 'en-US'), + ); + + expect(config.toJson(), { + 'speechConfig': { + 'voice_config': { + 'prebuilt_voice_config': {'voice_name': 'Aoede'} + }, + 'language_code': 'en-US', + } + }); + + final multiConfig = GenerationConfig( + speechConfig: SpeechConfig.multiSpeaker( + multiSpeakerVoiceConfig: MultiSpeakerVoiceConfig( + speakerVoiceConfigs: [ + SpeakerVoiceConfig(speaker: 'Joe', voiceName: 'Kore'), + ], + ), + ), + ); + + expect(multiConfig.toJson(), { + 'speechConfig': { + 'multi_speaker_voice_config': { + 'speaker_voice_configs': [ + { + 'speaker': 'Joe', + 'voice_config': { + 'prebuilt_voice_config': {'voice_name': 'Kore'} + } + } + ] + } + } + }); + }); + test('SessionResumptionConfig toJson() returns correct JSON', () { final resumableConfig = SessionResumptionConfig(); expect(resumableConfig.toJson(), {}); From 27b190587d3b434a5f08c72cbedcafc88c86d9b9 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Fri, 12 Jun 2026 13:10:20 -0700 Subject: [PATCH 118/137] chore(firebaseai): improve a bit of the tts test page (#18362) * improve a bit of the tts test page * format --- .../example/lib/pages/tts_page.dart | 209 +++++++++++------- 1 file changed, 124 insertions(+), 85 deletions(-) diff --git a/packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart b/packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart index 06ba3a63a9a0..41b221c193c1 100644 --- a/packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart +++ b/packages/firebase_ai/firebase_ai/example/lib/pages/tts_page.dart @@ -51,14 +51,17 @@ class _TTSPageState extends State { String _selectedVoice = 'Kore'; // Multi Speaker Controllers - final TextEditingController _multiScriptController = TextEditingController( - text: "Joe: How's it going today Jane?\nJane: Not too bad, how about you?", - ); final TextEditingController _speaker1NameController = TextEditingController(text: 'Joe'); + final TextEditingController _speaker1LineController = TextEditingController( + text: "How's it going today Jane?", + ); String _speaker1Voice = 'Kore'; final TextEditingController _speaker2NameController = TextEditingController(text: 'Jane'); + final TextEditingController _speaker2LineController = TextEditingController( + text: 'Not too bad, how about you?', + ); String _speaker2Voice = 'Puck'; final List _availableVoices = [ @@ -85,9 +88,10 @@ class _TTSPageState extends State { _mockAmpGen.stop(); _playbackTimer?.cancel(); _singlePromptController.dispose(); - _multiScriptController.dispose(); _speaker1NameController.dispose(); + _speaker1LineController.dispose(); _speaker2NameController.dispose(); + _speaker2LineController.dispose(); super.dispose(); } @@ -124,7 +128,9 @@ class _TTSPageState extends State { final String prompt; if (_isMultiSpeaker) { - prompt = _multiScriptController.text; + prompt = + '${_speaker1NameController.text}: ${_speaker1LineController.text}\n' + '${_speaker2NameController.text}: ${_speaker2LineController.text}'; config = GenerationConfig( responseModalities: [ResponseModalities.audio], speechConfig: SpeechConfig.multiSpeaker( @@ -154,12 +160,10 @@ class _TTSPageState extends State { } // Use the preview model for TTS - final modelName = widget.useVertexBackend - ? 'gemini-2.5-flash-tts' - : 'gemini-3.1-flash-tts-preview'; + const modelName = 'gemini-3.1-flash-tts-preview'; final GenerativeModel model; if (widget.useVertexBackend) { - model = FirebaseAI.vertexAI(location: 'global').generativeModel( + model = FirebaseAI.vertexAI().generativeModel( model: modelName, generationConfig: config, ); @@ -268,93 +272,128 @@ class _TTSPageState extends State { ); } - Widget _buildMultiSpeakerForm() { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextField( - controller: _multiScriptController, - decoration: const InputDecoration( - labelText: 'Script', - hintText: 'Format: Name: text to say', - border: OutlineInputBorder(), - ), - maxLines: 5, + Widget _buildSpeakerCard({ + required String title, + required TextEditingController nameController, + required String selectedVoice, + required ValueChanged onVoiceChanged, + required TextEditingController lineController, + required Color accentColor, + }) { + return Card( + elevation: 2, + margin: const EdgeInsets.symmetric(vertical: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: accentColor.withAlpha(80), + width: 1.5, ), - const SizedBox(height: 16), - Row( + ), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: TextField( - controller: _speaker1NameController, - decoration: const InputDecoration( - labelText: 'Speaker 1 Name', - border: OutlineInputBorder(), + Row( + children: [ + Icon(Icons.person, color: accentColor), + const SizedBox(width: 8), + Text( + title, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + color: accentColor, + ), ), - ), + ], ), - const SizedBox(width: 8), - Expanded( - child: DropdownButtonFormField( - initialValue: _speaker1Voice, - decoration: const InputDecoration( - labelText: 'Speaker 1 Voice', - border: OutlineInputBorder(), + const SizedBox(height: 12), + Row( + children: [ + Expanded( + flex: 2, + child: TextField( + controller: nameController, + decoration: const InputDecoration( + labelText: 'Speaker Name', + prefixIcon: Icon(Icons.badge_outlined), + border: OutlineInputBorder(), + ), + ), ), - items: _availableVoices.map((voice) { - return DropdownMenuItem( - value: voice, - child: Text(voice), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - setState(() { - _speaker1Voice = value; - }); - } - }, - ), - ), - ], - ), - const SizedBox(height: 16), - Row( - children: [ - Expanded( - child: TextField( - controller: _speaker2NameController, - decoration: const InputDecoration( - labelText: 'Speaker 2 Name', - border: OutlineInputBorder(), + const SizedBox(width: 12), + Expanded( + flex: 3, + child: DropdownButtonFormField( + initialValue: selectedVoice, + decoration: const InputDecoration( + labelText: 'Voice Name', + prefixIcon: Icon(Icons.settings_voice_outlined), + border: OutlineInputBorder(), + ), + items: _availableVoices.map((voice) { + return DropdownMenuItem( + value: voice, + child: Text(voice), + ); + }).toList(), + onChanged: onVoiceChanged, + ), ), - ), + ], ), - const SizedBox(width: 8), - Expanded( - child: DropdownButtonFormField( - initialValue: _speaker2Voice, - decoration: const InputDecoration( - labelText: 'Speaker 2 Voice', - border: OutlineInputBorder(), - ), - items: _availableVoices.map((voice) { - return DropdownMenuItem( - value: voice, - child: Text(voice), - ); - }).toList(), - onChanged: (value) { - if (value != null) { - setState(() { - _speaker2Voice = value; - }); - } - }, + const SizedBox(height: 12), + TextField( + controller: lineController, + decoration: const InputDecoration( + labelText: 'Speech Line', + prefixIcon: Icon(Icons.chat_bubble_outline), + hintText: 'Enter what this speaker will say', + border: OutlineInputBorder(), ), + maxLines: 2, ), ], ), + ), + ); + } + + Widget _buildMultiSpeakerForm() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSpeakerCard( + title: 'Speaker 1', + nameController: _speaker1NameController, + selectedVoice: _speaker1Voice, + onVoiceChanged: (value) { + if (value != null) { + setState(() { + _speaker1Voice = value; + }); + } + }, + lineController: _speaker1LineController, + accentColor: Theme.of(context).colorScheme.primary, + ), + const SizedBox(height: 8), + _buildSpeakerCard( + title: 'Speaker 2', + nameController: _speaker2NameController, + selectedVoice: _speaker2Voice, + onVoiceChanged: (value) { + if (value != null) { + setState(() { + _speaker2Voice = value; + }); + } + }, + lineController: _speaker2LineController, + accentColor: Theme.of(context).colorScheme.secondary, + ), ], ); } From 673ba035c3eeca1de6294e41d930cca642c27a9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2026 12:29:51 +0000 Subject: [PATCH 119/137] chore(deps): bump @grpc/grpc-js (#18361) Bumps [@grpc/grpc-js](https://github.com/grpc/grpc-node) from 1.9.15 to 1.9.16. - [Release notes](https://github.com/grpc/grpc-node/releases) - [Commits](https://github.com/grpc/grpc-node/compare/@grpc/grpc-js@1.9.15...@grpc/grpc-js@1.9.16) --- updated-dependencies: - dependency-name: "@grpc/grpc-js" dependency-version: 1.9.16 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../example/bundled-service-worker/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock index 2b3d27d8e5b1..62c2cfc9c225 100644 --- a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock +++ b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock @@ -519,9 +519,9 @@ integrity sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw== "@grpc/grpc-js@~1.9.0": - version "1.9.15" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" - integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== + version "1.9.16" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.16.tgz#614f85036ac8e3c957374c1bd1ebb05934a79a1c" + integrity sha512-wE4Ut/olIzfKqp631XrG+wbF0v1vWFN4YL9FyXC2LJiG33DsV7PLzURjrCvY/6je2ntdRkeLpPDluzSRGaVltQ== dependencies: "@grpc/proto-loader" "^0.7.8" "@types/node" ">=12.12.47" From 11fca7a347c12e09cfa6dda45f1dfe0e1a936bde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2026 12:30:14 +0000 Subject: [PATCH 120/137] chore(deps-dev): bump esbuild (#18367) Bumps [esbuild](https://github.com/evanw/esbuild) from 0.25.0 to 0.28.1. - [Release notes](https://github.com/evanw/esbuild/releases) - [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG-2025.md) - [Commits](https://github.com/evanw/esbuild/compare/v0.25.0...v0.28.1) --- updated-dependencies: - dependency-name: esbuild dependency-version: 0.28.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../bundled-service-worker/package.json | 2 +- .../example/bundled-service-worker/yarn.lock | 312 +++++++++--------- 2 files changed, 160 insertions(+), 154 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/package.json b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/package.json index 3f3d3ce3102d..7905143e79e1 100644 --- a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/package.json +++ b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/package.json @@ -3,7 +3,7 @@ "firebase": "12" }, "devDependencies": { - "esbuild": "^0.25.0" + "esbuild": "^0.28.1" }, "scripts": { "build": "esbuild firebase-messaging-sw.ts --outdir=../web --bundle --sourcemap --minify --format=esm" diff --git a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock index 62c2cfc9c225..a4bb680fac03 100644 --- a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock +++ b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock @@ -2,130 +2,135 @@ # yarn lockfile v1 -"@esbuild/aix-ppc64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64" - integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ== - -"@esbuild/android-arm64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f" - integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g== - -"@esbuild/android-arm@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b" - integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g== - -"@esbuild/android-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163" - integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg== - -"@esbuild/darwin-arm64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c" - integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw== - -"@esbuild/darwin-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a" - integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg== - -"@esbuild/freebsd-arm64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce" - integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w== - -"@esbuild/freebsd-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7" - integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A== - -"@esbuild/linux-arm64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73" - integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg== - -"@esbuild/linux-arm@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3" - integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg== - -"@esbuild/linux-ia32@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19" - integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg== - -"@esbuild/linux-loong64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7" - integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw== - -"@esbuild/linux-mips64el@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1" - integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ== - -"@esbuild/linux-ppc64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951" - integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw== - -"@esbuild/linux-riscv64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987" - integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA== - -"@esbuild/linux-s390x@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4" - integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA== - -"@esbuild/linux-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a" - integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw== - -"@esbuild/netbsd-arm64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b" - integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw== - -"@esbuild/netbsd-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b" - integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA== - -"@esbuild/openbsd-arm64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7" - integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw== - -"@esbuild/openbsd-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde" - integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg== - -"@esbuild/sunos-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92" - integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg== - -"@esbuild/win32-arm64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c" - integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw== - -"@esbuild/win32-ia32@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079" - integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA== - -"@esbuild/win32-x64@0.25.0": - version "0.25.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b" - integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ== +"@esbuild/aix-ppc64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz#7a01a8d2ec2fbb2dac78adad09b0fa781e4082be" + integrity sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ== + +"@esbuild/android-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz#b540a27d14e4afd058496a4dbec4d3f414db110a" + integrity sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg== + +"@esbuild/android-arm@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz#704bd297de6d762de54eabbeafbf55f6756abe2f" + integrity sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ== + +"@esbuild/android-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz#d1cb166d34b0fbf0fe8ab460a5594f24a378701e" + integrity sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng== + +"@esbuild/darwin-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz#1034b26457fc886368fe61bbd09f653f6afa8e54" + integrity sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q== + +"@esbuild/darwin-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz#65556a432a1e4d72032d8218c1932fcca1a49772" + integrity sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ== + +"@esbuild/freebsd-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz#2e61e0592f9030d7e3dae18ee25ebc535918aef6" + integrity sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw== + +"@esbuild/freebsd-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz#c95ec289959ef8079c4dca817a1e2c4be66b9bd3" + integrity sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ== + +"@esbuild/linux-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz#40b22175dda06182f3ee8141186c5ff304c4a717" + integrity sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g== + +"@esbuild/linux-arm@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz#c09a0f67917592ac0de892a9be4d3814debd2a6c" + integrity sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ== + +"@esbuild/linux-ia32@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz#a580f9c676797833891e519fc7a1337c8afd8db3" + integrity sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w== + +"@esbuild/linux-loong64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz#46452cf321dc7f9e91c2fa780a56bb56e79cd68b" + integrity sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg== + +"@esbuild/linux-mips64el@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz#4211b3184dd6608f53dcb22e39f5d34ee08852c8" + integrity sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ== + +"@esbuild/linux-ppc64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz#697857c2a61cb9b0b6bb6652e40c1dc5e1ca8e5d" + integrity sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ== + +"@esbuild/linux-riscv64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz#d192943eb146a40ac4c6497d0cf7be35b986bf08" + integrity sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ== + +"@esbuild/linux-s390x@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz#acea0356da0e0ebc08f97cf7b9c2e401e1e648dc" + integrity sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag== + +"@esbuild/linux-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz#6f0c3ce0cb64c534b70c4c45ecb2c16d34e35dfd" + integrity sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA== + +"@esbuild/netbsd-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz#8bcd77077a0dce3378b574fedb26d2a253b73d36" + integrity sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw== + +"@esbuild/netbsd-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz#e7fb2a01e99c830c94e6623cd9fefb4c8fb58347" + integrity sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg== + +"@esbuild/openbsd-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz#c52909372db8b86e2c55e05a8940033b5660a3b2" + integrity sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q== + +"@esbuild/openbsd-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz#c427b9be5a64c262ff9a7eb70b5fbbaadf446c6c" + integrity sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw== + +"@esbuild/openharmony-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz#dc9b147baca2e6c4b3c85571741ef4860a489097" + integrity sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg== + +"@esbuild/sunos-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz#ce866d12df13c15e4c99f073a3d466f6e0649b3a" + integrity sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ== + +"@esbuild/win32-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz#7468e3692d01d629d5941e5d83817bb80f9e39b4" + integrity sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA== + +"@esbuild/win32-ia32@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz#a5bc0063fb2bcab6d0ed63f2a1537958bc269ec6" + integrity sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg== + +"@esbuild/win32-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz#10064ee44f4347b90c9a02b446bbf80a91632b12" + integrity sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A== "@firebase/ai@2.9.0": version "2.9.0" @@ -631,36 +636,37 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -esbuild@^0.25.0: - version "0.25.0" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" - integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw== +esbuild@^0.28.1: + version "0.28.1" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.1.tgz#ef45b4634c9c9d97a296aea4114a5f9840f95578" + integrity sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw== optionalDependencies: - "@esbuild/aix-ppc64" "0.25.0" - "@esbuild/android-arm" "0.25.0" - "@esbuild/android-arm64" "0.25.0" - "@esbuild/android-x64" "0.25.0" - "@esbuild/darwin-arm64" "0.25.0" - "@esbuild/darwin-x64" "0.25.0" - "@esbuild/freebsd-arm64" "0.25.0" - "@esbuild/freebsd-x64" "0.25.0" - "@esbuild/linux-arm" "0.25.0" - "@esbuild/linux-arm64" "0.25.0" - "@esbuild/linux-ia32" "0.25.0" - "@esbuild/linux-loong64" "0.25.0" - "@esbuild/linux-mips64el" "0.25.0" - "@esbuild/linux-ppc64" "0.25.0" - "@esbuild/linux-riscv64" "0.25.0" - "@esbuild/linux-s390x" "0.25.0" - "@esbuild/linux-x64" "0.25.0" - "@esbuild/netbsd-arm64" "0.25.0" - "@esbuild/netbsd-x64" "0.25.0" - "@esbuild/openbsd-arm64" "0.25.0" - "@esbuild/openbsd-x64" "0.25.0" - "@esbuild/sunos-x64" "0.25.0" - "@esbuild/win32-arm64" "0.25.0" - "@esbuild/win32-ia32" "0.25.0" - "@esbuild/win32-x64" "0.25.0" + "@esbuild/aix-ppc64" "0.28.1" + "@esbuild/android-arm" "0.28.1" + "@esbuild/android-arm64" "0.28.1" + "@esbuild/android-x64" "0.28.1" + "@esbuild/darwin-arm64" "0.28.1" + "@esbuild/darwin-x64" "0.28.1" + "@esbuild/freebsd-arm64" "0.28.1" + "@esbuild/freebsd-x64" "0.28.1" + "@esbuild/linux-arm" "0.28.1" + "@esbuild/linux-arm64" "0.28.1" + "@esbuild/linux-ia32" "0.28.1" + "@esbuild/linux-loong64" "0.28.1" + "@esbuild/linux-mips64el" "0.28.1" + "@esbuild/linux-ppc64" "0.28.1" + "@esbuild/linux-riscv64" "0.28.1" + "@esbuild/linux-s390x" "0.28.1" + "@esbuild/linux-x64" "0.28.1" + "@esbuild/netbsd-arm64" "0.28.1" + "@esbuild/netbsd-x64" "0.28.1" + "@esbuild/openbsd-arm64" "0.28.1" + "@esbuild/openbsd-x64" "0.28.1" + "@esbuild/openharmony-arm64" "0.28.1" + "@esbuild/sunos-x64" "0.28.1" + "@esbuild/win32-arm64" "0.28.1" + "@esbuild/win32-ia32" "0.28.1" + "@esbuild/win32-x64" "0.28.1" escalade@^3.1.1: version "3.1.1" From 1cd3a0bd76fd594139356519fabee0e0d2b12f31 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 17 Jun 2026 00:33:16 -0700 Subject: [PATCH 121/137] feat(core): bump Firebase android SDK to 34.15.0 (#18374) --- packages/firebase_core/firebase_core/android/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/android/gradle.properties b/packages/firebase_core/firebase_core/android/gradle.properties index 5bb4c09aee2f..afd66c21b0e2 100644 --- a/packages/firebase_core/firebase_core/android/gradle.properties +++ b/packages/firebase_core/firebase_core/android/gradle.properties @@ -1,2 +1,2 @@ # https://firebase.google.com/support/release-notes/android -FirebaseSDKVersion=34.14.0 +FirebaseSDKVersion=34.15.0 From 4d083764c3abd94d6e4590a170fbdaaa4b161202 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 17 Jun 2026 00:33:33 -0700 Subject: [PATCH 122/137] feat(core): bump Firebase ios SDK to 12.15.0 (#18375) --- .../firebase_core/firebase_core/ios/firebase_sdk_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb index ee689042b0d1..b4c1fd28f447 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb +++ b/packages/firebase_core/firebase_core/ios/firebase_sdk_version.rb @@ -1,4 +1,4 @@ # https://firebase.google.com/support/release-notes/ios def firebase_sdk_version!() - '12.14.0' + '12.15.0' end From 22eb4d5d0f3f14207e080e9c9fc8373052258ef4 Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 17 Jun 2026 00:33:48 -0700 Subject: [PATCH 123/137] feat(core): bump Firebase web SDK to 12.15.0 (#18376) --- .../firebase_core_web/lib/src/firebase_sdk_version.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart index c3eca6802c29..9da313efa4b7 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart @@ -6,4 +6,4 @@ part of '../firebase_core_web.dart'; /// The currently supported Firebase JS SDK version. -const String supportedFirebaseJsSdkVersion = '12.14.0'; +const String supportedFirebaseJsSdkVersion = '12.15.0'; From 036a860a0e66d46b5c57eb3df3a0f9e5846ef00b Mon Sep 17 00:00:00 2001 From: Cynthia J Date: Wed, 17 Jun 2026 00:34:54 -0700 Subject: [PATCH 124/137] feat(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) (#18261) * first commit for appcheck recaptcha support * update example * apple tentative implementation * add recaptcha in the plugin swift * minor fix * some dart fix * updated sample app UI * update api name and parameter * pigeon update * setup for web, need https://github.com/firebase/flutterfire/pull/18334 for e2e test * make the web work with default rCE provider * Add recaptcha sitekey from options to native sdk * add test for option recaptchaSiteKey * address code review * update the example UI * only make the new web provider const * some clean up in gradle * change the import of recaptcha from implementation to compileOnly * don't need appcheck example update for this PR * fix analyze and format (some) * not use compileOnly, but instead actually depend on appcheck-recaptcha * fix the format of pigeon generated files * bump Firebase android SDK to 34.15.0 * bump Firebase ios SDK to 12.15.0 * bump Firebase web SDK to 12.15.0 * update appcheck test app kotlin version * Add recaptcha dependency to flutter appcheck plugin --- .../firebase_app_check/android/build.gradle | 1 + .../appcheck/FirebaseAppCheckPlugin.kt | 5 + .../GeneratedAndroidFirebaseAppCheck.g.kt | 4 +- .../example/android/settings.gradle | 2 +- .../ios/firebase_app_check/Package.swift | 2 + .../FirebaseAppCheckMessages.g.swift | 82 +++--- .../FirebaseAppCheckPlugin.swift | 43 ++- .../lib/firebase_app_check.dart | 4 + .../firebase_app_check/windows/messages.g.cpp | 254 ++++++++++++++++-- .../firebase_app_check/windows/messages.g.h | 29 +- .../lib/src/android_providers.dart | 7 + .../lib/src/apple_providers.dart | 7 + .../lib/src/pigeon/messages.pigeon.dart | 175 ++++++------ .../lib/src/web_providers.dart | 7 +- ...ethod_channel_firebase_app_check_test.dart | 56 ++++ .../lib/firebase_app_check_web.dart | 5 + .../lib/src/interop/app_check.dart | 6 +- .../lib/src/interop/app_check_interop.dart | 4 +- .../test/firebase_app_check_web_test.dart | 13 + .../core/FlutterFirebaseCorePlugin.java | 7 +- .../firebase_core/FLTFirebaseCorePlugin.m | 6 +- .../method_channel_firebase.dart | 2 + .../test/firebase_options_test.dart | 2 + .../lib/firebase_core_web.dart | 22 +- .../lib/src/firebase_core_web.dart | 4 +- .../lib/src/interop/core.dart | 2 + .../lib/src/interop/core_interop.dart | 3 + .../firebase_core/firebase_core_e2e_test.dart | 31 +++ 28 files changed, 571 insertions(+), 214 deletions(-) diff --git a/packages/firebase_app_check/firebase_app_check/android/build.gradle b/packages/firebase_app_check/firebase_app_check/android/build.gradle index d4fdbc15fca9..cc7c342a5ca7 100644 --- a/packages/firebase_app_check/firebase_app_check/android/build.gradle +++ b/packages/firebase_app_check/firebase_app_check/android/build.gradle @@ -78,6 +78,7 @@ android { implementation platform("com.google.firebase:firebase-bom:${getRootProjectExtOrCoreProperty("FirebaseSDKVersion", firebaseCoreProject)}") implementation 'com.google.firebase:firebase-appcheck-debug' implementation 'com.google.firebase:firebase-appcheck-playintegrity' + implementation 'com.google.firebase:firebase-appcheck-recaptcha' implementation 'androidx.annotation:annotation:1.7.0' } } diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt index cdf1ca77a6ea..99aab95ea256 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/FirebaseAppCheckPlugin.kt @@ -11,6 +11,7 @@ import com.google.firebase.FirebaseApp import com.google.firebase.appcheck.FirebaseAppCheck import com.google.firebase.appcheck.debug.DebugAppCheckProviderFactory import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory +import com.google.firebase.appcheck.recaptcha.RecaptchaAppCheckProviderFactory import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.BinaryMessenger @@ -62,6 +63,10 @@ class FirebaseAppCheckPlugin : FlutterFirebasePlugin, FlutterPlugin, FirebaseApp firebaseAppCheck.installAppCheckProviderFactory( DebugAppCheckProviderFactory.getInstance()) } + "recaptcha" -> { + firebaseAppCheck.installAppCheckProviderFactory( + RecaptchaAppCheckProviderFactory.getInstance()) + } else -> { firebaseAppCheck.installAppCheckProviderFactory( PlayIntegrityAppCheckProviderFactory.getInstance()) diff --git a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt index 5e3ea8faca0c..4cd7a39bc1b4 100644 --- a/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt +++ b/packages/firebase_app_check/firebase_app_check/android/src/main/kotlin/io/flutter/plugins/firebase/appcheck/GeneratedAndroidFirebaseAppCheck.g.kt @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -44,7 +44,7 @@ class FlutterError( val code: String, override val message: String? = null, val details: Any? = null -) : Throwable() +) : RuntimeException() private open class GeneratedAndroidFirebaseAppCheckPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { diff --git a/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle b/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle index 30463c1cf2f2..4fb566e9929e 100644 --- a/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle +++ b/packages/firebase_app_check/firebase_app_check/example/android/settings.gradle @@ -22,7 +22,7 @@ plugins { // START: FlutterFire Configuration id "com.google.gms.google-services" version "4.3.15" apply false // END: FlutterFire Configuration - id "org.jetbrains.kotlin.android" version "1.9.22" apply false + id "org.jetbrains.kotlin.android" version "2.1.0" apply false } include ":app" diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index 8b543e4b1358..c61c10b252e1 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -19,6 +19,7 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), + .package(url: "https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk.git", from: "18.0.0"), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ @@ -26,6 +27,7 @@ let package = Package( name: "firebase_app_check", dependencies: [ .product(name: "FirebaseAppCheck", package: "firebase-ios-sdk"), + .product(name: "RecaptchaEnterprise", package: "recaptcha-enterprise-mobile-sdk"), .product(name: "firebase-core", package: "firebase_core"), ], resources: [ diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift index 57e0accedf53..cc94a926d933 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -27,12 +27,13 @@ final class PigeonError: Error { } var localizedDescription: String { - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" } } private func wrapResult(_ result: Any?) -> [Any?] { - [result] + return [result] } private func wrapError(_ error: Any) -> [Any?] { @@ -52,13 +53,13 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } private func isNullish(_ value: Any?) -> Bool { - value is NSNull || value == nil + return value is NSNull || value == nil } private func nilOrValue(_ value: Any?) -> T? { @@ -66,52 +67,46 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } -private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader {} +private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader { +} -private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter {} +private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter { +} private class FirebaseAppCheckMessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { override func reader(with data: Data) -> FlutterStandardReader { - FirebaseAppCheckMessagesPigeonCodecReader(data: data) + return FirebaseAppCheckMessagesPigeonCodecReader(data: data) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - FirebaseAppCheckMessagesPigeonCodecWriter(data: data) + return FirebaseAppCheckMessagesPigeonCodecWriter(data: data) } } class FirebaseAppCheckMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = - FirebaseAppCheckMessagesPigeonCodec( - readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter() - ) + static let shared = FirebaseAppCheckMessagesPigeonCodec( + readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter()) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseAppCheckHostApi { func activate( - appName: String, androidProvider: String?, appleProvider: String?, - debugToken: String?, completion: @escaping (Result) -> Void) + appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, + completion: @escaping (Result) -> Void) func getToken( - appName: String, forceRefresh: Bool, - completion: @escaping (Result) -> Void) + appName: String, forceRefresh: Bool, completion: @escaping (Result) -> Void) func setTokenAutoRefreshEnabled( appName: String, isTokenAutoRefreshEnabled: Bool, completion: @escaping (Result) -> Void) func registerTokenListener(appName: String, completion: @escaping (Result) -> Void) func getLimitedUseAppCheckToken( - appName: String, - completion: @escaping (Result) -> Void) + appName: String, completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class FirebaseAppCheckHostApiSetup { - static var codec: FlutterStandardMessageCodec { - FirebaseAppCheckMessagesPigeonCodec.shared - } - - /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the - /// `binaryMessenger`. + static var codec: FlutterStandardMessageCodec { FirebaseAppCheckMessagesPigeonCodec.shared } + /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binaryMessenger`. static func setUp( binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppCheckHostApi?, messageChannelSuffix: String = "" @@ -120,10 +115,8 @@ class FirebaseAppCheckHostApiSetup { let activateChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { activateChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String @@ -131,9 +124,7 @@ class FirebaseAppCheckHostApiSetup { let appleProviderArg: String? = nilOrValue(args[2]) let debugTokenArg: String? = nilOrValue(args[3]) api.activate( - appName: appNameArg, - androidProvider: androidProviderArg, - appleProvider: appleProviderArg, + appName: appNameArg, androidProvider: androidProviderArg, appleProvider: appleProviderArg, debugToken: debugTokenArg ) { result in switch result { @@ -150,10 +141,8 @@ class FirebaseAppCheckHostApiSetup { let getTokenChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { getTokenChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String @@ -173,17 +162,14 @@ class FirebaseAppCheckHostApiSetup { let setTokenAutoRefreshEnabledChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { setTokenAutoRefreshEnabledChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String let isTokenAutoRefreshEnabledArg = args[1] as! Bool api.setTokenAutoRefreshEnabled( - appName: appNameArg, - isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabledArg + appName: appNameArg, isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabledArg ) { result in switch result { case .success: @@ -199,10 +185,8 @@ class FirebaseAppCheckHostApiSetup { let registerTokenListenerChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { registerTokenListenerChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String @@ -221,10 +205,8 @@ class FirebaseAppCheckHostApiSetup { let getLimitedUseAppCheckTokenChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken\(channelSuffix)", - binaryMessenger: binaryMessenger, - codec: codec - ) - if let api { + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { getLimitedUseAppCheckTokenChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift index c737dcd75a22..2d63a7652e18 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckPlugin.swift @@ -79,7 +79,11 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, } let provider = appleProvider ?? "deviceCheck" - providerFactory?.configure(app: app, providerName: provider, debugToken: debugToken) + providerFactory?.configure( + app: app, + providerName: provider, + debugToken: debugToken + ) completion(.success(())) } @@ -192,7 +196,7 @@ public class FirebaseAppCheckPlugin: NSObject, FlutterPlugin, channel.setStreamHandler(nil) } for (_, handler) in streamHandlers { - handler.onCancel(withArguments: nil) + _ = handler.onCancel(withArguments: nil) } eventChannels.removeAll() streamHandlers.removeAll() @@ -277,24 +281,40 @@ class FlutterAppCheckProviderFactory: NSObject, AppCheckProviderFactory { if providers[app.name] == nil { let wrapper = AppCheckProviderWrapper() // Default to deviceCheck. activate() will reconfigure with the correct provider. - wrapper.configure(app: app, providerName: "deviceCheck", debugToken: nil) + wrapper.configure( + app: app, + providerName: "deviceCheck", + debugToken: nil + ) providers[app.name] = wrapper } return providers[app.name] } - func configure(app: FirebaseApp, providerName: String, debugToken: String?) { + func configure( + app: FirebaseApp, + providerName: String, + debugToken: String? + ) { if providers[app.name] == nil { providers[app.name] = AppCheckProviderWrapper() } - providers[app.name]?.configure(app: app, providerName: providerName, debugToken: debugToken) + providers[app.name]?.configure( + app: app, + providerName: providerName, + debugToken: debugToken + ) } } class AppCheckProviderWrapper: NSObject, AppCheckProvider { private var delegateProvider: (any AppCheckProvider)? - func configure(app: FirebaseApp, providerName: String, debugToken: String?) { + func configure( + app: FirebaseApp, + providerName: String, + debugToken: String? + ) { switch providerName { case "debug": if let debugToken { @@ -316,6 +336,17 @@ class AppCheckProviderWrapper: NSObject, AppCheckProvider { } else { delegateProvider = DeviceCheckProvider(app: app) } + case "recaptcha": + #if os(iOS) + delegateProvider = RecaptchaProvider(app: app) + if delegateProvider == nil { + print( + "Firebase App Check: failed to initialize RecaptchaProvider. Ensure site key is in GoogleService-Info.plist." + ) + } + #else + print("Firebase App Check: reCAPTCHA is only supported on iOS.") + #endif default: // deviceCheck delegateProvider = DeviceCheckProvider(app: app) diff --git a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart index cd569468c12c..5e6a8cc98b81 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/firebase_app_check.dart @@ -13,15 +13,19 @@ export 'package:firebase_app_check_platform_interface/firebase_app_check_platfor AndroidAppCheckProvider, AndroidDebugProvider, AndroidPlayIntegrityProvider, + AndroidReCaptchaProvider, AppleProvider, AppleAppCheckProvider, AppleDebugProvider, AppleDeviceCheckProvider, AppleAppAttestProvider, AppleAppAttestWithDeviceCheckFallbackProvider, + AppleReCaptchaProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, WebDebugProvider, + WebProvider, + WebReCaptchaProvider, WindowsAppCheckProvider, WindowsDebugProvider; export 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp index 0343b73ea815..0da3e3c1ded5 100644 --- a/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.cpp @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #undef _HAS_EXCEPTIONS @@ -13,16 +13,18 @@ #include #include +#include +#include #include #include #include namespace firebase_app_check_windows { -using flutter::BasicMessageChannel; -using flutter::CustomEncodableValue; -using flutter::EncodableList; -using flutter::EncodableMap; -using flutter::EncodableValue; +using ::flutter::BasicMessageChannel; +using ::flutter::CustomEncodableValue; +using ::flutter::EncodableList; +using ::flutter::EncodableMap; +using ::flutter::EncodableValue; FlutterError CreateConnectionError(const std::string channel_name) { return FlutterError( @@ -31,34 +33,242 @@ FlutterError CreateConnectionError(const std::string channel_name) { EncodableValue("")); } +namespace { +template +bool PigeonInternalDeepEquals(const T& a, const T& b); + +bool PigeonInternalDeepEquals(const double& a, const double& b); + +template +bool PigeonInternalDeepEquals(const std::vector& a, const std::vector& b); + +template +bool PigeonInternalDeepEquals(const std::map& a, const std::map& b); + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b); + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b); + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b); + +template +bool PigeonInternalDeepEquals(const T& a, const T& b) { + return a == b; +} + +template +bool PigeonInternalDeepEquals(const std::vector& a, + const std::vector& b) { + if (a.size() != b.size()) { + return false; + } + for (size_t i = 0; i < a.size(); ++i) { + if (!PigeonInternalDeepEquals(a[i], b[i])) { + return false; + } + } + return true; +} + +template +bool PigeonInternalDeepEquals(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& kv : a) { + bool found = false; + for (const auto& b_kv : b) { + if (PigeonInternalDeepEquals(kv.first, b_kv.first)) { + if (PigeonInternalDeepEquals(kv.second, b_kv.second)) { + found = true; + break; + } else { + return false; + } + } + } + if (!found) { + return false; + } + } + return true; +} + +bool PigeonInternalDeepEquals(const double& a, const double& b) { + // Normalize -0.0 to 0.0 and handle NaN equality. + return (a == b) || (std::isnan(a) && std::isnan(b)); +} + +template +bool PigeonInternalDeepEquals(const std::optional& a, + const std::optional& b) { + if (!a && !b) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +template +bool PigeonInternalDeepEquals(const std::unique_ptr& a, + const std::unique_ptr& b) { + if (a.get() == b.get()) { + return true; + } + if (!a || !b) { + return false; + } + return PigeonInternalDeepEquals(*a, *b); +} + +bool PigeonInternalDeepEquals(const ::flutter::EncodableValue& a, + const ::flutter::EncodableValue& b) { + if (a.index() != b.index()) { + return false; + } + if (const double* da = std::get_if(&a)) { + return PigeonInternalDeepEquals(*da, std::get(b)); + } else if (const ::flutter::EncodableList* la = + std::get_if<::flutter::EncodableList>(&a)) { + return PigeonInternalDeepEquals(*la, std::get<::flutter::EncodableList>(b)); + } else if (const ::flutter::EncodableMap* ma = + std::get_if<::flutter::EncodableMap>(&a)) { + return PigeonInternalDeepEquals(*ma, std::get<::flutter::EncodableMap>(b)); + } + return a == b; +} + +template +size_t PigeonInternalDeepHash(const T& v); + +size_t PigeonInternalDeepHash(const double& v); + +template +size_t PigeonInternalDeepHash(const std::vector& v); + +template +size_t PigeonInternalDeepHash(const std::map& v); + +template +size_t PigeonInternalDeepHash(const std::optional& v); + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v); + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v); + +template +size_t PigeonInternalDeepHash(const T& v) { + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::vector& v) { + size_t result = 1; + for (const auto& item : v) { + result = result * 31 + PigeonInternalDeepHash(item); + } + return result; +} + +template +size_t PigeonInternalDeepHash(const std::map& v) { + size_t result = 0; + for (const auto& kv : v) { + result += ((PigeonInternalDeepHash(kv.first) * 31) ^ + PigeonInternalDeepHash(kv.second)); + } + return result; +} + +size_t PigeonInternalDeepHash(const double& v) { + if (std::isnan(v)) { + // Normalize NaN to a consistent hash. + return std::hash()(std::numeric_limits::quiet_NaN()); + } + if (v == 0.0) { + // Normalize -0.0 to 0.0 so they have the same hash code. + return std::hash()(0.0); + } + return std::hash()(v); +} + +template +size_t PigeonInternalDeepHash(const std::optional& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +template +size_t PigeonInternalDeepHash(const std::unique_ptr& v) { + return v ? PigeonInternalDeepHash(*v) : 0; +} + +size_t PigeonInternalDeepHash(const ::flutter::EncodableValue& v) { + size_t result = v.index(); + if (const double* dv = std::get_if(&v)) { + result = result * 31 + PigeonInternalDeepHash(*dv); + } else if (const ::flutter::EncodableList* lv = + std::get_if<::flutter::EncodableList>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*lv); + } else if (const ::flutter::EncodableMap* mv = + std::get_if<::flutter::EncodableMap>(&v)) { + result = result * 31 + PigeonInternalDeepHash(*mv); + } else { + std::visit( + [&result](const auto& val) { + using T = std::decay_t; + if constexpr (!std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v && + !std::is_same_v) { + result = result * 31 + PigeonInternalDeepHash(val); + } + }, + v); + } + return result; +} + +} // namespace + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const { - return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + uint8_t type, ::flutter::ByteStreamReader* stream) const { + return ::flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } void PigeonInternalCodecSerializer::WriteValue( - const EncodableValue& value, flutter::ByteStreamWriter* stream) const { - flutter::StandardCodecSerializer::WriteValue(value, stream); + const EncodableValue& value, ::flutter::ByteStreamWriter* stream) const { + ::flutter::StandardCodecSerializer::WriteValue(value, stream); } /// The codec used by FirebaseAppCheckHostApi. -const flutter::StandardMessageCodec& FirebaseAppCheckHostApi::GetCodec() { - return flutter::StandardMessageCodec::GetInstance( +const ::flutter::StandardMessageCodec& FirebaseAppCheckHostApi::GetCodec() { + return ::flutter::StandardMessageCodec::GetInstance( &PigeonInternalCodecSerializer::GetInstance()); } // Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through // the `binary_messenger`. -void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api) { +void FirebaseAppCheckHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, + FirebaseAppCheckHostApi* api) { FirebaseAppCheckHostApi::SetUp(binary_messenger, api, ""); } -void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, - FirebaseAppCheckHostApi* api, - const std::string& message_channel_suffix) { +void FirebaseAppCheckHostApi::SetUp( + ::flutter::BinaryMessenger* binary_messenger, FirebaseAppCheckHostApi* api, + const std::string& message_channel_suffix) { const std::string prepended_suffix = message_channel_suffix.length() > 0 ? std::string(".") + message_channel_suffix @@ -73,7 +283,7 @@ void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -121,7 +331,7 @@ void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -173,7 +383,7 @@ void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -221,7 +431,7 @@ void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); @@ -260,7 +470,7 @@ void FirebaseAppCheckHostApi::SetUp(flutter::BinaryMessenger* binary_messenger, if (api != nullptr) { channel.SetMessageHandler( [api](const EncodableValue& message, - const flutter::MessageReply& reply) { + const ::flutter::MessageReply& reply) { try { const auto& args = std::get(message); const auto& encodable_app_name_arg = args.at(0); diff --git a/packages/firebase_app_check/firebase_app_check/windows/messages.g.h b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h index c56d71862604..50ae482963dc 100644 --- a/packages/firebase_app_check/firebase_app_check/windows/messages.g.h +++ b/packages/firebase_app_check/firebase_app_check/windows/messages.g.h @@ -1,7 +1,7 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon #ifndef PIGEON_MESSAGES_G_H_ @@ -25,17 +25,17 @@ class FlutterError { explicit FlutterError(const std::string& code, const std::string& message) : code_(code), message_(message) {} explicit FlutterError(const std::string& code, const std::string& message, - const flutter::EncodableValue& details) + const ::flutter::EncodableValue& details) : code_(code), message_(message), details_(details) {} const std::string& code() const { return code_; } const std::string& message() const { return message_; } - const flutter::EncodableValue& details() const { return details_; } + const ::flutter::EncodableValue& details() const { return details_; } private: std::string code_; std::string message_; - flutter::EncodableValue details_; + ::flutter::EncodableValue details_; }; template @@ -58,7 +58,8 @@ class ErrorOr { std::variant v_; }; -class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { +class PigeonInternalCodecSerializer + : public ::flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); inline static PigeonInternalCodecSerializer& GetInstance() { @@ -66,12 +67,12 @@ class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { return sInstance; } - void WriteValue(const flutter::EncodableValue& value, - flutter::ByteStreamWriter* stream) const override; + void WriteValue(const ::flutter::EncodableValue& value, + ::flutter::ByteStreamWriter* stream) const override; protected: - flutter::EncodableValue ReadValueOfType( - uint8_t type, flutter::ByteStreamReader* stream) const override; + ::flutter::EncodableValue ReadValueOfType( + uint8_t type, ::flutter::ByteStreamReader* stream) const override; }; // Generated interface from Pigeon that represents a handler of messages from @@ -100,16 +101,16 @@ class FirebaseAppCheckHostApi { std::function reply)> result) = 0; // The codec used by FirebaseAppCheckHostApi. - static const flutter::StandardMessageCodec& GetCodec(); + static const ::flutter::StandardMessageCodec& GetCodec(); // Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through // the `binary_messenger`. - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAppCheckHostApi* api); - static void SetUp(flutter::BinaryMessenger* binary_messenger, + static void SetUp(::flutter::BinaryMessenger* binary_messenger, FirebaseAppCheckHostApi* api, const std::string& message_channel_suffix); - static flutter::EncodableValue WrapError(std::string_view error_message); - static flutter::EncodableValue WrapError(const FlutterError& error); + static ::flutter::EncodableValue WrapError(std::string_view error_message); + static ::flutter::EncodableValue WrapError(const FlutterError& error); protected: FirebaseAppCheckHostApi() = default; diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart index c827b3184022..47640028475a 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/android_providers.dart @@ -32,3 +32,10 @@ class AndroidDebugProvider extends AndroidAppCheckProvider { class AndroidPlayIntegrityProvider extends AndroidAppCheckProvider { const AndroidPlayIntegrityProvider() : super('playIntegrity'); } + +/// reCAPTCHA provider for Android. +/// +/// The site key is retrieved automatically from google-services.json. +class AndroidReCaptchaProvider extends AndroidAppCheckProvider { + const AndroidReCaptchaProvider() : super('recaptcha'); +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart index 5e6af1ce2359..e768fca29477 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/apple_providers.dart @@ -54,3 +54,10 @@ class AppleAppAttestWithDeviceCheckFallbackProvider const AppleAppAttestWithDeviceCheckFallbackProvider() : super('appAttestWithDeviceCheckFallback'); } + +/// reCAPTCHA provider for Apple platforms. +/// +/// The site key is retrieved automatically from GoogleService-Info.plist. +class AppleReCaptchaProvider extends AppleAppCheckProvider { + const AppleReCaptchaProvider() : super('recaptcha'); +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart index 8916928599ce..ca154bea1029 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/pigeon/messages.pigeon.dart @@ -1,21 +1,40 @@ // Copyright 2025, the Chromium project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// Autogenerated from Pigeon (v25.3.2), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } class _PigeonCodec extends StandardMessageCodec { @@ -56,143 +75,101 @@ class FirebaseAppCheckHostApi { Future activate(String appName, String? androidProvider, String? appleProvider, String? debugToken) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel .send([appName, androidProvider, appleProvider, debugToken]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future getToken(String appName, bool forceRefresh) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, forceRefresh]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as String?); - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); + return pigeonVar_replyValue as String?; } Future setTokenAutoRefreshEnabled( String appName, bool isTokenAutoRefreshEnabled) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName, isTokenAutoRefreshEnabled]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } Future registerTokenListener(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as String?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } Future getLimitedUseAppCheckToken(String appName) async { - final String pigeonVar_channelName = + final pigeonVar_channelName = 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = pigeonVar_channel.send([appName]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as String?)!; - } + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as String; } } diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/web_providers.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/web_providers.dart index 55d5ab576c7e..6d4a59844cd4 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/web_providers.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/lib/src/web_providers.dart @@ -5,7 +5,7 @@ abstract class WebProvider { final String siteKey; - WebProvider(this.siteKey); + const WebProvider(this.siteKey); } class ReCaptchaV3Provider extends WebProvider { @@ -31,3 +31,8 @@ class WebDebugProvider extends WebProvider { /// The debug token for this provider. final String? debugToken; } + +/// reCAPTCHA Enterprise provider for Web that does not use the enterprise name and does not take in a siteKey. +class WebReCaptchaProvider extends WebProvider { + const WebReCaptchaProvider() : super(''); +} diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart index 0839886ba264..7c60c253ff3d 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/test/method_channel_tests/method_channel_firebase_app_check_test.dart @@ -7,6 +7,7 @@ import 'package:firebase_app_check_platform_interface/src/pigeon/messages.pigeon import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter/services.dart'; import '../mock.dart'; @@ -121,5 +122,60 @@ void main() { expect(calls.single[3], 'android-debug-token'); }); }); + + group('activate() with Recaptcha', () { + test('passes recaptcha on Android', () async { + final appCheck = MethodChannelFirebaseAppCheck(app: Firebase.app()); + + final List log = []; + + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', + (message) async { + final list = const StandardMessageCodec().decodeMessage(message) + as List; + log.add(list); + return const StandardMessageCodec() + .encodeMessage([null]); // Return success + }, + ); + + await appCheck.activate( + providerAndroid: const AndroidReCaptchaProvider(), + ); + + expect(log.length, 1); + expect(log[0][0], '[DEFAULT]'); // appName + expect(log[0][1], 'recaptcha'); // androidProvider + }); + + test('passes recaptcha on iOS', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + final appCheck = MethodChannelFirebaseAppCheck(app: Firebase.app()); + + final List log = []; + + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler( + 'dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate', + (message) async { + final list = const StandardMessageCodec().decodeMessage(message) + as List; + log.add(list); + return const StandardMessageCodec() + .encodeMessage([null]); // Return success + }, + ); + + await appCheck.activate( + providerApple: const AppleReCaptchaProvider(), + ); + + expect(log.length, 1); + expect(log[0][0], '[DEFAULT]'); // appName + expect(log[0][2], 'recaptcha'); // appleProvider + }); + }); }); } diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart b/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart index cfb4a24e9ce0..f4cd415164c8 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/firebase_app_check_web.dart @@ -23,6 +23,7 @@ class FirebaseAppCheckWeb extends FirebaseAppCheckPlatform { static const recaptchaTypeV3 = 'recaptcha-v3'; static const recaptchaTypeEnterprise = 'enterprise'; static const recaptchaTypeDebug = 'debug'; + static const recaptchaTypeWebRecaptcha = 'web-recaptcha'; static Map> _tokenChangesListeners = {}; /// Stub initializer to allow the [registerWith] to create an instance without @@ -63,6 +64,8 @@ class FirebaseAppCheckWeb extends FirebaseAppCheckPlatform { final debugToken = recaptchaSiteKey?.isNotEmpty ?? false ? recaptchaSiteKey : null; provider = WebDebugProvider(debugToken: debugToken); + } else if (recaptchaType == recaptchaTypeWebRecaptcha) { + provider = const WebReCaptchaProvider(); } else if (recaptchaSiteKey != null) { if (recaptchaType == recaptchaTypeV3) { provider = ReCaptchaV3Provider(recaptchaSiteKey); @@ -143,6 +146,8 @@ class FirebaseAppCheckWeb extends FirebaseAppCheckPlatform { recaptchaType = recaptchaTypeV3; } else if (webProvider is ReCaptchaEnterpriseProvider) { recaptchaType = recaptchaTypeEnterprise; + } else if (webProvider is WebReCaptchaProvider) { + recaptchaType = recaptchaTypeWebRecaptcha; } else { throw Exception('Invalid web provider: $webProvider'); } diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check.dart b/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check.dart index c35a5d1d8d16..a3d2b896e96b 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check.dart @@ -16,9 +16,11 @@ export 'app_check_interop.dart'; /// Given an AppJSImp, return the AppCheck instance. AppCheck? getAppCheckInstance([App? app, WebProvider? provider]) { - late app_check_interop.ReCaptchaProvider jsProvider; + app_check_interop.ReCaptchaProvider? jsProvider; - if (provider is WebDebugProvider) { + if (provider == null || provider is WebReCaptchaProvider) { + jsProvider = null; + } else if (provider is WebDebugProvider) { // Set the debug token global before initializing App Check. // The Firebase JS SDK reads this and creates a DebugProvider internally. if (provider.debugToken != null) { diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check_interop.dart b/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check_interop.dart index a72b2cf0c2a4..1afb3a69b181 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check_interop.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/src/interop/app_check_interop.dart @@ -74,14 +74,14 @@ extension type AppCheckTokenResultJsImpl._(JSObject _) implements JSObject { class AppCheckOptions { external factory AppCheckOptions({ JSBoolean? isTokenAutoRefreshEnabled, - ReCaptchaProvider provider, + ReCaptchaProvider? provider, }); } extension AppCheckOptionsJsImplX on AppCheckOptions { external JSBoolean? get isTokenAutoRefreshEnabled; - external ReCaptchaProvider get provider; + external ReCaptchaProvider? get provider; } extension type AppCheckJsImpl._(JSObject _) implements JSObject { diff --git a/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.dart b/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.dart index dd91f9bde80a..f549b3419891 100644 --- a/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.dart +++ b/packages/firebase_app_check/firebase_app_check_web/test/firebase_app_check_web_test.dart @@ -58,6 +58,19 @@ void main() { verifyNoMoreInteractions(appCheck); }); + test('activate with WebReCaptchaProvider', () async { + const provider = WebReCaptchaProvider(); + await appCheck.activate( + webProvider: provider, + ); + verify( + appCheck.activate( + webProvider: provider, + ), + ); + verifyNoMoreInteractions(appCheck); + }); + test('getToken', () async { await appCheck.getToken(true); verify(appCheck.getToken(true)); diff --git a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java index fcdeb2a7f5ac..0714b3bf7676 100644 --- a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java +++ b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java @@ -63,7 +63,9 @@ private GeneratedAndroidFirebaseCore.CoreFirebaseOptions firebaseOptionsToMap( firebaseOptions.setDatabaseURL(options.getDatabaseUrl()); firebaseOptions.setStorageBucket(options.getStorageBucket()); firebaseOptions.setTrackingId(options.getGaTrackingId()); - // TODO(recaptchaSiteKey): Map recaptchaSiteKey if stored. + if (options.getRecaptchaSiteKey() != null) { + firebaseOptions.setRecaptchaSiteKey(options.getRecaptchaSiteKey()); + } return firebaseOptions.build(); } @@ -150,6 +152,7 @@ public void initializeApp( .setProjectId(initializeAppRequest.getProjectId()) .setStorageBucket(initializeAppRequest.getStorageBucket()) .setGaTrackingId(initializeAppRequest.getTrackingId()) + .setRecaptchaSiteKey(initializeAppRequest.getRecaptchaSiteKey()) .build(); // TODO(Salakar) hacky workaround a bug with FirebaseInAppMessaging causing the error: // Can't create handler inside thread Thread[pool-3-thread-1,5,main] that has not @@ -166,8 +169,6 @@ public void initializeApp( customAuthDomain.put(appName, initializeAppRequest.getAuthDomain()); } - // TODO(recaptchaSiteKey): Store or use recaptchaSiteKey if needed. - FirebaseApp firebaseApp = FirebaseApp.initializeApp(applicationContext, options, appName); taskCompletionSource.setResult(Tasks.await(firebaseAppToMap(firebaseApp))); diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m index b68d963b08c7..0b713b7c9f80 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m @@ -93,7 +93,7 @@ - (CoreFirebaseOptions *)optionsFromFIROptions:(FIROptions *)options { pigeonOptions.iosBundleId = (id)options.bundleID ?: [NSNull null]; pigeonOptions.iosClientId = (id)options.clientID ?: [NSNull null]; pigeonOptions.appGroupId = (id)options.appGroupID ?: [NSNull null]; - // TODO(recaptchaSiteKey): Map recaptchaSiteKey if stored. + pigeonOptions.recaptchaSiteKey = (id)options.recaptchaSiteKey ?: [NSNull null]; return pigeonOptions; } @@ -179,7 +179,9 @@ - (void)initializeAppAppName:(nonnull NSString *)appName options.appGroupID = initializeAppRequest.appGroupId; } - // TODO(recaptchaSiteKey): Store or use recaptchaSiteKey if needed. + if (![initializeAppRequest.recaptchaSiteKey isEqual:[NSNull null]]) { + options.recaptchaSiteKey = initializeAppRequest.recaptchaSiteKey; + } if (initializeAppRequest.authDomain != nil) { customAuthDomains[appNameIos] = initializeAppRequest.authDomain; diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart index bb5d2636000f..0937f05f8243 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart @@ -107,6 +107,7 @@ class MethodChannelFirebase extends FirebasePlatform { iosClientId: _options.iosClientId, iosBundleId: _options.iosBundleId, appGroupId: _options.appGroupId, + recaptchaSiteKey: _options.recaptchaSiteKey, ))); defaultApp = appInstances[defaultFirebaseAppName]; } @@ -173,6 +174,7 @@ class MethodChannelFirebase extends FirebasePlatform { iosClientId: options.iosClientId, iosBundleId: options.iosBundleId, appGroupId: options.appGroupId, + recaptchaSiteKey: options.recaptchaSiteKey, ))); return appInstances[name]!; } diff --git a/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart b/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart index 91f66e2a03c0..2291efa88878 100644 --- a/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart +++ b/packages/firebase_core/firebase_core_platform_interface/test/firebase_options_test.dart @@ -55,6 +55,7 @@ void main() { appId: 'appId', messagingSenderId: 'messagingSenderId', projectId: 'projectId', + recaptchaSiteKey: 'recaptchaSiteKey', ), ); @@ -63,6 +64,7 @@ void main() { appId: 'appId', messagingSenderId: 'messagingSenderId', projectId: 'projectId', + recaptchaSiteKey: 'recaptchaSiteKey', ); expect(options1 == options2, isTrue); diff --git a/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart index 34729d337821..4ce9bf96a5a6 100644 --- a/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/firebase_core_web.dart @@ -27,17 +27,23 @@ FirebaseAppPlatform _createFromJsApp(firebase.App jsApp) { return FirebaseAppWeb._(jsApp.name, _createFromJsOptions(jsApp.options)); } +String? _safeToDart(JSString? jsString) { + if (jsString == null || jsString.isUndefinedOrNull) return null; + return jsString.toDart; +} + /// Returns a [FirebaseOptions] instance from [firebase.FirebaseOptions]. FirebaseOptions _createFromJsOptions(firebase.FirebaseOptions options) { return FirebaseOptions( - apiKey: options.apiKey?.toDart ?? '', - projectId: options.projectId?.toDart ?? '', - authDomain: options.authDomain?.toDart, - databaseURL: options.databaseURL?.toDart, - storageBucket: options.storageBucket?.toDart, - messagingSenderId: options.messagingSenderId?.toDart ?? '', - appId: options.appId?.toDart ?? '', - measurementId: options.measurementId?.toDart, + apiKey: _safeToDart(options.apiKey) ?? '', + projectId: _safeToDart(options.projectId) ?? '', + authDomain: _safeToDart(options.authDomain), + databaseURL: _safeToDart(options.databaseURL), + storageBucket: _safeToDart(options.storageBucket), + messagingSenderId: _safeToDart(options.messagingSenderId) ?? '', + appId: _safeToDart(options.appId) ?? '', + measurementId: _safeToDart(options.measurementId), + recaptchaSiteKey: _safeToDart(options.recaptchaSiteKey), ); } diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart index f649fa1a2f5e..1cd96ad51f99 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_web.dart @@ -334,7 +334,6 @@ class FirebaseCoreWeb extends FirebasePlatform { // At this point, there is no default app so we need to create it with // the users options. - // TODO(recaptchaSiteKey): Pass recaptchaSiteKey if supported. app = firebase.initializeApp( apiKey: options!.apiKey, authDomain: options.authDomain, @@ -344,6 +343,7 @@ class FirebaseCoreWeb extends FirebasePlatform { messagingSenderId: options.messagingSenderId, appId: options.appId, measurementId: options.measurementId, + recaptchaSiteKey: options.recaptchaSiteKey, ); } } @@ -356,7 +356,6 @@ class FirebaseCoreWeb extends FirebasePlatform { ); try { - // TODO(recaptchaSiteKey): Pass recaptchaSiteKey if supported. app = firebase.initializeApp( name: name, apiKey: options!.apiKey, @@ -367,6 +366,7 @@ class FirebaseCoreWeb extends FirebasePlatform { messagingSenderId: options.messagingSenderId, appId: options.appId, measurementId: options.measurementId, + recaptchaSiteKey: options.recaptchaSiteKey, ); } catch (e) { if (_getJSErrorCode(e as JSError) == 'app/duplicate-app') { diff --git a/packages/firebase_core/firebase_core_web/lib/src/interop/core.dart b/packages/firebase_core/firebase_core_web/lib/src/interop/core.dart index 36f439e65689..254d07f38292 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/interop/core.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/interop/core.dart @@ -33,6 +33,7 @@ App initializeApp({ String? name, String? measurementId, String? appId, + String? recaptchaSiteKey, }) { name ??= defaultFirebaseAppName; @@ -47,6 +48,7 @@ App initializeApp({ messagingSenderId: messagingSenderId?.toJS, measurementId: measurementId?.toJS, appId: appId?.toJS, + recaptchaSiteKey: recaptchaSiteKey?.toJS, ), name.toJS, ), diff --git a/packages/firebase_core/firebase_core_web/lib/src/interop/core_interop.dart b/packages/firebase_core/firebase_core_web/lib/src/interop/core_interop.dart index c4f3be7aa58e..1aeaafe4ebd0 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/interop/core_interop.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/interop/core_interop.dart @@ -62,6 +62,7 @@ extension type FirebaseOptions._(JSObject _) implements JSObject { JSString? messagingSenderId, JSString? measurementId, JSString? appId, + JSString? recaptchaSiteKey, }); } @@ -82,4 +83,6 @@ extension FirebaseOptionsExtension on FirebaseOptions { external set measurementId(JSString? s); external JSString? get appId; external set appId(JSString? s); + external JSString? get recaptchaSiteKey; + external set recaptchaSiteKey(JSString? s); } diff --git a/tests/integration_test/firebase_core/firebase_core_e2e_test.dart b/tests/integration_test/firebase_core/firebase_core_e2e_test.dart index 8f31a8ddbd65..f7759ed5035c 100644 --- a/tests/integration_test/firebase_core/firebase_core_e2e_test.dart +++ b/tests/integration_test/firebase_core/firebase_core_e2e_test.dart @@ -78,5 +78,36 @@ void main() { await app.setAutomaticResourceManagementEnabled(true); }); + + test('Firebase.initializeApp with recaptchaSiteKey', () async { + String appName = 'recaptcha-test-app'; + FirebaseOptions options = DefaultFirebaseOptions.currentPlatform.copyWith( + recaptchaSiteKey: 'test-recaptcha-site-key', + ); + + await Firebase.initializeApp( + name: appName, + options: options, + ); + + FirebaseApp app = Firebase.app(appName); + expect(app.options.recaptchaSiteKey, 'test-recaptcha-site-key'); + + await app.delete(); + }); + + test('Default app recaptchaSiteKey precedence test', () async { + // Natively initialized default app has no recaptchaSiteKey. + // Trying to initialize it again with different recaptchaSiteKey in Dart. + FirebaseApp app = await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform.copyWith( + recaptchaSiteKey: 'dart-recaptcha-key', + ), + ); + + // It should NOT update the key, because native initializeApp was skipped. + // (It returns the natively initialized app which has null key). + expect(app.options.recaptchaSiteKey, isNull); + }); }); } From cb0d466ec285385787c9af3475fdee1edfc0f444 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Wed, 17 Jun 2026 11:56:28 +0200 Subject: [PATCH 125/137] chore: format (#18377) * chore: format * format --- .../ios/cloud_firestore/Package.swift | 4 +- .../macos/cloud_firestore/Package.swift | 4 +- .../ios/cloud_functions/Package.swift | 2 +- .../macos/cloud_functions/Package.swift | 2 +- .../firebase_ai/example/ios/Podfile | 43 +++++++++++++ .../firebase_ai/example/macos/Podfile | 42 +++++++++++++ .../ios/firebase_analytics/Package.swift | 2 +- .../macos/firebase_analytics/Package.swift | 2 +- .../firebase_app_check/example/ios/Podfile | 43 +++++++++++++ .../firebase_app_check/example/macos/Podfile | 42 +++++++++++++ .../ios/firebase_app_check/Package.swift | 7 ++- .../FirebaseAppCheckMessages.g.swift | 62 +++++++++++-------- .../macos/firebase_app_check/Package.swift | 2 +- .../firebase_app_installations/Package.swift | 2 +- .../firebase_app_installations/Package.swift | 2 +- .../ios/firebase_auth/Package.swift | 4 +- .../macos/firebase_auth/Package.swift | 4 +- .../ios/firebase_core/Package.swift | 4 +- .../firebase_core/FLTFirebaseCorePlugin.m | 7 +-- .../macos/firebase_core/Package.swift | 4 +- .../ios/firebase_crashlytics/Package.swift | 4 +- .../macos/firebase_crashlytics/Package.swift | 4 +- .../ios/firebase_database/Package.swift | 4 +- .../macos/firebase_database/Package.swift | 4 +- .../firebase_in_app_messaging/Package.swift | 4 +- .../ios/firebase_messaging/Package.swift | 4 +- .../macos/firebase_messaging/Package.swift | 4 +- .../Package.swift | 2 +- .../Package.swift | 2 +- .../ios/firebase_performance/Package.swift | 4 +- .../ios/firebase_remote_config/Package.swift | 2 +- .../firebase_remote_config/Package.swift | 2 +- .../ios/firebase_storage/Package.swift | 4 +- .../macos/firebase_storage/Package.swift | 4 +- 34 files changed, 256 insertions(+), 76 deletions(-) create mode 100644 packages/firebase_ai/firebase_ai/example/ios/Podfile create mode 100644 packages/firebase_ai/firebase_ai/example/macos/Podfile create mode 100644 packages/firebase_app_check/firebase_app_check/example/ios/Podfile create mode 100644 packages/firebase_app_check/firebase_app_check/example/macos/Podfile diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index 427e6eba2b86..9186315f1eb7 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "6.4.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "6.5.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index 5bd2446dda51..c7584955d7a4 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "6.4.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "6.5.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "cloud_firestore", diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift index cd030b08914f..3f8528c174c0 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "cloud_functions", diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift index df1ccce51ab8..2c25ccde9d22 100644 --- a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "cloud_functions", diff --git a/packages/firebase_ai/firebase_ai/example/ios/Podfile b/packages/firebase_ai/firebase_ai/example/ios/Podfile new file mode 100644 index 000000000000..620e46eba607 --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +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 + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/firebase_ai/firebase_ai/example/macos/Podfile b/packages/firebase_ai/firebase_ai/example/macos/Podfile new file mode 100644 index 000000000000..ff5ddb3b8bdc --- /dev/null +++ b/packages/firebase_ai/firebase_ai/example/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', '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 + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift index 23763dbc6049..65aee5313d06 100644 --- a/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/ios/firebase_analytics/Package.swift @@ -8,7 +8,7 @@ import Foundation import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" // Set FIREBASE_ANALYTICS_WITHOUT_ADID=true to use FirebaseAnalyticsCore. // e.g. FIREBASE_ANALYTICS_WITHOUT_ADID=true flutter build ios diff --git a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift index d547defc1ed5..c9533bf1e70f 100644 --- a/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift +++ b/packages/firebase_analytics/firebase_analytics/macos/firebase_analytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_analytics", diff --git a/packages/firebase_app_check/firebase_app_check/example/ios/Podfile b/packages/firebase_app_check/firebase_app_check/example/ios/Podfile new file mode 100644 index 000000000000..620e46eba607 --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +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 + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/firebase_app_check/firebase_app_check/example/macos/Podfile b/packages/firebase_app_check/firebase_app_check/example/macos/Podfile new file mode 100644 index 000000000000..ff5ddb3b8bdc --- /dev/null +++ b/packages/firebase_app_check/firebase_app_check/example/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', '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 + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift index c61c10b252e1..14de1a767958 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_app_check", @@ -19,7 +19,10 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/firebase/firebase-ios-sdk", exact: firebaseSdkVersion), - .package(url: "https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk.git", from: "18.0.0"), + .package( + url: "https://github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk.git", + from: "18.0.0" + ), .package(name: "firebase_core", path: "../firebase_core"), ], targets: [ diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift index cc94a926d933..d8f3a100c89b 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/FirebaseAppCheckMessages.g.swift @@ -27,13 +27,12 @@ final class PigeonError: Error { } var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" } } private func wrapResult(_ result: Any?) -> [Any?] { - return [result] + [result] } private func wrapError(_ error: Any) -> [Any?] { @@ -59,7 +58,7 @@ private func wrapError(_ error: Any) -> [Any?] { } private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil + value is NSNull || value == nil } private func nilOrValue(_ value: Any?) -> T? { @@ -67,46 +66,52 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } -private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader { -} +private class FirebaseAppCheckMessagesPigeonCodecReader: FlutterStandardReader {} -private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter { -} +private class FirebaseAppCheckMessagesPigeonCodecWriter: FlutterStandardWriter {} private class FirebaseAppCheckMessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter { override func reader(with data: Data) -> FlutterStandardReader { - return FirebaseAppCheckMessagesPigeonCodecReader(data: data) + FirebaseAppCheckMessagesPigeonCodecReader(data: data) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return FirebaseAppCheckMessagesPigeonCodecWriter(data: data) + FirebaseAppCheckMessagesPigeonCodecWriter(data: data) } } class FirebaseAppCheckMessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { static let shared = FirebaseAppCheckMessagesPigeonCodec( - readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter()) + readerWriter: FirebaseAppCheckMessagesPigeonCodecReaderWriter() + ) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FirebaseAppCheckHostApi { func activate( - appName: String, androidProvider: String?, appleProvider: String?, debugToken: String?, + appName: String, androidProvider: String?, appleProvider: String?, + debugToken: String?, completion: @escaping (Result) -> Void) func getToken( - appName: String, forceRefresh: Bool, completion: @escaping (Result) -> Void) + appName: String, forceRefresh: Bool, + completion: @escaping (Result) -> Void) func setTokenAutoRefreshEnabled( appName: String, isTokenAutoRefreshEnabled: Bool, completion: @escaping (Result) -> Void) func registerTokenListener(appName: String, completion: @escaping (Result) -> Void) func getLimitedUseAppCheckToken( - appName: String, completion: @escaping (Result) -> Void) + appName: String, + completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class FirebaseAppCheckHostApiSetup { - static var codec: FlutterStandardMessageCodec { FirebaseAppCheckMessagesPigeonCodec.shared } - /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the `binaryMessenger`. + static var codec: FlutterStandardMessageCodec { + FirebaseAppCheckMessagesPigeonCodec.shared + } + + /// Sets up an instance of `FirebaseAppCheckHostApi` to handle messages through the + /// `binaryMessenger`. static func setUp( binaryMessenger: FlutterBinaryMessenger, api: FirebaseAppCheckHostApi?, messageChannelSuffix: String = "" @@ -115,8 +120,9 @@ class FirebaseAppCheckHostApiSetup { let activateChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.activate\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { + binaryMessenger: binaryMessenger, codec: codec + ) + if let api { activateChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String @@ -141,8 +147,9 @@ class FirebaseAppCheckHostApiSetup { let getTokenChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getToken\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { + binaryMessenger: binaryMessenger, codec: codec + ) + if let api { getTokenChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String @@ -162,8 +169,9 @@ class FirebaseAppCheckHostApiSetup { let setTokenAutoRefreshEnabledChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.setTokenAutoRefreshEnabled\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { + binaryMessenger: binaryMessenger, codec: codec + ) + if let api { setTokenAutoRefreshEnabledChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String @@ -185,8 +193,9 @@ class FirebaseAppCheckHostApiSetup { let registerTokenListenerChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.registerTokenListener\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { + binaryMessenger: binaryMessenger, codec: codec + ) + if let api { registerTokenListenerChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String @@ -205,8 +214,9 @@ class FirebaseAppCheckHostApiSetup { let getLimitedUseAppCheckTokenChannel = FlutterBasicMessageChannel( name: "dev.flutter.pigeon.firebase_app_check_platform_interface.FirebaseAppCheckHostApi.getLimitedUseAppCheckToken\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { + binaryMessenger: binaryMessenger, codec: codec + ) + if let api { getLimitedUseAppCheckTokenChannel.setMessageHandler { message, reply in let args = message as! [Any?] let appNameArg = args[0] as! String diff --git a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift index 5e18628c4123..2edc73e6569f 100644 --- a/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift +++ b/packages/firebase_app_check/firebase_app_check/macos/firebase_app_check/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_app_check", diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift index 7427d6bc97d7..9227ec496045 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift index 16b1f01b9764..2e91bb5f3819 100644 --- a/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift +++ b/packages/firebase_app_installations/firebase_app_installations/macos/firebase_app_installations/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_app_installations", diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index fb20508740d9..8c5d6ca619c2 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "6.5.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "6.5.2" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index 2f0c6134c574..7e5367f65668 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "6.5.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "6.5.2" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_auth", diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index 2564661516ae..0080eea73902 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersionString = "4.9.0" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersionString = "4.10.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m index 0b713b7c9f80..192f984e59fb 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Sources/firebase_core/FLTFirebaseCorePlugin.m @@ -93,7 +93,8 @@ - (CoreFirebaseOptions *)optionsFromFIROptions:(FIROptions *)options { pigeonOptions.iosBundleId = (id)options.bundleID ?: [NSNull null]; pigeonOptions.iosClientId = (id)options.clientID ?: [NSNull null]; pigeonOptions.appGroupId = (id)options.appGroupID ?: [NSNull null]; - pigeonOptions.recaptchaSiteKey = (id)options.recaptchaSiteKey ?: [NSNull null]; + // recaptchaSiteKey is currently only exposed by Firebase JS options. + pigeonOptions.recaptchaSiteKey = [NSNull null]; return pigeonOptions; } @@ -179,10 +180,6 @@ - (void)initializeAppAppName:(nonnull NSString *)appName options.appGroupID = initializeAppRequest.appGroupId; } - if (![initializeAppRequest.recaptchaSiteKey isEqual:[NSNull null]]) { - options.recaptchaSiteKey = initializeAppRequest.recaptchaSiteKey; - } - if (initializeAppRequest.authDomain != nil) { customAuthDomains[appNameIos] = initializeAppRequest.authDomain; } diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index 03cdee9a4167..76ca886cb995 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersionString = "4.9.0" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersionString = "4.10.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_core", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index 4a0a87574f4e..52abad688be9 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "5.2.2" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "5.2.3" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index 619e14e93216..688d2aeada02 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "5.2.2" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "5.2.3" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_crashlytics", diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index d961803fe9fa..d895419bf4cf 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "12.4.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "12.4.2" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index d322efdf7030..7c49a085ea0d 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "12.4.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "12.4.2" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_database", diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index b389528c60ee..6cd63b4f83c8 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "0.9.2-2" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "0.9.2-3" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_in_app_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index 74d6a74e26b3..18784af00022 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "16.2.2" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "16.3.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index 820f2875e68a..f91b6fc3ecb2 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "16.2.2" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "16.3.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_messaging", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift index 739d1f6494ee..269a6407d7e9 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift index cfdcb0d35386..864e62e3cbdd 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/macos/firebase_ml_model_downloader/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_ml_model_downloader", diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index 9058965e7e35..dff9cf422bdd 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "0.11.4-1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "0.11.4-2" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_performance", diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift index f932cb140ee9..43a620865941 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift index f2bb3d72b4e3..a5e6bcd78225 100644 --- a/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift +++ b/packages/firebase_remote_config/firebase_remote_config/macos/firebase_remote_config/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let firebaseSdkVersion: Version = "12.14.0" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_remote_config", diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index 149ea8699915..43f4b656a206 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "13.4.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "13.4.2" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_storage", diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index 581580fc09ea..aeb81c040fdc 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -7,8 +7,8 @@ import PackageDescription -let libraryVersion = "13.4.1" -let firebaseSdkVersion: Version = "12.14.0" +let libraryVersion = "13.4.2" +let firebaseSdkVersion: Version = "12.15.0" let package = Package( name: "firebase_storage", From 214afc3df80d6ae0319c5715da36861da112cb49 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Wed, 17 Jun 2026 15:44:52 +0200 Subject: [PATCH 126/137] chore(release): publish packages (#18378) * chore(release): publish packages - cloud_firestore@6.6.0 - cloud_firestore_web@5.6.0 - firebase_ai@3.13.0 - firebase_analytics@12.4.3 - firebase_app_check@0.4.5 - firebase_app_check_platform_interface@0.4.1 - firebase_app_check_web@0.2.5 - firebase_core@4.11.0 - firebase_core_platform_interface@7.1.0 - firebase_core_web@3.9.0 - firebase_messaging@16.4.0 - firebase_messaging_platform_interface@4.9.0 - firebase_data_connect@0.3.0+4 - _flutterfire_internals@1.3.73 - cloud_firestore_platform_interface@8.0.3 - cloud_functions@6.3.3 - cloud_functions_platform_interface@6.0.3 - cloud_functions_web@5.1.9 - firebase_analytics_platform_interface@6.0.3 - firebase_analytics_web@0.6.1+9 - firebase_app_installations@0.4.2+4 - firebase_app_installations_platform_interface@0.1.4+72 - firebase_app_installations_web@0.1.7+9 - firebase_auth@6.5.3 - firebase_auth_platform_interface@9.0.3 - firebase_auth_web@6.2.3 - firebase_crashlytics@5.2.4 - firebase_crashlytics_platform_interface@3.8.24 - firebase_database@12.4.3 - firebase_database_platform_interface@0.4.0+3 - firebase_database_web@0.2.7+10 - firebase_in_app_messaging@0.9.2+4 - firebase_in_app_messaging_platform_interface@0.2.5+24 - firebase_messaging_web@4.2.1 - firebase_ml_model_downloader@0.4.2+4 - firebase_ml_model_downloader_platform_interface@0.1.5+24 - firebase_performance@0.11.4+3 - firebase_performance_platform_interface@0.2.0+3 - firebase_performance_web@0.1.8+9 - firebase_remote_config@6.5.3 - firebase_remote_config_platform_interface@3.0.3 - firebase_remote_config_web@1.10.10 - firebase_storage@13.4.3 - firebase_storage_platform_interface@6.0.3 - firebase_storage_web@3.11.9 * chore: BoM Version 4.16.0 * updates * fix * fix * fix * fixing --- CHANGELOG.md | 158 ++++++++++++++++++ VERSIONS.md | 38 +++++ packages/_flutterfire_internals/CHANGELOG.md | 4 + packages/_flutterfire_internals/pubspec.yaml | 6 +- .../cloud_firestore/CHANGELOG.md | 4 + .../cloud_firestore/example/pubspec.yaml | 4 +- .../ios/cloud_firestore/Package.swift | 2 +- .../macos/cloud_firestore/Package.swift | 2 +- .../pipeline_example/pubspec.yaml | 2 +- .../cloud_firestore/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../cloud_firestore_web/CHANGELOG.md | 4 + .../lib/src/cloud_firestore_version.dart | 2 +- .../cloud_firestore_web/pubspec.yaml | 12 +- .../cloud_functions/CHANGELOG.md | 4 + .../cloud_functions/example/pubspec.yaml | 4 +- .../Sources/cloud_functions/Constants.swift | 2 +- .../cloud_functions/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../cloud_functions_web/CHANGELOG.md | 4 + .../lib/src/cloud_functions_version.dart | 2 +- .../cloud_functions_web/pubspec.yaml | 10 +- packages/firebase_ai/firebase_ai/CHANGELOG.md | 8 + .../firebase_ai/example/pubspec.yaml | 6 +- .../lib/src/firebaseai_version.dart | 2 +- packages/firebase_ai/firebase_ai/pubspec.yaml | 10 +- .../firebase_analytics/CHANGELOG.md | 4 + .../firebase_analytics/example/pubspec.yaml | 4 +- .../firebase_analytics/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_analytics_web/CHANGELOG.md | 4 + .../lib/src/firebase_analytics_version.dart | 2 +- .../firebase_analytics_web/pubspec.yaml | 10 +- .../firebase_app_check/CHANGELOG.md | 4 + .../firebase_app_check/example/pubspec.yaml | 6 +- .../firebase_app_check/Constants.swift | 2 +- .../firebase_app_check/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_app_check_web/CHANGELOG.md | 4 + .../lib/src/firebase_app_check_version.dart | 2 +- .../firebase_app_check_web/pubspec.yaml | 12 +- .../firebase_app_installations/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../Constants.swift | 2 +- .../firebase_app_installations/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../firebase_app_installations_version.dart | 2 +- .../pubspec.yaml | 12 +- .../firebase_auth/firebase_auth/CHANGELOG.md | 4 + .../firebase_auth/example/pubspec.yaml | 6 +- .../ios/firebase_auth/Package.swift | 2 +- .../macos/firebase_auth/Package.swift | 2 +- .../firebase_auth/firebase_auth/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../src/method_channel/utils/exception.dart | 19 ++- .../pubspec.yaml | 8 +- .../utils_tests/exception_test.dart | 38 +++++ .../firebase_auth_web/CHANGELOG.md | 4 + .../lib/src/firebase_auth_version.dart | 2 +- .../firebase_auth_web/pubspec.yaml | 8 +- .../firebase_core/firebase_core/CHANGELOG.md | 7 + .../firebase_core/example/pubspec.yaml | 2 +- .../ios/firebase_core/Package.swift | 2 +- .../macos/firebase_core/Package.swift | 2 +- .../firebase_core/firebase_core/pubspec.yaml | 6 +- .../CHANGELOG.md | 5 + .../pubspec.yaml | 2 +- .../firebase_core_web/CHANGELOG.md | 6 + .../lib/src/firebase_core_version.dart | 2 +- .../firebase_core_web/pubspec.yaml | 4 +- .../firebase_crashlytics/CHANGELOG.md | 4 + .../firebase_crashlytics/example/pubspec.yaml | 6 +- .../ios/firebase_crashlytics/Package.swift | 2 +- .../macos/firebase_crashlytics/Package.swift | 2 +- .../firebase_crashlytics/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_data_connect/CHANGELOG.md | 4 + .../example/pubspec.yaml | 6 +- .../lib/src/dataconnect_version.dart | 2 +- .../firebase_data_connect/pubspec.yaml | 14 +- .../firebase_database/CHANGELOG.md | 4 + .../firebase_database/example/pubspec.yaml | 4 +- .../ios/firebase_database/Package.swift | 2 +- .../macos/firebase_database/Package.swift | 2 +- .../firebase_database/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_database_web/CHANGELOG.md | 4 + .../lib/src/firebase_database_version.dart | 2 +- .../firebase_database_web/pubspec.yaml | 10 +- .../firebase_in_app_messaging/CHANGELOG.md | 4 + .../example/pubspec.yaml | 8 +- .../firebase_in_app_messaging/Package.swift | 2 +- .../firebase_in_app_messaging/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_messaging/CHANGELOG.md | 5 + .../firebase_messaging/example/pubspec.yaml | 4 +- .../ios/firebase_messaging/Package.swift | 2 +- .../macos/firebase_messaging/Package.swift | 2 +- .../firebase_messaging/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_messaging_web/CHANGELOG.md | 4 + .../lib/src/firebase_messaging_version.dart | 2 +- .../firebase_messaging_web/pubspec.yaml | 12 +- .../firebase_ml_model_downloader/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../Constants.swift | 2 +- .../firebase_ml_model_downloader/pubspec.yaml | 8 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 6 +- .../firebase_performance/CHANGELOG.md | 4 + .../firebase_performance/example/pubspec.yaml | 4 +- .../ios/firebase_performance/Package.swift | 2 +- .../firebase_performance/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_performance_web/CHANGELOG.md | 4 + .../lib/src/firebase_performance_version.dart | 2 +- .../firebase_performance_web/pubspec.yaml | 10 +- .../firebase_remote_config/CHANGELOG.md | 4 + .../example/pubspec.yaml | 4 +- .../firebase_remote_config/Constants.swift | 2 +- .../firebase_remote_config/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_remote_config_web/CHANGELOG.md | 4 + .../src/firebase_remote_config_version.dart | 2 +- .../firebase_remote_config_web/pubspec.yaml | 12 +- .../firebase_storage/CHANGELOG.md | 4 + .../firebase_storage/example/pubspec.yaml | 4 +- .../ios/firebase_storage/Package.swift | 2 +- .../macos/firebase_storage/Package.swift | 2 +- .../firebase_storage/pubspec.yaml | 10 +- .../CHANGELOG.md | 4 + .../pubspec.yaml | 8 +- .../firebase_storage_web/CHANGELOG.md | 4 + .../lib/src/firebase_storage_version.dart | 2 +- .../firebase_storage_web/pubspec.yaml | 12 +- scripts/versions.json | 28 ++++ tests/android/gradle.properties | 4 + tests/integration_test/e2e_test.dart | 3 +- .../firebase_core/firebase_core_e2e_test.dart | 31 +++- tests/pubspec.yaml | 72 ++++---- 152 files changed, 811 insertions(+), 327 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b09d164ca4c7..f36264ac63f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,164 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2026-06-17 - [BoM 4.16.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4160-2026-06-17) + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`cloud_firestore` - `v6.6.0`](#cloud_firestore---v660) + - [`cloud_firestore_web` - `v5.6.0`](#cloud_firestore_web---v560) + - [`firebase_ai` - `v3.13.0`](#firebase_ai---v3130) + - [`firebase_analytics` - `v12.4.3`](#firebase_analytics---v1243) + - [`firebase_app_check` - `v0.4.5`](#firebase_app_check---v045) + - [`firebase_app_check_platform_interface` - `v0.4.1`](#firebase_app_check_platform_interface---v041) + - [`firebase_app_check_web` - `v0.2.5`](#firebase_app_check_web---v025) + - [`firebase_core` - `v4.11.0`](#firebase_core---v4110) + - [`firebase_core_platform_interface` - `v7.1.0`](#firebase_core_platform_interface---v710) + - [`firebase_core_web` - `v3.9.0`](#firebase_core_web---v390) + - [`firebase_messaging` - `v16.4.0`](#firebase_messaging---v1640) + - [`firebase_messaging_platform_interface` - `v4.9.0`](#firebase_messaging_platform_interface---v490) + - [`firebase_data_connect` - `v0.3.0+4`](#firebase_data_connect---v0304) + - [`_flutterfire_internals` - `v1.3.73`](#_flutterfire_internals---v1373) + - [`cloud_firestore_platform_interface` - `v8.0.3`](#cloud_firestore_platform_interface---v803) + - [`cloud_functions` - `v6.3.3`](#cloud_functions---v633) + - [`cloud_functions_platform_interface` - `v6.0.3`](#cloud_functions_platform_interface---v603) + - [`cloud_functions_web` - `v5.1.9`](#cloud_functions_web---v519) + - [`firebase_analytics_platform_interface` - `v6.0.3`](#firebase_analytics_platform_interface---v603) + - [`firebase_analytics_web` - `v0.6.1+9`](#firebase_analytics_web---v0619) + - [`firebase_app_installations` - `v0.4.2+4`](#firebase_app_installations---v0424) + - [`firebase_app_installations_platform_interface` - `v0.1.4+72`](#firebase_app_installations_platform_interface---v01472) + - [`firebase_app_installations_web` - `v0.1.7+9`](#firebase_app_installations_web---v0179) + - [`firebase_auth` - `v6.5.3`](#firebase_auth---v653) + - [`firebase_auth_platform_interface` - `v9.0.3`](#firebase_auth_platform_interface---v903) + - [`firebase_auth_web` - `v6.2.3`](#firebase_auth_web---v623) + - [`firebase_crashlytics` - `v5.2.4`](#firebase_crashlytics---v524) + - [`firebase_crashlytics_platform_interface` - `v3.8.24`](#firebase_crashlytics_platform_interface---v3824) + - [`firebase_database` - `v12.4.3`](#firebase_database---v1243) + - [`firebase_database_platform_interface` - `v0.4.0+3`](#firebase_database_platform_interface---v0403) + - [`firebase_database_web` - `v0.2.7+10`](#firebase_database_web---v02710) + - [`firebase_in_app_messaging` - `v0.9.2+4`](#firebase_in_app_messaging---v0924) + - [`firebase_in_app_messaging_platform_interface` - `v0.2.5+24`](#firebase_in_app_messaging_platform_interface---v02524) + - [`firebase_messaging_web` - `v4.2.1`](#firebase_messaging_web---v421) + - [`firebase_ml_model_downloader` - `v0.4.2+4`](#firebase_ml_model_downloader---v0424) + - [`firebase_ml_model_downloader_platform_interface` - `v0.1.5+24`](#firebase_ml_model_downloader_platform_interface---v01524) + - [`firebase_performance` - `v0.11.4+3`](#firebase_performance---v01143) + - [`firebase_performance_platform_interface` - `v0.2.0+3`](#firebase_performance_platform_interface---v0203) + - [`firebase_performance_web` - `v0.1.8+9`](#firebase_performance_web---v0189) + - [`firebase_remote_config` - `v6.5.3`](#firebase_remote_config---v653) + - [`firebase_remote_config_platform_interface` - `v3.0.3`](#firebase_remote_config_platform_interface---v303) + - [`firebase_remote_config_web` - `v1.10.10`](#firebase_remote_config_web---v11010) + - [`firebase_storage` - `v13.4.3`](#firebase_storage---v1343) + - [`firebase_storage_platform_interface` - `v6.0.3`](#firebase_storage_platform_interface---v603) + - [`firebase_storage_web` - `v3.11.9`](#firebase_storage_web---v3119) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `firebase_data_connect` - `v0.3.0+4` + - `_flutterfire_internals` - `v1.3.73` + - `cloud_firestore_platform_interface` - `v8.0.3` + - `cloud_functions` - `v6.3.3` + - `cloud_functions_platform_interface` - `v6.0.3` + - `cloud_functions_web` - `v5.1.9` + - `firebase_analytics_platform_interface` - `v6.0.3` + - `firebase_analytics_web` - `v0.6.1+9` + - `firebase_app_installations` - `v0.4.2+4` + - `firebase_app_installations_platform_interface` - `v0.1.4+72` + - `firebase_app_installations_web` - `v0.1.7+9` + - `firebase_auth` - `v6.5.3` + - `firebase_auth_platform_interface` - `v9.0.3` + - `firebase_auth_web` - `v6.2.3` + - `firebase_crashlytics` - `v5.2.4` + - `firebase_crashlytics_platform_interface` - `v3.8.24` + - `firebase_database` - `v12.4.3` + - `firebase_database_platform_interface` - `v0.4.0+3` + - `firebase_database_web` - `v0.2.7+10` + - `firebase_in_app_messaging` - `v0.9.2+4` + - `firebase_in_app_messaging_platform_interface` - `v0.2.5+24` + - `firebase_messaging_web` - `v4.2.1` + - `firebase_ml_model_downloader` - `v0.4.2+4` + - `firebase_ml_model_downloader_platform_interface` - `v0.1.5+24` + - `firebase_performance` - `v0.11.4+3` + - `firebase_performance_platform_interface` - `v0.2.0+3` + - `firebase_performance_web` - `v0.1.8+9` + - `firebase_remote_config` - `v6.5.3` + - `firebase_remote_config_platform_interface` - `v3.0.3` + - `firebase_remote_config_web` - `v1.10.10` + - `firebase_storage` - `v13.4.3` + - `firebase_storage_platform_interface` - `v6.0.3` + - `firebase_storage_web` - `v3.11.9` + +--- + +#### `cloud_firestore` - `v6.6.0` + + - **FEAT**(firestore): add support for search in firestore pipeline ([#18312](https://github.com/firebase/flutterfire/issues/18312)). ([b3c835f7](https://github.com/firebase/flutterfire/commit/b3c835f7bae8684d4c98167d78a071d9ed88f980)) + +#### `cloud_firestore_web` - `v5.6.0` + + - **FEAT**(firestore): add support for search in firestore pipeline ([#18312](https://github.com/firebase/flutterfire/issues/18312)). ([b3c835f7](https://github.com/firebase/flutterfire/commit/b3c835f7bae8684d4c98167d78a071d9ed88f980)) + +#### `firebase_ai` - `v3.13.0` + + - **FIX**(ai): firebase_ai server template image inputs passed as InlineDataPart were serialized as normal generative inlineData ([#18350](https://github.com/firebase/flutterfire/issues/18350)). ([f3c53792](https://github.com/firebase/flutterfire/commit/f3c53792f1acf19ab1c2c7c3d157fca3a183b5d1)) + - **FEAT**(firebaseai): Add speech config and TTS sample page ([#18358](https://github.com/firebase/flutterfire/issues/18358)). ([0af51b50](https://github.com/firebase/flutterfire/commit/0af51b501603a611c7c6800efd9d98c478abab4d)) + - **FEAT**(ai): add language code support for SpeechConfig ([#18353](https://github.com/firebase/flutterfire/issues/18353)). ([3471afc7](https://github.com/firebase/flutterfire/commit/3471afc7ffa7bae58981683982d58d669ac71d50)) + - **FEAT**(ai): add mediaResolution parameter ([#18354](https://github.com/firebase/flutterfire/issues/18354)). ([79547569](https://github.com/firebase/flutterfire/commit/795475692384385a17511b295640ad6f8ab625f6)) + - **FEAT**(ai): add support for cancellable clients for in-flight requests ([#18349](https://github.com/firebase/flutterfire/issues/18349)). ([566cfed4](https://github.com/firebase/flutterfire/commit/566cfed42599318cf0f24eefc5d696223e46128c)) + +#### `firebase_analytics` - `v12.4.3` + + - **FIX**(analytics,iOS): update iOS dependency instructions for IDFA-free usage ([#18337](https://github.com/firebase/flutterfire/issues/18337)). ([c21fc77b](https://github.com/firebase/flutterfire/commit/c21fc77b68a87b9691fc1615454c5dac39dd4ed4)) + +#### `firebase_app_check` - `v0.4.5` + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + +#### `firebase_app_check_platform_interface` - `v0.4.1` + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + +#### `firebase_app_check_web` - `v0.2.5` + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + +#### `firebase_core` - `v4.11.0` + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + - **FEAT**(core): bump Firebase ios SDK to 12.15.0 ([#18375](https://github.com/firebase/flutterfire/issues/18375)). ([4d083764](https://github.com/firebase/flutterfire/commit/4d083764c3abd94d6e4590a170fbdaaa4b161202)) + - **FEAT**(core): bump Firebase android SDK to 34.15.0 ([#18374](https://github.com/firebase/flutterfire/issues/18374)). ([1cd3a0bd](https://github.com/firebase/flutterfire/commit/1cd3a0bd76fd594139356519fabee0e0d2b12f31)) + - **FEAT**(core): Add Recaptcha Site Key to FirebaseOptions ([#18334](https://github.com/firebase/flutterfire/issues/18334)). ([57be7027](https://github.com/firebase/flutterfire/commit/57be702778d34b9b7e86b40817d93acaec4c3ca4)) + +#### `firebase_core_platform_interface` - `v7.1.0` + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + - **FEAT**(core): Add Recaptcha Site Key to FirebaseOptions ([#18334](https://github.com/firebase/flutterfire/issues/18334)). ([57be7027](https://github.com/firebase/flutterfire/commit/57be702778d34b9b7e86b40817d93acaec4c3ca4)) + +#### `firebase_core_web` - `v3.9.0` + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + - **FEAT**(core): bump Firebase web SDK to 12.15.0 ([#18376](https://github.com/firebase/flutterfire/issues/18376)). ([22eb4d5d](https://github.com/firebase/flutterfire/commit/22eb4d5d0f3f14207e080e9c9fc8373052258ef4)) + - **FEAT**(core): Add Recaptcha Site Key to FirebaseOptions ([#18334](https://github.com/firebase/flutterfire/issues/18334)). ([57be7027](https://github.com/firebase/flutterfire/commit/57be702778d34b9b7e86b40817d93acaec4c3ca4)) + +#### `firebase_messaging` - `v16.4.0` + + - **FIX**(messaging,ios): fix a race condition that could happen when getting initial message ([#18352](https://github.com/firebase/flutterfire/issues/18352)). ([77396b81](https://github.com/firebase/flutterfire/commit/77396b81ae56943a38c23b429249b0b9cbd4bc21)) + - **FEAT**(messaging,ios): add support for actionIdentifier on iOS devices ([#18357](https://github.com/firebase/flutterfire/issues/18357)). ([d60af4d9](https://github.com/firebase/flutterfire/commit/d60af4d9e1345c113490e875c85bd9ac62dad935)) + +#### `firebase_messaging_platform_interface` - `v4.9.0` + + - **FEAT**(messaging,ios): add support for actionIdentifier on iOS devices ([#18357](https://github.com/firebase/flutterfire/issues/18357)). ([d60af4d9](https://github.com/firebase/flutterfire/commit/d60af4d9e1345c113490e875c85bd9ac62dad935)) + + ## 2026-06-01 - [BoM 4.15.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4150-2026-06-01) ### Changes diff --git a/VERSIONS.md b/VERSIONS.md index db11f40769e8..af9edfa82d42 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -4,6 +4,44 @@ This document is listing all the compatible versions of the FlutterFire plugins. # Versions +## [Flutter BoM 4.16.0 (2026-06-17)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-06-17) + +Install this version using FlutterFire CLI + +```bash +flutterfire install 4.16.0 +``` + +### Included Native Firebase SDK Versions +| Firebase SDK | Version | Link | +|--------------|---------|------| +| Android SDK | 34.15.0 | [Release Notes](https://firebase.google.com/support/release-notes/android) | +| iOS SDK | 12.15.0 | [Release Notes](https://firebase.google.com/support/release-notes/ios) | +| Web SDK | 12.15.0 | [Release Notes](https://firebase.google.com/support/release-notes/js) | +| Windows SDK | 13.5.0 | [Release Notes](https://firebase.google.com/support/release-notes/cpp-relnotes) | + +### FlutterFire Plugin Versions +| Plugin | Version | Dart Version | Flutter Version | +|--------|---------|--------------|-----------------| +| [cloud_firestore](https://pub.dev/packages/cloud_firestore/versions/6.6.0) | 6.6.0 | ^3.6.0 | >=3.27.0 | +| [cloud_functions](https://pub.dev/packages/cloud_functions/versions/6.3.3) | 6.3.3 | ^3.6.0 | >=3.27.0 | +| [firebase_ai](https://pub.dev/packages/firebase_ai/versions/3.13.0) | 3.13.0 | ^3.6.0 | >=3.16.0 | +| [firebase_analytics](https://pub.dev/packages/firebase_analytics/versions/12.4.3) | 12.4.3 | ^3.6.0 | >=3.27.0 | +| [firebase_app_check](https://pub.dev/packages/firebase_app_check/versions/0.4.5) | 0.4.5 | ^3.6.0 | >=3.27.0 | +| [firebase_app_installations](https://pub.dev/packages/firebase_app_installations/versions/0.4.2+4) | 0.4.2+4 | ^3.6.0 | >=3.27.0 | +| [firebase_auth](https://pub.dev/packages/firebase_auth/versions/6.5.3) | 6.5.3 | ^3.6.0 | >=3.16.0 | +| [firebase_core](https://pub.dev/packages/firebase_core/versions/4.11.0) | 4.11.0 | ^3.6.0 | >=3.27.0 | +| [firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics/versions/5.2.4) | 5.2.4 | ^3.6.0 | >=3.27.0 | +| [firebase_data_connect](https://pub.dev/packages/firebase_data_connect/versions/0.3.0+4) | 0.3.0+4 | ^3.6.0 | >=3.27.0 | +| [firebase_database](https://pub.dev/packages/firebase_database/versions/12.4.3) | 12.4.3 | ^3.6.0 | >=3.27.0 | +| [firebase_in_app_messaging](https://pub.dev/packages/firebase_in_app_messaging/versions/0.9.2+4) | 0.9.2+4 | ^3.6.0 | >=3.27.0 | +| [firebase_messaging](https://pub.dev/packages/firebase_messaging/versions/16.4.0) | 16.4.0 | ^3.6.0 | >=3.27.0 | +| [firebase_ml_model_downloader](https://pub.dev/packages/firebase_ml_model_downloader/versions/0.4.2+4) | 0.4.2+4 | ^3.6.0 | >=3.27.0 | +| [firebase_performance](https://pub.dev/packages/firebase_performance/versions/0.11.4+3) | 0.11.4+3 | ^3.6.0 | >=3.27.0 | +| [firebase_remote_config](https://pub.dev/packages/firebase_remote_config/versions/6.5.3) | 6.5.3 | ^3.6.0 | >=3.27.0 | +| [firebase_storage](https://pub.dev/packages/firebase_storage/versions/13.4.3) | 13.4.3 | ^3.6.0 | >=3.27.0 | + + ## [Flutter BoM 4.15.0 (2026-06-01)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-06-01) Install this version using FlutterFire CLI diff --git a/packages/_flutterfire_internals/CHANGELOG.md b/packages/_flutterfire_internals/CHANGELOG.md index 254758ebbfe1..b94305236a5a 100644 --- a/packages/_flutterfire_internals/CHANGELOG.md +++ b/packages/_flutterfire_internals/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.73 + + - Update a dependency to the latest release. + ## 1.3.72 - Update a dependency to the latest release. diff --git a/packages/_flutterfire_internals/pubspec.yaml b/packages/_flutterfire_internals/pubspec.yaml index bce4b217cd37..226a77a68d01 100755 --- a/packages/_flutterfire_internals/pubspec.yaml +++ b/packages/_flutterfire_internals/pubspec.yaml @@ -2,7 +2,7 @@ name: _flutterfire_internals description: A package hosting Dart code shared between FlutterFire plugins. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/_flutterfire_internals -version: 1.3.72 +version: 1.3.73 resolution: workspace environment: @@ -11,8 +11,8 @@ environment: dependencies: collection: ^1.0.0 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md index 508b326b3129..050b12b70400 100644 --- a/packages/cloud_firestore/cloud_firestore/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.6.0 + + - **FEAT**(firestore): add support for search in firestore pipeline ([#18312](https://github.com/firebase/flutterfire/issues/18312)). ([b3c835f7](https://github.com/firebase/flutterfire/commit/b3c835f7bae8684d4c98167d78a071d9ed88f980)) + ## 6.5.0 - **FIX**(firestore,ios): add forceIndex parameter to collection source stage initializations ([#18332](https://github.com/firebase/flutterfire/issues/18332)). ([1bf50d2f](https://github.com/firebase/flutterfire/commit/1bf50d2f5bbdcac29797268632e2ed8b7e344c7d)) diff --git a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml index 9dcba518072c..82e0b95a3f31 100755 --- a/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.5.0 - firebase_core: ^4.10.0 + cloud_firestore: ^6.6.0 + firebase_core: ^4.11.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift index 9186315f1eb7..46f60ccd5cdf 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "6.5.0" +let libraryVersion = "6.6.0" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift index c7584955d7a4..fa4433624d5b 100644 --- a/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift +++ b/packages/cloud_firestore/cloud_firestore/macos/cloud_firestore/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "6.5.0" +let libraryVersion = "6.6.0" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml index 5bb006b6195c..92730168658a 100644 --- a/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pipeline_example/pubspec.yaml @@ -31,7 +31,7 @@ environment: dependencies: cloud_firestore: path: .. - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/cloud_firestore/cloud_firestore/pubspec.yaml b/packages/cloud_firestore/cloud_firestore/pubspec.yaml index f5a18b6741cf..9502c092d57b 100755 --- a/packages/cloud_firestore/cloud_firestore/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore/pubspec.yaml @@ -4,7 +4,7 @@ description: live synchronization and offline support on Android and iOS. homepage: https://firebase.google.com/docs/firestore repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore -version: 6.5.0 +version: 6.6.0 resolution: workspace topics: - firebase @@ -21,11 +21,11 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore_platform_interface: ^8.0.2 - cloud_firestore_web: ^5.5.0 + cloud_firestore_platform_interface: ^8.0.3 + cloud_firestore_web: ^5.6.0 collection: ^1.0.0 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md index fbaf07c6dfdd..04eb8b9e92c8 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 8.0.3 + + - Update a dependency to the latest release. + ## 8.0.2 - Update a dependency to the latest release. diff --git a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml index 0b4dd4487be0..9a4ba100e7b3 100644 --- a/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_firestore_platform_interface description: A common platform interface for the cloud_firestore plugin. -version: 8.0.2 +version: 8.0.3 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 + _flutterfire_internals: ^1.3.73 collection: ^1.15.0 - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md index 9e9a4f0b0f13..707fbe40588e 100644 --- a/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md +++ b/packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.6.0 + + - **FEAT**(firestore): add support for search in firestore pipeline ([#18312](https://github.com/firebase/flutterfire/issues/18312)). ([b3c835f7](https://github.com/firebase/flutterfire/commit/b3c835f7bae8684d4c98167d78a071d9ed88f980)) + ## 5.5.0 - **FEAT**(firestore): add support for new array expressions ([#18283](https://github.com/firebase/flutterfire/issues/18283)). ([2293dee0](https://github.com/firebase/flutterfire/commit/2293dee00767cc6eebd57a340eb2b72bdab41d52)) diff --git a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart index 200e74209d4f..bc5f696e6123 100644 --- a/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart +++ b/packages/cloud_firestore/cloud_firestore_web/lib/src/cloud_firestore_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.0'; +const packageVersion = '6.6.0'; diff --git a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml index 38c3a8e4db89..60dc877769ac 100644 --- a/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml +++ b/packages/cloud_firestore/cloud_firestore_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_firestore homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_web -version: 5.5.0 +version: 5.6.0 resolution: workspace environment: @@ -11,18 +11,18 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 - cloud_firestore_platform_interface: ^8.0.2 + _flutterfire_internals: ^1.3.73 + cloud_firestore_platform_interface: ^8.0.3 collection: ^1.0.0 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_functions/cloud_functions/CHANGELOG.md b/packages/cloud_functions/cloud_functions/CHANGELOG.md index b9c498844f5f..06e155cfcd83 100644 --- a/packages/cloud_functions/cloud_functions/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.3.3 + + - Update a dependency to the latest release. + ## 6.3.2 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions/example/pubspec.yaml b/packages/cloud_functions/cloud_functions/example/pubspec.yaml index 267ecca8fc47..8b854b769f49 100644 --- a/packages/cloud_functions/cloud_functions/example/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions: ^6.3.2 - firebase_core: ^4.10.0 + cloud_functions: ^6.3.3 + firebase_core: ^4.11.0 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift index 37927a798850..794e70dce372 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.3.2" +public let versionNumber = "6.3.3" diff --git a/packages/cloud_functions/cloud_functions/pubspec.yaml b/packages/cloud_functions/cloud_functions/pubspec.yaml index 01dc55e8ad0e..243eb4c37e5c 100644 --- a/packages/cloud_functions/cloud_functions/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions/pubspec.yaml @@ -1,6 +1,6 @@ name: cloud_functions description: A Flutter plugin allowing you to use Firebase Cloud Functions. -version: 6.3.2 +version: 6.3.3 resolution: workspace homepage: https://firebase.google.com/docs/functions repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_functions_platform_interface: ^6.0.2 - cloud_functions_web: ^5.1.8 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + cloud_functions_platform_interface: ^6.0.3 + cloud_functions_web: ^5.1.9 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter diff --git a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md index 8238e18b3c1e..71b37c8b6c4a 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.3 + + - Update a dependency to the latest release. + ## 6.0.2 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml index 4c7df1baa665..298c86cec507 100644 --- a/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_platform_interface/pubspec.yaml @@ -5,7 +5,7 @@ repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_fun # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 6.0.2 +version: 6.0.3 resolution: workspace environment: @@ -13,14 +13,14 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md index 38e93f128498..8ec1fc957392 100644 --- a/packages/cloud_functions/cloud_functions_web/CHANGELOG.md +++ b/packages/cloud_functions/cloud_functions_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.1.9 + + - Update a dependency to the latest release. + ## 5.1.8 - Update a dependency to the latest release. diff --git a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart index c4cc8e8cb6af..065006fb014e 100644 --- a/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart +++ b/packages/cloud_functions/cloud_functions_web/lib/src/cloud_functions_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.3.2'; +const packageVersion = '6.3.3'; diff --git a/packages/cloud_functions/cloud_functions_web/pubspec.yaml b/packages/cloud_functions/cloud_functions_web/pubspec.yaml index 3135d2a2e580..11e8e305cda9 100644 --- a/packages/cloud_functions/cloud_functions_web/pubspec.yaml +++ b/packages/cloud_functions/cloud_functions_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of cloud_functions homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_functions/cloud_functions_web -version: 5.1.8 +version: 5.1.9 resolution: workspace environment: @@ -11,9 +11,9 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions_platform_interface: ^6.0.2 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 + cloud_functions_platform_interface: ^6.0.3 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 flutter: sdk: flutter flutter_web_plugins: @@ -21,7 +21,7 @@ dependencies: web: ^1.1.1 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index 6150180a2058..5bb326ac31b7 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,3 +1,11 @@ +## 3.13.0 + + - **FIX**(ai): firebase_ai server template image inputs passed as InlineDataPart were serialized as normal generative inlineData ([#18350](https://github.com/firebase/flutterfire/issues/18350)). ([f3c53792](https://github.com/firebase/flutterfire/commit/f3c53792f1acf19ab1c2c7c3d157fca3a183b5d1)) + - **FEAT**(firebaseai): Add speech config and TTS sample page ([#18358](https://github.com/firebase/flutterfire/issues/18358)). ([0af51b50](https://github.com/firebase/flutterfire/commit/0af51b501603a611c7c6800efd9d98c478abab4d)) + - **FEAT**(ai): add language code support for SpeechConfig ([#18353](https://github.com/firebase/flutterfire/issues/18353)). ([3471afc7](https://github.com/firebase/flutterfire/commit/3471afc7ffa7bae58981683982d58d669ac71d50)) + - **FEAT**(ai): add mediaResolution parameter ([#18354](https://github.com/firebase/flutterfire/issues/18354)). ([79547569](https://github.com/firebase/flutterfire/commit/795475692384385a17511b295640ad6f8ab625f6)) + - **FEAT**(ai): add support for cancellable clients for in-flight requests ([#18349](https://github.com/firebase/flutterfire/issues/18349)). ([566cfed4](https://github.com/firebase/flutterfire/commit/566cfed42599318cf0f24eefc5d696223e46128c)) + ## 3.12.2 - Update a dependency to the latest release. diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index 54c54a17901a..81b51bd0abc4 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -23,9 +23,9 @@ dependencies: camera: ^0.12.0+1 cupertino_icons: ^1.0.6 - firebase_ai: ^3.12.2 - firebase_core: ^4.10.0 - firebase_storage: ^13.4.2 + firebase_ai: ^3.13.0 + firebase_core: ^4.11.0 + firebase_storage: ^13.4.3 flutter: sdk: flutter flutter_animate: ^4.5.2 diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart index f22c6b444513..dadc0f336cec 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.3.0+3'; +const packageVersion = '0.3.0+4'; diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index 7e7cb3731c59..840e07588312 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI Logic SDK. -version: 3.12.2 +version: 3.13.0 resolution: workspace homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: @@ -21,10 +21,10 @@ environment: flutter: ">=3.16.0" dependencies: - firebase_app_check: ^0.4.4+2 - firebase_auth: ^6.5.2 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_app_check: ^0.4.5 + firebase_auth: ^6.5.3 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter http: ^1.1.0 diff --git a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md index 14388f20e359..ea4beafd4ce1 100644 --- a/packages/firebase_analytics/firebase_analytics/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.4.3 + + - **FIX**(analytics,iOS): update iOS dependency instructions for IDFA-free usage ([#18337](https://github.com/firebase/flutterfire/issues/18337)). ([c21fc77b](https://github.com/firebase/flutterfire/commit/c21fc77b68a87b9691fc1615454c5dac39dd4ed4)) + ## 12.4.2 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml index 8cf3373a2454..9a7913f98582 100755 --- a/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.2 - firebase_core: ^4.10.0 + firebase_analytics: ^12.4.3 + firebase_core: ^4.11.0 flutter: sdk: flutter in_app_purchase: ^3.2.3 diff --git a/packages/firebase_analytics/firebase_analytics/pubspec.yaml b/packages/firebase_analytics/firebase_analytics/pubspec.yaml index b9c1dbaf1d2e..921d71b0baa6 100755 --- a/packages/firebase_analytics/firebase_analytics/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics/pubspec.yaml @@ -4,7 +4,7 @@ description: solution that provides insight on app usage and user engagement on Android and iOS. homepage: https://firebase.google.com/docs/analytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics -version: 12.4.2 +version: 12.4.3 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics_platform_interface: ^6.0.2 - firebase_analytics_web: ^0.6.1+8 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_analytics_platform_interface: ^6.0.3 + firebase_analytics_web: ^0.6.1+9 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md index 6e3bd6bbec3f..5a7a0c8acac8 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.3 + + - Update a dependency to the latest release. + ## 6.0.2 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml index a2943142e0f3..e4e6b4346487 100644 --- a/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_platform_interface description: A common platform interface for the firebase_analytics plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_platform_interface -version: 6.0.2 +version: 6.0.3 resolution: workspace environment: @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter pigeon: 26.3.4 diff --git a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md index 0a45170f90d5..1eff940b91ce 100644 --- a/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md +++ b/packages/firebase_analytics/firebase_analytics_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.1+9 + + - Update a dependency to the latest release. + ## 0.6.1+8 - Update a dependency to the latest release. diff --git a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart index ef292c6ef4f2..5ae950bfa0b5 100644 --- a/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart +++ b/packages/firebase_analytics/firebase_analytics_web/lib/src/firebase_analytics_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.4.2'; +const packageVersion = '12.4.3'; diff --git a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml index 1c4ed3660da5..fb7a006cfb7b 100644 --- a/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml +++ b/packages/firebase_analytics/firebase_analytics_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_analytics_web description: The web implementation of firebase_analytics homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_analytics/firebase_analytics_web -version: 0.6.1+8 +version: 0.6.1+9 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_analytics_platform_interface: ^6.0.2 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 + _flutterfire_internals: ^1.3.73 + firebase_analytics_platform_interface: ^6.0.3 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md index 91b6517e88c3..ee988ff330aa 100644 --- a/packages/firebase_app_check/firebase_app_check/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.5 + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + ## 0.4.4+2 - Update a dependency to the latest release. diff --git a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml index 72614cde959d..c652ec309fe8 100644 --- a/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/example/pubspec.yaml @@ -11,9 +11,9 @@ environment: flutter: '>=3.27.0' dependencies: - cloud_firestore: ^6.5.0 - firebase_app_check: ^0.4.4+2 - firebase_core: ^4.10.0 + cloud_firestore: ^6.6.0 + firebase_app_check: ^0.4.5 + firebase_core: ^4.11.0 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift index b11b6dfc1d0e..28a2ec57bc1b 100644 --- a/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift +++ b/packages/firebase_app_check/firebase_app_check/ios/firebase_app_check/Sources/firebase_app_check/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.4+2" +public let versionNumber = "0.4.5" diff --git a/packages/firebase_app_check/firebase_app_check/pubspec.yaml b/packages/firebase_app_check/firebase_app_check/pubspec.yaml index 3def275e7ff9..605a2914b2f6 100644 --- a/packages/firebase_app_check/firebase_app_check/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_app_check description: App Check works alongside other Firebase services to help protect your backend resources from abuse, such as billing fraud or phishing. homepage: https://firebase.google.com/docs/app-check repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check -version: 0.4.4+2 +version: 0.4.5 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_check_platform_interface: ^0.4.0+2 - firebase_app_check_web: ^0.2.4+3 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_app_check_platform_interface: ^0.4.1 + firebase_app_check_web: ^0.2.5 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md index 2de79fe09408..00c7fb3e4937 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + ## 0.4.0+2 - Update a dependency to the latest release. diff --git a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml index 263db479caa7..ee66bbb1fca0 100644 --- a/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_platform_interface/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_platform_interface description: A common platform interface for the firebase_app_check plugin. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_platform_interface -version: 0.4.0+2 +version: 0.4.1 resolution: workspace environment: @@ -9,15 +9,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md index 6d7350e574cc..fd2e9954aac8 100644 --- a/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md +++ b/packages/firebase_app_check/firebase_app_check_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.5 + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + ## 0.2.4+3 - Update a dependency to the latest release. diff --git a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart index e143129de7ca..5e2793aa9166 100644 --- a/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart +++ b/packages/firebase_app_check/firebase_app_check_web/lib/src/firebase_app_check_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.4+2'; +const packageVersion = '0.4.5'; diff --git a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml index 52417bf7fa33..2e52290f7f64 100644 --- a/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml +++ b/packages/firebase_app_check/firebase_app_check_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_app_check_web description: The web implementation of firebase_app_check homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_check/firebase_app_check_web -version: 0.2.4+3 +version: 0.2.5 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_app_check_platform_interface: ^0.4.0+2 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 + _flutterfire_internals: ^1.3.73 + firebase_app_check_platform_interface: ^0.4.1 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 flutter: sdk: flutter flutter_web_plugins: @@ -21,7 +21,7 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md index 33ede781c342..387cd4d64fe3 100644 --- a/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+4 + + - Update a dependency to the latest release. + ## 0.4.2+3 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml index 95832dbeffa3..56d8d3b8a94f 100644 --- a/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/example/pubspec.yaml @@ -11,8 +11,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_app_installations: ^0.4.2+3 + firebase_core: ^4.11.0 + firebase_app_installations: ^0.4.2+4 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift index fc15ead900f2..2e6a3b8195d8 100644 --- a/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift +++ b/packages/firebase_app_installations/firebase_app_installations/ios/firebase_app_installations/Sources/firebase_app_installations/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2+3" +public let versionNumber = "0.4.2+4" diff --git a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml index 6299d7967809..76cf8f419538 100644 --- a/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations description: A Flutter plugin allowing you to use Firebase Installations. -version: 0.4.2+3 +version: 0.4.2+4 resolution: workspace homepage: https://firebase.google.com/docs/projects/manage-installations#flutter repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_app_installations_platform_interface: ^0.1.4+71 - firebase_app_installations_web: ^0.1.7+8 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_app_installations_platform_interface: ^0.1.4+72 + firebase_app_installations_web: ^0.1.7+9 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md index 21683e87b2e3..093953d2ece0 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+72 + + - Update a dependency to the latest release. + ## 0.1.4+71 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml index 64d10dd9bbdc..6710e216bc45 100644 --- a/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_platform_interface description: A common platform interface for the firebase_app_installations plugin. -version: 0.1.4+71 +version: 0.1.4+72 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_platform_interface @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md index 80e0d4b48ab1..75ae2b8f134f 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md +++ b/packages/firebase_app_installations/firebase_app_installations_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.7+9 + + - Update a dependency to the latest release. + ## 0.1.7+8 - Update a dependency to the latest release. diff --git a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart index 4bcc9cc38b98..e26978d18006 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart +++ b/packages/firebase_app_installations/firebase_app_installations_web/lib/src/firebase_app_installations_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.4.2+3'; +const packageVersion = '0.4.2+4'; diff --git a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml index 7fa7cf26ab51..b7d74891d862 100644 --- a/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml +++ b/packages/firebase_app_installations/firebase_app_installations_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_app_installations_web description: The web implementation of firebase_app_installations. -version: 0.1.7+8 +version: 0.1.7+9 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_app_installations/firebase_app_installations_web @@ -10,17 +10,17 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_app_installations_platform_interface: ^0.1.4+71 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 + _flutterfire_internals: ^1.3.73 + firebase_app_installations_platform_interface: ^0.1.4+72 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_auth/firebase_auth/CHANGELOG.md b/packages/firebase_auth/firebase_auth/CHANGELOG.md index 2018745da16f..3b7f98b4fadd 100644 --- a/packages/firebase_auth/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.5.3 + + - Update a dependency to the latest release. + ## 6.5.2 - **FIX**(auth,android): update token retrieval in PigeonParser to handle Number type correctly ([#18328](https://github.com/firebase/flutterfire/issues/18328)). ([3b77147b](https://github.com/firebase/flutterfire/commit/3b77147bc00bb19af5f4821436a1a4cdd8ff6791)) diff --git a/packages/firebase_auth/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/firebase_auth/example/pubspec.yaml index d4945ff996a9..05cd94c9150e 100644 --- a/packages/firebase_auth/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/example/pubspec.yaml @@ -8,9 +8,9 @@ environment: dependencies: barcode_widget: ^2.0.4 - firebase_auth: ^6.5.2 - firebase_core: ^4.10.0 - firebase_messaging: ^16.3.0 + firebase_auth: ^6.5.3 + firebase_core: ^4.11.0 + firebase_messaging: ^16.4.0 flutter: sdk: flutter flutter_facebook_auth: ^7.1.5 diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index 8c5d6ca619c2..e687407db159 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "6.5.2" +let libraryVersion = "6.5.3" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index 7e5367f65668..d49db8749cba 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "6.5.2" +let libraryVersion = "6.5.3" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_auth/firebase_auth/pubspec.yaml b/packages/firebase_auth/firebase_auth/pubspec.yaml index d559a058e9fa..75a5a05fc800 100755 --- a/packages/firebase_auth/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling like Google, Facebook and Twitter. homepage: https://firebase.google.com/docs/auth repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth -version: 6.5.2 +version: 6.5.3 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.16.0' dependencies: - firebase_auth_platform_interface: ^9.0.2 - firebase_auth_web: ^6.2.2 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_auth_platform_interface: ^9.0.3 + firebase_auth_web: ^6.2.3 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md index 28e508b89d1e..bff12ebd7d1b 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 9.0.3 + + - Update a dependency to the latest release. + ## 9.0.2 - **DOCS**(auth): clarify behavior of password reset email with email enumeration protection enabled ([#18296](https://github.com/firebase/flutterfire/issues/18296)). ([0bcce87a](https://github.com/firebase/flutterfire/commit/0bcce87a17830797dae6ff3c1a8ba4ce210c2c0d)) diff --git a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart index e1f83202ff97..d01fedccb150 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/lib/src/method_channel/utils/exception.dart @@ -42,9 +42,12 @@ FirebaseException platformExceptionToFirebaseAuthException( .replaceAll('ERROR_', '') .toLowerCase() .replaceAll('_', '-'); + final details = platformException.details is Map + ? platformException.details as Map + : null; final customCode = _getCustomCode( - platformException.details, + details, platformException.message, ); if (customCode != null) { @@ -60,12 +63,10 @@ FirebaseException platformExceptionToFirebaseAuthException( AuthCredential? credential; String? email; - if (platformException.details != null) { - if (platformException.details['authCredential'] != null && - platformException.details['authCredential'] - is InternalAuthCredential) { - InternalAuthCredential pigeonAuthCredential = - platformException.details['authCredential']; + if (details != null) { + if (details['authCredential'] != null && + details['authCredential'] is InternalAuthCredential) { + InternalAuthCredential pigeonAuthCredential = details['authCredential']; credential = AuthCredential( providerId: pigeonAuthCredential.providerId, @@ -75,8 +76,8 @@ FirebaseException platformExceptionToFirebaseAuthException( ); } - if (platformException.details['email'] != null) { - email = platformException.details['email']; + if (details['email'] != null) { + email = details['email']; } } diff --git a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml index 778b1ce6d0aa..53a9c3386020 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_au repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 9.0.2 +version: 9.0.3 resolution: workspace environment: @@ -12,9 +12,9 @@ environment: flutter: '>=3.16.0' dependencies: - _flutterfire_internals: ^1.3.72 + _flutterfire_internals: ^1.3.73 collection: ^1.16.0 - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter http: ^1.1.0 @@ -22,7 +22,7 @@ dependencies: plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.4.0 diff --git a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart index 2fdfb6df6271..5669b1e6aa9e 100644 --- a/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart +++ b/packages/firebase_auth/firebase_auth_platform_interface/test/method_channel_tests/utils_tests/exception_test.dart @@ -50,9 +50,47 @@ void main() { ), ); }); + + test('should catch a [PlatformException] with non-Map details', () async { + PlatformException platformException = PlatformException( + code: 'ERROR_INTERNAL_ERROR', + message: 'An internal error has occurred', + details: 'Native error details', + ); + + expect( + () => convertPlatformException(platformException, StackTrace.empty), + throwsA( + isA() + .having((e) => e.code, 'code', 'internal-error') + .having( + (e) => e.message, + 'message', + 'An internal error has occurred', + ), + ), + ); + }); }); group('platformExceptionToFirebaseAuthException()', () { + test('handles non-Map pigeon details', () { + PlatformException platformException = PlatformException( + code: 'ERROR_INTERNAL_ERROR', + message: 'An internal error has occurred', + details: 'Native error details', + ); + + FirebaseAuthException result = platformExceptionToFirebaseAuthException( + platformException, + ) as FirebaseAuthException; + + expect(result.code, equals('internal-error')); + expect(result.message, equals('An internal error has occurred')); + expect(result.email, isNull); + expect(result.credential, isNull); + }); + test('sets code to default value', () { AuthCredential authCredential = const AuthCredential( providerId: 'testProviderId', diff --git a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md index 0538fc7ce19c..e4f18e958bc1 100644 --- a/packages/firebase_auth/firebase_auth_web/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.2.3 + + - Update a dependency to the latest release. + ## 6.2.2 - Update a dependency to the latest release. diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart index 5351a5a16546..3b927bd0b786 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.2'; +const packageVersion = '6.5.3'; diff --git a/packages/firebase_auth/firebase_auth_web/pubspec.yaml b/packages/firebase_auth/firebase_auth_web/pubspec.yaml index ec422dd434b5..a004fee15b81 100644 --- a/packages/firebase_auth/firebase_auth_web/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_auth_web description: The web implementation of firebase_auth homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth_web -version: 6.2.2 +version: 6.2.3 resolution: workspace environment: @@ -10,9 +10,9 @@ environment: flutter: '>=3.22.0' dependencies: - firebase_auth_platform_interface: ^9.0.2 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 + firebase_auth_platform_interface: ^9.0.3 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_core/firebase_core/CHANGELOG.md b/packages/firebase_core/firebase_core/CHANGELOG.md index e8fcbe2a2d90..a6a7c965ecbd 100644 --- a/packages/firebase_core/firebase_core/CHANGELOG.md +++ b/packages/firebase_core/firebase_core/CHANGELOG.md @@ -1,3 +1,10 @@ +## 4.11.0 + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + - **FEAT**(core): bump Firebase ios SDK to 12.15.0 ([#18375](https://github.com/firebase/flutterfire/issues/18375)). ([4d083764](https://github.com/firebase/flutterfire/commit/4d083764c3abd94d6e4590a170fbdaaa4b161202)) + - **FEAT**(core): bump Firebase android SDK to 34.15.0 ([#18374](https://github.com/firebase/flutterfire/issues/18374)). ([1cd3a0bd](https://github.com/firebase/flutterfire/commit/1cd3a0bd76fd594139356519fabee0e0d2b12f31)) + - **FEAT**(core): Add Recaptcha Site Key to FirebaseOptions ([#18334](https://github.com/firebase/flutterfire/issues/18334)). ([57be7027](https://github.com/firebase/flutterfire/commit/57be702778d34b9b7e86b40817d93acaec4c3ca4)) + ## 4.10.0 - **FEAT**(core): bump Firebase ios SDK to 12.14.0 ([#18330](https://github.com/firebase/flutterfire/issues/18330)). ([b1cfe745](https://github.com/firebase/flutterfire/commit/b1cfe745d221f09665943762c83cdd64684c6e6c)) diff --git a/packages/firebase_core/firebase_core/example/pubspec.yaml b/packages/firebase_core/firebase_core/example/pubspec.yaml index a5489ddbd498..e90d66a06680 100644 --- a/packages/firebase_core/firebase_core/example/pubspec.yaml +++ b/packages/firebase_core/firebase_core/example/pubspec.yaml @@ -7,7 +7,7 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter diff --git a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift index 0080eea73902..2aa49bcdf308 100644 --- a/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/ios/firebase_core/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersionString = "4.10.0" +let libraryVersionString = "4.11.0" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift index 76ca886cb995..ebf94947c34b 100644 --- a/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift +++ b/packages/firebase_core/firebase_core/macos/firebase_core/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersionString = "4.10.0" +let libraryVersionString = "4.11.0" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_core/firebase_core/pubspec.yaml b/packages/firebase_core/firebase_core/pubspec.yaml index ec426a170d59..7cd0fe7e59cb 100644 --- a/packages/firebase_core/firebase_core/pubspec.yaml +++ b/packages/firebase_core/firebase_core/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Core, enabling connecting to multiple Firebase apps. homepage: https://firebase.google.com/docs/flutter/setup repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core -version: 4.10.0 +version: 4.11.0 resolution: workspace topics: - firebase @@ -17,8 +17,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core_platform_interface: ^7.0.1 - firebase_core_web: ^3.8.0 + firebase_core_platform_interface: ^7.1.0 + firebase_core_web: ^3.9.0 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md b/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md index 55beefdaa877..7a2bed6fa102 100644 --- a/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_platform_interface/CHANGELOG.md @@ -1,3 +1,8 @@ +## 7.1.0 + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + - **FEAT**(core): Add Recaptcha Site Key to FirebaseOptions ([#18334](https://github.com/firebase/flutterfire/issues/18334)). ([57be7027](https://github.com/firebase/flutterfire/commit/57be702778d34b9b7e86b40817d93acaec4c3ca4)) + ## 7.0.1 - **FIX**(core,iOS): use namespaced iOS Pigeon header import ([#18281](https://github.com/firebase/flutterfire/issues/18281)). ([7c1257e7](https://github.com/firebase/flutterfire/commit/7c1257e7295f9ba67f3f5820493f105a14d34d52)) diff --git a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml index 4eb784d0d021..5e994a589e5a 100644 --- a/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml +++ b/packages/firebase_core/firebase_core_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_co repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 7.0.1 +version: 7.1.0 resolution: workspace environment: diff --git a/packages/firebase_core/firebase_core_web/CHANGELOG.md b/packages/firebase_core/firebase_core_web/CHANGELOG.md index 6b75c49b7dd0..5fc2c8fd90a6 100644 --- a/packages/firebase_core/firebase_core_web/CHANGELOG.md +++ b/packages/firebase_core/firebase_core_web/CHANGELOG.md @@ -1,3 +1,9 @@ +## 3.9.0 + + - **FEAT**(appcheck): appcheck reCAPTCHA mobile support (gradually rolling out) ([#18261](https://github.com/firebase/flutterfire/issues/18261)). ([036a860a](https://github.com/firebase/flutterfire/commit/036a860a0e66d46b5c57eb3df3a0f9e5846ef00b)) + - **FEAT**(core): bump Firebase web SDK to 12.15.0 ([#18376](https://github.com/firebase/flutterfire/issues/18376)). ([22eb4d5d](https://github.com/firebase/flutterfire/commit/22eb4d5d0f3f14207e080e9c9fc8373052258ef4)) + - **FEAT**(core): Add Recaptcha Site Key to FirebaseOptions ([#18334](https://github.com/firebase/flutterfire/issues/18334)). ([57be7027](https://github.com/firebase/flutterfire/commit/57be702778d34b9b7e86b40817d93acaec4c3ca4)) + ## 3.8.0 - **FEAT**(core): bump Firebase web SDK to 12.14.0 ([#18331](https://github.com/firebase/flutterfire/issues/18331)). ([3f31a88a](https://github.com/firebase/flutterfire/commit/3f31a88ab6ad96914f427e292b919b6465cf4996)) diff --git a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart index eda9aff3d0fc..b30db3ebafec 100644 --- a/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart +++ b/packages/firebase_core/firebase_core_web/lib/src/firebase_core_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '4.10.0'; +const packageVersion = '4.11.0'; diff --git a/packages/firebase_core/firebase_core_web/pubspec.yaml b/packages/firebase_core/firebase_core_web/pubspec.yaml index 8cc5a1448f0f..c04a1f978ffb 100644 --- a/packages/firebase_core/firebase_core_web/pubspec.yaml +++ b/packages/firebase_core/firebase_core_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_core_web description: The web implementation of firebase_core homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_core/firebase_core_web -version: 3.8.0 +version: 3.9.0 resolution: workspace environment: @@ -10,7 +10,7 @@ environment: flutter: '>=3.22.0' dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md index 4c5828d063e0..3935a1bb77e5 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.2.4 + + - Update a dependency to the latest release. + ## 5.2.3 - Update a dependency to the latest release. diff --git a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml index f10713cc4179..80285ca58403 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/example/pubspec.yaml @@ -7,9 +7,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.2 - firebase_core: ^4.10.0 - firebase_crashlytics: ^5.2.3 + firebase_analytics: ^12.4.3 + firebase_core: ^4.11.0 + firebase_crashlytics: ^5.2.4 flutter: sdk: flutter diff --git a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift index 52abad688be9..304276713365 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/ios/firebase_crashlytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "5.2.3" +let libraryVersion = "5.2.4" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift index 688d2aeada02..f386382b93cf 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift +++ b/packages/firebase_crashlytics/firebase_crashlytics/macos/firebase_crashlytics/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "5.2.3" +let libraryVersion = "5.2.4" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml index bbfc54d297c2..9c7b33d58dc0 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 5.2.3 +version: 5.2.4 resolution: workspace homepage: https://firebase.google.com/docs/crashlytics repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics @@ -20,9 +20,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_crashlytics_platform_interface: ^3.8.23 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_crashlytics_platform_interface: ^3.8.24 flutter: sdk: flutter stack_trace: ^1.10.0 diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md index 71491658215c..518c200d25aa 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.8.24 + + - Update a dependency to the latest release. + ## 3.8.23 - Update a dependency to the latest release. diff --git a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml index 64a89fdc4234..f2a9fbbc723a 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml +++ b/packages/firebase_crashlytics/firebase_crashlytics_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_crashlytics_platform_interface description: A common platform interface for the firebase_crashlytics plugin. -version: 3.8.23 +version: 3.8.24 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_crashlytics/firebase_crashlytics_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 + _flutterfire_internals: ^1.3.73 collection: ^1.15.0 - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md index e8f2eae2e258..eed3ac938eda 100644 --- a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md +++ b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+4 + + - Update a dependency to the latest release. + ## 0.3.0+3 - Update a dependency to the latest release. diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index 6968fe1eb773..6a66ad2477d3 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -13,16 +13,16 @@ environment: dependencies: flutter: sdk: flutter - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 google_sign_in: ^6.1.0 - firebase_auth: ^6.5.2 + firebase_auth: ^6.5.3 firebase_data_connect: path: ../ cupertino_icons: ^1.0.6 flutter_rating_bar: ^4.0.1 protobuf: ^3.1.0 - firebase_app_check: ^0.4.4+2 + firebase_app_check: ^0.4.5 dev_dependencies: build_runner: ^2.3.3 diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart index 15f614400c2f..462675913477 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// version number for the package, should be align with pubspec.yaml. -const packageVersion = '0.3.0+3'; +const packageVersion = '0.3.0+4'; diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index 34df0b12dd1e..681de7546e35 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_data_connect description: 'Flutter plugin for Firebase Data Connect, a relational database service that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL.' -version: 0.3.0+3 +version: 0.3.0+4 resolution: workspace homepage: https://firebase.google.com/docs/data-connect/quickstart?platform=flutter false_secrets: @@ -13,10 +13,10 @@ environment: dependencies: crypto: ^3.0.6 - firebase_app_check: ^0.4.4+2 - firebase_auth: ^6.5.2 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 + firebase_app_check: ^0.4.5 + firebase_auth: ^6.5.3 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 fixnum: ^1.1.1 flutter: sdk: flutter @@ -31,8 +31,8 @@ dependencies: dev_dependencies: build_runner: ^2.4.12 - firebase_app_check_platform_interface: ^0.4.0+2 - firebase_auth_platform_interface: ^9.0.2 + firebase_app_check_platform_interface: ^0.4.1 + firebase_auth_platform_interface: ^9.0.3 flutter_lints: ^6.0.0 flutter_test: sdk: flutter diff --git a/packages/firebase_database/firebase_database/CHANGELOG.md b/packages/firebase_database/firebase_database/CHANGELOG.md index 3e112c5c8d10..902feea3e65d 100644 --- a/packages/firebase_database/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/firebase_database/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.4.3 + + - Update a dependency to the latest release. + ## 12.4.2 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database/example/pubspec.yaml b/packages/firebase_database/firebase_database/example/pubspec.yaml index 495579667ce3..a086c7957152 100755 --- a/packages/firebase_database/firebase_database/example/pubspec.yaml +++ b/packages/firebase_database/firebase_database/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_database: ^12.4.2 + firebase_core: ^4.11.0 + firebase_database: ^12.4.3 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index d895419bf4cf..12f1b8b035d1 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "12.4.2" +let libraryVersion = "12.4.3" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index 7c49a085ea0d..d9f4a4a782ae 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "12.4.2" +let libraryVersion = "12.4.3" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index d5a57955f1ff..4353e8f0a53c 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. homepage: https://firebase.google.com/docs/database repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database -version: 12.4.2 +version: 12.4.3 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_database_platform_interface: ^0.4.0+2 - firebase_database_web: ^0.2.7+9 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_database_platform_interface: ^0.4.0+3 + firebase_database_web: ^0.2.7+10 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md index de01cef222b3..22029dd973e2 100755 --- a/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.0+3 + + - Update a dependency to the latest release. + ## 0.4.0+2 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml index e8a36dfbaa96..ff978b08c9fc 100755 --- a/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml +++ b/packages/firebase_database/firebase_database_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_platform_interface description: A common platform interface for the firebase_database plugin. -version: 0.4.0+2 +version: 0.4.0+3 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_platform_interface @@ -9,16 +9,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 + _flutterfire_internals: ^1.3.73 collection: ^1.14.3 - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.2 diff --git a/packages/firebase_database/firebase_database_web/CHANGELOG.md b/packages/firebase_database/firebase_database_web/CHANGELOG.md index 47761d5d87bd..adcbb395042f 100644 --- a/packages/firebase_database/firebase_database_web/CHANGELOG.md +++ b/packages/firebase_database/firebase_database_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.7+10 + + - Update a dependency to the latest release. + ## 0.2.7+9 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart index ef292c6ef4f2..5ae950bfa0b5 100644 --- a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.4.2'; +const packageVersion = '12.4.3'; diff --git a/packages/firebase_database/firebase_database_web/pubspec.yaml b/packages/firebase_database/firebase_database_web/pubspec.yaml index 517f77c419dc..42b3063bc3c9 100644 --- a/packages/firebase_database/firebase_database_web/pubspec.yaml +++ b/packages/firebase_database/firebase_database_web/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_database_web description: The web implementation of firebase_database -version: 0.2.7+9 +version: 0.2.7+10 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database_web @@ -10,16 +10,16 @@ environment: dependencies: collection: ^1.18.0 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 - firebase_database_platform_interface: ^0.4.0+2 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 + firebase_database_platform_interface: ^0.4.0+3 flutter: sdk: flutter flutter_web_plugins: sdk: flutter dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter flutter_lints: ^6.0.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md index e4616da45bb5..62726a23b7e2 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2+4 + + - Update a dependency to the latest release. + ## 0.9.2+3 - Update a dependency to the latest release. diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml index 71f63d2126f3..5b7c6222409c 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/example/pubspec.yaml @@ -8,10 +8,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_analytics: ^12.4.2 - firebase_core: ^4.10.0 - firebase_in_app_messaging: ^0.9.2+3 - firebase_in_app_messaging_platform_interface: ^0.2.5+23 + firebase_analytics: ^12.4.3 + firebase_core: ^4.11.0 + firebase_in_app_messaging: ^0.9.2+4 + firebase_in_app_messaging_platform_interface: ^0.2.5+24 flutter: sdk: flutter diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift index 6cd63b4f83c8..7a0a9c0a68d0 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/ios/firebase_in_app_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "0.9.2-3" +let libraryVersion = "0.9.2-4" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml index 88bd5d6b871d..4667d8612f0d 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_in_app_messaging description: Flutter plugin for Firebase In-App Messaging. -version: 0.9.2+3 +version: 0.9.2+4 resolution: workspace homepage: https://firebase.google.com/docs/in-app-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_in_app_messaging_platform_interface: ^0.2.5+23 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_in_app_messaging_platform_interface: ^0.2.5+24 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md index 199f096d87de..4ff64dde37bc 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.5+24 + + - Update a dependency to the latest release. + ## 0.2.5+23 - Update a dependency to the latest release. diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml index b136ddc599bc..41e9ce87d2a3 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the firebase_in_app_messaging plugi homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_in_app_messaging/firebase_in_app_messagin_platform_interface -version: 0.2.5+23 +version: 0.2.5+24 resolution: workspace environment: @@ -11,14 +11,14 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter diff --git a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md index 7e4f180e0d34..6875615ff2a1 100644 --- a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md @@ -1,3 +1,8 @@ +## 16.4.0 + + - **FIX**(messaging,ios): fix a race condition that could happen when getting initial message ([#18352](https://github.com/firebase/flutterfire/issues/18352)). ([77396b81](https://github.com/firebase/flutterfire/commit/77396b81ae56943a38c23b429249b0b9cbd4bc21)) + - **FEAT**(messaging,ios): add support for actionIdentifier on iOS devices ([#18357](https://github.com/firebase/flutterfire/issues/18357)). ([d60af4d9](https://github.com/firebase/flutterfire/commit/d60af4d9e1345c113490e875c85bd9ac62dad935)) + ## 16.3.0 - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index d9d7fa996837..23b76e909a1a 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_messaging: ^16.3.0 + firebase_core: ^4.11.0 + firebase_messaging: ^16.4.0 flutter: sdk: flutter flutter_local_notifications: ^21.0.0 diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index 18784af00022..d619affbdf30 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "16.3.0" +let libraryVersion = "16.4.0" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index f91b6fc3ecb2..bde751bc41cc 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "16.3.0" +let libraryVersion = "16.4.0" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_messaging/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/pubspec.yaml index 6837ec856e4e..e27001039e4e 100644 --- a/packages/firebase_messaging/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. homepage: https://firebase.google.com/docs/cloud-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging -version: 16.3.0 +version: 16.4.0 resolution: workspace topics: - firebase @@ -18,10 +18,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_messaging_platform_interface: ^4.8.0 - firebase_messaging_web: ^4.2.0 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_messaging_platform_interface: ^4.9.0 + firebase_messaging_web: ^4.2.1 flutter: sdk: flutter meta: ^1.8.0 diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md index 9d3eac10bb81..819ee4094334 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.9.0 + + - **FEAT**(messaging,ios): add support for actionIdentifier on iOS devices ([#18357](https://github.com/firebase/flutterfire/issues/18357)). ([d60af4d9](https://github.com/firebase/flutterfire/commit/d60af4d9e1345c113490e875c85bd9ac62dad935)) + ## 4.8.0 - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) diff --git a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml index 779bc3f5c651..898d483ec248 100644 --- a/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_messaging_platform_interface description: A common platform interface for the firebase_messaging plugin. -version: 4.8.0 +version: 4.9.0 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_platform_interface @@ -10,15 +10,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md index a6d684fd425a..63be15929d2b 100644 --- a/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.2.1 + + - Update a dependency to the latest release. + ## 4.2.0 - **FEAT**(messaging,web): add support for custom service worker script path in `getToken` method ([#18290](https://github.com/firebase/flutterfire/issues/18290)). ([b37722db](https://github.com/firebase/flutterfire/commit/b37722db13548aca57b3a24ba0f27b5de021be02)) diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart index 3094ad1dfb37..51998e4d285d 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '16.3.0'; +const packageVersion = '16.4.0'; diff --git a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml index 22dc76ad722c..c01c9de8ade4 100644 --- a/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_messaging_web description: The web implementation of firebase_messaging homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging_web -version: 4.2.0 +version: 4.2.1 resolution: workspace environment: @@ -10,10 +10,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 - firebase_messaging_platform_interface: ^4.8.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 + firebase_messaging_platform_interface: ^4.9.0 flutter: sdk: flutter flutter_web_plugins: @@ -22,7 +22,7 @@ dependencies: web: ^1.0.0 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md index 524d08186d64..117f4710460a 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.2+4 + + - Update a dependency to the latest release. + ## 0.4.2+3 - Update a dependency to the latest release. diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml index 4adc9fc6d2a9..59798dc7aed1 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/example/pubspec.yaml @@ -12,8 +12,8 @@ dependencies: flutter: sdk: flutter - firebase_core: ^4.10.0 - firebase_ml_model_downloader: ^0.4.2+3 + firebase_core: ^4.11.0 + firebase_ml_model_downloader: ^0.4.2+4 dev_dependencies: flutter_lints: ^6.0.0 diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift index fc15ead900f2..2e6a3b8195d8 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/ios/firebase_ml_model_downloader/Sources/firebase_ml_model_downloader/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "0.4.2+3" +public let versionNumber = "0.4.2+4" diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml index 6546173101f4..26f00b2fa077 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader description: A Flutter plugin allowing you to use Firebase Ml Model Downloader. -version: 0.4.2+3 +version: 0.4.2+4 resolution: workspace homepage: https://firebase.google.com/docs/ml/flutter/use-custom-models repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader @@ -18,9 +18,9 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_ml_model_downloader_platform_interface: ^0.1.5+23 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_ml_model_downloader_platform_interface: ^0.1.5+24 flutter: sdk: flutter diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md index 3fa53ef8b6f5..5965a9ea6644 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5+24 + + - Update a dependency to the latest release. + ## 0.1.5+23 - Update a dependency to the latest release. diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml index 8dd1812fc071..d1dc2f74d473 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ml_model_downloader_platform_interface description: A common platform interface for the firebase_ml_model_downloader plugin. -version: 0.1.5+23 +version: 0.1.5+24 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_ml_model_downloader/firebase_ml_model_downloader_platform_interface @@ -10,14 +10,14 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_performance/firebase_performance/CHANGELOG.md b/packages/firebase_performance/firebase_performance/CHANGELOG.md index 3fc0d4b19850..b8507b5bf931 100644 --- a/packages/firebase_performance/firebase_performance/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.11.4+3 + + - Update a dependency to the latest release. + ## 0.11.4+2 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance/example/pubspec.yaml b/packages/firebase_performance/firebase_performance/example/pubspec.yaml index 2f95bb40c267..a461975acb21 100644 --- a/packages/firebase_performance/firebase_performance/example/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_performance: ^0.11.4+2 + firebase_core: ^4.11.0 + firebase_performance: ^0.11.4+3 flutter: sdk: flutter http: ^1.0.0 diff --git a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift index dff9cf422bdd..0c98e15d060a 100644 --- a/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift +++ b/packages/firebase_performance/firebase_performance/ios/firebase_performance/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "0.11.4-2" +let libraryVersion = "0.11.4-3" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_performance/firebase_performance/pubspec.yaml b/packages/firebase_performance/firebase_performance/pubspec.yaml index f1efe47bbdca..64487a310848 100644 --- a/packages/firebase_performance/firebase_performance/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance/pubspec.yaml @@ -5,7 +5,7 @@ description: iOS. homepage: https://firebase.google.com/docs/perf-mon repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance -version: 0.11.4+2 +version: 0.11.4+3 resolution: workspace topics: - firebase @@ -21,10 +21,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_performance_platform_interface: ^0.2.0+2 - firebase_performance_web: ^0.1.8+8 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_performance_platform_interface: ^0.2.0+3 + firebase_performance_web: ^0.1.8+9 flutter: sdk: flutter diff --git a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md index 920a623d6d49..4108e365daca 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0+3 + + - Update a dependency to the latest release. + ## 0.2.0+2 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml index b2570eb69d05..a2bd31242d8a 100644 --- a/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_performance_platform_interface description: A common platform interface for the firebase_performance plugin. -version: 0.2.0+2 +version: 0.2.0+3 resolution: workspace homepage: https://firebase.google.com/docs/perf-mon/flutter/get-started @@ -9,15 +9,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter pigeon: 26.3.4 diff --git a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md index 3a89643a8c64..366e8731fb1d 100644 --- a/packages/firebase_performance/firebase_performance_web/CHANGELOG.md +++ b/packages/firebase_performance/firebase_performance_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8+9 + + - Update a dependency to the latest release. + ## 0.1.8+8 - Update a dependency to the latest release. diff --git a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart index 255778793f09..462fc9d7e82a 100644 --- a/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart +++ b/packages/firebase_performance/firebase_performance_web/lib/src/firebase_performance_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.11.4+2'; +const packageVersion = '0.11.4+3'; diff --git a/packages/firebase_performance/firebase_performance_web/pubspec.yaml b/packages/firebase_performance/firebase_performance_web/pubspec.yaml index 55b45f611c7c..3ec46cc78e2a 100644 --- a/packages/firebase_performance/firebase_performance_web/pubspec.yaml +++ b/packages/firebase_performance/firebase_performance_web/pubspec.yaml @@ -1,7 +1,7 @@ name: firebase_performance_web description: Web implementation of Firebase Performance monitoring. homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_performance/firebase_performance_web -version: 0.1.8+8 +version: 0.1.8+9 resolution: workspace environment: @@ -9,10 +9,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 - firebase_performance_platform_interface: ^0.2.0+2 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 + firebase_performance_platform_interface: ^0.2.0+3 flutter: sdk: flutter flutter_web_plugins: diff --git a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md index d0bcb89e6655..dcf9d7e976e6 100644 --- a/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.5.3 + + - Update a dependency to the latest release. + ## 6.5.2 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml index 4587601f52c9..d78f440ce15b 100644 --- a/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/example/pubspec.yaml @@ -9,8 +9,8 @@ environment: dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - firebase_core: ^4.10.0 - firebase_remote_config: ^6.5.2 + firebase_core: ^4.11.0 + firebase_remote_config: ^6.5.3 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift index 0541cf200ad6..a80378388ef9 100644 --- a/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift +++ b/packages/firebase_remote_config/firebase_remote_config/ios/firebase_remote_config/Sources/firebase_remote_config/Constants.swift @@ -3,4 +3,4 @@ // found in the LICENSE file. /// Auto-generated file. Do not edit. -public let versionNumber = "6.5.2" +public let versionNumber = "6.5.3" diff --git a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml index 148239b17b22..ebd5e1e14f2d 100644 --- a/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config/pubspec.yaml @@ -4,7 +4,7 @@ description: re-releasing. homepage: https://firebase.google.com/docs/remote-config repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config -version: 6.5.2 +version: 6.5.3 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_remote_config_platform_interface: ^3.0.2 - firebase_remote_config_web: ^1.10.9 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_remote_config_platform_interface: ^3.0.3 + firebase_remote_config_web: ^1.10.10 flutter: sdk: flutter diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md index 613e250aecc5..69f88aa1c97b 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.0.3 + + - Update a dependency to the latest release. + ## 3.0.2 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml index a4e13e30ca2e..cd08bec8ce61 100644 --- a/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_re repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 3.0.2 +version: 3.0.3 resolution: workspace environment: @@ -12,15 +12,15 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md index fbfedb61c59c..a6ac5f7f5ece 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md +++ b/packages/firebase_remote_config/firebase_remote_config_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.10 + + - Update a dependency to the latest release. + ## 1.10.9 - Update a dependency to the latest release. diff --git a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart index 5351a5a16546..3b927bd0b786 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart +++ b/packages/firebase_remote_config/firebase_remote_config_web/lib/src/firebase_remote_config_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.2'; +const packageVersion = '6.5.3'; diff --git a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml index ba8ac04ee536..23aac942e5ea 100644 --- a/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml +++ b/packages/firebase_remote_config/firebase_remote_config_web/pubspec.yaml @@ -3,7 +3,7 @@ description: The web implementation of firebase_remote_config homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_remote_config/firebase_remote_config_web -version: 1.10.9 +version: 1.10.10 resolution: workspace environment: @@ -11,10 +11,10 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 - firebase_remote_config_platform_interface: ^3.0.2 + _flutterfire_internals: ^1.3.73 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 + firebase_remote_config_platform_interface: ^3.0.3 flutter: sdk: flutter flutter_web_plugins: @@ -22,7 +22,7 @@ dependencies: dev_dependencies: build_runner: ^2.3.3 - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_storage/firebase_storage/CHANGELOG.md b/packages/firebase_storage/firebase_storage/CHANGELOG.md index d618e079120b..195f5e8984c0 100644 --- a/packages/firebase_storage/firebase_storage/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage/CHANGELOG.md @@ -1,3 +1,7 @@ +## 13.4.3 + + - Update a dependency to the latest release. + ## 13.4.2 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage/example/pubspec.yaml b/packages/firebase_storage/firebase_storage/example/pubspec.yaml index 93cf6b6cabf9..b6c7fd6c00ba 100755 --- a/packages/firebase_storage/firebase_storage/example/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/example/pubspec.yaml @@ -7,8 +7,8 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_storage: ^13.4.2 + firebase_core: ^4.11.0 + firebase_storage: ^13.4.3 flutter: sdk: flutter image_picker: ^1.1.2 diff --git a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift index 43f4b656a206..968917087c67 100644 --- a/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/ios/firebase_storage/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "13.4.2" +let libraryVersion = "13.4.3" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift index aeb81c040fdc..e14f91280ac1 100644 --- a/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift +++ b/packages/firebase_storage/firebase_storage/macos/firebase_storage/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "13.4.2" +let libraryVersion = "13.4.3" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_storage/firebase_storage/pubspec.yaml b/packages/firebase_storage/firebase_storage/pubspec.yaml index ceffd8cb4fdf..45bccdd06158 100755 --- a/packages/firebase_storage/firebase_storage/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS. homepage: https://firebase.google.com/docs/storage/flutter/start repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage -version: 13.4.2 +version: 13.4.3 resolution: workspace topics: - firebase @@ -20,10 +20,10 @@ environment: flutter: '>=3.27.0' dependencies: - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_storage_platform_interface: ^6.0.2 - firebase_storage_web: ^3.11.8 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_storage_platform_interface: ^6.0.3 + firebase_storage_web: ^3.11.9 flutter: sdk: flutter mime: ^2.0.0 diff --git a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md index 1ce02076f1eb..34ad71f0e918 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.0.3 + + - Update a dependency to the latest release. + ## 6.0.2 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml index 1d91f519d7db..fc2d1d2a11de 100644 --- a/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_storage_platform_interface description: A common platform interface for the firebase_storage plugin. -version: 6.0.2 +version: 6.0.3 resolution: workspace homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_platform_interface @@ -10,16 +10,16 @@ environment: flutter: '>=3.27.0' dependencies: - _flutterfire_internals: ^1.3.72 + _flutterfire_internals: ^1.3.73 collection: ^1.15.0 - firebase_core: ^4.10.0 + firebase_core: ^4.11.0 flutter: sdk: flutter meta: ^1.8.0 plugin_platform_interface: ^2.1.3 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md index f4837884ab38..c2e357a071b3 100644 --- a/packages/firebase_storage/firebase_storage_web/CHANGELOG.md +++ b/packages/firebase_storage/firebase_storage_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.11.9 + + - Update a dependency to the latest release. + ## 3.11.8 - Update a dependency to the latest release. diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart index 3e3d25ef6fcd..68ee68ba7f8f 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '13.4.2'; +const packageVersion = '13.4.3'; diff --git a/packages/firebase_storage/firebase_storage_web/pubspec.yaml b/packages/firebase_storage/firebase_storage_web/pubspec.yaml index cab7da4cca23..a6cc41d54e2e 100644 --- a/packages/firebase_storage/firebase_storage_web/pubspec.yaml +++ b/packages/firebase_storage/firebase_storage_web/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_storage_web description: The web implementation of firebase_storage homepage: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_storage/firebase_storage_web -version: 3.11.8 +version: 3.11.9 resolution: workspace environment: @@ -10,11 +10,11 @@ environment: flutter: '>=3.22.0' dependencies: - _flutterfire_internals: ^1.3.72 + _flutterfire_internals: ^1.3.73 async: ^2.5.0 - firebase_core: ^4.10.0 - firebase_core_web: ^3.8.0 - firebase_storage_platform_interface: ^6.0.2 + firebase_core: ^4.11.0 + firebase_core_web: ^3.9.0 + firebase_storage_platform_interface: ^6.0.3 flutter: sdk: flutter flutter_web_plugins: @@ -24,7 +24,7 @@ dependencies: web: ^1.0.0 dev_dependencies: - firebase_core_platform_interface: ^7.0.1 + firebase_core_platform_interface: ^7.1.0 flutter_test: sdk: flutter mockito: ^5.0.0 diff --git a/scripts/versions.json b/scripts/versions.json index 2e948eeed641..fb3b516b8ba3 100644 --- a/scripts/versions.json +++ b/scripts/versions.json @@ -1,4 +1,32 @@ { + "4.16.0": { + "date": "2026-06-17", + "firebase_sdk": { + "android": "34.15.0", + "ios": "12.15.0", + "web": "12.15.0", + "windows": "13.5.0" + }, + "packages": { + "cloud_firestore": "6.6.0", + "cloud_functions": "6.3.3", + "firebase_ai": "3.13.0", + "firebase_analytics": "12.4.3", + "firebase_app_check": "0.4.5", + "firebase_app_installations": "0.4.2+4", + "firebase_auth": "6.5.3", + "firebase_core": "4.11.0", + "firebase_crashlytics": "5.2.4", + "firebase_data_connect": "0.3.0+4", + "firebase_database": "12.4.3", + "firebase_in_app_messaging": "0.9.2+4", + "firebase_messaging": "16.4.0", + "firebase_ml_model_downloader": "0.4.2+4", + "firebase_performance": "0.11.4+3", + "firebase_remote_config": "6.5.3", + "firebase_storage": "13.4.3" + } + }, "4.15.0": { "date": "2026-06-01", "firebase_sdk": { diff --git a/tests/android/gradle.properties b/tests/android/gradle.properties index 3b5b324f6e3f..1551eb080642 100644 --- a/tests/android/gradle.properties +++ b/tests/android/gradle.properties @@ -1,3 +1,7 @@ org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/tests/integration_test/e2e_test.dart b/tests/integration_test/e2e_test.dart index 12511585363c..094897c954de 100644 --- a/tests/integration_test/e2e_test.dart +++ b/tests/integration_test/e2e_test.dart @@ -89,7 +89,7 @@ void main() { } void runAllTests() { - firebase_core.main(); + firebase_core.main(includeRecaptchaTests: false); firebase_ai.main(); firebase_auth.main(); firebase_database.main(); @@ -103,4 +103,5 @@ void runAllTests() { firebase_remote_config.main(); firebase_storage.main(); firebase_app_check.main(); + firebase_core.recaptchaMain(); } diff --git a/tests/integration_test/firebase_core/firebase_core_e2e_test.dart b/tests/integration_test/firebase_core/firebase_core_e2e_test.dart index f7759ed5035c..bb8349369128 100644 --- a/tests/integration_test/firebase_core/firebase_core_e2e_test.dart +++ b/tests/integration_test/firebase_core/firebase_core_e2e_test.dart @@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:tests/firebase_options.dart'; -void main() { +void main({bool includeRecaptchaTests = true}) { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); group('firebase_core', () { @@ -76,12 +76,37 @@ void main() { test('FirebaseApp.setAutomaticResourceManagementEnabled()', () async { FirebaseApp app = Firebase.app(testAppName); - await app.setAutomaticResourceManagementEnabled(true); + try { + await app.setAutomaticResourceManagementEnabled(true); + } finally { + await app.setAutomaticResourceManagementEnabled(false); + } + }); + }); + + if (includeRecaptchaTests) { + recaptchaMain(); + } +} + +void recaptchaMain() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + group('firebase_core recaptcha', () { + setUpAll(() async { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); }); test('Firebase.initializeApp with recaptchaSiteKey', () async { String appName = 'recaptcha-test-app'; - FirebaseOptions options = DefaultFirebaseOptions.currentPlatform.copyWith( + FirebaseOptions options = (defaultTargetPlatform == TargetPlatform.android + ? DefaultFirebaseOptions.currentPlatform.copyWith( + appId: '1:1234567890:android:fedcba0987654321fedcba', + ) + : DefaultFirebaseOptions.currentPlatform) + .copyWith( recaptchaSiteKey: 'test-recaptcha-site-key', ); diff --git a/tests/pubspec.yaml b/tests/pubspec.yaml index 004abfe9653f..c76e0a380153 100644 --- a/tests/pubspec.yaml +++ b/tests/pubspec.yaml @@ -10,43 +10,43 @@ environment: flutter: '>=3.22.0' dependencies: - cloud_functions: ^6.3.2 - cloud_functions_platform_interface: ^6.0.2 - cloud_functions_web: ^5.1.8 + cloud_functions: ^6.3.3 + cloud_functions_platform_interface: ^6.0.3 + cloud_functions_web: ^5.1.9 collection: ^1.15.0 - firebase_ai: ^3.12.2 - firebase_analytics: ^12.4.2 - firebase_analytics_platform_interface: ^6.0.2 - firebase_analytics_web: ^0.6.1+8 - firebase_app_check: ^0.4.4+2 - firebase_app_check_platform_interface: ^0.4.0+2 - firebase_app_check_web: ^0.2.4+3 - firebase_app_installations: ^0.4.2+3 - firebase_app_installations_platform_interface: ^0.1.4+71 - firebase_app_installations_web: ^0.1.7+8 - firebase_auth: ^6.5.2 - firebase_auth_platform_interface: ^9.0.2 - firebase_auth_web: ^6.2.2 - firebase_core: ^4.10.0 - firebase_core_platform_interface: ^7.0.1 - firebase_core_web: ^3.8.0 - firebase_crashlytics: ^5.2.3 - firebase_crashlytics_platform_interface: ^3.8.23 - firebase_database: ^12.4.2 - firebase_database_platform_interface: ^0.4.0+2 - firebase_database_web: ^0.2.7+9 - firebase_messaging: ^16.3.0 - firebase_messaging_platform_interface: ^4.8.0 - firebase_messaging_web: ^4.2.0 - firebase_ml_model_downloader: ^0.4.2+3 - firebase_ml_model_downloader_platform_interface: ^0.1.5+23 - firebase_performance: ^0.11.4+2 - firebase_remote_config: ^6.5.2 - firebase_remote_config_platform_interface: ^3.0.2 - firebase_remote_config_web: ^1.10.9 - firebase_storage: ^13.4.2 - firebase_storage_platform_interface: ^6.0.2 - firebase_storage_web: ^3.11.8 + firebase_ai: ^3.13.0 + firebase_analytics: ^12.4.3 + firebase_analytics_platform_interface: ^6.0.3 + firebase_analytics_web: ^0.6.1+9 + firebase_app_check: ^0.4.5 + firebase_app_check_platform_interface: ^0.4.1 + firebase_app_check_web: ^0.2.5 + firebase_app_installations: ^0.4.2+4 + firebase_app_installations_platform_interface: ^0.1.4+72 + firebase_app_installations_web: ^0.1.7+9 + firebase_auth: ^6.5.3 + firebase_auth_platform_interface: ^9.0.3 + firebase_auth_web: ^6.2.3 + firebase_core: ^4.11.0 + firebase_core_platform_interface: ^7.1.0 + firebase_core_web: ^3.9.0 + firebase_crashlytics: ^5.2.4 + firebase_crashlytics_platform_interface: ^3.8.24 + firebase_database: ^12.4.3 + firebase_database_platform_interface: ^0.4.0+3 + firebase_database_web: ^0.2.7+10 + firebase_messaging: ^16.4.0 + firebase_messaging_platform_interface: ^4.9.0 + firebase_messaging_web: ^4.2.1 + firebase_ml_model_downloader: ^0.4.2+4 + firebase_ml_model_downloader_platform_interface: ^0.1.5+24 + firebase_performance: ^0.11.4+3 + firebase_remote_config: ^6.5.3 + firebase_remote_config_platform_interface: ^3.0.3 + firebase_remote_config_web: ^1.10.10 + firebase_storage: ^13.4.3 + firebase_storage_platform_interface: ^6.0.3 + firebase_storage_web: ^3.11.9 flutter: sdk: flutter http: ^1.0.0 From bad452875def7ec070ef3c11261eb8063f11f7de Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:21:37 +0000 Subject: [PATCH 127/137] fix(database, iOS): prevent duplicate database instance initialization in `FLTFirebaseDatabasePlugin` (#18373) --- .../FLTFirebaseDatabasePlugin.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift index d94bc937593f..469164b0256f 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Sources/firebase_database/FLTFirebaseDatabasePlugin.swift @@ -169,6 +169,12 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug app: DatabasePigeonFirebaseApp, host: String, port: Int64, completion: @escaping (Result) -> Void ) { + let instanceKey = databaseInstanceKey(app) + guard Self.cachedDatabaseInstances[instanceKey] == nil else { + completion(.success(())) + return + } + let database = getDatabaseFromPigeonApp(app) database.useEmulator(withHost: host, port: Int(port)) completion(.success(())) @@ -733,8 +739,12 @@ public class FLTFirebaseDatabasePlugin: NSObject, FlutterPlugin, FLTFirebasePlug // MARK: - Helper Methods + private func databaseInstanceKey(_ app: DatabasePigeonFirebaseApp) -> String { + app.appName + (app.databaseURL ?? "") + } + private func getDatabaseFromPigeonApp(_ app: DatabasePigeonFirebaseApp) -> Database { - let instanceKey = app.appName + (app.databaseURL ?? "") + let instanceKey = databaseInstanceKey(app) if let cachedInstance = Self.cachedDatabaseInstances[instanceKey] { return cachedInstance From 48d67196a10affe09724529df5f67cf40b62bccf Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Thu, 18 Jun 2026 11:23:09 +0000 Subject: [PATCH 128/137] fix: resolve FlutterSceneLifeCycleDelegate conformance guard (#18385) --- .../firebase_auth/include/Public/FLTFirebaseAuthPlugin.h | 3 +-- .../firebase_messaging/include/FLTFirebaseMessagingPlugin.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/FLTFirebaseAuthPlugin.h b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/FLTFirebaseAuthPlugin.h index 552728aab958..53e20eca48b6 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/FLTFirebaseAuthPlugin.h +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Sources/firebase_auth/include/Public/FLTFirebaseAuthPlugin.h @@ -34,8 +34,7 @@ ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding #if !TARGET_OS_OSX -#if __has_include() || \ - defined(FlutterSceneLifeCycleDelegate) +#if __has_include() , FlutterSceneLifeCycleDelegate #endif diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/include/FLTFirebaseMessagingPlugin.h b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/include/FLTFirebaseMessagingPlugin.h index d233a4889764..23125d5dff3a 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/include/FLTFirebaseMessagingPlugin.h +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Sources/firebase_messaging/include/FLTFirebaseMessagingPlugin.h @@ -54,7 +54,7 @@ API_AVAILABLE(ios(10.0)) FLTFirebasePlugin, FIRMessagingDelegate, UIApplicationDelegate -#if __has_include() || defined(FlutterSceneLifeCycleDelegate) +#if __has_include() , FlutterSceneLifeCycleDelegate #endif @@ -63,7 +63,7 @@ API_AVAILABLE(ios(10.0)) @interface FLTFirebaseMessagingPlugin : FLTFirebasePlugin ) || defined(FlutterSceneLifeCycleDelegate) +#if __has_include() , FlutterSceneLifeCycleDelegate #endif From 6c28f8e499bafb3663d82c272e8adbfb430ca8b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jun 2026 13:45:29 +0200 Subject: [PATCH 129/137] chore(deps): bump protobufjs (#18380) Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.6.0 to 7.6.4. - [Release notes](https://github.com/protobufjs/protobuf.js/releases) - [Changelog](https://github.com/protobufjs/protobuf.js/blob/protobufjs-v7.6.4/CHANGELOG.md) - [Commits](https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.6.0...protobufjs-v7.6.4) --- updated-dependencies: - dependency-name: protobufjs dependency-version: 7.6.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../example/bundled-service-worker/yarn.lock | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock index a4bb680fac03..6a54b940e7bf 100644 --- a/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock +++ b/packages/firebase_messaging/firebase_messaging/example/bundled-service-worker/yarn.lock @@ -556,10 +556,10 @@ resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.5.tgz#d9315ad7cf3f30aac70bda3c068443dc6f143659" integrity sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g== -"@protobufjs/eventemitter@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" - integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== +"@protobufjs/eventemitter@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz#d512cb26c0ae026091ee2c1167f1be6faf5c842a" + integrity sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg== "@protobufjs/fetch@^1.1.1": version "1.1.1" @@ -573,11 +573,6 @@ resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== -"@protobufjs/inquire@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.2.tgz#ae64fbc014ff44c8bfad03dd4c93cd2d6a4c82db" - integrity sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw== - "@protobufjs/path@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" @@ -750,17 +745,16 @@ long@^5.3.2: integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== protobufjs@^7.2.5: - version "7.6.0" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.6.0.tgz#61e42285beec2708a9c84d7abbb5f22e2ddc54d4" - integrity sha512-LtESOsMPTZgyYtwxhvdgdjGL0HmXEaRA/hVD6sol4zA60hVXXXP/SGmxnqDbgGE8gy7pYex7cym+5vYPcmaXBQ== + version "7.6.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.6.4.tgz#8bb000300026efd63eb7951d26e5dbb38f5658f2" + integrity sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" "@protobufjs/codegen" "^2.0.5" - "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/eventemitter" "^1.1.1" "@protobufjs/fetch" "^1.1.1" "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.2" "@protobufjs/path" "^1.1.2" "@protobufjs/pool" "^1.1.0" "@protobufjs/utf8" "^1.1.1" From 80d8a19d26c65caf987600e9238399c3c8f9e568 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Thu, 18 Jun 2026 06:47:02 -0500 Subject: [PATCH 130/137] ci(ios): add ensure-simulator-ready script for reliable boot/ready waits (#18382) Port boot-status polling from react-native-firebase CI: wait for simctl bootstatus after simulator-action (or simctl boot) --- .github/workflows/e2e_tests_fdc.yaml | 12 +- .github/workflows/e2e_tests_pipeline.yaml | 6 + .github/workflows/ios.yaml | 7 +- .github/workflows/scripts/drive-example.sh | 9 +- .../scripts/ensure-simulator-ready.sh | 182 ++++++++++++++++++ 5 files changed, 206 insertions(+), 10 deletions(-) create mode 100755 .github/workflows/scripts/ensure-simulator-ready.sh diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 979e715f88ca..d840b38f2695 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -218,7 +218,13 @@ jobs: - uses: futureware-tech/simulator-action@e89aa8f93d3aec35083ff49d2854d07f7186f7f5 id: simulator with: + # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#installed-simulators model: "iPhone 16" + - name: Ensure Simulator Ready + env: + SIMULATOR: ${{ steps.simulator.outputs.udid }} + ENSURE_BOOT_IF_NEEDED: "0" + run: .github/workflows/scripts/ensure-simulator-ready.sh - name: 'E2E Tests' working-directory: 'packages/firebase_data_connect/firebase_data_connect/example' env: @@ -226,13 +232,11 @@ jobs: run: | # Uncomment following line to have simulator logs printed out for debugging purposes. # xcrun simctl spawn booted log stream --predicate 'eventMessage contains "flutter"' & - # The iOS simulator sometimes fails to connect the VM Service. Keep a - # limit around the full test command and retry once with a simulator reboot. + # Retry once after VM Service / simulator flake (reboot + migration-aware wait). perl -e 'alarm 900; exec @ARGV' -- flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --dart-define=CI=true --timeout 10x || { echo "First attempt failed or timed out. Rebooting simulator and retrying..." xcrun simctl shutdown "$SIMULATOR" || true - xcrun simctl boot "$SIMULATOR" - xcrun simctl bootstatus "$SIMULATOR" -b + "${GITHUB_WORKSPACE}/.github/workflows/scripts/ensure-simulator-ready.sh" flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --dart-define=CI=true --timeout 10x } - name: Save Firestore Emulator Cache diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index 4b101184499d..c45b311ee3ed 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -204,11 +204,17 @@ jobs: - uses: futureware-tech/simulator-action@e89aa8f93d3aec35083ff49d2854d07f7186f7f5 id: simulator with: + # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#installed-simulators model: "iPhone 16" - name: Build iOS (simulator) working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example run: | flutter build ios --no-codesign --simulator --debug --target=./integration_test/pipeline/pipeline_live_test.dart --dart-define=CI=true + - name: Ensure Simulator Ready + env: + SIMULATOR: ${{ steps.simulator.outputs.udid }} + ENSURE_BOOT_IF_NEEDED: "0" + run: .github/workflows/scripts/ensure-simulator-ready.sh - name: Run pipeline E2E tests (iOS) working-directory: packages/cloud_firestore/cloud_firestore/pipeline_example env: diff --git a/.github/workflows/ios.yaml b/.github/workflows/ios.yaml index fa88c610490c..1a8d7841ff5c 100644 --- a/.github/workflows/ios.yaml +++ b/.github/workflows/ios.yaml @@ -125,8 +125,13 @@ jobs: - uses: futureware-tech/simulator-action@e89aa8f93d3aec35083ff49d2854d07f7186f7f5 id: simulator with: - # List of available simulators: https://github.com/actions/runner-images/blob/main/images/macos/macos-14-Readme.md#installed-simulators + # List of available simulators: https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#installed-simulators model: "iPhone 16" + - name: Ensure Simulator Ready + env: + SIMULATOR: ${{ steps.simulator.outputs.udid }} + ENSURE_BOOT_IF_NEEDED: "0" + run: .github/workflows/scripts/ensure-simulator-ready.sh - name: 'E2E Tests' working-directory: ${{ matrix.working_directory }} env: diff --git a/.github/workflows/scripts/drive-example.sh b/.github/workflows/scripts/drive-example.sh index 2004a01b45ca..2c342e3f0fdd 100755 --- a/.github/workflows/scripts/drive-example.sh +++ b/.github/workflows/scripts/drive-example.sh @@ -13,12 +13,11 @@ fi if [ "$ACTION" == "ios" ] then - SIMULATOR="iPhone 14" - # Boot simulator and wait for System app to be ready. - xcrun simctl bootstatus "$SIMULATOR" -b + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + SIMULATOR="${SIMULATOR:-iPhone 16}" + export SIMULATOR + "${SCRIPT_DIR}/ensure-simulator-ready.sh" xcrun simctl logverbose "$SIMULATOR" enable - # Sleep to allow simulator to settle. - sleep 15 # Uncomment following line to have simulator logs printed out for debugging purposes. # xcrun simctl spawn booted log stream --predicate 'eventMessage contains "flutter"' & melos exec -c 1 --fail-fast --scope="$FLUTTERFIRE_PLUGIN_SCOPE_EXAMPLE" --dir-exists=integration_test -- \ diff --git a/.github/workflows/scripts/ensure-simulator-ready.sh b/.github/workflows/scripts/ensure-simulator-ready.sh new file mode 100755 index 000000000000..5a18a42f791a --- /dev/null +++ b/.github/workflows/scripts/ensure-simulator-ready.sh @@ -0,0 +1,182 @@ +#!/bin/bash + +# Wait until an iOS Simulator is fully ready for integration tests (including first-boot +# data migration). Intended to run after futureware-tech/simulator-action (or any step +# that has issued simctl boot) and before flutter test / flutter drive. +# +# Usage: +# SIMULATOR= ./ensure-simulator-ready.sh +# ./ensure-simulator-ready.sh +# +# Environment: +# SIMULATOR UDID or device name (required if not passed as arg) +# BOOT_POLL_INTERVAL_SECONDS Poll interval (default: 20) +# BOOT_PROBE_TIMEOUT_SECONDS Per-probe timeout (default: 12) +# BOOT_MAX_WAIT_SECONDS Max wait for full boot (default: 660) +# ENSURE_OPEN_SIMULATOR_APP Open Simulator.app when booting (default: 1) +# ENSURE_BOOT_IF_NEEDED simctl boot when not Booted yet (default: 1) +set -euo pipefail + +BOOT_POLL_INTERVAL_SECONDS="${BOOT_POLL_INTERVAL_SECONDS:-20}" +BOOT_PROBE_TIMEOUT_SECONDS="${BOOT_PROBE_TIMEOUT_SECONDS:-12}" +BOOT_MAX_WAIT_SECONDS="${BOOT_MAX_WAIT_SECONDS:-660}" +ENSURE_OPEN_SIMULATOR_APP="${ENSURE_OPEN_SIMULATOR_APP:-1}" +ENSURE_BOOT_IF_NEEDED="${ENSURE_BOOT_IF_NEEDED:-1}" + +DEVICE="${SIMULATOR:-${1:-}}" +if [[ -z "$DEVICE" ]]; then + echo "[boot-status] ERROR: set SIMULATOR or pass device UDID/name as first argument" >&2 + exit 1 +fi + +run_with_timeout() { + local max="$1" + shift + "$@" & + local cmd_pid=$! + local waited=0 + while kill -0 "$cmd_pid" 2>/dev/null && (( waited < max )); do + sleep 1 + waited=$((waited + 1)) + done + if kill -0 "$cmd_pid" 2>/dev/null; then + kill "$cmd_pid" 2>/dev/null + wait "$cmd_pid" 2>/dev/null || true + return 124 + fi + wait "$cmd_pid" +} + +log_boot_status() { + echo "[boot-status] $*" +} + +is_udid() { + [[ "$1" =~ ^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$ ]] +} + +describe_booted_device() { + local device="$1" + if is_udid "$device"; then + xcrun simctl list devices booted 2>/dev/null \ + | grep -F "$device" \ + | grep -v 'unavailable' \ + | head -1 \ + || true + else + xcrun simctl list devices booted 2>/dev/null \ + | grep -i "${device} (" \ + | grep -v 'Phone:' \ + | grep -v 'unavailable' \ + | grep -v CoreSimulator \ + | head -1 \ + || true + fi +} + +is_device_booted() { + [[ -n "$(describe_booted_device "$1")" ]] +} + +log_migration_status() { + local device="$1" + local migration_output probe_rc + + log_boot_status "probing data migration (bootstatus -d, up to ${BOOT_PROBE_TIMEOUT_SECONDS}s)..." + set +e + migration_output="$(run_with_timeout "$BOOT_PROBE_TIMEOUT_SECONDS" xcrun simctl bootstatus "$device" -d 2>&1)" + probe_rc=$? + set -e + + if [[ "$probe_rc" -eq 124 ]]; then + log_boot_status " data migration / system bring-up still in progress" + return 1 + fi + + if [[ -n "$migration_output" ]]; then + while IFS= read -r line; do + [[ -z "$line" ]] && continue + log_boot_status " ${line}" + done <<<"$migration_output" + else + log_boot_status " no migration details reported" + fi + return 0 +} + +wait_for_simulator_ready() { + local device="$1" + local start=$SECONDS + + while (( SECONDS - start < BOOT_MAX_WAIT_SECONDS )); do + local elapsed=$(( SECONDS - start )) + local booted_line ready_rc + + log_boot_status "elapsed=${elapsed}s phase=wait_for_full_boot device=\"${device}\"" + + booted_line="$(describe_booted_device "$device")" + if [[ -z "$booted_line" ]]; then + log_boot_status " simctl list: not in Booted state yet" + else + log_boot_status " simctl list: ${booted_line}" + log_migration_status "$device" || true + fi + + set +e + run_with_timeout "$BOOT_PROBE_TIMEOUT_SECONDS" xcrun simctl bootstatus "$device" >/dev/null 2>&1 + ready_rc=$? + set -e + + if [[ "$ready_rc" -eq 0 ]]; then + log_boot_status "bootstatus: simulator ready after ${elapsed}s" + log_migration_status "$device" || true + return 0 + fi + + if [[ "$ready_rc" -eq 124 ]]; then + log_boot_status "bootstatus: still booting (probe timed out after ${BOOT_PROBE_TIMEOUT_SECONDS}s)" + else + log_boot_status "bootstatus: probe exited with status ${ready_rc}" + fi + + sleep "$BOOT_POLL_INTERVAL_SECONDS" + done + + log_boot_status "ERROR: timed out after ${BOOT_MAX_WAIT_SECONDS}s waiting for simulator to become ready" + return 1 +} + +if is_udid "$DEVICE"; then + log_boot_status "phase=resolve_device udid=\"${DEVICE}\"" +else + log_boot_status "phase=resolve_device name=\"${DEVICE}\"" +fi + +if ! is_device_booted "$DEVICE"; then + if [[ "$ENSURE_BOOT_IF_NEEDED" == "1" ]]; then + log_boot_status "phase=boot_command device not Booted; starting simctl boot..." + set +e + boot_output="$(xcrun simctl boot "$DEVICE" 2>&1)" + boot_rc=$? + set -e + if [[ "$boot_rc" -ne 0 ]]; then + log_boot_status "simctl boot exited ${boot_rc}: ${boot_output}" + else + log_boot_status "simctl boot command returned (device may still be migrating data)" + fi + if [[ "$ENSURE_OPEN_SIMULATOR_APP" == "1" ]]; then + log_boot_status "phase=foreground_simulator opening Simulator.app..." + open -a Simulator.app || true + fi + else + log_boot_status "phase=boot_command skipped (ENSURE_BOOT_IF_NEEDED=0); waiting for existing boot..." + fi +else + log_boot_status "phase=boot_command device already Booted; waiting for full readiness..." +fi + +if ! wait_for_simulator_ready "$DEVICE"; then + exit 1 +fi + +log_boot_status "phase=complete device=\"${DEVICE}\" ready for flutter test" From ca60218b154acd35877738ca6bddde09729ed86d Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Mon, 22 Jun 2026 08:36:24 +0200 Subject: [PATCH 131/137] ci: fix running issues (#18379) * ci: fix running issues * fix * fix * fix * fix --- .../core/FlutterFirebaseCorePlugin.java | 10 +- .../test/firebase_core_test.dart | 70 +++++++++++ .../method_channel_firebase.dart | 114 ++++++++++++------ tests/integration_test/e2e_test.dart | 12 +- .../firebase_app_installations_e2e_test.dart | 25 ++-- 5 files changed, 174 insertions(+), 57 deletions(-) diff --git a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java index 0714b3bf7676..9763cfd0ab57 100644 --- a/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java +++ b/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java @@ -292,12 +292,10 @@ public void delete(@NonNull String appName, GeneratedAndroidFirebaseCore.VoidRes () -> { try { FirebaseApp firebaseApp = FirebaseApp.getInstance(appName); - try { - firebaseApp.delete(); - } catch (IllegalStateException appNotFoundException) { - // Ignore app not found exceptions. - } - + firebaseApp.delete(); + taskCompletionSource.setResult(null); + } catch (IllegalStateException appNotFoundException) { + // Ignore app not found exceptions. taskCompletionSource.setResult(null); } catch (Exception e) { taskCompletionSource.setException(e); diff --git a/packages/firebase_core/firebase_core/test/firebase_core_test.dart b/packages/firebase_core/firebase_core/test/firebase_core_test.dart index 4354f38c5824..cb2bf2f67e12 100755 --- a/packages/firebase_core/firebase_core/test/firebase_core_test.dart +++ b/packages/firebase_core/firebase_core/test/firebase_core_test.dart @@ -5,6 +5,9 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; +import 'package:firebase_core_platform_interface/src/pigeon/messages.pigeon.dart' + as pigeon; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; @@ -155,6 +158,73 @@ void main() { mock.app(expectedName), ]); }); + + test('.initializeApp() preserves recaptchaSiteKey if native drops it', + () async { + Firebase.delegatePackingProperty = null; + MethodChannelFirebase.appInstances.clear(); + MethodChannelFirebase.isCoreInitialized = false; + + const String appName = 'recaptcha-test-app'; + const FirebaseOptions options = FirebaseOptions( + apiKey: 'apiKey', + appId: 'appId', + messagingSenderId: 'messagingSenderId', + projectId: 'projectId', + recaptchaSiteKey: 'test-recaptcha-site-key', + ); + + final TestDefaultBinaryMessenger messenger = + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger; + + messenger.setMockMessageHandler( + 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeCore', + (ByteData? message) async { + return pigeon.FirebaseCoreHostApi.pigeonChannelCodec.encodeMessage( + [[]], + ); + }, + ); + messenger.setMockMessageHandler( + 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeApp', + (ByteData? message) async { + return pigeon.FirebaseCoreHostApi.pigeonChannelCodec.encodeMessage( + [ + pigeon.CoreInitializeResponse( + name: appName, + options: pigeon.CoreFirebaseOptions( + apiKey: options.apiKey, + appId: options.appId, + messagingSenderId: options.messagingSenderId, + projectId: options.projectId, + ), + pluginConstants: const {}, + ), + ], + ); + }, + ); + addTearDown(() { + messenger.setMockMessageHandler( + 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeCore', + null, + ); + messenger.setMockMessageHandler( + 'dev.flutter.pigeon.firebase_core_platform_interface.FirebaseCoreHostApi.initializeApp', + null, + ); + MethodChannelFirebase.appInstances.clear(); + MethodChannelFirebase.isCoreInitialized = false; + Firebase.delegatePackingProperty = null; + }); + + final FirebaseApp app = await Firebase.initializeApp( + name: appName, + options: options, + ); + + expect(app.options.recaptchaSiteKey, 'test-recaptcha-site-key'); + }); } class MockFirebaseCore extends Mock diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart index 0937f05f8243..2cc1755614cc 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart @@ -50,6 +50,40 @@ class MethodChannelFirebase extends FirebasePlatform { response.pluginConstants; } + CoreInitializeResponse _preserveRecaptchaSiteKey( + CoreInitializeResponse response, + FirebaseOptions options, + ) { + if (response.options.recaptchaSiteKey != null || + options.recaptchaSiteKey == null) { + return response; + } + + return CoreInitializeResponse( + name: response.name, + options: CoreFirebaseOptions( + apiKey: response.options.apiKey, + appId: response.options.appId, + messagingSenderId: response.options.messagingSenderId, + projectId: response.options.projectId, + authDomain: response.options.authDomain, + databaseURL: response.options.databaseURL, + storageBucket: response.options.storageBucket, + measurementId: response.options.measurementId, + trackingId: response.options.trackingId, + deepLinkURLScheme: response.options.deepLinkURLScheme, + androidClientId: response.options.androidClientId, + iosClientId: response.options.iosClientId, + iosBundleId: response.options.iosBundleId, + appGroupId: response.options.appGroupId, + recaptchaSiteKey: options.recaptchaSiteKey, + ), + isAutomaticDataCollectionEnabled: + response.isAutomaticDataCollectionEnabled, + pluginConstants: response.pluginConstants, + ); + } + /// Returns the created [FirebaseAppPlatform] instances. @override List get apps { @@ -90,25 +124,27 @@ class MethodChannelFirebase extends FirebasePlatform { // If no options are present & no default app has been setup, the user is // trying to initialize default from Dart if (defaultApp == null && _options != null) { - _initializeFirebaseAppFromMap(await api.initializeApp( - defaultFirebaseAppName, - CoreFirebaseOptions( - apiKey: _options.apiKey, - appId: _options.appId, - messagingSenderId: _options.messagingSenderId, - projectId: _options.projectId, - authDomain: _options.authDomain, - databaseURL: _options.databaseURL, - storageBucket: _options.storageBucket, - measurementId: _options.measurementId, - trackingId: _options.trackingId, - deepLinkURLScheme: _options.deepLinkURLScheme, - androidClientId: _options.androidClientId, - iosClientId: _options.iosClientId, - iosBundleId: _options.iosBundleId, - appGroupId: _options.appGroupId, - recaptchaSiteKey: _options.recaptchaSiteKey, - ))); + _initializeFirebaseAppFromMap(_preserveRecaptchaSiteKey( + await api.initializeApp( + defaultFirebaseAppName, + CoreFirebaseOptions( + apiKey: _options.apiKey, + appId: _options.appId, + messagingSenderId: _options.messagingSenderId, + projectId: _options.projectId, + authDomain: _options.authDomain, + databaseURL: _options.databaseURL, + storageBucket: _options.storageBucket, + measurementId: _options.measurementId, + trackingId: _options.trackingId, + deepLinkURLScheme: _options.deepLinkURLScheme, + androidClientId: _options.androidClientId, + iosClientId: _options.iosClientId, + iosBundleId: _options.iosBundleId, + appGroupId: _options.appGroupId, + recaptchaSiteKey: _options.recaptchaSiteKey, + )), + _options)); defaultApp = appInstances[defaultFirebaseAppName]; } @@ -157,25 +193,27 @@ class MethodChannelFirebase extends FirebasePlatform { } } - _initializeFirebaseAppFromMap(await api.initializeApp( - name, - CoreFirebaseOptions( - apiKey: options!.apiKey, - appId: options.appId, - messagingSenderId: options.messagingSenderId, - projectId: options.projectId, - authDomain: options.authDomain, - databaseURL: options.databaseURL, - storageBucket: options.storageBucket, - measurementId: options.measurementId, - trackingId: options.trackingId, - deepLinkURLScheme: options.deepLinkURLScheme, - androidClientId: options.androidClientId, - iosClientId: options.iosClientId, - iosBundleId: options.iosBundleId, - appGroupId: options.appGroupId, - recaptchaSiteKey: options.recaptchaSiteKey, - ))); + _initializeFirebaseAppFromMap(_preserveRecaptchaSiteKey( + await api.initializeApp( + name, + CoreFirebaseOptions( + apiKey: options!.apiKey, + appId: options.appId, + messagingSenderId: options.messagingSenderId, + projectId: options.projectId, + authDomain: options.authDomain, + databaseURL: options.databaseURL, + storageBucket: options.storageBucket, + measurementId: options.measurementId, + trackingId: options.trackingId, + deepLinkURLScheme: options.deepLinkURLScheme, + androidClientId: options.androidClientId, + iosClientId: options.iosClientId, + iosBundleId: options.iosBundleId, + appGroupId: options.appGroupId, + recaptchaSiteKey: options.recaptchaSiteKey, + )), + options)); return appInstances[name]!; } diff --git a/tests/integration_test/e2e_test.dart b/tests/integration_test/e2e_test.dart index 094897c954de..e4ef09e84009 100644 --- a/tests/integration_test/e2e_test.dart +++ b/tests/integration_test/e2e_test.dart @@ -51,10 +51,12 @@ void main() { return; } if (kIsWeb) { - firebase_core.main(); + // Web has its own ordering because App Check runs in a separate job and + // Auth can leave emulator state that interferes with Database tests. + firebase_core.main(includeRecaptchaTests: false); firebase_ai.main(); - firebase_auth.main(); firebase_database.main(); + firebase_auth.main(); firebase_crashlytics.main(); firebase_analytics.main(); cloud_functions.main(); @@ -64,6 +66,7 @@ void main() { firebase_performance.main(); firebase_remote_config.main(); firebase_storage.main(); + firebase_core.recaptchaMain(); return; } @@ -89,6 +92,9 @@ void main() { } void runAllTests() { + // Native platforms run the full suite in package order, but keep the + // recaptcha core tests before App Check because Android App Check activation + // changes native recaptcha configuration for later secondary app checks. firebase_core.main(includeRecaptchaTests: false); firebase_ai.main(); firebase_auth.main(); @@ -102,6 +108,6 @@ void runAllTests() { firebase_performance.main(); firebase_remote_config.main(); firebase_storage.main(); - firebase_app_check.main(); firebase_core.recaptchaMain(); + firebase_app_check.main(); } diff --git a/tests/integration_test/firebase_app_installations/firebase_app_installations_e2e_test.dart b/tests/integration_test/firebase_app_installations/firebase_app_installations_e2e_test.dart index 50562a38aa53..af34b20b0267 100644 --- a/tests/integration_test/firebase_app_installations/firebase_app_installations_e2e_test.dart +++ b/tests/integration_test/firebase_app_installations/firebase_app_installations_e2e_test.dart @@ -20,6 +20,11 @@ void main() { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); + if (defaultTargetPlatform == TargetPlatform.android) { + // Android Installations can deadlock if token/id APIs race native + // heartbeat initialization immediately after manual app init. + await Future.delayed(const Duration(seconds: 2)); + } }); test( @@ -47,6 +52,16 @@ void main() { skip: defaultTargetPlatform == TargetPlatform.macOS && isCI, ); + test( + '.getToken', + () async { + final token = await FirebaseInstallations.instance.getToken(); + expect(token, isNotEmpty); + // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 + }, + skip: defaultTargetPlatform == TargetPlatform.macOS, + ); + test( '.delete', () async { @@ -79,16 +94,6 @@ void main() { }, skip: defaultTargetPlatform == TargetPlatform.macOS, ); - - test( - '.getToken', - () async { - final token = await FirebaseInstallations.instance.getToken(); - expect(token, isNotEmpty); - // macOS skipped because it needs keychain sharing entitlement. See: https://github.com/firebase/flutterfire/issues/9538 - }, - skip: defaultTargetPlatform == TargetPlatform.macOS, - ); }, ); } From 7b01439002b31b1d0b4bbbd5d620a3fa7a1897b7 Mon Sep 17 00:00:00 2001 From: Jude Selase Kwashie <64037520+SelaseKay@users.noreply.github.com> Date: Mon, 22 Jun 2026 13:26:19 +0000 Subject: [PATCH 132/137] chore(release): publish packages (#18389) * chore(release): publish packages - firebase_auth@6.5.4 - firebase_database@12.4.4 - firebase_messaging@16.4.1 - firebase_ai@3.13.1 - firebase_data_connect@0.3.0+5 * chore: BoM Version 4.16.1 --- CHANGELOG.md | 40 +++++++++++++++++++ VERSIONS.md | 38 ++++++++++++++++++ packages/firebase_ai/firebase_ai/CHANGELOG.md | 4 ++ .../firebase_ai/example/pubspec.yaml | 2 +- .../lib/src/firebaseai_version.dart | 2 +- packages/firebase_ai/firebase_ai/pubspec.yaml | 4 +- .../firebase_auth/firebase_auth/CHANGELOG.md | 4 ++ .../firebase_auth/example/pubspec.yaml | 4 +- .../ios/firebase_auth/Package.swift | 2 +- .../macos/firebase_auth/Package.swift | 2 +- .../firebase_auth/firebase_auth/pubspec.yaml | 2 +- .../lib/src/firebase_auth_version.dart | 2 +- .../firebase_data_connect/CHANGELOG.md | 4 ++ .../example/pubspec.yaml | 2 +- .../lib/src/dataconnect_version.dart | 2 +- .../firebase_data_connect/pubspec.yaml | 4 +- .../firebase_database/CHANGELOG.md | 4 ++ .../firebase_database/example/pubspec.yaml | 2 +- .../ios/firebase_database/Package.swift | 2 +- .../macos/firebase_database/Package.swift | 2 +- .../firebase_database/pubspec.yaml | 2 +- .../lib/src/firebase_database_version.dart | 2 +- .../firebase_messaging/CHANGELOG.md | 4 ++ .../firebase_messaging/example/pubspec.yaml | 2 +- .../ios/firebase_messaging/Package.swift | 2 +- .../macos/firebase_messaging/Package.swift | 2 +- .../firebase_messaging/pubspec.yaml | 2 +- .../lib/src/firebase_messaging_version.dart | 2 +- scripts/versions.json | 28 +++++++++++++ tests/pubspec.yaml | 8 ++-- 30 files changed, 154 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f36264ac63f4..7588ab4f535c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,46 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2026-06-22 - [BoM 4.16.1](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4161-2026-06-22) + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`firebase_auth` - `v6.5.4`](#firebase_auth---v654) + - [`firebase_database` - `v12.4.4`](#firebase_database---v1244) + - [`firebase_messaging` - `v16.4.1`](#firebase_messaging---v1641) + - [`firebase_ai` - `v3.13.1`](#firebase_ai---v3131) + - [`firebase_data_connect` - `v0.3.0+5`](#firebase_data_connect---v0305) + +Packages with dependency updates only: + +> Packages listed below depend on other packages in this workspace that have had changes. Their versions have been incremented to bump the minimum dependency versions of the packages they depend upon in this project. + + - `firebase_ai` - `v3.13.1` + - `firebase_data_connect` - `v0.3.0+5` + +--- + +#### `firebase_auth` - `v6.5.4` + + - **FIX**: resolve FlutterSceneLifeCycleDelegate conformance guard ([#18385](https://github.com/firebase/flutterfire/issues/18385)). ([48d67196](https://github.com/firebase/flutterfire/commit/48d67196a10affe09724529df5f67cf40b62bccf)) + +#### `firebase_database` - `v12.4.4` + + - **FIX**(database,iOS): prevent duplicate database instance initialization in `FLTFirebaseDatabasePlugin` ([#18373](https://github.com/firebase/flutterfire/issues/18373)). ([bad45287](https://github.com/firebase/flutterfire/commit/bad452875def7ec070ef3c11261eb8063f11f7de)) + +#### `firebase_messaging` - `v16.4.1` + + - **FIX**: resolve FlutterSceneLifeCycleDelegate conformance guard ([#18385](https://github.com/firebase/flutterfire/issues/18385)). ([48d67196](https://github.com/firebase/flutterfire/commit/48d67196a10affe09724529df5f67cf40b62bccf)) + + ## 2026-06-17 - [BoM 4.16.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-4160-2026-06-17) ### Changes diff --git a/VERSIONS.md b/VERSIONS.md index af9edfa82d42..e3bc373d0cc6 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -4,6 +4,44 @@ This document is listing all the compatible versions of the FlutterFire plugins. # Versions +## [Flutter BoM 4.16.1 (2026-06-22)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-06-22) + +Install this version using FlutterFire CLI + +```bash +flutterfire install 4.16.1 +``` + +### Included Native Firebase SDK Versions +| Firebase SDK | Version | Link | +|--------------|---------|------| +| Android SDK | 34.15.0 | [Release Notes](https://firebase.google.com/support/release-notes/android) | +| iOS SDK | 12.15.0 | [Release Notes](https://firebase.google.com/support/release-notes/ios) | +| Web SDK | 12.15.0 | [Release Notes](https://firebase.google.com/support/release-notes/js) | +| Windows SDK | 13.5.0 | [Release Notes](https://firebase.google.com/support/release-notes/cpp-relnotes) | + +### FlutterFire Plugin Versions +| Plugin | Version | Dart Version | Flutter Version | +|--------|---------|--------------|-----------------| +| [cloud_firestore](https://pub.dev/packages/cloud_firestore/versions/6.6.0) | 6.6.0 | ^3.6.0 | >=3.27.0 | +| [cloud_functions](https://pub.dev/packages/cloud_functions/versions/6.3.3) | 6.3.3 | ^3.6.0 | >=3.27.0 | +| [firebase_ai](https://pub.dev/packages/firebase_ai/versions/3.13.1) | 3.13.1 | ^3.6.0 | >=3.16.0 | +| [firebase_analytics](https://pub.dev/packages/firebase_analytics/versions/12.4.3) | 12.4.3 | ^3.6.0 | >=3.27.0 | +| [firebase_app_check](https://pub.dev/packages/firebase_app_check/versions/0.4.5) | 0.4.5 | ^3.6.0 | >=3.27.0 | +| [firebase_app_installations](https://pub.dev/packages/firebase_app_installations/versions/0.4.2+4) | 0.4.2+4 | ^3.6.0 | >=3.27.0 | +| [firebase_auth](https://pub.dev/packages/firebase_auth/versions/6.5.4) | 6.5.4 | ^3.6.0 | >=3.16.0 | +| [firebase_core](https://pub.dev/packages/firebase_core/versions/4.11.0) | 4.11.0 | ^3.6.0 | >=3.27.0 | +| [firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics/versions/5.2.4) | 5.2.4 | ^3.6.0 | >=3.27.0 | +| [firebase_data_connect](https://pub.dev/packages/firebase_data_connect/versions/0.3.0+5) | 0.3.0+5 | ^3.6.0 | >=3.27.0 | +| [firebase_database](https://pub.dev/packages/firebase_database/versions/12.4.4) | 12.4.4 | ^3.6.0 | >=3.27.0 | +| [firebase_in_app_messaging](https://pub.dev/packages/firebase_in_app_messaging/versions/0.9.2+4) | 0.9.2+4 | ^3.6.0 | >=3.27.0 | +| [firebase_messaging](https://pub.dev/packages/firebase_messaging/versions/16.4.1) | 16.4.1 | ^3.6.0 | >=3.27.0 | +| [firebase_ml_model_downloader](https://pub.dev/packages/firebase_ml_model_downloader/versions/0.4.2+4) | 0.4.2+4 | ^3.6.0 | >=3.27.0 | +| [firebase_performance](https://pub.dev/packages/firebase_performance/versions/0.11.4+3) | 0.11.4+3 | ^3.6.0 | >=3.27.0 | +| [firebase_remote_config](https://pub.dev/packages/firebase_remote_config/versions/6.5.3) | 6.5.3 | ^3.6.0 | >=3.27.0 | +| [firebase_storage](https://pub.dev/packages/firebase_storage/versions/13.4.3) | 13.4.3 | ^3.6.0 | >=3.27.0 | + + ## [Flutter BoM 4.16.0 (2026-06-17)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2026-06-17) Install this version using FlutterFire CLI diff --git a/packages/firebase_ai/firebase_ai/CHANGELOG.md b/packages/firebase_ai/firebase_ai/CHANGELOG.md index 5bb326ac31b7..8f0e6f6744e3 100644 --- a/packages/firebase_ai/firebase_ai/CHANGELOG.md +++ b/packages/firebase_ai/firebase_ai/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.13.1 + + - Update a dependency to the latest release. + ## 3.13.0 - **FIX**(ai): firebase_ai server template image inputs passed as InlineDataPart were serialized as normal generative inlineData ([#18350](https://github.com/firebase/flutterfire/issues/18350)). ([f3c53792](https://github.com/firebase/flutterfire/commit/f3c53792f1acf19ab1c2c7c3d157fca3a183b5d1)) diff --git a/packages/firebase_ai/firebase_ai/example/pubspec.yaml b/packages/firebase_ai/firebase_ai/example/pubspec.yaml index 81b51bd0abc4..22e3bc9e71ee 100644 --- a/packages/firebase_ai/firebase_ai/example/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/example/pubspec.yaml @@ -23,7 +23,7 @@ dependencies: camera: ^0.12.0+1 cupertino_icons: ^1.0.6 - firebase_ai: ^3.13.0 + firebase_ai: ^3.13.1 firebase_core: ^4.11.0 firebase_storage: ^13.4.3 flutter: diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart index dadc0f336cec..bf472cb55ffa 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebaseai_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '0.3.0+4'; +const packageVersion = '0.3.0+5'; diff --git a/packages/firebase_ai/firebase_ai/pubspec.yaml b/packages/firebase_ai/firebase_ai/pubspec.yaml index 840e07588312..92d03c96661c 100644 --- a/packages/firebase_ai/firebase_ai/pubspec.yaml +++ b/packages/firebase_ai/firebase_ai/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_ai description: Firebase AI Logic SDK. -version: 3.13.0 +version: 3.13.1 resolution: workspace homepage: https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter topics: @@ -22,7 +22,7 @@ environment: dependencies: firebase_app_check: ^0.4.5 - firebase_auth: ^6.5.3 + firebase_auth: ^6.5.4 firebase_core: ^4.11.0 firebase_core_platform_interface: ^7.1.0 flutter: diff --git a/packages/firebase_auth/firebase_auth/CHANGELOG.md b/packages/firebase_auth/firebase_auth/CHANGELOG.md index 3b7f98b4fadd..b712b5e1e36a 100644 --- a/packages/firebase_auth/firebase_auth/CHANGELOG.md +++ b/packages/firebase_auth/firebase_auth/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.5.4 + + - **FIX**: resolve FlutterSceneLifeCycleDelegate conformance guard ([#18385](https://github.com/firebase/flutterfire/issues/18385)). ([48d67196](https://github.com/firebase/flutterfire/commit/48d67196a10affe09724529df5f67cf40b62bccf)) + ## 6.5.3 - Update a dependency to the latest release. diff --git a/packages/firebase_auth/firebase_auth/example/pubspec.yaml b/packages/firebase_auth/firebase_auth/example/pubspec.yaml index 05cd94c9150e..5068e9614644 100644 --- a/packages/firebase_auth/firebase_auth/example/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/example/pubspec.yaml @@ -8,9 +8,9 @@ environment: dependencies: barcode_widget: ^2.0.4 - firebase_auth: ^6.5.3 + firebase_auth: ^6.5.4 firebase_core: ^4.11.0 - firebase_messaging: ^16.4.0 + firebase_messaging: ^16.4.1 flutter: sdk: flutter flutter_facebook_auth: ^7.1.5 diff --git a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift index e687407db159..9793367d8229 100644 --- a/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/ios/firebase_auth/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "6.5.3" +let libraryVersion = "6.5.4" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift index d49db8749cba..d6451507d751 100644 --- a/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift +++ b/packages/firebase_auth/firebase_auth/macos/firebase_auth/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "6.5.3" +let libraryVersion = "6.5.4" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_auth/firebase_auth/pubspec.yaml b/packages/firebase_auth/firebase_auth/pubspec.yaml index 75a5a05fc800..ed5194bda425 100755 --- a/packages/firebase_auth/firebase_auth/pubspec.yaml +++ b/packages/firebase_auth/firebase_auth/pubspec.yaml @@ -4,7 +4,7 @@ description: Flutter plugin for Firebase Auth, enabling like Google, Facebook and Twitter. homepage: https://firebase.google.com/docs/auth repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_auth/firebase_auth -version: 6.5.3 +version: 6.5.4 resolution: workspace topics: - firebase diff --git a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart index 3b927bd0b786..ec220d667792 100644 --- a/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart +++ b/packages/firebase_auth/firebase_auth_web/lib/src/firebase_auth_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '6.5.3'; +const packageVersion = '6.5.4'; diff --git a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md index eed3ac938eda..471ecf4d462a 100644 --- a/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md +++ b/packages/firebase_data_connect/firebase_data_connect/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.0+5 + + - Update a dependency to the latest release. + ## 0.3.0+4 - Update a dependency to the latest release. diff --git a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml index 6a66ad2477d3..637a411ad07f 100644 --- a/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/example/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: sdk: flutter firebase_core: ^4.11.0 google_sign_in: ^6.1.0 - firebase_auth: ^6.5.3 + firebase_auth: ^6.5.4 firebase_data_connect: path: ../ diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart index 462675913477..e5a8a4417906 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/dataconnect_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// version number for the package, should be align with pubspec.yaml. -const packageVersion = '0.3.0+4'; +const packageVersion = '0.3.0+5'; diff --git a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml index 681de7546e35..bdc841a51a73 100644 --- a/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml +++ b/packages/firebase_data_connect/firebase_data_connect/pubspec.yaml @@ -1,6 +1,6 @@ name: firebase_data_connect description: 'Flutter plugin for Firebase Data Connect, a relational database service that lets you build and scale using a fully-managed PostgreSQL database powered by Cloud SQL.' -version: 0.3.0+4 +version: 0.3.0+5 resolution: workspace homepage: https://firebase.google.com/docs/data-connect/quickstart?platform=flutter false_secrets: @@ -14,7 +14,7 @@ environment: dependencies: crypto: ^3.0.6 firebase_app_check: ^0.4.5 - firebase_auth: ^6.5.3 + firebase_auth: ^6.5.4 firebase_core: ^4.11.0 firebase_core_platform_interface: ^7.1.0 fixnum: ^1.1.1 diff --git a/packages/firebase_database/firebase_database/CHANGELOG.md b/packages/firebase_database/firebase_database/CHANGELOG.md index 902feea3e65d..e7184d6478d2 100644 --- a/packages/firebase_database/firebase_database/CHANGELOG.md +++ b/packages/firebase_database/firebase_database/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.4.4 + + - **FIX**(database,iOS): prevent duplicate database instance initialization in `FLTFirebaseDatabasePlugin` ([#18373](https://github.com/firebase/flutterfire/issues/18373)). ([bad45287](https://github.com/firebase/flutterfire/commit/bad452875def7ec070ef3c11261eb8063f11f7de)) + ## 12.4.3 - Update a dependency to the latest release. diff --git a/packages/firebase_database/firebase_database/example/pubspec.yaml b/packages/firebase_database/firebase_database/example/pubspec.yaml index a086c7957152..fd0970d6a2e6 100755 --- a/packages/firebase_database/firebase_database/example/pubspec.yaml +++ b/packages/firebase_database/firebase_database/example/pubspec.yaml @@ -8,7 +8,7 @@ environment: dependencies: firebase_core: ^4.11.0 - firebase_database: ^12.4.3 + firebase_database: ^12.4.4 flutter: sdk: flutter diff --git a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift index 12f1b8b035d1..d0e60a5b8670 100644 --- a/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/ios/firebase_database/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "12.4.3" +let libraryVersion = "12.4.4" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift index d9f4a4a782ae..7d7a24d5ddc5 100644 --- a/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift +++ b/packages/firebase_database/firebase_database/macos/firebase_database/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "12.4.3" +let libraryVersion = "12.4.4" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_database/firebase_database/pubspec.yaml b/packages/firebase_database/firebase_database/pubspec.yaml index 4353e8f0a53c..50aedb988970 100755 --- a/packages/firebase_database/firebase_database/pubspec.yaml +++ b/packages/firebase_database/firebase_database/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Database, a cloud-hosted NoSQL database with realtime data syncing across Android and iOS clients, and offline access. homepage: https://firebase.google.com/docs/database repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_database/firebase_database -version: 12.4.3 +version: 12.4.4 resolution: workspace topics: - firebase diff --git a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart index 5ae950bfa0b5..02b9baec59d4 100644 --- a/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart +++ b/packages/firebase_database/firebase_database_web/lib/src/firebase_database_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '12.4.3'; +const packageVersion = '12.4.4'; diff --git a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md index 6875615ff2a1..cf1646bc73d9 100644 --- a/packages/firebase_messaging/firebase_messaging/CHANGELOG.md +++ b/packages/firebase_messaging/firebase_messaging/CHANGELOG.md @@ -1,3 +1,7 @@ +## 16.4.1 + + - **FIX**: resolve FlutterSceneLifeCycleDelegate conformance guard ([#18385](https://github.com/firebase/flutterfire/issues/18385)). ([48d67196](https://github.com/firebase/flutterfire/commit/48d67196a10affe09724529df5f67cf40b62bccf)) + ## 16.4.0 - **FIX**(messaging,ios): fix a race condition that could happen when getting initial message ([#18352](https://github.com/firebase/flutterfire/issues/18352)). ([77396b81](https://github.com/firebase/flutterfire/commit/77396b81ae56943a38c23b429249b0b9cbd4bc21)) diff --git a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml index 23b76e909a1a..636eb595024b 100644 --- a/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/example/pubspec.yaml @@ -8,7 +8,7 @@ environment: dependencies: firebase_core: ^4.11.0 - firebase_messaging: ^16.4.0 + firebase_messaging: ^16.4.1 flutter: sdk: flutter flutter_local_notifications: ^21.0.0 diff --git a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift index d619affbdf30..303f043dab1f 100644 --- a/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/ios/firebase_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "16.4.0" +let libraryVersion = "16.4.1" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift index bde751bc41cc..c60187265b2e 100644 --- a/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift +++ b/packages/firebase_messaging/firebase_messaging/macos/firebase_messaging/Package.swift @@ -7,7 +7,7 @@ import PackageDescription -let libraryVersion = "16.4.0" +let libraryVersion = "16.4.1" let firebaseSdkVersion: Version = "12.15.0" let package = Package( diff --git a/packages/firebase_messaging/firebase_messaging/pubspec.yaml b/packages/firebase_messaging/firebase_messaging/pubspec.yaml index e27001039e4e..63fef2fddcbd 100644 --- a/packages/firebase_messaging/firebase_messaging/pubspec.yaml +++ b/packages/firebase_messaging/firebase_messaging/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS. homepage: https://firebase.google.com/docs/cloud-messaging repository: https://github.com/firebase/flutterfire/tree/main/packages/firebase_messaging/firebase_messaging -version: 16.4.0 +version: 16.4.1 resolution: workspace topics: - firebase diff --git a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart index 51998e4d285d..63e6b5e50558 100644 --- a/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart +++ b/packages/firebase_messaging/firebase_messaging_web/lib/src/firebase_messaging_version.dart @@ -13,4 +13,4 @@ // limitations under the License. /// generated version number for the package, do not manually edit -const packageVersion = '16.4.0'; +const packageVersion = '16.4.1'; diff --git a/scripts/versions.json b/scripts/versions.json index fb3b516b8ba3..d88c2d975598 100644 --- a/scripts/versions.json +++ b/scripts/versions.json @@ -1,4 +1,32 @@ { + "4.16.1": { + "date": "2026-06-22", + "firebase_sdk": { + "android": "34.15.0", + "ios": "12.15.0", + "web": "12.15.0", + "windows": "13.5.0" + }, + "packages": { + "cloud_firestore": "6.6.0", + "cloud_functions": "6.3.3", + "firebase_ai": "3.13.1", + "firebase_analytics": "12.4.3", + "firebase_app_check": "0.4.5", + "firebase_app_installations": "0.4.2+4", + "firebase_auth": "6.5.4", + "firebase_core": "4.11.0", + "firebase_crashlytics": "5.2.4", + "firebase_data_connect": "0.3.0+5", + "firebase_database": "12.4.4", + "firebase_in_app_messaging": "0.9.2+4", + "firebase_messaging": "16.4.1", + "firebase_ml_model_downloader": "0.4.2+4", + "firebase_performance": "0.11.4+3", + "firebase_remote_config": "6.5.3", + "firebase_storage": "13.4.3" + } + }, "4.16.0": { "date": "2026-06-17", "firebase_sdk": { diff --git a/tests/pubspec.yaml b/tests/pubspec.yaml index c76e0a380153..68b6296dcb78 100644 --- a/tests/pubspec.yaml +++ b/tests/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: cloud_functions_platform_interface: ^6.0.3 cloud_functions_web: ^5.1.9 collection: ^1.15.0 - firebase_ai: ^3.13.0 + firebase_ai: ^3.13.1 firebase_analytics: ^12.4.3 firebase_analytics_platform_interface: ^6.0.3 firebase_analytics_web: ^0.6.1+9 @@ -24,7 +24,7 @@ dependencies: firebase_app_installations: ^0.4.2+4 firebase_app_installations_platform_interface: ^0.1.4+72 firebase_app_installations_web: ^0.1.7+9 - firebase_auth: ^6.5.3 + firebase_auth: ^6.5.4 firebase_auth_platform_interface: ^9.0.3 firebase_auth_web: ^6.2.3 firebase_core: ^4.11.0 @@ -32,10 +32,10 @@ dependencies: firebase_core_web: ^3.9.0 firebase_crashlytics: ^5.2.4 firebase_crashlytics_platform_interface: ^3.8.24 - firebase_database: ^12.4.3 + firebase_database: ^12.4.4 firebase_database_platform_interface: ^0.4.0+3 firebase_database_web: ^0.2.7+10 - firebase_messaging: ^16.4.0 + firebase_messaging: ^16.4.1 firebase_messaging_platform_interface: ^4.9.0 firebase_messaging_web: ^4.2.1 firebase_ml_model_downloader: ^0.4.2+4 From 36c31c7ee978855d2f9ea1722785b80a2248ecc9 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 23 Jun 2026 15:16:42 +0200 Subject: [PATCH 133/137] chore: remove unused extend from PlatformInterface (#18392) * chore: remove unused extend from PlatformInterface * fix --- .../cloud_firestore/lib/cloud_firestore.dart | 2 +- .../cloud_firestore/lib/src/firestore.dart | 2 +- .../cloud_functions/lib/cloud_functions.dart | 2 +- .../lib/src/firebase_functions.dart | 2 +- .../firebase_ai/lib/src/firebase_ai.dart | 4 ++-- .../firebase_analytics/lib/firebase_analytics.dart | 2 +- .../lib/src/firebase_analytics.dart | 2 +- .../lib/src/firebase_app_check.dart | 3 +-- .../lib/firebase_app_installations.dart | 2 +- .../lib/src/firebase_app_installations.dart | 2 +- .../firebase_auth/lib/src/firebase_auth.dart | 2 +- .../method_channel/method_channel_firebase.dart | 5 ++--- .../method_channel_firebase_app.dart | 2 +- .../platform_interface_firebase_plugin.dart | 14 +++----------- .../platform_interface_firebase_core_test.dart | 10 ++++++++++ .../lib/firebase_crashlytics.dart | 2 +- .../lib/src/firebase_crashlytics.dart | 2 +- .../lib/src/firebase_data_connect.dart | 2 +- .../firebase_database/lib/firebase_database.dart | 2 +- .../lib/src/firebase_database.dart | 2 +- .../lib/firebase_in_app_messaging.dart | 4 ++-- .../firebase_messaging/lib/firebase_messaging.dart | 2 +- .../firebase_messaging/lib/src/messaging.dart | 2 +- .../lib/firebase_ml_model_downloader.dart | 2 +- .../lib/src/firebase_ml_model_downloader.dart | 2 +- .../lib/src/firebase_performance.dart | 2 +- .../lib/firebase_remote_config.dart | 2 +- .../lib/src/firebase_remote_config.dart | 2 +- .../firebase_storage/lib/firebase_storage.dart | 2 +- .../firebase_storage/lib/src/firebase_storage.dart | 2 +- 30 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart index 1fcccbee21bc..6578ad8f5c9a 100755 --- a/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart @@ -5,7 +5,7 @@ import 'package:cloud_firestore_platform_interface/cloud_firestore_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:flutter/foundation.dart'; import 'package:meta/meta.dart'; diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart index 35b09f3f5d3b..3c51c65d55c3 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart @@ -15,7 +15,7 @@ part of '../cloud_firestore.dart'; /// /// FirebaseFirestore firestore = FirebaseFirestore.instanceFor(app: secondaryApp); /// ``` -class FirebaseFirestore extends FirebasePluginPlatform { +class FirebaseFirestore extends FirebasePlugin { FirebaseFirestore._({ required this.app, required this.databaseId, diff --git a/packages/cloud_functions/cloud_functions/lib/cloud_functions.dart b/packages/cloud_functions/cloud_functions/lib/cloud_functions.dart index f95683cac2bd..3aacd08bc7e7 100644 --- a/packages/cloud_functions/cloud_functions/lib/cloud_functions.dart +++ b/packages/cloud_functions/cloud_functions/lib/cloud_functions.dart @@ -11,7 +11,7 @@ import 'dart:typed_data'; import 'package:cloud_functions_platform_interface/cloud_functions_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:flutter/foundation.dart'; export 'package:cloud_functions_platform_interface/cloud_functions_platform_interface.dart' diff --git a/packages/cloud_functions/cloud_functions/lib/src/firebase_functions.dart b/packages/cloud_functions/cloud_functions/lib/src/firebase_functions.dart index 94a3e25e85d1..aef9a37c036a 100644 --- a/packages/cloud_functions/cloud_functions/lib/src/firebase_functions.dart +++ b/packages/cloud_functions/cloud_functions/lib/src/firebase_functions.dart @@ -8,7 +8,7 @@ part of '../cloud_functions.dart'; /// The entry point for accessing FirebaseFunctions. /// /// You can get an instance by calling [FirebaseFunctions.instance]. -class FirebaseFunctions extends FirebasePluginPlatform { +class FirebaseFunctions extends FirebasePlugin { FirebaseFunctions._({required this.app, String? region}) : _region = region ??= 'us-central1', super(app.name, 'plugins.flutter.io/firebase_functions'); diff --git a/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart b/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart index ff7011af5bce..5841c0d2de47 100644 --- a/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart +++ b/packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart @@ -16,7 +16,7 @@ import 'package:firebase_app_check/firebase_app_check.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:http/http.dart' as http; import 'package:meta/meta.dart'; @@ -26,7 +26,7 @@ import 'base_model.dart'; const _defaultLocation = 'us-central1'; /// The entrypoint for generative models. -class FirebaseAI extends FirebasePluginPlatform { +class FirebaseAI extends FirebasePlugin { FirebaseAI._({ required this.app, required this.location, diff --git a/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart index 0b526dcc6eb4..882f04c0e743 100644 --- a/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/firebase_analytics.dart @@ -5,7 +5,7 @@ import 'package:firebase_analytics_platform_interface/firebase_analytics_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; diff --git a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart index b649a953ad6b..c67f9eb71533 100755 --- a/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart +++ b/packages/firebase_analytics/firebase_analytics/lib/src/firebase_analytics.dart @@ -5,7 +5,7 @@ part of '../firebase_analytics.dart'; /// Firebase Analytics API. -class FirebaseAnalytics extends FirebasePluginPlatform { +class FirebaseAnalytics extends FirebasePlugin { FirebaseAnalytics._({ required this.app, this.webOptions, diff --git a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart index 8deabfc99208..0553fa116e03 100644 --- a/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart +++ b/packages/firebase_app_check/firebase_app_check/lib/src/firebase_app_check.dart @@ -5,8 +5,7 @@ part of '../firebase_app_check.dart'; -class FirebaseAppCheck extends FirebasePluginPlatform - implements FirebaseService { +class FirebaseAppCheck extends FirebasePlugin implements FirebaseService { static Map _firebaseAppCheckInstances = {}; FirebaseAppCheck._({required this.app}) diff --git a/packages/firebase_app_installations/firebase_app_installations/lib/firebase_app_installations.dart b/packages/firebase_app_installations/firebase_app_installations/lib/firebase_app_installations.dart index 2bfd24bab7b3..44a0e46bd29c 100644 --- a/packages/firebase_app_installations/firebase_app_installations/lib/firebase_app_installations.dart +++ b/packages/firebase_app_installations/firebase_app_installations/lib/firebase_app_installations.dart @@ -5,6 +5,6 @@ import 'package:firebase_app_installations_platform_interface/firebase_app_installations_platform_interface.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; part 'src/firebase_app_installations.dart'; diff --git a/packages/firebase_app_installations/firebase_app_installations/lib/src/firebase_app_installations.dart b/packages/firebase_app_installations/firebase_app_installations/lib/src/firebase_app_installations.dart index 627386b104e6..fa21dd564810 100644 --- a/packages/firebase_app_installations/firebase_app_installations/lib/src/firebase_app_installations.dart +++ b/packages/firebase_app_installations/firebase_app_installations/lib/src/firebase_app_installations.dart @@ -4,7 +4,7 @@ part of '../firebase_app_installations.dart'; -class FirebaseInstallations extends FirebasePluginPlatform { +class FirebaseInstallations extends FirebasePlugin { FirebaseInstallations._({required this.app}) : super(app.name, 'plugins.flutter.io/firebase_app_installations'); diff --git a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart index 2f4ebe4258f4..3c07d4b4707a 100644 --- a/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart +++ b/packages/firebase_auth/firebase_auth/lib/src/firebase_auth.dart @@ -6,7 +6,7 @@ part of '../firebase_auth.dart'; /// The entry point of the Firebase Authentication SDK. -class FirebaseAuth extends FirebasePluginPlatform implements FirebaseService { +class FirebaseAuth extends FirebasePlugin implements FirebaseService { // Cached instances of [FirebaseAuth]. static Map _firebaseAuthInstances = {}; diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart index 2cc1755614cc..dff6228fdce1 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase.dart @@ -33,7 +33,7 @@ class MethodChannelFirebase extends FirebasePlatform { } /// Creates and attaches a new [MethodChannelFirebaseApp] to the [MethodChannelFirebase] - /// and adds any constants to the [FirebasePluginPlatform] class. + /// and adds any constants to the [FirebasePlugin] class. void _initializeFirebaseAppFromMap(CoreInitializeResponse response) { MethodChannelFirebaseApp methodChannelFirebaseApp = MethodChannelFirebaseApp( @@ -45,8 +45,7 @@ class MethodChannelFirebase extends FirebasePlatform { appInstances[methodChannelFirebaseApp.name] = methodChannelFirebaseApp; - FirebasePluginPlatform - ._constantsForPluginApps[methodChannelFirebaseApp.name] = + FirebasePlugin._constantsForPluginApps[methodChannelFirebaseApp.name] = response.pluginConstants; } diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase_app.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase_app.dart index 6689c25ae0e2..1b33d6cb28a1 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase_app.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/method_channel/method_channel_firebase_app.dart @@ -52,7 +52,7 @@ class MethodChannelFirebaseApp extends FirebaseAppPlatform { await _api.delete(name); MethodChannelFirebase.appInstances.remove(name); - FirebasePluginPlatform._constantsForPluginApps.remove(name); + FirebasePlugin._constantsForPluginApps.remove(name); _isDeleted = true; } diff --git a/packages/firebase_core/firebase_core_platform_interface/lib/src/platform_interface/platform_interface_firebase_plugin.dart b/packages/firebase_core/firebase_core_platform_interface/lib/src/platform_interface/platform_interface_firebase_plugin.dart index afd5dcfbb499..42e470fdc1b6 100644 --- a/packages/firebase_core/firebase_core_platform_interface/lib/src/platform_interface/platform_interface_firebase_plugin.dart +++ b/packages/firebase_core/firebase_core_platform_interface/lib/src/platform_interface/platform_interface_firebase_plugin.dart @@ -5,14 +5,13 @@ part of '../../firebase_core_platform_interface.dart'; -/// The interface that other FlutterFire plugins must extend. +/// The base class that other FlutterFire plugins must extend. /// /// This class provides access to common plugin properties and constants which /// are available once the user has initialized FlutterFire. -abstract class FirebasePluginPlatform extends PlatformInterface { +abstract class FirebasePlugin { // ignore: public_member_api_docs - FirebasePluginPlatform(this._appName, this._methodChannelName) - : super(token: _token); + FirebasePlugin(this._appName, this._methodChannelName); /// The global data store for all constants, for each plugin and [FirebaseAppPlatform] instance. /// @@ -26,13 +25,6 @@ abstract class FirebasePluginPlatform extends PlatformInterface { final String _methodChannelName; - static final Object _token = Object(); - - // ignore: public_member_api_docs - static void verify(FirebasePluginPlatform instance) { - PlatformInterface.verify(instance, _token); - } - /// Returns any plugin constants this plugin app instance has initialized. Map get pluginConstants { final appConstants = diff --git a/packages/firebase_core/firebase_core_platform_interface/test/platform_interface_tests/platform_interface_firebase_core_test.dart b/packages/firebase_core/firebase_core_platform_interface/test/platform_interface_tests/platform_interface_firebase_core_test.dart index 63e1e24534d9..5393a22f99d8 100644 --- a/packages/firebase_core/firebase_core_platform_interface/test/platform_interface_tests/platform_interface_firebase_core_test.dart +++ b/packages/firebase_core/firebase_core_platform_interface/test/platform_interface_tests/platform_interface_firebase_core_test.dart @@ -39,6 +39,12 @@ void main() { FirebasePlatform.instance = mock; }); }); + + group('$FirebasePlugin', () { + test('is not a platform interface', () { + expect(TestFirebasePlugin(), isNot(isA())); + }); + }); } class ImplementsFirebasePlatform implements FirebasePlatform { @@ -70,3 +76,7 @@ class FirebaseCoreMockPlatform extends Mock MockPlatformInterfaceMixin implements FirebasePlatform {} + +class TestFirebasePlugin extends FirebasePlugin { + TestFirebasePlugin() : super(defaultFirebaseAppName, 'test_plugin'); +} diff --git a/packages/firebase_crashlytics/firebase_crashlytics/lib/firebase_crashlytics.dart b/packages/firebase_crashlytics/firebase_crashlytics/lib/firebase_crashlytics.dart index 835af28b344f..800d683e306b 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/lib/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/firebase_crashlytics/lib/firebase_crashlytics.dart @@ -5,7 +5,7 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:firebase_crashlytics_platform_interface/firebase_crashlytics_platform_interface.dart'; import 'package:flutter/foundation.dart' show DiagnosticLevel, FlutterError, FlutterErrorDetails, kDebugMode; diff --git a/packages/firebase_crashlytics/firebase_crashlytics/lib/src/firebase_crashlytics.dart b/packages/firebase_crashlytics/firebase_crashlytics/lib/src/firebase_crashlytics.dart index a43208f8563b..e6b07ca2efb0 100644 --- a/packages/firebase_crashlytics/firebase_crashlytics/lib/src/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/firebase_crashlytics/lib/src/firebase_crashlytics.dart @@ -8,7 +8,7 @@ part of '../firebase_crashlytics.dart'; /// The entry point for accessing a [FirebaseCrashlytics]. /// /// You can get an instance by calling [FirebaseCrashlytics.instance]. -class FirebaseCrashlytics extends FirebasePluginPlatform { +class FirebaseCrashlytics extends FirebasePlugin { FirebaseCrashlytics._({required this.app}) : super(app.name, 'plugins.flutter.io/firebase_crashlytics'); diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart index 45ec2f1815cd..165b6f5d62fb 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/firebase_data_connect.dart @@ -27,7 +27,7 @@ import 'cache/cache_data_types.dart'; import 'cache/cache.dart'; /// DataConnect class -class FirebaseDataConnect extends FirebasePluginPlatform { +class FirebaseDataConnect extends FirebasePlugin { /// Constructor for initializing Data Connect @visibleForTesting FirebaseDataConnect( diff --git a/packages/firebase_database/firebase_database/lib/firebase_database.dart b/packages/firebase_database/firebase_database/lib/firebase_database.dart index 1da1eb1889f1..80624a3eb319 100755 --- a/packages/firebase_database/firebase_database/lib/firebase_database.dart +++ b/packages/firebase_database/firebase_database/lib/firebase_database.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:firebase_database_platform_interface/firebase_database_platform_interface.dart'; import 'package:flutter/foundation.dart'; diff --git a/packages/firebase_database/firebase_database/lib/src/firebase_database.dart b/packages/firebase_database/firebase_database/lib/src/firebase_database.dart index 8c71d3ff8cc6..4090063e08a4 100644 --- a/packages/firebase_database/firebase_database/lib/src/firebase_database.dart +++ b/packages/firebase_database/firebase_database/lib/src/firebase_database.dart @@ -6,7 +6,7 @@ part of '../firebase_database.dart'; /// The entry point for accessing a Firebase Database. You can get an instance /// by calling `FirebaseDatabase.instance` or `FirebaseDatabase.instanceFor()`. -class FirebaseDatabase extends FirebasePluginPlatform { +class FirebaseDatabase extends FirebasePlugin { FirebaseDatabase._({required this.app, this.databaseURL}) : super(app.name, 'plugins.flutter.io/firebase_database') { if (databaseURL != null && databaseURL!.endsWith('/')) { diff --git a/packages/firebase_in_app_messaging/firebase_in_app_messaging/lib/firebase_in_app_messaging.dart b/packages/firebase_in_app_messaging/firebase_in_app_messaging/lib/firebase_in_app_messaging.dart index 857c0f25c376..ef35ef27655f 100644 --- a/packages/firebase_in_app_messaging/firebase_in_app_messaging/lib/firebase_in_app_messaging.dart +++ b/packages/firebase_in_app_messaging/firebase_in_app_messaging/lib/firebase_in_app_messaging.dart @@ -4,10 +4,10 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:firebase_in_app_messaging_platform_interface/firebase_in_app_messaging_platform_interface.dart'; -class FirebaseInAppMessaging extends FirebasePluginPlatform { +class FirebaseInAppMessaging extends FirebasePlugin { FirebaseInAppMessaging._({required this.app}) : super(app.name, 'plugins.flutter.io/firebase_in_app_messaging'); diff --git a/packages/firebase_messaging/firebase_messaging/lib/firebase_messaging.dart b/packages/firebase_messaging/firebase_messaging/lib/firebase_messaging.dart index 6df5ee9d223a..1783d4654c91 100644 --- a/packages/firebase_messaging/firebase_messaging/lib/firebase_messaging.dart +++ b/packages/firebase_messaging/firebase_messaging/lib/firebase_messaging.dart @@ -7,7 +7,7 @@ import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:firebase_messaging_platform_interface/firebase_messaging_platform_interface.dart'; export 'package:firebase_messaging_platform_interface/firebase_messaging_platform_interface.dart' diff --git a/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart b/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart index de82a44a0dc1..b9f6a0ccea45 100644 --- a/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart +++ b/packages/firebase_messaging/firebase_messaging/lib/src/messaging.dart @@ -8,7 +8,7 @@ part of '../firebase_messaging.dart'; /// The [FirebaseMessaging] entry point. /// /// To get a new instance, call [FirebaseMessaging.instance]. -class FirebaseMessaging extends FirebasePluginPlatform { +class FirebaseMessaging extends FirebasePlugin { // Cached and lazily loaded instance of [FirebaseMessagingPlatform] to avoid // creating a [MethodChannelFirebaseMessaging] when not needed or creating an // instance with the default app before a user specifies an app. diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/firebase_ml_model_downloader.dart b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/firebase_ml_model_downloader.dart index 6fbe5b541f75..6c741e8e81f9 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/firebase_ml_model_downloader.dart +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/firebase_ml_model_downloader.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:firebase_ml_model_downloader_platform_interface/firebase_ml_model_downloader_platform_interface.dart'; import 'package:flutter/foundation.dart'; diff --git a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/src/firebase_ml_model_downloader.dart b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/src/firebase_ml_model_downloader.dart index 699f318e53dd..211e751234c4 100644 --- a/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/src/firebase_ml_model_downloader.dart +++ b/packages/firebase_ml_model_downloader/firebase_ml_model_downloader/lib/src/firebase_ml_model_downloader.dart @@ -4,7 +4,7 @@ part of '../firebase_ml_model_downloader.dart'; -class FirebaseModelDownloader extends FirebasePluginPlatform { +class FirebaseModelDownloader extends FirebasePlugin { FirebaseModelDownloader._({required this.app}) : super(app.name, 'plugins.flutter.io/firebase_ml_model_downloader'); diff --git a/packages/firebase_performance/firebase_performance/lib/src/firebase_performance.dart b/packages/firebase_performance/firebase_performance/lib/src/firebase_performance.dart index fb044c723939..5061983318c5 100644 --- a/packages/firebase_performance/firebase_performance/lib/src/firebase_performance.dart +++ b/packages/firebase_performance/firebase_performance/lib/src/firebase_performance.dart @@ -7,7 +7,7 @@ part of '../firebase_performance.dart'; /// The Firebase Performance API. /// /// You can get an instance by calling [FirebasePerformance.instance]. -class FirebasePerformance extends FirebasePluginPlatform { +class FirebasePerformance extends FirebasePlugin { FirebasePerformance._({required this.app}) : super(app.name, 'plugins.flutter.io/firebase_performance'); diff --git a/packages/firebase_remote_config/firebase_remote_config/lib/firebase_remote_config.dart b/packages/firebase_remote_config/firebase_remote_config/lib/firebase_remote_config.dart index ba8c7fdcc5d0..5a23bdbb8672 100644 --- a/packages/firebase_remote_config/firebase_remote_config/lib/firebase_remote_config.dart +++ b/packages/firebase_remote_config/firebase_remote_config/lib/firebase_remote_config.dart @@ -6,7 +6,7 @@ import 'dart:async'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:firebase_remote_config_platform_interface/firebase_remote_config_platform_interface.dart'; export 'package:firebase_remote_config_platform_interface/firebase_remote_config_platform_interface.dart' diff --git a/packages/firebase_remote_config/firebase_remote_config/lib/src/firebase_remote_config.dart b/packages/firebase_remote_config/firebase_remote_config/lib/src/firebase_remote_config.dart index 6d5a5845cddb..d7ed0f77fde0 100644 --- a/packages/firebase_remote_config/firebase_remote_config/lib/src/firebase_remote_config.dart +++ b/packages/firebase_remote_config/firebase_remote_config/lib/src/firebase_remote_config.dart @@ -9,7 +9,7 @@ part of '../firebase_remote_config.dart'; /// You can get an instance by calling [FirebaseRemoteConfig.instance]. Note /// [FirebaseRemoteConfig.instance] is async. // ignore: prefer_mixin -class FirebaseRemoteConfig extends FirebasePluginPlatform { +class FirebaseRemoteConfig extends FirebasePlugin { FirebaseRemoteConfig._({required this.app}) : super(app.name, 'plugins.flutter.io/firebase_remote_config'); diff --git a/packages/firebase_storage/firebase_storage/lib/firebase_storage.dart b/packages/firebase_storage/firebase_storage/lib/firebase_storage.dart index 9a19065a691d..f93119421fd0 100755 --- a/packages/firebase_storage/firebase_storage/lib/firebase_storage.dart +++ b/packages/firebase_storage/firebase_storage/lib/firebase_storage.dart @@ -12,7 +12,7 @@ import 'dart:io' show File; // import 'package:flutter/foundation.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart' - show FirebasePluginPlatform; + show FirebasePlugin; import 'package:firebase_storage_platform_interface/firebase_storage_platform_interface.dart'; import 'package:flutter/foundation.dart'; import 'package:mime/mime.dart'; diff --git a/packages/firebase_storage/firebase_storage/lib/src/firebase_storage.dart b/packages/firebase_storage/firebase_storage/lib/src/firebase_storage.dart index b833bfaba6e4..bc53c6bd5ef1 100644 --- a/packages/firebase_storage/firebase_storage/lib/src/firebase_storage.dart +++ b/packages/firebase_storage/firebase_storage/lib/src/firebase_storage.dart @@ -6,7 +6,7 @@ part of firebase_storage; /// The entrypoint for [FirebaseStorage]. -class FirebaseStorage extends FirebasePluginPlatform { +class FirebaseStorage extends FirebasePlugin { FirebaseStorage._({required this.app, required this.bucket}) : super(app.name, 'plugins.flutter.io/firebase_storage'); From 0ce3c202c011ccc1f7ed1d1ecd4d8ed431b0de59 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 23 Jun 2026 15:39:01 +0200 Subject: [PATCH 134/137] fix(firestore): large snapshots do not block frame scheduling (#18390) * fix(firestore): large snapshots do not block frame scheduling * fix * fix * fix --- .../FlutterFirebaseFirestorePlugin.java | 3 +- .../QuerySnapshotsStreamHandler.java | 22 +++-- .../example/android/gradle.properties | 6 +- .../example/integration_test/query_e2e.dart | 83 +++++++++++++++++++ .../FLTQuerySnapshotStreamHandler.m | 13 ++- 5 files changed, 117 insertions(+), 10 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java index 14046b1179d6..e377f2737121 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/FlutterFirebaseFirestorePlugin.java @@ -989,7 +989,8 @@ public void querySnapshot( includeMetadataChanges, PigeonParser.parsePigeonServerTimestampBehavior( options.getServerTimestampBehavior()), - PigeonParser.parseListenSource(source)))); + PigeonParser.parseListenSource(source), + cachedThreadPool))); } @Override diff --git a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java index e0fe62b31ec7..8aade3f8a9c2 100644 --- a/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java +++ b/packages/cloud_firestore/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/firestore/streamhandler/QuerySnapshotsStreamHandler.java @@ -8,6 +8,8 @@ import static io.flutter.plugins.firebase.firestore.FlutterFirebaseFirestorePlugin.DEFAULT_ERROR_CODE; +import android.os.Handler; +import android.os.Looper; import com.google.firebase.firestore.DocumentSnapshot; import com.google.firebase.firestore.ListenSource; import com.google.firebase.firestore.ListenerRegistration; @@ -19,27 +21,32 @@ import io.flutter.plugins.firebase.firestore.utils.ExceptionConverter; import io.flutter.plugins.firebase.firestore.utils.PigeonParser; import java.util.Map; +import java.util.concurrent.Executor; public class QuerySnapshotsStreamHandler implements StreamHandler { ListenerRegistration listenerRegistration; + private final Handler mainHandler = new Handler(Looper.getMainLooper()); Query query; MetadataChanges metadataChanges; DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior; ListenSource source; + Executor snapshotExecutor; public QuerySnapshotsStreamHandler( Query query, Boolean includeMetadataChanges, DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior, - ListenSource source) { + ListenSource source, + Executor snapshotExecutor) { this.query = query; this.metadataChanges = includeMetadataChanges ? MetadataChanges.INCLUDE : MetadataChanges.EXCLUDE; this.serverTimestampBehavior = serverTimestampBehavior; this.source = source; + this.snapshotExecutor = snapshotExecutor; } @Override @@ -47,6 +54,7 @@ public void onListen(Object arguments, EventSink events) { SnapshotListenOptions.Builder optionsBuilder = new SnapshotListenOptions.Builder(); optionsBuilder.setMetadataChanges(metadataChanges); optionsBuilder.setSource(source); + optionsBuilder.setExecutor(snapshotExecutor); listenerRegistration = query.addSnapshotListener( @@ -54,8 +62,11 @@ public void onListen(Object arguments, EventSink events) { (querySnapshot, exception) -> { if (exception != null) { Map exceptionDetails = ExceptionConverter.createDetails(exception); - events.error(DEFAULT_ERROR_CODE, exception.getMessage(), exceptionDetails); - events.endOfStream(); + mainHandler.post( + () -> { + events.error(DEFAULT_ERROR_CODE, exception.getMessage(), exceptionDetails); + events.endOfStream(); + }); onCancel(null); } else { @@ -63,8 +74,9 @@ public void onListen(Object arguments, EventSink events) { // nested `InternalDocumentSnapshot` / `InternalDocumentChange` / // `InternalSnapshotMetadata` with their proper type codes. Pigeon 26 // no longer flattens nested types via `.toList()`. - events.success( - PigeonParser.toPigeonQuerySnapshot(querySnapshot, serverTimestampBehavior)); + Object pigeonSnapshot = + PigeonParser.toPigeonQuerySnapshot(querySnapshot, serverTimestampBehavior); + mainHandler.post(() -> events.success(pigeonSnapshot)); } }); } diff --git a/packages/cloud_firestore/cloud_firestore/example/android/gradle.properties b/packages/cloud_firestore/cloud_firestore/example/android/gradle.properties index 3c0f502f334a..6bb94725c175 100644 --- a/packages/cloud_firestore/cloud_firestore/example/android/gradle.properties +++ b/packages/cloud_firestore/cloud_firestore/example/android/gradle.properties @@ -1,4 +1,8 @@ org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true -androidGradlePluginVersion=8.3.0 \ No newline at end of file +androidGradlePluginVersion=8.3.0 +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart b/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart index 5c62d73b5db8..d97ddc4e2fda 100644 --- a/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/example/integration_test/query_e2e.dart @@ -8,6 +8,7 @@ import 'dart:math'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void runQueryTests() { @@ -374,6 +375,88 @@ void runQueryTests() { await subscription.cancel(); }); + testWidgets( + 'large snapshots do not block frame scheduling', + (WidgetTester tester) async { + CollectionReference> collection = + await initializeTest('large-snapshot-listener'); + const int documentCount = 1000; + final String payload = List.filled(1024, 'x').join(); + + for (int start = 0; start < documentCount; start += 400) { + final WriteBatch batch = firestore.batch(); + final int end = min(start + 400, documentCount); + for (int index = start; index < end; index++) { + batch.set(collection.doc('doc-$index'), { + 'index': index, + 'payload': payload, + }); + } + await batch.commit(); + } + + final Completer initialSnapshot = Completer(); + final Completer receivedUpdates = Completer(); + var initialSnapshotReceived = false; + var updateSnapshots = 0; + + final StreamSubscription>> + subscription = collection.snapshots().listen((snapshot) { + if (!initialSnapshotReceived && snapshot.size == documentCount) { + initialSnapshotReceived = true; + initialSnapshot.complete(); + return; + } + + if (initialSnapshotReceived && snapshot.docChanges.isNotEmpty) { + updateSnapshots++; + if (updateSnapshots >= 3 && !receivedUpdates.isCompleted) { + receivedUpdates.complete(); + } + } + }); + addTearDown(subscription.cancel); + + await initialSnapshot.future.timeout(const Duration(seconds: 30)); + await tester.pumpWidget( + const Directionality( + textDirection: TextDirection.ltr, + child: Center(child: CircularProgressIndicator()), + ), + ); + + var updatesDone = false; + final updateFuture = Future(() async { + for (int index = 0; index < 3; index++) { + await collection.doc('doc-0').update({ + 'counter': index, + 'payload': payload, + }); + } + await receivedUpdates.future.timeout(const Duration(seconds: 30)); + }).whenComplete(() { + updatesDone = true; + }); + + final pumpDurations = []; + while (!updatesDone) { + final Stopwatch stopwatch = Stopwatch()..start(); + await tester.pump(const Duration(milliseconds: 16)); + stopwatch.stop(); + pumpDurations.add(stopwatch.elapsed); + } + await updateFuture; + + expect(pumpDurations, isNotEmpty); + final Duration longestPump = pumpDurations.reduce( + (current, next) => current > next ? current : next, + ); + expect(longestPump, lessThan(const Duration(milliseconds: 750))); + }, + timeout: const Timeout.factor(10), + skip: kIsWeb || defaultTargetPlatform == TargetPlatform.windows, + ); + test( 'listeners throws a [FirebaseException] with Query', () async { diff --git a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m index b90ee46db10a..a821cc35e94f 100644 --- a/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m +++ b/packages/cloud_firestore/cloud_firestore/ios/cloud_firestore/Sources/cloud_firestore/FLTQuerySnapshotStreamHandler.m @@ -16,6 +16,7 @@ @interface FLTQuerySnapshotStreamHandler () @property(readwrite, strong) id listenerRegistration; +@property(nonatomic) dispatch_queue_t snapshotQueue; @end @implementation FLTQuerySnapshotStreamHandler @@ -32,6 +33,8 @@ - (instancetype)initWithFirestore:(FIRFirestore *)firestore _includeMetadataChanges = includeMetadataChanges; _serverTimestampBehavior = serverTimestampBehavior; _source = source; + _snapshotQueue = dispatch_queue_create("io.flutter.plugins.firebase.firestore.query_snapshot", + DISPATCH_QUEUE_SERIAL); } return self; } @@ -64,13 +67,17 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments andOptionalNSError:error]); }); } else { - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_async(self.snapshotQueue, ^{ // Emit the Pigeon object directly; the Pigeon-aware codec serializes nested // `InternalDocumentSnapshot` / `InternalDocumentChange` / `InternalSnapshotMetadata` // with their proper type codes. Pigeon 26 no longer flattens nested types // via `toList`. - events([FirestorePigeonParser toPigeonQuerySnapshot:snapshot - serverTimestampBehavior:self.serverTimestampBehavior]); + InternalQuerySnapshot *pigeonSnapshot = + [FirestorePigeonParser toPigeonQuerySnapshot:snapshot + serverTimestampBehavior:self.serverTimestampBehavior]; + dispatch_async(dispatch_get_main_queue(), ^{ + events(pigeonSnapshot); + }); }); } }; From ac200e4fccfe851ff80689e3814d1793a7bb893e Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Tue, 23 Jun 2026 16:57:14 +0200 Subject: [PATCH 135/137] feat(firestore): add support for withConverter on Writebatch (#18394) --- .../integration_test/write_batch_e2e.dart | 154 ++++++++++++++++++ .../cloud_firestore/lib/src/write_batch.dart | 13 +- 2 files changed, 165 insertions(+), 2 deletions(-) diff --git a/packages/cloud_firestore/cloud_firestore/example/integration_test/write_batch_e2e.dart b/packages/cloud_firestore/cloud_firestore/example/integration_test/write_batch_e2e.dart index 7eb49c04016b..5853c56da4bb 100644 --- a/packages/cloud_firestore/cloud_firestore/example/integration_test/write_batch_e2e.dart +++ b/packages/cloud_firestore/cloud_firestore/example/integration_test/write_batch_e2e.dart @@ -70,6 +70,94 @@ void runWriteBatchTests() { expect(snapshot.exists, false); }); + test('updates with typed data through withConverter', () async { + CollectionReference> collection = + await initializeTest('with-converter-batch-update'); + WriteBatch batch = firestore.batch(); + + DocumentReference doc = collection.doc('doc1').withConverter( + fromFirestore: (snapshot, options) { + return snapshot.data()!['value'] as int; + }, + toFirestore: (value, options) => {'value': value}, + ); + + await doc.set(42); + + batch.update(doc, 21); + + await batch.commit(); + + DocumentSnapshot snapshot = await doc.get(); + expect(snapshot.exists, isTrue); + expect(snapshot.data(), 21); + }); + + test('updates complex typed data through withConverter', () async { + CollectionReference> collection = + await initializeTest('with-converter-complex-batch-update'); + DocumentReference> rawDoc = collection.doc('doc1'); + DocumentReference<_WriteBatchProfile> doc = rawDoc.withConverter( + fromFirestore: (snapshot, options) { + return _WriteBatchProfile.fromFirestore(snapshot.data()!); + }, + toFirestore: (value, options) => value.toFirestore(), + ); + + await rawDoc.set({ + 'existing': 'preserved', + 'name': 'before', + }); + + WriteBatch batch = firestore.batch(); + batch.update<_WriteBatchProfile>( + doc, + _WriteBatchProfile( + name: 'Ada', + score: 42, + address: _WriteBatchAddress(city: 'London', postcode: 'NW1'), + tags: ['admin', 'tester'], + preferences: { + 'email': true, + 'theme': 'dark', + }, + nickname: null, + ), + ); + + await batch.commit(); + + DocumentSnapshot> rawSnapshot = await rawDoc.get(); + expect(rawSnapshot.data(), { + 'existing': 'preserved', + 'name': 'Ada', + 'score': 42, + 'address': { + 'city': 'London', + 'postcode': 'NW1', + }, + 'tags': ['admin', 'tester'], + 'preferences': { + 'email': true, + 'theme': 'dark', + }, + 'nickname': null, + }); + + DocumentSnapshot<_WriteBatchProfile> snapshot = await doc.get(); + _WriteBatchProfile profile = snapshot.data()!; + expect(profile.name, 'Ada'); + expect(profile.score, 42); + expect(profile.address.city, 'London'); + expect(profile.address.postcode, 'NW1'); + expect(profile.tags, ['admin', 'tester']); + expect(profile.preferences, { + 'email': true, + 'theme': 'dark', + }); + expect(profile.nickname, isNull); + }); + test('should update a document using FieldPath keys', () async { CollectionReference> collection = await initializeTest('write-batch-field-path'); @@ -153,3 +241,69 @@ void runWriteBatchTests() { }); }); } + +class _WriteBatchProfile { + _WriteBatchProfile({ + required this.name, + required this.score, + required this.address, + required this.tags, + required this.preferences, + required this.nickname, + }); + + factory _WriteBatchProfile.fromFirestore(Map data) { + return _WriteBatchProfile( + name: data['name'] as String, + score: data['score'] as int, + address: _WriteBatchAddress.fromFirestore( + data['address'] as Map, + ), + tags: (data['tags'] as List).cast(), + preferences: Map.from(data['preferences'] as Map), + nickname: data['nickname'] as String?, + ); + } + + final String name; + final int score; + final _WriteBatchAddress address; + final List tags; + final Map preferences; + final String? nickname; + + Map toFirestore() { + return { + 'name': name, + 'score': score, + 'address': address.toFirestore(), + 'tags': tags, + 'preferences': preferences, + 'nickname': nickname, + }; + } +} + +class _WriteBatchAddress { + _WriteBatchAddress({ + required this.city, + required this.postcode, + }); + + factory _WriteBatchAddress.fromFirestore(Map data) { + return _WriteBatchAddress( + city: data['city'] as String, + postcode: data['postcode'] as String, + ); + } + + final String city; + final String postcode; + + Map toFirestore() { + return { + 'city': city, + 'postcode': postcode, + }; + } +} diff --git a/packages/cloud_firestore/cloud_firestore/lib/src/write_batch.dart b/packages/cloud_firestore/cloud_firestore/lib/src/write_batch.dart index b07a4734b4a5..c8a60f3ee5fd 100644 --- a/packages/cloud_firestore/cloud_firestore/lib/src/write_batch.dart +++ b/packages/cloud_firestore/cloud_firestore/lib/src/write_batch.dart @@ -68,14 +68,23 @@ class WriteBatch { /// If the document does not yet exist, an exception will be thrown. /// /// Objects key can be a String or a FieldPath. - void update(DocumentReference document, Map data) { + void update(DocumentReference document, T data) { assert( document.firestore == _firestore, 'the document provided is from a different Firestore instance', ); + + Map firestoreData; + if (data is Map) { + firestoreData = data; + } else { + final withConverterDoc = document as _WithConverterDocumentReference; + firestoreData = withConverterDoc._toFirestore(data, null); + } + return _delegate.update( document.path, - _CodecUtility.replaceValueWithDelegatesInMapFieldPath(data)!, + _CodecUtility.replaceValueWithDelegatesInMapFieldPath(firestoreData)!, ); } } From c0dc30feea4b9dc29d8a784a6c409108d8427143 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Mon, 29 Jun 2026 07:08:18 -0500 Subject: [PATCH 136/137] ci(android): store AVD on /mnt for emulator e2e workflows (#18387) --- .github/workflows/android.yaml | 19 +++++++++++++++++-- .github/workflows/e2e_tests_fdc.yaml | 16 ++++++++++++++-- .github/workflows/e2e_tests_pipeline.yaml | 16 ++++++++++++++-- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/.github/workflows/android.yaml b/.github/workflows/android.yaml index 58bd4d22398e..dc00cfb53eca 100644 --- a/.github/workflows/android.yaml +++ b/.github/workflows/android.yaml @@ -98,6 +98,13 @@ jobs: remove-codeql: true remove-docker-images: true remove-large-packages: true + - name: Prepare AVD home on /mnt + # GitHub-hosted runners mount a ~74GB volume at /mnt. Create it before AVD cache + # restore and android-emulator-runner (avdmanager needs the space at create time). + run: | + sudo mkdir -p /mnt/avd + sudo chown "$USER:$USER" /mnt/avd + df -h / /mnt - name: AVD cache uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true @@ -105,11 +112,19 @@ jobs: with: # Must match the save path exactly path: | - ~/.android/avd/* + /mnt/avd/* ~/.android/adb* key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} + - name: Link AVD home to /mnt + # android-emulator-runner exportVariables ANDROID_AVD_HOME to $HOME/.android/avd + run: | + mkdir -p "$HOME/.android" + rm -rf "$HOME/.android/avd" + ln -s /mnt/avd "$HOME/.android/avd" - name: Start AVD then run E2E tests uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a + env: + ANDROID_AVD_HOME: /mnt/avd with: api-level: ${{ env.AVD_API_LEVEL }} target: ${{ env.AVD_TARGET }} @@ -141,7 +156,7 @@ jobs: key: ${{ steps.avd-cache.outputs.cache-primary-key }} # Must match the restore path exactly path: | - ~/.android/avd/* + /mnt/avd/* ~/.android/adb* agp9-compatibility: diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index d840b38f2695..ce9e4e570691 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -97,6 +97,11 @@ jobs: remove-codeql: true remove-docker-images: true remove-large-packages: true + - name: Prepare AVD home on /mnt + run: | + sudo mkdir -p /mnt/avd + sudo chown "$USER:$USER" /mnt/avd + df -h / /mnt - name: AVD cache uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae id: avd-cache @@ -104,11 +109,18 @@ jobs: with: # Must match the save path exactly path: | - ~/.android/avd/* + /mnt/avd/* ~/.android/adb* key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} + - name: Link AVD home to /mnt + run: | + mkdir -p "$HOME/.android" + rm -rf "$HOME/.android/avd" + ln -s /mnt/avd "$HOME/.android/avd" - name: Start AVD then run E2E tests uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a + env: + ANDROID_AVD_HOME: /mnt/avd with: api-level: ${{ env.AVD_API_LEVEL }} target: ${{ env.AVD_TARGET }} @@ -126,7 +138,7 @@ jobs: key: ${{ steps.avd-cache.outputs.cache-primary-key }} # Must match the restore path exactly path: | - ~/.android/avd/* + /mnt/avd/* ~/.android/adb* - name: Save Firestore Emulator Cache # Branches can read main cache but main cannot read branch cache. Avoid LRU eviction with main-only cache. diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index c45b311ee3ed..22ffb4736201 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -79,17 +79,29 @@ jobs: remove-codeql: true remove-docker-images: true remove-large-packages: true + - name: Prepare AVD home on /mnt + run: | + sudo mkdir -p /mnt/avd + sudo chown "$USER:$USER" /mnt/avd + df -h / /mnt - name: AVD cache uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae continue-on-error: true id: avd-cache with: path: | - ~/.android/avd/* + /mnt/avd/* ~/.android/adb* key: avd-${{ runner.os }}-${{ env.AVD_API_LEVEL }}-${{ env.AVD_TARGET }}-${{ env.AVD_ARCH }} + - name: Link AVD home to /mnt + run: | + mkdir -p "$HOME/.android" + rm -rf "$HOME/.android/avd" + ln -s /mnt/avd "$HOME/.android/avd" - name: Start AVD then run pipeline E2E tests uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a + env: + ANDROID_AVD_HOME: /mnt/avd with: api-level: ${{ env.AVD_API_LEVEL }} target: ${{ env.AVD_TARGET }} @@ -108,7 +120,7 @@ jobs: with: key: ${{ steps.avd-cache.outputs.cache-primary-key }} path: | - ~/.android/avd/* + /mnt/avd/* ~/.android/adb* pipeline-e2e-web: From 734fcd8a6a3a905c057724285e082974e690d9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Almstr=C3=B6m?= Date: Mon, 29 Jun 2026 14:09:26 +0200 Subject: [PATCH 137/137] feat(windows): bump Windows C++ SDK to version 13.9.0 (#18400) --- packages/firebase_core/firebase_core/windows/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_core/firebase_core/windows/CMakeLists.txt b/packages/firebase_core/firebase_core/windows/CMakeLists.txt index 277ea0e10c24..3d856893cd65 100644 --- a/packages/firebase_core/firebase_core/windows/CMakeLists.txt +++ b/packages/firebase_core/firebase_core/windows/CMakeLists.txt @@ -4,7 +4,7 @@ # customers of the plugin. cmake_minimum_required(VERSION 3.14) -set(FIREBASE_SDK_VERSION "13.5.0") +set(FIREBASE_SDK_VERSION "13.9.0") if (EXISTS $ENV{FIREBASE_CPP_SDK_DIR}/include/firebase/version.h) file(READ "$ENV{FIREBASE_CPP_SDK_DIR}/include/firebase/version.h" existing_version)