Skip to content

Commit 4ad8731

Browse files
cynthiajoanMichaelVerdonSelaseKayLyokonelukemmtt
authored
chore(firebaseai): merge main into developer api branch (#17341)
* chore(ci): bump macos-14 to macos-15 (#17311) * feat(cloud_functions): add support for cloud functions stream (#17214) * chore: add platform interface and method channel implementation for Cloud Functions stream * chore: add `httpsCallableStreamFromUrl` and `httpsStreamCallableWithUri` * chore: resolve comments * chore: add Android implementation for Cloud Functions stream * chore: resolve formatting issues * chore: correct variable name * chore: add support for Cloud Functions Stream(Android) * chore: create dedicated StreamHandler class * chore: add streamhandler implementation for ios * chore: add iOS implementation for Cloud Functions stream * chore: add license header to stream handler files * chore: web Cloud Functions stream wip * chore: push all * chore: update functions based on API Doc modification * chore: clean up code * chore: add web package * chore: add streaming example * chore: fix ci issues * chore: fix ci * chore: fix cloud function test * chore: add missing doc * chore: fixes and clean up * chore: add e2e for Cloud Functions Stream * chore: fix formatting issue * chore: add more tests and fix timeout for Android * chore: add test for map and list * chore: fix test * chore: update year to 2025 in files * chore(web): add support for abort signal * chore: resolve comments and add test for Abort * chore: fix test * chore: fix test * chore: update copyright year * chore: print error to console * chore(release): publish packages (#17314) * chore(release): publish packages - [email protected] - [email protected] - [email protected] - [email protected] - [email protected] - [email protected] - [email protected] - [email protected] - [email protected]+1 * chore: BoM Version 3.10.0 * constants * fix(auth,apple): prevent EXC_BAD_ACCESS crash in Apple Sign-In completion handler (#17273) - Locally captures completion handler to prevent deallocation - Fixes crash during async Apple Sign-In operations * chore(docs): Update Extension Helper Docs (#17327) * feat(vertexai): Add HarmBlockThreshold.OFF (#17325) * Add HarmBlockThreshold.OFF. Add unit test for api. Fix the schema output json. * fix a nit * feat(fdc): Included platform detection changes (#17308) * feat(vertexai): Add responseModality (#17326) * Add responseModality * review comments * handle omit tokenCount nicely (#17336) * Add new attributes for schema (#17340) * tweak after merge main * fix analyzer for vertexai/api_test.dart * remove dependency_overrides in pubspec.yaml --------- Co-authored-by: MichaelV00 <[email protected]> Co-authored-by: Jude Selase Kwashie <[email protected]> Co-authored-by: Guillaume Bernos <[email protected]> Co-authored-by: Luke Memet <[email protected]> Co-authored-by: Maneesh Tewani <[email protected]>
1 parent 78725d3 commit 4ad8731

File tree

74 files changed

+3609
-2143
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+3609
-2143
lines changed

.github/workflows/all_plugins.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ jobs:
123123
melos exec -c 1 --scope="*example*" --dir-exists="web" -- \
124124
"flutter build web"
125125
swift-integration:
126-
runs-on: macos-latest
126+
runs-on: macos-15
127127
timeout-minutes: 30
128128
env:
129129
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_dynamic_links firebase_crashlytics firebase_ml_model_downloader firebase_app_installations"

.github/workflows/scripts/functions/package-lock.json

+971-1,952
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/scripts/functions/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
},
1515
"main": "lib/index.js",
1616
"dependencies": {
17-
"firebase-admin": "^11.5.0",
18-
"firebase-functions": "^4.5.0"
17+
"firebase-admin": "^13.2.0",
18+
"firebase-functions": "^6.3.2"
1919
},
2020
"devDependencies": {
2121
"firebase-functions-test": "^0.2.0",

.github/workflows/scripts/functions/src/index.ts

+95-32
Original file line numberDiff line numberDiff line change
@@ -2,72 +2,99 @@ import * as assert from 'assert';
22
import * as functions from 'firebase-functions';
33
import * as functionsv2 from 'firebase-functions/v2';
44

5+
56
// For example app.
67
// noinspection JSUnusedGlobalSymbols
78
export const listFruit = functions.https.onCall(() => {
89
return ['Apple', 'Banana', 'Cherry', 'Date', 'Fig', 'Grapes'];
910
});
1011

11-
export const listfruits2ndgen = functionsv2.https.onCall(() => {
12-
return ['Apple', 'Banana', 'Cherry', 'Date', 'Fig', 'Grapes'];
12+
export const listfruits2ndgen = functionsv2.https.onCall((res, req) => {
13+
const fruitList = ['Apple', 'Banana', 'Cherry', 'Date', 'Fig', 'Grapes'];
14+
const allFruits = fruitList.map(async (fruit) => {
15+
if (res.acceptsStreaming) {
16+
req?.sendChunk(fruit)
17+
}
18+
})
19+
return Promise.all(allFruits);
1320
});
1421

1522
// For e2e testing a custom region.
1623
// noinspection JSUnusedGlobalSymbols
17-
export const testFunctionCustomRegion = functions
18-
.region('europe-west1')
19-
.https.onCall(() => 'europe-west1');
24+
25+
export const testFunctionCustomRegion = functions.https.onCall(
26+
{
27+
region: 'europe-west1'
28+
},
29+
() => 'europe-west1'
30+
);
2031

2132
// For e2e testing timeouts.
22-
export const testFunctionTimeout = functions.https.onCall((data) => {
33+
export const testFunctionTimeout = functions.https.onCall((req, res) => {
34+
const data = req.data
2335
console.log(JSON.stringify({ data }));
24-
return new Promise((resolve, reject) => {
25-
if (data && data.testTimeout) {
26-
setTimeout(
27-
() => resolve({ timeLimit: 'exceeded' }),
28-
parseInt(data.testTimeout, 10)
29-
);
30-
} else {
31-
reject(
32-
new functions.https.HttpsError(
33-
'invalid-argument',
34-
'testTimeout must be provided.'
35-
)
36-
);
37-
}
36+
37+
const timeoutMs = parseInt(data?.testTimeout, 10);
38+
39+
if (isNaN(timeoutMs)) {
40+
throw new functions.https.HttpsError(
41+
'invalid-argument',
42+
'testTimeout must be provided.'
43+
);
44+
}
45+
46+
if (req.acceptsStreaming) {
47+
setTimeout(() => {
48+
res?.sendChunk({ timeLimit: 'exceeded' });
49+
}, timeoutMs);
50+
51+
return new Promise((resolve) => {
52+
setTimeout(resolve, timeoutMs + 100);
53+
});
54+
}
55+
56+
return new Promise((resolve) => {
57+
setTimeout(() => resolve({ timeLimit: 'exceeded' }), timeoutMs);
3858
});
59+
3960
});
4061

4162
// For e2e testing errors & return values.
4263
// noinspection JSUnusedGlobalSymbols
43-
export const testFunctionDefaultRegion = functions.https.onCall((data) => {
64+
export const testFunctionDefaultRegion = functions.https.onCall((req, res) => {
65+
const data = req.data;
4466
console.log(JSON.stringify({ data }));
45-
if (typeof data === 'undefined') {
46-
return 'undefined';
47-
}
67+
68+
const sendResponse = (value: any) => {
69+
if (req.acceptsStreaming && res) {
70+
res.sendChunk(value);
71+
return value;
72+
}
73+
return value;
74+
};
4875

4976
if (typeof data === 'string') {
50-
return 'string';
77+
return sendResponse('string');
5178
}
5279

5380
if (typeof data === 'number') {
54-
return 'number';
81+
return sendResponse('number');
5582
}
5683

5784
if (typeof data === 'boolean') {
58-
return 'boolean';
85+
return sendResponse('boolean');
5986
}
6087

6188
if (data === null) {
62-
return 'null';
89+
return sendResponse('null');
6390
}
6491

6592
if (Array.isArray(data)) {
66-
return 'array';
93+
return sendResponse('array');
6794
}
6895

69-
if(data.type === 'rawData') {
70-
return data;
96+
if (data.type === 'rawData') {
97+
return sendResponse(data);
7198
}
7299

73100
const sampleData: {
@@ -153,9 +180,45 @@ export const testFunctionDefaultRegion = functions.https.onCall((data) => {
153180
);
154181
}
155182

156-
return outputData;
183+
return sendResponse(outputData);
157184
});
158185

159186
export const testMapConvertType = functions.https.onCall((data) => ({
160187
foo: 'bar',
161188
}));
189+
190+
export const testStream = functions.https.onCall((req, res) => {
191+
const data = req.data;
192+
if (data === null || undefined) {
193+
if (req.acceptsStreaming) {
194+
res?.sendChunk('null');
195+
}
196+
return
197+
}
198+
199+
const results = [];
200+
results.push(data)
201+
202+
const allResults = results.map(async (result) => {
203+
if (req.acceptsStreaming) {
204+
res?.sendChunk(result);
205+
}
206+
return result;
207+
});
208+
return Promise.all(allResults);
209+
})
210+
211+
export const testStreamResponse = functions.https.onCall(async (request, response) => {
212+
const fruits = ['Apple', 'Mango', 'Banana']
213+
214+
const allFruits = fruits.map(async (fruit) => {
215+
// Stream each fruit as it resolves!
216+
if (request.acceptsStreaming) {
217+
response?.sendChunk(fruit);
218+
}
219+
return fruit;
220+
});
221+
222+
// Fallback for non-streaming clients
223+
return Promise.all(allFruits);
224+
});

CHANGELOG.md

+62
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,68 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## 2025-04-28 - [BoM 3.10.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-3100-2025-04-28)
7+
8+
### Changes
9+
10+
---
11+
12+
Packages with breaking changes:
13+
14+
- There are no breaking changes in this release.
15+
16+
Packages with other changes:
17+
18+
- [`cloud_firestore` - `v5.6.7`](#cloud_firestore---v567)
19+
- [`cloud_firestore_platform_interface` - `v6.6.7`](#cloud_firestore_platform_interface---v667)
20+
- [`cloud_functions` - `v5.5.0`](#cloud_functions---v550)
21+
- [`cloud_functions_platform_interface` - `v5.7.0`](#cloud_functions_platform_interface---v570)
22+
- [`cloud_functions_web` - `v4.11.0`](#cloud_functions_web---v4110)
23+
- [`firebase_auth` - `v5.5.3`](#firebase_auth---v553)
24+
- [`firebase_vertexai` - `v1.6.0`](#firebase_vertexai---v160)
25+
- [`cloud_firestore_web` - `v4.4.7`](#cloud_firestore_web---v447)
26+
- [`firebase_data_connect` - `v0.1.4+1`](#firebase_data_connect---v0141)
27+
28+
Packages with dependency updates only:
29+
30+
> 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.
31+
32+
- `cloud_firestore_web` - `v4.4.7`
33+
- `firebase_data_connect` - `v0.1.4+1`
34+
35+
---
36+
37+
#### `cloud_firestore` - `v5.6.7`
38+
39+
- **FIX**(firestore): Change asserts to throw argumentError ([#17302](https://github.com/firebase/flutterfire/issues/17302)). ([ec1e6a5e](https://github.com/firebase/flutterfire/commit/ec1e6a5eef149680b2750900d1f16d8074e09b38))
40+
- **FIX**(cloud_firestore): correct nanoseconds calculation for pre-1970 dates ([#17195](https://github.com/firebase/flutterfire/issues/17195)). ([a13deae3](https://github.com/firebase/flutterfire/commit/a13deae3334045fb1a48817ff9300cbe0696d177))
41+
42+
#### `cloud_firestore_platform_interface` - `v6.6.7`
43+
44+
- **FIX**(cloud_firestore): correct nanoseconds calculation for pre-1970 dates ([#17195](https://github.com/firebase/flutterfire/issues/17195)). ([a13deae3](https://github.com/firebase/flutterfire/commit/a13deae3334045fb1a48817ff9300cbe0696d177))
45+
46+
#### `cloud_functions` - `v5.5.0`
47+
48+
- **FEAT**(cloud_functions): add support for cloud functions stream ([#17214](https://github.com/firebase/flutterfire/issues/17214)). ([509e0f3c](https://github.com/firebase/flutterfire/commit/509e0f3cc984a7b56a67979b4b27aff72defdd55))
49+
50+
#### `cloud_functions_platform_interface` - `v5.7.0`
51+
52+
- **FEAT**(cloud_functions): add support for cloud functions stream ([#17214](https://github.com/firebase/flutterfire/issues/17214)). ([509e0f3c](https://github.com/firebase/flutterfire/commit/509e0f3cc984a7b56a67979b4b27aff72defdd55))
53+
54+
#### `cloud_functions_web` - `v4.11.0`
55+
56+
- **FEAT**(cloud_functions): add support for cloud functions stream ([#17214](https://github.com/firebase/flutterfire/issues/17214)). ([509e0f3c](https://github.com/firebase/flutterfire/commit/509e0f3cc984a7b56a67979b4b27aff72defdd55))
57+
58+
#### `firebase_auth` - `v5.5.3`
59+
60+
- **FIX**(auth,iOS): include missing email and credential in account-exists-with-different-credential error ([#17180](https://github.com/firebase/flutterfire/issues/17180)). ([2a0bdc64](https://github.com/firebase/flutterfire/commit/2a0bdc64086e99f8a98bd18b472b36bcfe05a9a4))
61+
62+
#### `firebase_vertexai` - `v1.6.0`
63+
64+
- **FIX**(vertexai): add missing HarmBlockThreshold to exported APIs ([#17249](https://github.com/firebase/flutterfire/issues/17249)). ([59d902c6](https://github.com/firebase/flutterfire/commit/59d902c63bd1bd040f5357cb6a341db446429430))
65+
- **FEAT**(vertexai): Live API breaking changes ([#17299](https://github.com/firebase/flutterfire/issues/17299)). ([69cd2a64](https://github.com/firebase/flutterfire/commit/69cd2a640d25e0f2b623f2e631d090ead8af140d))
66+
67+
668
## 2025-03-31 - [BoM 3.9.0](https://github.com/firebase/flutterfire/blob/main/VERSIONS.md#flutter-bom-390-2025-03-31)
769

870
### Changes

VERSIONS.md

+39
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,45 @@ This document is listing all the compatible versions of the FlutterFire plugins.
44

55
# Versions
66

7+
## [Flutter BoM 3.10.0 (2025-04-28)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2025-04-28)
8+
9+
Install this version using FlutterFire CLI
10+
11+
```bash
12+
flutterfire install 3.10.0
13+
```
14+
15+
### Included Native Firebase SDK Versions
16+
| Firebase SDK | Version | Link |
17+
|--------------|---------|------|
18+
| Android SDK | 33.11.0 | [Release Notes](https://firebase.google.com/support/release-notes/android) |
19+
| iOS SDK | 11.10.0 | [Release Notes](https://firebase.google.com/support/release-notes/ios) |
20+
| Web SDK | 11.5.0 | [Release Notes](https://firebase.google.com/support/release-notes/js) |
21+
| Windows SDK | 12.7.0 | [Release Notes](https://firebase.google.com/support/release-notes/cpp-relnotes) |
22+
23+
### FlutterFire Plugin Versions
24+
| Plugin | Version | Dart Version | Flutter Version |
25+
|--------|---------|--------------|-----------------|
26+
| [cloud_firestore](https://pub.dev/packages/cloud_firestore/versions/5.6.7) | 5.6.7 | >=3.2.0 <4.0.0 | >=3.3.0 |
27+
| [cloud_functions](https://pub.dev/packages/cloud_functions/versions/5.5.0) | 5.5.0 | >=3.2.0 <4.0.0 | >=3.3.0 |
28+
| [firebase_analytics](https://pub.dev/packages/firebase_analytics/versions/11.4.5) | 11.4.5 | >=3.2.0 <4.0.0 | >=3.3.0 |
29+
| [firebase_app_check](https://pub.dev/packages/firebase_app_check/versions/0.3.2+5) | 0.3.2+5 | >=3.2.0 <4.0.0 | >=3.3.0 |
30+
| [firebase_app_installations](https://pub.dev/packages/firebase_app_installations/versions/0.3.2+5) | 0.3.2+5 | >=3.2.0 <4.0.0 | >=3.3.0 |
31+
| [firebase_auth](https://pub.dev/packages/firebase_auth/versions/5.5.3) | 5.5.3 | >=3.2.0 <4.0.0 | >=3.16.0 |
32+
| [firebase_core](https://pub.dev/packages/firebase_core/versions/3.13.0) | 3.13.0 | >=3.2.0 <4.0.0 | >=3.3.0 |
33+
| [firebase_crashlytics](https://pub.dev/packages/firebase_crashlytics/versions/4.3.5) | 4.3.5 | >=3.2.0 <4.0.0 | >=3.3.0 |
34+
| [firebase_data_connect](https://pub.dev/packages/firebase_data_connect/versions/0.1.4+1) | 0.1.4+1 | >=3.2.0 <4.0.0 | >=3.3.0 |
35+
| [firebase_database](https://pub.dev/packages/firebase_database/versions/11.3.5) | 11.3.5 | >=3.2.0 <4.0.0 | >=3.3.0 |
36+
| [firebase_dynamic_links](https://pub.dev/packages/firebase_dynamic_links/versions/6.1.5) | 6.1.5 | >=3.2.0 <4.0.0 | >=3.3.0 |
37+
| [firebase_in_app_messaging](https://pub.dev/packages/firebase_in_app_messaging/versions/0.8.1+5) | 0.8.1+5 | >=3.2.0 <4.0.0 | >=3.3.0 |
38+
| [firebase_messaging](https://pub.dev/packages/firebase_messaging/versions/15.2.5) | 15.2.5 | >=3.2.0 <4.0.0 | >=3.3.0 |
39+
| [firebase_ml_model_downloader](https://pub.dev/packages/firebase_ml_model_downloader/versions/0.3.3+3) | 0.3.3+3 | >=3.2.0 <4.0.0 | >=3.3.0 |
40+
| [firebase_performance](https://pub.dev/packages/firebase_performance/versions/0.10.1+5) | 0.10.1+5 | >=3.2.0 <4.0.0 | >=3.3.0 |
41+
| [firebase_remote_config](https://pub.dev/packages/firebase_remote_config/versions/5.4.3) | 5.4.3 | >=3.2.0 <4.0.0 | >=3.3.0 |
42+
| [firebase_storage](https://pub.dev/packages/firebase_storage/versions/12.4.5) | 12.4.5 | >=3.2.0 <4.0.0 | >=3.3.0 |
43+
| [firebase_vertexai](https://pub.dev/packages/firebase_vertexai/versions/1.6.0) | 1.6.0 | >=3.2.0 <4.0.0 | >=3.16.0 |
44+
45+
746
## [Flutter BoM 3.9.0 (2025-03-31)](https://github.com/firebase/flutterfire/blob/main/CHANGELOG.md#2025-03-31)
847

948
Install this version using FlutterFire CLI

docs/cloud-messaging/receive.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -529,13 +529,13 @@ At this point, everything should still be running normally. The final step is in
529529
```objc
530530
#import "NotificationService.h"
531531
#import "FirebaseMessaging.h"
532-
#import "FirebaseAuth.h" // Add this line if you are using FirebaseAuth phone authentication
532+
#import <FirebaseAuth/FirebaseAuth-Swift.h> // Add this line if you are using FirebaseAuth phone authentication
533533
#import <UIKit/UIKit.h> // Add this line if you are using FirebaseAuth phone authentication
534534
535-
@interface NotificationService ()
535+
@interface NotificationService () <NSURLSessionDelegate>
536536
537-
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
538-
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
537+
@property(nonatomic) void (^contentHandler)(UNNotificationContent *contentToDeliver);
538+
@property(nonatomic) UNMutableNotificationContent *bestAttemptContent;
539539
540540
@end
541541

packages/cloud_firestore/cloud_firestore/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 5.6.7
2+
3+
- **FIX**(firestore): Change asserts to throw argumentError ([#17302](https://github.com/firebase/flutterfire/issues/17302)). ([ec1e6a5e](https://github.com/firebase/flutterfire/commit/ec1e6a5eef149680b2750900d1f16d8074e09b38))
4+
- **FIX**(cloud_firestore): correct nanoseconds calculation for pre-1970 dates ([#17195](https://github.com/firebase/flutterfire/issues/17195)). ([a13deae3](https://github.com/firebase/flutterfire/commit/a13deae3334045fb1a48817ff9300cbe0696d177))
5+
16
## 5.6.6
27

38
- Update a dependency to the latest release.

packages/cloud_firestore/cloud_firestore/example/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ environment:
55
sdk: '>=3.2.0 <4.0.0'
66

77
dependencies:
8-
cloud_firestore: ^5.6.6
8+
cloud_firestore: ^5.6.7
99
firebase_core: ^3.13.0
1010
flutter:
1111
sdk: flutter

packages/cloud_firestore/cloud_firestore/pubspec.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description:
44
live synchronization and offline support on Android and iOS.
55
homepage: https://firebase.google.com/docs/firestore
66
repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore
7-
version: 5.6.6
7+
version: 5.6.7
88
topics:
99
- firebase
1010
- firestore
@@ -20,8 +20,8 @@ environment:
2020
flutter: '>=3.3.0'
2121

2222
dependencies:
23-
cloud_firestore_platform_interface: ^6.6.6
24-
cloud_firestore_web: ^4.4.6
23+
cloud_firestore_platform_interface: ^6.6.7
24+
cloud_firestore_web: ^4.4.7
2525
collection: ^1.0.0
2626
firebase_core: ^3.13.0
2727
firebase_core_platform_interface: ^5.4.0

packages/cloud_firestore/cloud_firestore_platform_interface/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 6.6.7
2+
3+
- **FIX**(cloud_firestore): correct nanoseconds calculation for pre-1970 dates ([#17195](https://github.com/firebase/flutterfire/issues/17195)). ([a13deae3](https://github.com/firebase/flutterfire/commit/a13deae3334045fb1a48817ff9300cbe0696d177))
4+
15
## 6.6.6
26

37
- Update a dependency to the latest release.

packages/cloud_firestore/cloud_firestore_platform_interface/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: cloud_firestore_platform_interface
22
description: A common platform interface for the cloud_firestore plugin.
3-
version: 6.6.6
3+
version: 6.6.7
44
homepage: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface
55
repository: https://github.com/firebase/flutterfire/tree/main/packages/cloud_firestore/cloud_firestore_platform_interface
66

packages/cloud_firestore/cloud_firestore_web/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 4.4.7
2+
3+
- Update a dependency to the latest release.
4+
15
## 4.4.6
26

37
- Update a dependency to the latest release.

0 commit comments

Comments
 (0)