diff --git a/README.md b/README.md index c40a28a..11be0be 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ package's `README.md` and `PORTING_REPORT.md`. | [`firebase_auth_tvos`](packages/firebase_auth_tvos) [![pub](https://img.shields.io/pub/v/firebase_auth_tvos.svg)](https://pub.dev/packages/firebase_auth_tvos) | [`firebase_auth`](https://pub.dev/packages/firebase_auth) | | [`cloud_firestore_tvos`](packages/cloud_firestore_tvos) [![pub](https://img.shields.io/pub/v/cloud_firestore_tvos.svg)](https://pub.dev/packages/cloud_firestore_tvos) | [`cloud_firestore`](https://pub.dev/packages/cloud_firestore) | | [`firebase_storage_tvos`](packages/firebase_storage_tvos) [![pub](https://img.shields.io/pub/v/firebase_storage_tvos.svg)](https://pub.dev/packages/firebase_storage_tvos) | [`firebase_storage`](https://pub.dev/packages/firebase_storage) | +| [`firebase_ai_tvos`](packages/firebase_ai_tvos) [![pub](https://img.shields.io/pub/v/firebase_ai_tvos.svg)](https://pub.dev/packages/firebase_ai_tvos) | [`firebase_ai`](https://pub.dev/packages/firebase_ai) | | [`firebase_messaging_tvos`](packages/firebase_messaging_tvos) [![pub](https://img.shields.io/pub/v/firebase_messaging_tvos.svg)](https://pub.dev/packages/firebase_messaging_tvos) | [`firebase_messaging`](https://pub.dev/packages/firebase_messaging) | | [`firebase_analytics_tvos`](packages/firebase_analytics_tvos) [![pub](https://img.shields.io/pub/v/firebase_analytics_tvos.svg)](https://pub.dev/packages/firebase_analytics_tvos) | [`firebase_analytics`](https://pub.dev/packages/firebase_analytics) | diff --git a/packages/firebase_ai_tvos/.gitignore b/packages/firebase_ai_tvos/.gitignore new file mode 100644 index 0000000..fd30348 --- /dev/null +++ b/packages/firebase_ai_tvos/.gitignore @@ -0,0 +1,26 @@ +# Dart / Flutter +.dart_tool/ +build/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub/ + +# CocoaPods +tvos/Pods/ +tvos/Podfile.lock +tvos/.symlinks/ +tvos/Flutter/Flutter.framework +tvos/Flutter/Flutter.podspec + +# Xcode / SwiftPM (per-user, generated when tvos/Package.swift is opened) +**/.swiftpm/ +**/xcuserdata/ + +# IDE +.idea/ +.vscode/ +*.iml + +# macOS +.DS_Store diff --git a/packages/firebase_ai_tvos/CHANGELOG.md b/packages/firebase_ai_tvos/CHANGELOG.md new file mode 100644 index 0000000..484db9a --- /dev/null +++ b/packages/firebase_ai_tvos/CHANGELOG.md @@ -0,0 +1,8 @@ +## 0.0.1 + +* Initial tvOS (Apple TV) implementation of `firebase_ai`, ported from + `firebase_ai` 3.13.1 with `flutter-tvos plugin port` and finished by hand. + Full API (Gemini Developer API via `FirebaseAI.googleAI()` and Vertex AI via + `FirebaseAI.vertexAI()`); no tvOS feature disables. +* Native layer is a single method channel (`getPlatformHeaders`) — no Firebase + native SDK dependency. Tracks the `firebase_core 4.11.x` FlutterFire train. diff --git a/packages/firebase_ai_tvos/LICENSE b/packages/firebase_ai_tvos/LICENSE new file mode 100644 index 0000000..e58143f --- /dev/null +++ b/packages/firebase_ai_tvos/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + 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. diff --git a/packages/firebase_ai_tvos/PORTING_REPORT.md b/packages/firebase_ai_tvos/PORTING_REPORT.md new file mode 100644 index 0000000..0f791b7 --- /dev/null +++ b/packages/firebase_ai_tvos/PORTING_REPORT.md @@ -0,0 +1,87 @@ +# firebase_ai_tvos — porting report + +Generated by `flutter-tvos plugin port` on 2026-08-14. + +Source: `firebase_ai` 3.13.1 (Swift). Base platform: ios. +Output: `./firebase_ai_tvos` + +> ✅ No tvOS-incompatible APIs detected at type level — the generated package is expected to compile on tvOS (still review stubbed/partial items below). + +## Summary + +| Status | Count | +|---|---| +| Methods ported as-is | 1 | +| Methods stubbed (iOS-only) | 0 | +| Native regions disabled on tvOS | 0 | +| tvOS build outlook | ✅ expected to compile | +| Manual review items | 0 | + +## Methods + +### `getPlatformHeaders` ✓ ported + +No tvOS-incompatible APIs detected in this handler. Copied across unchanged. + +## Imports removed + +None. Every `import` in the source compiles on tvOS. + +## Cross-platform Dart pruned + +None. The source ships no Dart files for non-Apple platforms — nothing had to be removed. + +## Disabled on tvOS + +None. No type-level tvOS-incompatible API was found; nothing had to be compiled out. + +## Manual review items + +None flagged automatically. You should still skim `tvos/Classes/` — regex-based porting is best-effort and cannot catch every obfuscated API use. + +## Checklist + +- [x] Stubbed methods — **N/A**: none. The one handler (`getPlatformHeaders`) ports as-is. +- [x] Partial methods — **N/A**: none. +- [x] Removed imports — **N/A**: none removed. +- [x] `flutter-tvos build tvos --simulator` compiles the generated registrant — **verified** (arm64). +- [x] Version set (`0.0.1`) and `CHANGELOG.md` updated. + +--- + +Manual review complete (2026-08-14) — see the addendum below. + +## Addendum: manual fixes + verification + +`firebase_ai` is unusual among the Firebase plugins: its heavy lifting (Gemini / +Imagen calls) happens in **Dart over HTTPS**, and its native layer is a single +method channel (`getPlatformHeaders`, returning the bundle id). So there is **no +Firebase native SDK** to link. Applied by hand: + +- **Podspec:** tvOS 15.0 floor; `static_framework`; no Flutter-CocoaPod dependency + (Flutter via `FRAMEWORK_SEARCH_PATHS`). **No `Firebase/*` or `firebase_core_tvos` + pod dependency** — the native side doesn't touch the Firebase SDK. +- **Deleted the generated `tvos/Package.swift`** (route via the podspec). +- **`lib/firebase_ai_tvos.dart`:** one-line re-export of + `package:firebase_ai/firebase_ai.dart` (the Dart API is platform-agnostic — + duplicating would create incompatible types). Copied Dart removed. +- **No `firebase_core` import repoint needed** — `FirebaseAIPlugin.swift` doesn't + import `firebase_core` at all. +- **pubspec:** depends only on `firebase_ai ^3.13.1` (no `firebase_core_tvos` — the + consuming app brings that for `Firebase.initializeApp`). + +**Version alignment:** `firebase_ai 3.13.1` is on the `firebase_core 4.11.x` train +(the same train as `firebase_core_tvos`). Keep the whole Firebase stack on one +consistent FlutterFire release. + +**Verified (runtime):** on **both** the tvOS simulator (26.2, Apple TV 4K) and a +**physical Apple TV 4K (release/AOT)** against a live Firebase project with AI +Logic enabled. `FirebaseAI.googleAI().generativeModel('gemini-flash-latest')` +`.generateContent(...)` executed on tvOS, the request reached the Gemini backend, +was **authenticated**, and the **model resolved** — confirmed on-device by writing +the backend reply to the app container and pulling it off with `devicectl device +copy from`. The generated-content payload additionally requires the Firebase +project to have Gemini API billing/credits (the test project's were depleted, so +the backend returned a billing message — which itself proves the full +native→Dart→backend round-trip works on tvOS). +`Platform.operatingSystem == "tvos"` / `Platform.isIOS == true`. diff --git a/packages/firebase_ai_tvos/README.md b/packages/firebase_ai_tvos/README.md new file mode 100644 index 0000000..8825e91 --- /dev/null +++ b/packages/firebase_ai_tvos/README.md @@ -0,0 +1,57 @@ +# firebase_ai_tvos + +The tvOS implementation of [`firebase_ai`](https://pub.dev/packages/firebase_ai). + +> Ported with [`flutter-tvos plugin port`](https://github.com/fluttertv/flutter-tvos) +> from `firebase_ai` 3.13.1, then finished + verified by hand. See +> `PORTING_REPORT.md`. + +## Usage + +Federated plugin implementation — no imports needed from app code; it registers +automatically. Apps that already use `firebase_ai` and target tvOS add: + +```yaml +dependencies: + firebase_ai: ^3.13.1 + firebase_ai_tvos: ^0.0.1 + firebase_core: ^4.11.0 + firebase_core_tvos: ^0.0.1 # for Firebase.initializeApp on tvOS +``` + +> **Version alignment.** This package tracks `firebase_ai 3.13.1`, which is on the +> `firebase_core 4.11.x` train. Keep your whole Firebase stack on one consistent +> FlutterFire release (the same train as `firebase_core_tvos`). + +`firebase_ai`'s heavy lifting (Gemini / Imagen requests) happens in **Dart over +HTTPS**, so it works on tvOS unchanged. Its native layer is tiny — a single +method channel that returns the app's bundle identifier — so this package has +**no Firebase native SDK dependency** and does not depend on `firebase_core_tvos` +itself (your app still needs `firebase_core_tvos` for `Firebase.initializeApp`). + +> **If you also use App Check or Auth with `firebase_ai`.** When those services +> are registered, `firebase_ai` attaches their tokens to its request headers +> (`getToken()` / `getIdToken()`) — and those calls are native. Add the matching +> tvOS implementation or you'll hit a `MissingPluginException`: +> `firebase_app_check_tvos` for App Check, `firebase_auth_tvos` for Auth. Plain +> Gemini, with neither service touched, needs only `firebase_core_tvos`. + +## Status + +| Platform | Implemented | Verified | +| --- | --- | --- | +| Apple TV (`appletvos`) | yes | ✅ verified on a **physical Apple TV 4K** (tvOS 26.x, release/AOT) — `generateContent` reached the Gemini backend and was authenticated + model-resolved on-device | +| Apple TV simulator (`appletvsimulator`) | yes | ✅ verified — same authenticated `generateContent` round-trip against a live project | + +The `firebase_ai` Dart API works on tvOS unchanged — Gemini Developer API via +`FirebaseAI.googleAI()` and Vertex AI via `FirebaseAI.vertexAI()` — because every +request is made from Dart over HTTPS, so nothing is platform-gated. The request +round-trip (native registration → Dart → Gemini backend → authenticated response) +is verified on device and simulator; returning generated content additionally +requires the Firebase project to have Gemini API billing/credits available. (If +your app pairs `firebase_ai` with App Check or Auth, see the dependency note +above.) + +## License + +fluttertv under a BSD-3-Clause license. See `LICENSE` for the full text. diff --git a/packages/firebase_ai_tvos/analysis_options.yaml b/packages/firebase_ai_tvos/analysis_options.yaml new file mode 100644 index 0000000..b49c352 --- /dev/null +++ b/packages/firebase_ai_tvos/analysis_options.yaml @@ -0,0 +1,7 @@ +include: package:flutter_lints/flutter.yaml + +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true diff --git a/packages/firebase_ai_tvos/example/README.md b/packages/firebase_ai_tvos/example/README.md new file mode 100644 index 0000000..5501550 --- /dev/null +++ b/packages/firebase_ai_tvos/example/README.md @@ -0,0 +1,19 @@ +# firebase_ai_tvos example (Apple TV) + +Minimal app that calls a Gemini generative model via **Firebase AI Logic** from +tvOS, to verify the `firebase_ai_tvos` plugin on the Simulator and a physical +Apple TV. + +## 1. Connect it to Firebase +On tvOS, `defaultTargetPlatform == TargetPlatform.iOS`, so the iOS Firebase app +config is used. Run `flutterfire configure` (pick your project → the iOS app), +and enable the **Firebase AI Logic** API + Gemini in the console. + +## 2. Run it +```bash +export PATH="/path/to/flutter-tvos/bin:$PATH" +flutter-tvos pub get +flutter-tvos run -d "Apple TV" # simulator, or a physical Apple TV +``` +Press **generateContent (Gemini)** with the Siri Remote. A returned sentence (or +even a backend error) confirms the request reached Firebase AI from Apple TV. diff --git a/packages/firebase_ai_tvos/example/lib/firebase_options.dart b/packages/firebase_ai_tvos/example/lib/firebase_options.dart new file mode 100644 index 0000000..77618a2 --- /dev/null +++ b/packages/firebase_ai_tvos/example/lib/firebase_options.dart @@ -0,0 +1,32 @@ +// PLACEHOLDER — replace by running `flutterfire configure` in this example dir. +// On tvOS, defaultTargetPlatform == TargetPlatform.iOS, so the `ios` entry is +// what Apple TV uses (your iOS Firebase app config is reused for tvOS). +// ignore_for_file: lines_longer_than_80_chars +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError('This example targets Apple TV (tvOS) only.'); + } + switch (defaultTargetPlatform) { + case TargetPlatform.iOS: // tvOS reports iOS + return ios; + default: + throw UnsupportedError('This example targets Apple TV (tvOS) only.'); + } + } + + // Replace with your real values — run `flutterfire configure`, or copy them + // from your iOS app's GoogleService-Info.plist / Firebase console. + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'REPLACE_ME', + appId: 'REPLACE_ME', // GOOGLE_APP_ID + messagingSenderId: 'REPLACE_ME', // GCM_SENDER_ID + projectId: 'REPLACE_ME', + storageBucket: 'REPLACE_ME', + iosBundleId: 'com.example.firebaseAiExample', + ); +} diff --git a/packages/firebase_ai_tvos/example/lib/main.dart b/packages/firebase_ai_tvos/example/lib/main.dart new file mode 100644 index 0000000..0cbd737 --- /dev/null +++ b/packages/firebase_ai_tvos/example/lib/main.dart @@ -0,0 +1,75 @@ +// Copyright 2026 Google LLC. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:firebase_ai/firebase_ai.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:flutter/material.dart'; + +import 'firebase_options.dart'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + runApp(const AiExampleApp()); +} + +class AiExampleApp extends StatelessWidget { + const AiExampleApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'firebase_ai tvOS example', + theme: ThemeData.dark(useMaterial3: true), + home: const AiHomePage(), + ); + } +} + +class AiHomePage extends StatefulWidget { + const AiHomePage({super.key}); + + @override + State createState() => _AiHomePageState(); +} + +class _AiHomePageState extends State { + String _status = 'Ready — ask Gemini with the Siri Remote.'; + + Future _ask() async { + setState(() => _status = 'thinking…'); + try { + final model = + FirebaseAI.googleAI().generativeModel(model: 'gemini-flash-latest'); + final response = await model.generateContent([ + Content.text('In one short sentence, what is Apple TV?'), + ]); + setState(() => _status = '✅ ${response.text ?? "(no text)"}'); + } catch (e) { + // Reaching the AI backend (even an error) proves the plugin works on tvOS. + setState(() => _status = '⚠️ $e'); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('firebase_ai · tvOS')), + body: Padding( + padding: const EdgeInsets.all(48), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text(_status, style: const TextStyle(fontSize: 24)), + const SizedBox(height: 32), + ElevatedButton( + autofocus: true, + onPressed: _ask, + child: const Text('generateContent (Gemini)'), + ), + ], + ), + ), + ); + } +} diff --git a/packages/firebase_ai_tvos/example/pubspec.yaml b/packages/firebase_ai_tvos/example/pubspec.yaml new file mode 100755 index 0000000..ef3ec83 --- /dev/null +++ b/packages/firebase_ai_tvos/example/pubspec.yaml @@ -0,0 +1,27 @@ +name: firebase_ai_example +description: Demonstrates how to use the firebase_ai plugin on tvOS. +publish_to: none + +environment: + sdk: '^3.6.0' + flutter: '>=3.27.0' + +dependencies: + # Pinned to the 4.11.x train (firebase_core_platform_interface 7.1.0) that the + # Firebase _tvos family ships on; newer firebase_core drifts to pi 8.1 and + # mismatches firebase_core_tvos's native Pigeon. + firebase_ai: 3.13.1 + firebase_ai_tvos: + path: ../ + firebase_core: 4.11.0 + firebase_core_tvos: ^0.0.1 + flutter: + sdk: flutter + +dev_dependencies: + flutter_lints: ^4.0.0 + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/packages/firebase_ai_tvos/example/tvos/.gitignore b/packages/firebase_ai_tvos/example/tvos/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/.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/firebase_ai_tvos/example/tvos/Flutter/Debug.xcconfig b/packages/firebase_ai_tvos/example/tvos/Flutter/Debug.xcconfig new file mode 100644 index 0000000..f5ba6d4 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "Generated.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" diff --git a/packages/firebase_ai_tvos/example/tvos/Flutter/Release.xcconfig b/packages/firebase_ai_tvos/example/tvos/Flutter/Release.xcconfig new file mode 100644 index 0000000..075d0bd --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include "Generated.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" diff --git a/packages/firebase_ai_tvos/example/tvos/Podfile b/packages/firebase_ai_tvos/example/tvos/Podfile new file mode 100644 index 0000000..2e1ee47 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Podfile @@ -0,0 +1,45 @@ +# Flutter tvOS Podfile — auto-generated by flutter-tvos create. +# Reads .flutter-plugins-dependencies and adds local pods for each plugin. + +platform :tvos, '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, +} + +target 'Runner' do + use_frameworks! + + # Install plugin pods from .flutter-plugins-dependencies + flutter_plugins_deps = File.expand_path(File.join('..', '.flutter-plugins-dependencies'), File.dirname(__FILE__)) + if File.exist?(flutter_plugins_deps) + require 'json' + deps = JSON.parse(File.read(flutter_plugins_deps)) + tvos_plugins = deps.dig('plugins', 'tvos') || [] + tvos_plugins.each do |plugin| + plugin_name = plugin['name'] + plugin_path = plugin['path'] + tvos_dir = File.join(plugin_path, 'tvos') + # Plugins that ship a Package.swift are resolved via Swift Package Manager + # (see flutter-tvos's generated FlutterGeneratedPluginSwiftPackage). Skip + # them here so they are never linked twice (SPM + CocoaPods). + has_spm = File.exist?(File.join(tvos_dir, 'Package.swift')) + if File.directory?(tvos_dir) && !has_spm && File.exist?(File.join(tvos_dir, "#{plugin_name}.podspec")) + pod plugin_name, :path => tvos_dir + end + end + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['TVOS_DEPLOYMENT_TARGET'] = '15.0' + end + end +end diff --git a/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.pbxproj b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ccaf1ba --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,564 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 69FC96ED025011896A40B981 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C376E448723773D75EC4B7DB /* Pods_Runner.framework */; }; + 97C146FB1CF9000082B4168C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000082B4168C /* AppDelegate.swift */; }; + 97C1470A1CF9000082B4168D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000082B4168D /* Main.storyboard */; }; + 97C1470B1CF9000082B4168D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000082B4168E /* LaunchScreen.storyboard */; }; + 97C1470F1CF9000082B4168C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000082B4168C /* Assets.xcassets */; }; + AAF20000000000000000F00D /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = AAF30000000000000000F00D /* FlutterGeneratedPluginSwiftPackage */; }; +/* End PBXBuildFile section */ + +/* 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 = ""; }; + 3B3967151E833CAB004F5970 /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 5C2882EE07DB51AF11121F93 /* 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 = ""; }; + 74858FAE1ED2DC5600515810 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000082B41680 /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FA1CF9000082B4168C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 97C146FD1CF9000082B4168C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C146FE1CF9000082B4168C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 97C146FF1CF9000082B4168D /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FF1CF9000082B4168E /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + AAA000000000000000000003 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + C376E448723773D75EC4B7DB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C5D40B00A3F9A1FE37D78EA0 /* 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 = ""; }; + E5FDE818A65A37D84788B042 /* 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 */ + 97C146EB1CF9000082B4168C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AAF20000000000000000F00D /* FlutterGeneratedPluginSwiftPackage in Frameworks */, + 69FC96ED025011896A40B981 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 72F2B22472AF13926912E010 /* Pods */ = { + isa = PBXGroup; + children = ( + E5FDE818A65A37D84788B042 /* Pods-Runner.debug.xcconfig */, + 5C2882EE07DB51AF11121F93 /* Pods-Runner.release.xcconfig */, + C5D40B00A3F9A1FE37D78EA0 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 97C146E51CF9000082B4168C = { + isa = PBXGroup; + children = ( + 97C146F01CF9000082B4168C /* Runner */, + 97C146F01CF9000082B4168E /* Flutter */, + 97C146F01CF9000082B4168F /* Frameworks */, + 97C146EF1CF9000082B41690 /* Products */, + 72F2B22472AF13926912E010 /* Pods */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000082B41690 /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000082B41680 /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000082B4168C /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000082B4168C /* AppDelegate.swift */, + AAA000000000000000000003 /* Runner-Bridging-Header.h */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 97C146FD1CF9000082B4168C /* Assets.xcassets */, + 97C146FE1CF9000082B4168C /* Info.plist */, + 97C146FF1CF9000082B4168D /* Main.storyboard */, + 97C146FF1CF9000082B4168E /* LaunchScreen.storyboard */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F01CF9000082B4168E /* Flutter */ = { + isa = PBXGroup; + children = ( + 74858FAE1ED2DC5600515810 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146F01CF9000082B4168F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAB004F5970 /* Flutter.framework */, + C376E448723773D75EC4B7DB /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000082B41690 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000082B4168C /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + FF571599D98BF3C1DDB19F8C /* [CP] Check Pods Manifest.lock */, + 97C146EA1CF9000082B4168C /* Sources */, + 97C146EB1CF9000082B4168C /* Frameworks */, + 97C146EC1CF9000082B4168C /* Resources */, + AAF10000000000000000F00D /* Embed App.framework */, + 9740EEB31CF901A200538489 /* Copy flutter_assets */, + 2E4ECA833C8DE363BE0B80E1 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + packageProductDependencies = ( + AAF30000000000000000F00D /* FlutterGeneratedPluginSwiftPackage */, + ); + productName = Runner; + productReference = 97C146EE1CF9000082B41680 /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000082B4168C /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1510; + LastUpgradeCheck = 1510; + TargetAttributes = { + 97C146ED1CF9000082B41690 = { + CreatedOnToolsVersion = 15.1; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000082B4168C /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000082B4168C; + packageReferences = ( + AAF40000000000000000F00D /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); + productRefGroup = 97C146EF1CF9000082B41690 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000082B41690 /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000082B4168C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C1470F1CF9000082B4168C /* Assets.xcassets in Resources */, + 97C1470A1CF9000082B4168D /* Main.storyboard in Resources */, + 97C1470B1CF9000082B4168D /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2E4ECA833C8DE363BE0B80E1 /* [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; + }; + 9740EEB31CF901A200538489 /* Copy flutter_assets */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(PROJECT_DIR)/Flutter/flutter_assets", + ); + name = "Copy flutter_assets"; + outputPaths = ( + "$(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).app/flutter_assets", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/bin/sh\n# Copy flutter_assets into the app bundle\nFLUTTER_ASSETS_SRC=\"${PROJECT_DIR}/Flutter/flutter_assets\"\nDEST=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/flutter_assets\"\nif [ -d \"${FLUTTER_ASSETS_SRC}\" ]; then\n echo \"Copying flutter_assets to app bundle...\"\n rsync -av --delete \"${FLUTTER_ASSETS_SRC}/\" \"${DEST}/\"\nelse\n echo \"warning: flutter_assets not found at ${FLUTTER_ASSETS_SRC}\"\nfi\n"; + }; + AAF10000000000000000F00D /* Embed App.framework */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(PROJECT_DIR)/Flutter/App.framework", + ); + name = "Embed App.framework"; + outputPaths = ( + "$(BUILT_PRODUCTS_DIR)/$(PRODUCT_NAME).app/Frameworks/App.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/bin/sh\n# Embed App.framework (AOT Dart snapshots) into the app bundle.\n# Present only for release/profile (AOT) builds; debug/JIT has no App.framework.\n# Runs for build, run, AND archive, so TestFlight/App Store builds get it too.\nAPP_FRAMEWORK_SRC=\"${PROJECT_DIR}/Flutter/App.framework\"\nDEST_FRAMEWORKS=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Frameworks\"\nif [ -d \"${APP_FRAMEWORK_SRC}\" ]; then\n echo \"Embedding App.framework...\"\n mkdir -p \"${DEST_FRAMEWORKS}\"\n rsync -av --delete \"${APP_FRAMEWORK_SRC}\" \"${DEST_FRAMEWORKS}/\"\n if [ \"${CODE_SIGNING_REQUIRED}\" != \"NO\" ] && [ -n \"${EXPANDED_CODE_SIGN_IDENTITY}\" ]; then\n echo \"Codesigning App.framework with ${EXPANDED_CODE_SIGN_IDENTITY}...\"\n codesign --force --sign \"${EXPANDED_CODE_SIGN_IDENTITY}\" --timestamp=none --generate-entitlement-der \"${DEST_FRAMEWORKS}/App.framework\"\n fi\nelse\n echo \"No App.framework to embed (debug/JIT build).\"\nfi\n"; + }; + FF571599D98BF3C1DDB19F8C /* [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 */ + 97C146EA1CF9000082B4168C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C146FB1CF9000082B4168C /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase 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++20"; + 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=appletvos*]" = "Apple Development"; + 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; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = appletvos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TVOS_DEPLOYMENT_TARGET = 15.0; + 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)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.firebaseAiExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000082B41691 /* 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++20"; + 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=appletvos*]" = "Apple Development"; + 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; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = appletvos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TVOS_DEPLOYMENT_TARGET = 15.0; + }; + name = Debug; + }; + 97C147031CF9000082B41692 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.firebaseAiExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147041CF9000082B41691 /* 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++20"; + 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=appletvos*]" = "Apple Development"; + 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; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = appletvos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TVOS_DEPLOYMENT_TARGET = 15.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147041CF9000082B41692 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.firebaseAiExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 3; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000082B4168C /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000082B41691 /* Debug */, + 97C147041CF9000082B41691 /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000082B4168C /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000082B41692 /* Debug */, + 97C147041CF9000082B41692 /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + AAF40000000000000000F00D /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + AAF30000000000000000F00D /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 97C146E61CF9000082B4168C /* Project object */; +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..ee3561d --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner.xcworkspace/contents.xcworkspacedata b/packages/firebase_ai_tvos/example/tvos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/firebase_ai_tvos/example/tvos/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/AppDelegate.swift b/packages/firebase_ai_tvos/example/tvos/Runner/AppDelegate.swift new file mode 100644 index 0000000..e867cf0 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/AppDelegate.swift @@ -0,0 +1,20 @@ +import UIKit +import Flutter + +@main +class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + let flutterViewController = FlutterViewController(project: nil, nibName: nil, bundle: nil) + let window = UIWindow(frame: UIScreen.main.bounds) + window.rootViewController = flutterViewController + window.makeKeyAndVisible() + self.window = window + + GeneratedPluginRegistrant.register(with: self) + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AccentColor.colorset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..c6a0bc3 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "large_back.png", + "scale" : "1x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/large_back.png b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/large_back.png new file mode 100644 index 0000000..b89e77a Binary files /dev/null and b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/large_back.png differ diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Contents.json new file mode 100644 index 0000000..de59d88 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ] +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..f7cf529 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "large_front.png", + "scale" : "1x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/large_front.png b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/large_front.png new file mode 100644 index 0000000..d1bf0b6 Binary files /dev/null and b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/large_front.png differ diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..fedb0ad --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "large_middle.png", + "scale" : "1x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/large_middle.png b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/large_middle.png new file mode 100644 index 0000000..eca5900 Binary files /dev/null and b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/large_middle.png differ diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..1d59796 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "small_back.png", + "scale" : "1x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/small_back.png b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/small_back.png new file mode 100644 index 0000000..eac8b47 Binary files /dev/null and b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/small_back.png differ diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Contents.json new file mode 100644 index 0000000..de59d88 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ] +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..e8f0da2 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "small_front.png", + "scale" : "1x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/small_front.png b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/small_front.png new file mode 100644 index 0000000..71eb8ae Binary files /dev/null and b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/small_front.png differ diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..9d01973 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "small_middle.png", + "scale" : "1x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/small_middle.png b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/small_middle.png new file mode 100644 index 0000000..624d2bb Binary files /dev/null and b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/small_middle.png differ diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Contents.json new file mode 100644 index 0000000..5af3206 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Contents.json @@ -0,0 +1,26 @@ +{ + "assets" : [ + { + "filename" : "App Icon - Large.imagestack", + "idiom" : "tv", + "role" : "primary-app-icon", + "size" : "1280x768" + }, + { + "filename" : "App Icon - Small.imagestack", + "idiom" : "tv", + "role" : "primary-app-icon", + "size" : "400x240" + }, + { + "filename" : "Top Shelf Image.imageset", + "idiom" : "tv", + "role" : "top-shelf-image", + "size" : "1920x720" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..74f7c24 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "tv", + "filename" : "top_shelf.png", + "scale" : "1x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/top_shelf.png b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/top_shelf.png new file mode 100644 index 0000000..cbbebf8 Binary files /dev/null and b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/AppIcon.brandassets/Top Shelf Image.imageset/top_shelf.png differ diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/Contents.json b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Base.lproj/LaunchScreen.storyboard b/packages/firebase_ai_tvos/example/tvos/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..088a3ba --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Base.lproj/Main.storyboard b/packages/firebase_ai_tvos/example/tvos/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..4e805a1 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Info.plist b/packages/firebase_ai_tvos/example/tvos/Runner/Info.plist new file mode 100644 index 0000000..c598d22 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Firebase_ai_example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + firebase_ai_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + + FLTAssetsPath + flutter_assets + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + + diff --git a/packages/firebase_ai_tvos/example/tvos/Runner/Runner-Bridging-Header.h b/packages/firebase_ai_tvos/example/tvos/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/packages/firebase_ai_tvos/example/tvos/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/firebase_ai_tvos/lib/firebase_ai_tvos.dart b/packages/firebase_ai_tvos/lib/firebase_ai_tvos.dart new file mode 100644 index 0000000..808580d --- /dev/null +++ b/packages/firebase_ai_tvos/lib/firebase_ai_tvos.dart @@ -0,0 +1,11 @@ +// Copyright 2026 Google LLC +// Use of this source code is governed by a BSD-style license. + +// firebase_ai's public Dart API (FirebaseAI, GenerativeModel, chat, imagen, …) +// has no per-platform Dart override — the generative calls are HTTPS from Dart, +// and the sole native touch-point is a `getPlatformHeaders` method channel. +// Duplicating the Dart here would create incompatible types vs. apps importing +// package:firebase_ai/firebase_ai.dart directly. This package only supplies the +// native tvOS pluginClass (tvos/Classes/); apps depend on firebase_ai (Dart API) +// and firebase_ai_tvos (native registration) side by side — see example/. +export 'package:firebase_ai/firebase_ai.dart'; diff --git a/packages/firebase_ai_tvos/pubspec.yaml b/packages/firebase_ai_tvos/pubspec.yaml new file mode 100644 index 0000000..1739123 --- /dev/null +++ b/packages/firebase_ai_tvos/pubspec.yaml @@ -0,0 +1,30 @@ +name: firebase_ai_tvos +description: >- + tvOS (Apple TV) implementation of the firebase_ai Flutter plugin, providing + Firebase AI Logic (Gemini generative models) on Apple TV. +version: 0.0.1 +homepage: https://fluttertv.dev +repository: https://github.com/fluttertv/plugins/tree/main/packages/firebase_ai_tvos +issue_tracker: https://github.com/fluttertv/plugins/issues +# Generated by `flutter-tvos plugin port`, then finished by hand. See PORTING_REPORT.md. +# License holder: fluttertv + +environment: + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.13.0" + +dependencies: + flutter: + sdk: flutter + firebase_ai: ^3.13.1 + +dev_dependencies: + flutter_lints: ^4.0.0 + flutter_test: + sdk: flutter + +flutter: + plugin: + platforms: + tvos: + pluginClass: FirebaseAIPlugin diff --git a/packages/firebase_ai_tvos/test/firebase_ai_tvos_test.dart b/packages/firebase_ai_tvos/test/firebase_ai_tvos_test.dart new file mode 100644 index 0000000..1f19ddd --- /dev/null +++ b/packages/firebase_ai_tvos/test/firebase_ai_tvos_test.dart @@ -0,0 +1,14 @@ +// Copyright 2026 fluttertv. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Generated on 2026-08-14 by `flutter-tvos plugin port`. +// Source plugin: firebase_ai + +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('test harness runs', () { + expect(1 + 1, 2); + }); +} diff --git a/packages/firebase_ai_tvos/tvos/Classes/FirebaseAIPlugin.swift b/packages/firebase_ai_tvos/tvos/Classes/FirebaseAIPlugin.swift new file mode 100644 index 0000000..a762121 --- /dev/null +++ b/packages/firebase_ai_tvos/tvos/Classes/FirebaseAIPlugin.swift @@ -0,0 +1,49 @@ +// 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. + +#if canImport(FlutterMacOS) + import FlutterMacOS +#else + import Flutter +#endif + +public class FirebaseAIPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + #if canImport(FlutterMacOS) + let messenger = registrar.messenger + #else + let messenger = registrar.messenger() + #endif + + let channel = FlutterMethodChannel( + name: "plugins.flutter.io/firebase_ai", + binaryMessenger: messenger + ) + let instance = FirebaseAIPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getPlatformHeaders": + var headers: [String: String] = [:] + if let bundleId = Bundle.main.bundleIdentifier { + headers["x-ios-bundle-identifier"] = bundleId + } + result(headers) + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/packages/firebase_ai_tvos/tvos/firebase_ai_tvos.podspec b/packages/firebase_ai_tvos/tvos/firebase_ai_tvos.podspec new file mode 100644 index 0000000..c384834 --- /dev/null +++ b/packages/firebase_ai_tvos/tvos/firebase_ai_tvos.podspec @@ -0,0 +1,35 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint firebase_ai_tvos.podspec` to validate before publishing. +# +# Generated by `flutter-tvos plugin port`, then finished by hand. License holder: fluttertv. +# +Pod::Spec.new do |s| + s.name = 'firebase_ai_tvos' + s.version = '0.0.1' + s.summary = 'tvOS implementation of firebase_ai.' + s.description = <<-DESC +tvOS implementation of firebase_ai, the federated platform +package that ships native code targeting Apple tvOS. + DESC + s.homepage = 'https://github.com/fluttertv/plugins/tree/main/packages/firebase_ai_tvos' + s.license = { :file => '../LICENSE' } + s.author = { 'fluttertv' => 'noreply@fluttertv.dev' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + # No Firebase native SDK dependency — firebase_ai's native side is a single + # method-channel plugin (getPlatformHeaders); the AI calls are HTTPS from Dart. + # tvOS 15.0 matches the rest of the Firebase _tvos family the app ships with. + s.platform = :tvos, '15.0' + s.swift_version = '5.0' + + # IMPORTANT: this podspec must not depend on the Flutter CocoaPod. That pod + # does not declare tvOS support, so depending on it breaks `pod install` for + # tvOS consumers. Flutter.framework is resolved via FRAMEWORK_SEARCH_PATHS. + s.xcconfig = { + 'FRAMEWORK_SEARCH_PATHS' => '"${PODS_ROOT}/../Flutter"', + 'OTHER_SWIFT_FLAGS' => '$(inherited) -DTARGET_OS_TV', + } + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } +end