diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index c4f228e..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,117 +0,0 @@ -## 0.x.x - -* fixed [#67](https://github.com/csells/flutter_ai_toolkit/issues/67): bug: audio recording translation repopulated after history cleared - -* fixed [#68](https://github.com/csells/flutter_ai_toolkit/issues/68): bug: need suggestion styling - -## 0.4.2 - -* upgraded to waveform_recorder 1.3.0 - -* fix [#69](https://github.com/csells/flutter_ai_toolkit/issues/69): SDK dependency conflict by lowering sdk requirement to 3.4.0 - -## 0.4.1 - -* updated samples, demo and README - -## 0.4.0 - -* implemented [#13](https://github.com/csells/flutter_ai_toolkit/issues/13): UI needs dark mode support - -* implemented [#30](https://github.com/csells/flutter_ai_toolkit/issues/30): chat serialization/deserialization - -* fixed [#64](https://github.com/csells/flutter_ai_toolkit/issues/64): bug: selection sticks around after clearing the history - -* fixed [#63](https://github.com/csells/flutter_ai_toolkit/issues/63): bug: broke multi-line text input - -* fixed [#60](https://github.com/csells/flutter_ai_toolkit/issues/60): bug: if an LLM request fails with no text in the response, the progress indicator never stops - -* implemented [#31](https://github.com/csells/flutter_ai_toolkit/issues/31): feature: provide a list of initial suggested prompts to display in an empty chat session - -* implemented [#25](https://github.com/csells/flutter_ai_toolkit/issues/25): better mobile long-press action menu for chat messages - -* fixed [#47](https://github.com/csells/flutter_ai_toolkit/issues/25): bug: Long pressing a message and then clicking outside of the toolbar should make the toolbar disappear - -## 0.3.0 - -* implemented [#32](https://github.com/csells/flutter_ai_toolkit/issues/32): feature: dev-configured LLM message icon - -* fixed [#19](https://github.com/csells/flutter_ai_toolkit/issues/19): prompt attachments are incorrectly merging when editing after adding attachments to a new prompt - -* implemented [#27](https://github.com/csells/flutter_ai_toolkit/issues/27): feature: styling of colors and fonts - -## 0.2.1 - -* fixing the user message edit menu - -* show errors and cancelations as separate from message output; this is necessary so that you can tell the difference between an LLM message response with a successful result that, for example, can be parsed as JSON, or an error - -## 0.2.0 - -* implemented [#33](https://github.com/csells/flutter_ai_toolkit/issues/33): feature: chat microphone only prompt input - -* added a `generateStream` method to `LlmProvider` to support talking to the underlying generative model w/o adding to the chat history; moved `chatModel` properties in the Gemini and Vertex providers to use a more generic `generativeModel` to make it clear which model is being used for both `sendMessageStream` and `generateStream`. - -* moved from [flutter_markdown_selectionarea](https://pub.dev/packages/flutter_markdown_selectionarea) to plain ol' [flutter_markdown](https://pub.dev/packages/flutter_markdown) which does now support selection if you ask it nicely. I still have some work to do on selection, however, as described in [issue #12](https://github.com/csells/flutter_ai_toolkit/issues/12). - -* implemented [#27](https://github.com/csells/flutter_ai_toolkit/issues/27): styling support, including a sample - -* fixed [#3](https://github.com/csells/flutter_ai_toolkit/issues/3): ensure Google Font Roboto is being resolved - -* implemented [#2](https://github.com/csells/flutter_ai_toolkit/issues/2): feature: enable full functionality inside a Cupertino app - -* fixed [#45](https://github.com/csells/flutter_ai_toolkit/issues/45): bug: X icon button is also pushing up against the top and left edges without any padding - -* fixed [#59](https://github.com/csells/flutter_ai_toolkit/issues/59): bug: Android Studio LadyBug Upgrade Issues - -* upgraded to the GA version of firebase_vertexai - -## 0.1.6 - -* added optional `welcomeMessage` to `LlmChatView` and a welcome sample. thanks, @berkaykurkcu! - -* updated VertexProvider to take a separate chat and embedding model like GeminiProvider - -* fixed #51 : Click on an image to get a preview. thanks, @Shashwat-111! - -* fixed #6: get a spark icon to designate the LLM - -* updated README for clarity - -## 0.1.5 - -* Reference docs update - -## 0.1.4 - -* CHANGELOG fix - -## 0.1.3 - -* new real-world-ish sample: recipes - -* new custom LLM provider sample: gemma - -* handling structured LLM responses via `responseBuilder` (see recipes sample) - -* app-provided prompt suggestions (see recipes sample) - -* pre-processing prompts to add prompt engineering via `messageSender` - -* pre-processing requests to enrich the output, e.g. host Flutter widgets (see recipes sample) - -* swappable support for LLM providers; oob support for Gemini and Vertex (see gemma example) - -* fixed trim and over-eager message editing issues -- thanks, @Shashwat-111! - -## 0.1.2 - -* More README fixups - -## 0.1.1 - -* Fixing README screenshot (sigh) - -## 0.1.0 - -* Initial alpha release \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index ff2b5cf..0000000 --- a/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -Copyright 2024, the Flutter AI Toolkit project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 225424d..0000000 --- a/README.md +++ /dev/null @@ -1,132 +0,0 @@ -Hello and welcome to the Flutter AI Toolkit! - -The AI Toolkit is a set of AI chat-related widgets to make it easy to add an AI chat window to your Flutter app. The AI Toolkit is organized around an abstract LLM provider API to make it easy to swap out the LLM provider that you'd like your chat provider to use. Out of the box, it comes with support for two LLM provider integrations: Google Gemini AI and Firebase Vertex AI. - -## Current Alpha Features -The AI Toolkit is currently under active development and at the alpha stage, with the following features currently available: - -- multi-turn chat (remembering context along the way) -- streaming responses -- multi-line chat text input (via Alt/Opt+Enter on web/desktop) -- cancel in-progress request -- edit the last prompt (starting with long-press as the UI gesture) -- rich text response display -- chat microphone speech-to-tech prompt input -- copy any response (starting with long-press as the UI gesture) -- multi-media attachments ([the web currently doesn't like file attachments](https://github.com/csells/flutter_ai_toolkit/issues/18), so they're disabled) -- handling structured LLM responses -- app-provided prompt suggestions -- pre-processing prompts to add prompt engineering, etc. -- pre-processing requests to enrich the output, e.g. host Flutter widgets -- updated UX based on Google design guidelines -- custom styling support -- dev-configured chatbot label + icon -- support for Cupertino as well as Material -- chat session serialization/deserialization -- swappable support for LLM providers; oob support for Gemini and Vertex -- support for all Flutter platforms, focusing initially on mobile and web - -Here's an example of [a sample app](https://github.com/csells/flutter_ai_toolkit/blob/main/example/lib/demo/demo.dart) hosting the AI Tookit running on the web: - - - -If you'd like to see it in action, check out [the online demo](https://flutter-ai-toolkit-examp-60bad.web.app/). - -## Getting started -Using the AI Toolkit is a matter of choosing which LLM provider you'd like to use (Gemini or Vertex), creating an instance and passing it to the `LlmChatView` widget, which is the main entry point for the AI Toolkit: - -```dart -// don't forget the pubspec.yaml entries for these, too -import 'package:google_generative_ai/google_generative_ai.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; - -... // app stuff here - -class ChatPage extends StatelessWidget { - const ChatPage({super.key}); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: const Text(App.title)), - // create the chat view, passing in the Gemini provider - body: LlmChatView( - provider: GeminiProvider( - model: 'gemini-1.5-flash', - apiKey: googleApiKey, - ), - ), - ); -} -``` - -Here we're creating an instance of the `GeminiProvider`, configuring it as appropriate and passing it to an instance of the `LlmChatView`. That yields the screenshot above using Google Gemini AI as the LLM. You can see more details about configuring both the Gemini and Vertex LLM providers below. - -## Gemini LLM Usage -To configure the `GeminiProvider` you two things: -1. model string, which you can ready about in [the Gemini models docs](https://ai.google.dev/gemini-api/docs/models/gemini), and -1. an API key, which you can get [in Gemini AI Studio](https://aistudio.google.com/app/apikey). - -With this in place, you're ready to write the Gemini code shown above. If you like, you can plug your API key and model string into the gemini.dart sample. This sample has been tested on Android, iOS, the web and macOS, so give it a whirl. - -Note: Be careful not to check your API key into a git repo or share it with anyone. - -## Vertex LLM Usage -While Gemini AI is useful for quick prototyping, the recommended solution for production apps is Firebase Vertext AI. And the reason for that is that there's no good way to keep your Gemini API key safe -- if you ship your Flutter app with the API key in there, someone can figure out how to dig it out. - -To solve this problem as well as many others that you're going to have in a real-world production app, the model for initializing an instance of the Vertex AI LLM provider doesn't have an API key. Instead, it relies on a Firebase project, which you then initialize in your app. You can do that with the steps described in [the Get started with the Gemini API using the Vertex AI in Firebase SDKs docs](https://firebase.google.com/docs/vertex-ai/get-started?platform=flutter). - -Also make sure you configure your FlutterApp using the `flutterfire` CLI tool as described in [the Add Firebase to your Flutter app docs](https://firebase.google.com/docs/flutter/setup). - -After following these instructions, you're ready to use Firebase Vertex AI in your project. Start by initializing Firebase: - -```dart -// don't forget the pubspec.yaml entries for these, too -import 'package:firebase_core/firebase_core.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; - -... // other imports - -import 'firebase_options.dart'; // from `flutterfire config` - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); - runApp(const App()); -} - -... // app stuff here -``` - -This is the same way that you'd initialize Firebase for use in any Flutter project, so it should be familiar to existing FlutterFire users. - -Now you're ready to create an instance of the Vertex provider: - -```dart -class ChatPage extends StatelessWidget { - const ChatPage({super.key}); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: const Text(App.title)), - // create the chat view, passing in the Vertex provider - body: LlmChatView( - provider: VertexProvider( - chatModel: FirebaseVertexAI.instance.generativeModel( - model: 'gemini-1.5-flash', - ), - ), - ), - ); -} -``` -If you like, use your Firebase project with the vertex.dart sample. This sample has also been tested on Android, iOS, the web and macOS. - -Note: There's no API key; Firebase manages all of that for you in the Firebase project. However, in the same way that someone can reverse engineer the Gemini API key out of your Flutter code, they can do that with your Firebase project ID and related settings. To guard against that, check out [Firebase AppCheck](https://firebase.google.com/learn/pathways/firebase-app-check), which is beyond the scope of the sample code in this project. - -## More Features Coming Soon! -As I mentioned, the AI Toolkit is just in the alpha phase of it's lifetime and it's under active development. Coming soon, you should expect the following features: -- stand-alone chatbot app sample with multi-session support -- thoroughly tested multi-platform support, including Windows and Linux - -## Feedback! -Along the way, as you use this package, please [log issues and feature requests](https://github.com/csells/flutter_ai_toolkit/issues) as well as any [code you'd like to contribute](https://github.com/csells/flutter_ai_toolkit/pulls). I want your feedback and your contributions to ensure that the AI Toolkit is just as robust and useful as it can be for your real apps. diff --git a/README/screenshot.png b/README/screenshot.png deleted file mode 100644 index 206141a..0000000 Binary files a/README/screenshot.png and /dev/null differ diff --git a/analysis_options.yaml b/analysis_options.yaml deleted file mode 100644 index 735d0e6..0000000 --- a/analysis_options.yaml +++ /dev/null @@ -1,36 +0,0 @@ -include: package:all_lint_rules_community/all.yaml - -analyzer: - exclude: - - "**/*.g.dart" - - "**/*.freezed.dart" - - "test/.test_coverage.dart" - - "bin/cache/**" - - "lib/generated_plugin_registrant.dart" - errors: - # without ignore here, we cause import of all_lint_rules to warn, because - # some rules conflict; instead, we're explicitly enabling even conflicting - # rules and are fixing the conflicts in this file - included_file_warning: ignore - unintended_html_in_doc_comment: ignore - -linter: - rules: - avoid_types_on_closure_parameters: true # no; prefer use of final instead - prefer_double_quotes: false # Dart prefers single quotes (for some reason) - unnecessary_final: false # love final! - always_specify_types: false # no; prefer use of final instead - prefer_final_parameters: false # I like the sentiment, but too much typing! - prefer_asserts_with_message: false # too lazy for this... - require_trailing_commas: false # not good for things all on one line - public_member_api_docs: true # except for public libs - avoid_classes_with_only_static_members: false # need this; no namespaces - always_put_control_body_on_new_line: false # single line is nice when we can - always_use_package_imports: false # prefer relative imports for local files - avoid_annotating_with_dynamic: false # be explicit about dynamic - avoid_redundant_argument_values: false # sometimes it's nice to be explicit - one_member_abstracts: false # interfaces can have a single method - flutter_style_todos: false # I'm too lazy for this... - diagnostic_describe_all_properties: false # too annoying for StatefulWidget - library_private_types_in_public_api: false # too annoying for StatefulWidget - cascade_invocations: false # not a fan... \ No newline at end of file diff --git a/check-docs.sh b/check-docs.sh deleted file mode 100755 index e976dd7..0000000 --- a/check-docs.sh +++ /dev/null @@ -1 +0,0 @@ -dart doc --dry-run diff --git a/deploy-demo.sh b/deploy-demo.sh deleted file mode 100755 index 7491465..0000000 --- a/deploy-demo.sh +++ /dev/null @@ -1,5 +0,0 @@ -cd example -rm -rf build/web -flutter build web --release --target lib/demo/demo.dart -firebase deploy -cd .. diff --git a/example/.firebase/hosting.YnVpbGQvd2Vi.cache b/example/.firebase/hosting.YnVpbGQvd2Vi.cache deleted file mode 100644 index ae692e4..0000000 --- a/example/.firebase/hosting.YnVpbGQvd2Vi.cache +++ /dev/null @@ -1,35 +0,0 @@ -manifest.json,1722130836723,f81e4554dc7f05633a2c5597416813859de5ace688342db41b201d42790fb8a7 -flutter.js,1726080818000,dec659847e4e16b505a257eb15bc32ef814f99a319e44e15b9c56294de0c9ecd -favicon.png,1716580864393,fcc7c4545d5b62ad01682589e6fdc7ea03d0a3b42069963c815c344b632eb5cf -icons/Icon-maskable-512.png,1716580886213,e7983524dc70254adc61764657d7e03d19284de8da586b5818d737bc08c6d14e -icons/Icon-maskable-192.png,1716580886213,dd96c123fdf6817cdf7e63d9693bcc246bac2e3782a41a6952fa41c0617c5573 -icons/Icon-512.png,1716580864394,7a31ce91e554f1941158ca46f31c7f3f2b7c8c129229ea74a8fae1affe335033 -icons/Icon-192.png,1716580864394,d2e0131bb7851eb9d98f7885edb5ae4b4d6b7a6c7addf8a25b9b712b39274c0f -canvaskit/skwasm.worker.js,1726081188000,ff1a6b2c254c1954106d62ce10432547fa6d6a7d99c0aaf9ea6144a23ef0c09b -canvaskit/skwasm.wasm,1726081188000,204bb6c7deaa41ccfdb811d09107bcacd7162a848d8e9faa45e46390fe0dda9a -canvaskit/skwasm.js.symbols,1726081188000,ea615fdcd1320bad0f3fb6b3e5bcb0dd3a4d8480c221af6a84455860775987c1 -canvaskit/skwasm.js,1726081188000,3da3d8d5b168f8f2cba2513cba2c65a9bfa650723545145cffa76a102a678e9d -canvaskit/canvaskit.wasm,1726081100000,2e91b313aa59675be755df469bb88efdfa2be8cdccc4e49bf743f9f22d16f933 -canvaskit/canvaskit.js.symbols,1726081098000,7687fed87ac2c6f61e5d991be1e3f8c0191e4271128c73a5afea2f28562ad0b8 -canvaskit/canvaskit.js,1726081100000,95f051f3c2845fb04127fd56e1fa3e52a69d271eea561869e97bfe4374548109 -canvaskit/chromium/canvaskit.wasm,1726081122000,d865adf21902388e4d4af54a5e430479e5ef37ac660649017db1877b29976a08 -canvaskit/chromium/canvaskit.js.symbols,1726081120000,9d7b8e9cc146e9ad2b68af9f0c8092b144a9aac73666941b468b8b2fd36cdb27 -canvaskit/chromium/canvaskit.js,1726081122000,c448a9b3e29d0dad724aa33a554695e7f1257c58b28baca305177fd18e62e411 -assets/packages/record_web/assets/js/record.worklet.js,1726247519128,bd510fc16afe17c0cfc943194267c8d2af8a4b88fa63b525926c95d319e544c7 -assets/packages/record_web/assets/js/record.fixwebmduration.js,1726247519130,77e2fe77324499420d0a882273998e7574fa885c3a7d944a8e69382e5daaab08 -assets/assets/recipes_default.json,1727751782273,1f90b422a85d1e7a708fd4d255d8b7db1b6206bf002813cb380d6cce0fbb4bd8 -assets/assets/halloween-bg.png,1729875831180,aa155fdcd4249179b89ca8e6dbfbff642a622534635e9cc6dce5c099d7445b7e -version.json,1730136001205,8e7012f17ec662cfb721c69523e82a27ac216e8e3c973b248b847e9a118cf603 -index.html,1730135983527,4c1651c60b2cd671eb40ebf9e77cd7d7f1894a90b21182fa149ead727d85095f -assets/FontManifest.json,1730136001277,d1784484a5fbf123cc38d6fb83f618e2f855cfc9a47c4b87c34565736fb1025f -flutter_service_worker.js,1730136002322,09a340c85d8522734c4db9521a920665aef469eec44a7162064304be50c817ee -assets/AssetManifest.json,1730136001277,5ee990889da9f2ce04fb308d72dfb0a4df0a2a8c4cfe808dcc784e0cea9560ea -assets/AssetManifest.bin.json,1730136001277,599a0b1e65a657294c65f94df02a01c115e4f2ef9a651ce3bbadad941866dc9d -assets/AssetManifest.bin,1730136001277,71fc78fcaf72348505ddacbfc2fc03fb686e543376e18388ecdca2509e70245d -flutter_bootstrap.js,1730135983509,257003d38cfc778893260c7ce9a69c191aa5c23c05402fb287677767cc049188 -assets/packages/flutter_ai_toolkit/lib/fonts/FatIcons.ttf,1730136002032,59c80e8640bde5d1fc73af52961bb52ed3f08fddd3af8f8fe172880442cc33b7 -assets/packages/cupertino_icons/assets/CupertinoIcons.ttf,1730136002030,a9dec9e47fcee105fc5f7ea79904e588215596ef681f1ba97034cd0829c0554b -assets/shaders/ink_sparkle.frag,1730136001332,80c6e65c75f1de434b1b22dba61e96ad82dba0f2fc5e8b3b59c2def46d794354 -assets/fonts/MaterialIcons-Regular.otf,1730136002034,d1e5ecfde56f17e87cc9b0e73792a40eadf95ed0372e336e13038744c8dc09cf -assets/NOTICES,1730136001278,b7c968ec8b44aa16ccd1a0138cfee73251738e425cae9fcc8fbdca9051337fc6 -main.dart.js,1730136001025,34484a94aff99c34bb6608f95d1a7e3d39b2bd66184d520341ff826ace776120 diff --git a/example/.gitignore b/example/.gitignore deleted file mode 100644 index b76857e..0000000 --- a/example/.gitignore +++ /dev/null @@ -1,47 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release - -# custom -gemini_api_key.dart -firebase_options.dart \ No newline at end of file diff --git a/example/.metadata b/example/.metadata deleted file mode 100644 index c689480..0000000 --- a/example/.metadata +++ /dev/null @@ -1,30 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "2663184aa79047d0a33a14a3b607954f8fdd8730" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 - base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 - - platform: android - create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 - base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml deleted file mode 100644 index 86ebcb7..0000000 --- a/example/analysis_options.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -analyzer: - errors: - library_private_types_in_public_api: ignore -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/example/android/.gitignore b/example/android/.gitignore deleted file mode 100644 index 55afd91..0000000 --- a/example/android/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle deleted file mode 100644 index 1c992a6..0000000 --- a/example/android/app/build.gradle +++ /dev/null @@ -1,48 +0,0 @@ -plugins { - id "com.android.application" - // START: FlutterFire Configuration - id 'com.google.gms.google-services' - // END: FlutterFire Configuration - id "kotlin-android" - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" -} - -android { - ndkVersion = "25.1.8937393" - namespace = "com.example.example" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.example" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = 23 // flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.debug - } - } -} - -flutter { - source = "../.." -} diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/example/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 3090d18..0000000 --- a/example/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt deleted file mode 100644 index 70f8f08..0000000 --- a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.example.example - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml deleted file mode 100644 index f74085f..0000000 --- a/example/android/app/src/main/res/drawable-v21/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f..0000000 --- a/example/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4..0000000 Binary files a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b7..0000000 Binary files a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 09d4391..0000000 Binary files a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d..0000000 Binary files a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372e..0000000 Binary files a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 06952be..0000000 --- a/example/android/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml deleted file mode 100644 index cb1ef88..0000000 --- a/example/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f698..0000000 --- a/example/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/example/android/build.gradle b/example/android/build.gradle deleted file mode 100644 index d2ffbff..0000000 --- a/example/android/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/example/android/gradle.properties b/example/android/gradle.properties deleted file mode 100644 index 2597170..0000000 --- a/example/android/gradle.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true -android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 9c5194d..0000000 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip \ No newline at end of file diff --git a/example/android/settings.gradle b/example/android/settings.gradle deleted file mode 100644 index c818a7c..0000000 --- a/example/android/settings.gradle +++ /dev/null @@ -1,28 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" -id "com.android.application" version "8.3.2" apply false - // START: FlutterFire Configuration - id "com.google.gms.google-services" version "4.3.15" apply false - // END: FlutterFire Configuration - id "org.jetbrains.kotlin.android" version "1.8.22" apply false -} - -include ":app" diff --git a/example/assets/README.md b/example/assets/README.md deleted file mode 100644 index 637991d..0000000 --- a/example/assets/README.md +++ /dev/null @@ -1,3 +0,0 @@ -The following assets have been generated by the Gemini LLM and are being used royalty-free in this project: -- halloween-bg.png -- recipes_default.json \ No newline at end of file diff --git a/example/assets/halloween-bg.png b/example/assets/halloween-bg.png deleted file mode 100644 index 3dfbd3a..0000000 Binary files a/example/assets/halloween-bg.png and /dev/null differ diff --git a/example/assets/recipes_default.json b/example/assets/recipes_default.json deleted file mode 100644 index 29ee4db..0000000 --- a/example/assets/recipes_default.json +++ /dev/null @@ -1,296 +0,0 @@ -[ - { - "id": "f8c3de3d-1fea-4d7c-a8b0-29f63c4c3454", - "title": "Spaghetti and Meatballs", - "description": "A classic Italian comfort food dish.", - "ingredients": [ - "1 pound spaghetti", - "1 pound ground beef", - "1 onion, chopped", - "2 cloves garlic, minced", - "1 (28 ounce) can crushed tomatoes", - "1 (15 ounce) can tomato sauce", - "1/4 cup chopped fresh parsley", - "1 teaspoon dried oregano", - "1/2 teaspoon salt", - "1/4 teaspoon black pepper" - ], - "instructions": [ - "Cook spaghetti according to package directions.", - "Mix ground beef, onion, garlic, and spices; form into meatballs.", - "Brown meatballs in a large skillet over medium heat.", - "Add crushed tomatoes and tomato sauce; simmer for 20 minutes.", - "Serve meatballs and sauce over cooked spaghetti." - ], - "tags": [ - "Italian", - "pasta", - "dinner", - "comfort food" - ], - "notes": "" - }, - { - "id": "a2c8d3e3-b1f7-4d5a-9c3b-1f8e7d4c6e5d", - "title": "Chicken Stir-Fry", - "description": "A quick and easy weeknight meal.", - "ingredients": [ - "1 pound boneless, skinless chicken breasts, cut into bite-sized pieces", - "1 tablespoon vegetable oil", - "1 onion, sliced", - "1 red bell pepper, sliced", - "1 green bell pepper, sliced", - "1 (14.5 ounce) can chicken broth", - "1/4 cup soy sauce", - "2 tablespoons cornstarch", - "1/4 cup water", - "1 teaspoon sesame oil" - ], - "instructions": [ - "Heat oil in a large skillet or wok over medium-high heat.", - "Add chicken and cook until browned, about 5 minutes.", - "Add onion and bell peppers; stir-fry for 3-4 minutes.", - "Mix chicken broth, soy sauce, cornstarch, and water in a bowl.", - "Pour sauce into the skillet and cook until thickened.", - "Drizzle with sesame oil and serve over rice." - ], - "tags": [ - "Asian", - "chicken", - "quick meal", - "stir-fry" - ], - "notes": "" - }, - { - "id": "b3d9e4f5-c2g8-6h7i-j9k0-l1m2n3o4p5q6", - "title": "Pancakes", - "description": "A delicious breakfast staple.", - "ingredients": [ - "1 1/2 cups all-purpose flour", - "2 tablespoons sugar", - "2 teaspoons baking powder", - "1/2 teaspoon salt", - "1 1/4 cups milk", - "1 egg", - "3 tablespoons melted unsalted butter" - ], - "instructions": [ - "Whisk together flour, sugar, baking powder, and salt in a bowl.", - "In another bowl, whisk milk, egg, and melted butter.", - "Pour wet ingredients into dry ingredients and mix until just combined.", - "Heat a griddle or non-stick pan over medium heat.", - "Pour 1/4 cup batter for each pancake and cook until bubbles form.", - "Flip and cook other side until golden brown.", - "Serve with maple syrup and butter." - ], - "tags": [ - "breakfast", - "sweet", - "quick", - "vegetarian" - ], - "notes": "" - }, - { - "id": "c4e0f5g6-h7i8-j9k0-l1m2-n3o4p5q6r7s8", - "title": "Grilled Salmon", - "description": "A healthy and flavorful seafood dish.", - "ingredients": [ - "4 salmon fillets", - "2 tablespoons olive oil", - "1 lemon, juiced", - "2 cloves garlic, minced", - "1 teaspoon dried dill", - "Salt and pepper to taste" - ], - "instructions": [ - "Preheat grill to medium-high heat.", - "In a small bowl, mix olive oil, lemon juice, garlic, and dill.", - "Season salmon fillets with salt and pepper.", - "Brush the marinade over the salmon fillets.", - "Grill salmon for 4-5 minutes per side, or until it flakes easily.", - "Serve with lemon wedges and your choice of sides." - ], - "tags": [ - "seafood", - "healthy", - "grilling", - "quick" - ], - "notes": "" - }, - { - "id": "d5f1g2h3-i4j5-k6l7-m8n9-o0p1q2r3s4t5", - "title": "Vegetable Lasagna", - "description": "A hearty vegetarian pasta dish.", - "ingredients": [ - "1 package lasagna noodles", - "2 zucchini, sliced", - "2 cups spinach", - "1 cup ricotta cheese", - "1 cup mozzarella cheese", - "1 jar marinara sauce", - "1/4 cup grated Parmesan cheese" - ], - "instructions": [ - "Preheat oven to 375°F (190°C).", - "Cook lasagna noodles according to package directions.", - "In a baking dish, layer noodles, zucchini, spinach, ricotta, and marinara sauce.", - "Repeat layers, ending with sauce and mozzarella on top.", - "Sprinkle with Parmesan cheese.", - "Bake for 25-30 minutes until cheese is melted and bubbly.", - "Let cool for 10 minutes before serving." - ], - "tags": [ - "vegetarian", - "Italian", - "pasta", - "casserole" - ], - "notes": "" - }, - { - "id": "e6g2h3i4-j5k6-l7m8-n9o0-p1q2r3s4t5u6", - "title": "Beef Tacos", - "description": "A Mexican-inspired favorite.", - "ingredients": [ - "1 pound ground beef", - "1 packet taco seasoning", - "8 taco shells", - "1 cup shredded lettuce", - "1 cup diced tomatoes", - "1 cup shredded cheddar cheese", - "1/2 cup sour cream" - ], - "instructions": [ - "Brown ground beef in a skillet over medium heat.", - "Drain excess fat and add taco seasoning with water as directed on packet.", - "Simmer for 5 minutes, stirring occasionally.", - "Warm taco shells according to package directions.", - "Fill shells with beef mixture, lettuce, tomatoes, cheese, and sour cream.", - "Serve immediately." - ], - "tags": [ - "Mexican", - "beef", - "quick", - "family-friendly" - ], - "notes": "" - }, - { - "id": "f7h3i4j5-k6l7-m8n9-o0p1-q2r3s4t5u6v7", - "title": "Caesar Salad", - "description": "A classic salad with a creamy dressing.", - "ingredients": [ - "1 head romaine lettuce", - "1/2 cup Caesar dressing", - "1/4 cup grated Parmesan cheese", - "1 cup croutons", - "1 lemon, juiced" - ], - "instructions": [ - "Wash and chop romaine lettuce into bite-sized pieces.", - "In a large bowl, toss lettuce with Caesar dressing.", - "Add Parmesan cheese and croutons, toss gently.", - "Squeeze fresh lemon juice over the salad.", - "Serve immediately." - ], - "tags": [ - "salad", - "vegetarian", - "quick", - "side dish" - ], - "notes": "" - }, - { - "id": "g8i4j5k6-l7m8-n9o0-p1q2-r3s4t5u6v7w8", - "title": "Chocolate Chip Cookies", - "description": "A beloved sweet treat.", - "ingredients": [ - "2 1/4 cups all-purpose flour", - "1 teaspoon baking soda", - "1 cup unsalted butter, softened", - "3/4 cup granulated sugar", - "3/4 cup brown sugar", - "2 large eggs", - "2 cups semisweet chocolate chips" - ], - "instructions": [ - "Preheat oven to 375°F (190°C).", - "In a bowl, mix flour and baking soda.", - "In another bowl, cream butter and sugars until light and fluffy.", - "Beat in eggs one at a time.", - "Gradually stir in flour mixture, then fold in chocolate chips.", - "Drop spoonfuls of dough onto ungreased baking sheets.", - "Bake for 9-11 minutes or until golden brown.", - "Cool on wire racks." - ], - "tags": [ - "dessert", - "baking", - "cookies", - "chocolate" - ], - "notes": "" - }, - { - "id": "h9j5k6l7-m8n9-o0p1-q2r3-s4t5u6v7w8x9", - "title": "Beef Stroganoff", - "description": "A creamy Russian-inspired dish.", - "ingredients": [ - "1 pound beef sirloin, sliced", - "1 onion, sliced", - "8 ounces mushrooms, sliced", - "1 cup beef broth", - "1 cup sour cream", - "2 tablespoons flour", - "1 package egg noodles" - ], - "instructions": [ - "Cook egg noodles according to package directions.", - "In a large skillet, brown beef over medium-high heat.", - "Add onions and mushrooms, cook until softened.", - "Sprinkle flour over the mixture and stir.", - "Pour in beef broth, simmer until thickened.", - "Stir in sour cream until heated through.", - "Serve over cooked egg noodles." - ], - "tags": [ - "Russian", - "beef", - "pasta", - "comfort food" - ], - "notes": "" - }, - { - "id": "i0k6l7m8-n9o0-p1q2-r3s4-t5u6v7w8x9y0", - "title": "Caprese Salad", - "description": "A simple Italian salad.", - "ingredients": [ - "3 large tomatoes, sliced", - "1 pound fresh mozzarella, sliced", - "1/4 cup fresh basil leaves", - "2 tablespoons olive oil", - "2 tablespoons balsamic vinegar", - "Salt and pepper to taste" - ], - "instructions": [ - "Arrange alternating slices of tomato and mozzarella on a serving platter.", - "Tuck basil leaves between the slices.", - "Drizzle with olive oil and balsamic vinegar.", - "Season with salt and pepper to taste.", - "Serve immediately at room temperature." - ], - "tags": [ - "Italian", - "salad", - "vegetarian", - "no-cook" - ], - "notes": "" - } -] \ No newline at end of file diff --git a/example/ios/.gitignore b/example/ios/.gitignore deleted file mode 100644 index 7a7f987..0000000 --- a/example/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/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/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index f187d29..0000000 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 13.0 - - diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6..0000000 --- a/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bf..0000000 --- a/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile deleted file mode 100644 index 3e44f9c..0000000 --- a/example/ios/Podfile +++ /dev/null @@ -1,44 +0,0 @@ -# Uncomment this line to define a global platform for your project -platform :ios, '13.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock deleted file mode 100644 index ab87222..0000000 --- a/example/ios/Podfile.lock +++ /dev/null @@ -1,169 +0,0 @@ -PODS: - - AppCheckCore (11.2.0): - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) - - PromisesObjC (~> 2.4) - - file_selector_ios (0.0.1): - - Flutter - - Firebase/Auth (11.2.0): - - Firebase/CoreOnly - - FirebaseAuth (~> 11.2.0) - - Firebase/CoreOnly (11.2.0): - - FirebaseCore (= 11.2.0) - - firebase_app_check (0.3.1-4): - - Firebase/CoreOnly (~> 11.2.0) - - firebase_core - - FirebaseAppCheck (~> 11.2.0) - - Flutter - - firebase_auth (5.3.1): - - Firebase/Auth (= 11.2.0) - - firebase_core - - Flutter - - firebase_core (3.6.0): - - Firebase/CoreOnly (= 11.2.0) - - Flutter - - FirebaseAppCheck (11.2.0): - - AppCheckCore (~> 11.0) - - FirebaseAppCheckInterop (~> 11.0) - - FirebaseCore (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) - - FirebaseAppCheckInterop (11.4.0) - - FirebaseAuth (11.2.0): - - FirebaseAppCheckInterop (~> 11.0) - - FirebaseAuthInterop (~> 11.0) - - FirebaseCore (~> 11.0) - - FirebaseCoreExtension (~> 11.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/Environment (~> 8.0) - - GTMSessionFetcher/Core (~> 3.4) - - RecaptchaInterop (~> 100.0) - - FirebaseAuthInterop (11.4.0) - - FirebaseCore (11.2.0): - - FirebaseCoreInternal (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Logger (~> 8.0) - - FirebaseCoreExtension (11.4.1): - - FirebaseCore (~> 11.0) - - FirebaseCoreInternal (11.4.2): - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - Flutter (1.0.0) - - GoogleUtilities/AppDelegateSwizzler (8.0.2): - - GoogleUtilities/Environment - - GoogleUtilities/Logger - - GoogleUtilities/Network - - GoogleUtilities/Privacy - - GoogleUtilities/Environment (8.0.2): - - GoogleUtilities/Privacy - - GoogleUtilities/Logger (8.0.2): - - GoogleUtilities/Environment - - GoogleUtilities/Privacy - - GoogleUtilities/Network (8.0.2): - - GoogleUtilities/Logger - - "GoogleUtilities/NSData+zlib" - - GoogleUtilities/Privacy - - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (8.0.2)": - - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (8.0.2) - - GoogleUtilities/Reachability (8.0.2): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - GoogleUtilities/UserDefaults (8.0.2): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - GTMSessionFetcher/Core (3.5.0) - - image_picker_ios (0.0.1): - - Flutter - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - - PromisesObjC (2.4.0) - - RecaptchaInterop (100.0.0) - - record_darwin (1.0.0): - - Flutter - - FlutterMacOS - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - url_launcher_ios (0.0.1): - - Flutter - -DEPENDENCIES: - - file_selector_ios (from `.symlinks/plugins/file_selector_ios/ios`) - - firebase_app_check (from `.symlinks/plugins/firebase_app_check/ios`) - - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - - Flutter (from `Flutter`) - - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - - record_darwin (from `.symlinks/plugins/record_darwin/ios`) - - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) - -SPEC REPOS: - trunk: - - AppCheckCore - - Firebase - - FirebaseAppCheck - - FirebaseAppCheckInterop - - FirebaseAuth - - FirebaseAuthInterop - - FirebaseCore - - FirebaseCoreExtension - - FirebaseCoreInternal - - GoogleUtilities - - GTMSessionFetcher - - PromisesObjC - - RecaptchaInterop - -EXTERNAL SOURCES: - file_selector_ios: - :path: ".symlinks/plugins/file_selector_ios/ios" - firebase_app_check: - :path: ".symlinks/plugins/firebase_app_check/ios" - firebase_auth: - :path: ".symlinks/plugins/firebase_auth/ios" - firebase_core: - :path: ".symlinks/plugins/firebase_core/ios" - Flutter: - :path: Flutter - image_picker_ios: - :path: ".symlinks/plugins/image_picker_ios/ios" - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" - record_darwin: - :path: ".symlinks/plugins/record_darwin/ios" - shared_preferences_foundation: - :path: ".symlinks/plugins/shared_preferences_foundation/darwin" - url_launcher_ios: - :path: ".symlinks/plugins/url_launcher_ios/ios" - -SPEC CHECKSUMS: - AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f - file_selector_ios: f0670c1064a8c8450e38145d8043160105d0b97c - Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c - firebase_app_check: 78383bfcd0445037a8ff9795b2e3023f39db5b78 - firebase_auth: 0c77e299a8f2d1c74d1b1f6b78b3d4d802c19f47 - firebase_core: 2bedc3136ec7c7b8561c6123ed0239387b53f2af - FirebaseAppCheck: a6a1c1ca169d795212b9e70b5cfb880083a28e7c - FirebaseAppCheckInterop: 1b9643ae2f1ee214488caa2f8e32b7bc2f0f3735 - FirebaseAuth: 2a198b8cdbbbd457f08d74df7040feb0a0e7777a - FirebaseAuthInterop: 9ac948965ac13ec9d8a080f39490ddb2bda30520 - FirebaseCore: a282032ae9295c795714ded2ec9c522fc237f8da - FirebaseCoreExtension: f1bc67a4702931a7caa097d8e4ac0a1b0d16720e - FirebaseCoreInternal: 35731192cab10797b88411be84940d2beb33a238 - Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d - GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 - image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 - record_darwin: df0a677188e5fed18472550298e675f19ddaffbe - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe - -PODFILE CHECKSUM: a57f30d18f102dd3ce366b1d62a55ecbef2158e5 - -COCOAPODS: 1.15.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 1cc2a0f..0000000 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,746 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 5853DDF772EBA46BB1EC0980 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73DC3E64BA2285A269793F59 /* Pods_Runner.framework */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - B8209442B72206F80B2B41F0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A52100434790B2DDB4EA253F /* Pods_RunnerTests.framework */; }; - D565CCEEA83645FC368483B6 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0525572EEDBE97E74D7DDF35 /* GoogleService-Info.plist */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 0525572EEDBE97E74D7DDF35 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 1AEA9205588D398DACB0BBEC /* 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 = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 4C6733E33EBCE7E3A93C4929 /* 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 = ""; }; - 4D51CEC3C93AE2BDFDF26EB9 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 73DC3E64BA2285A269793F59 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A164447E1EAD6D328C1DF712 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - A52100434790B2DDB4EA253F /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - CC0B39CCB5CBE2102537071A /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - D7AC61E63CBEC99A574C3EA1 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 53C62B63FFDC864785BE7F7C /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - B8209442B72206F80B2B41F0 /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 5853DDF772EBA46BB1EC0980 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - 99FEB944BC7811B3E28CD8B7 /* Pods */, - 0525572EEDBE97E74D7DDF35 /* GoogleService-Info.plist */, - BF5E33A5486DDBB12757C4BB /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; - 99FEB944BC7811B3E28CD8B7 /* Pods */ = { - isa = PBXGroup; - children = ( - 1AEA9205588D398DACB0BBEC /* Pods-Runner.debug.xcconfig */, - D7AC61E63CBEC99A574C3EA1 /* Pods-Runner.release.xcconfig */, - 4C6733E33EBCE7E3A93C4929 /* Pods-Runner.profile.xcconfig */, - A164447E1EAD6D328C1DF712 /* Pods-RunnerTests.debug.xcconfig */, - CC0B39CCB5CBE2102537071A /* Pods-RunnerTests.release.xcconfig */, - 4D51CEC3C93AE2BDFDF26EB9 /* Pods-RunnerTests.profile.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; - BF5E33A5486DDBB12757C4BB /* Frameworks */ = { - isa = PBXGroup; - children = ( - 73DC3E64BA2285A269793F59 /* Pods_Runner.framework */, - A52100434790B2DDB4EA253F /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 0C16F134BB1DA24E19CA911F /* [CP] Check Pods Manifest.lock */, - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - 53C62B63FFDC864785BE7F7C /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 3DF0055CC8139EC8B29E4689 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - E9A04598EF71D77A5C4ADD25 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - D565CCEEA83645FC368483B6 /* GoogleService-Info.plist in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 0C16F134BB1DA24E19CA911F /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 3DF0055CC8139EC8B29E4689 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; - E9A04598EF71D77A5C4ADD25 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 7Y2C479G3R; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = A164447E1EAD6D328C1DF712 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CC0B39CCB5CBE2102537071A /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4D51CEC3C93AE2BDFDF26EB9 /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 7Y2C479G3R; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 7Y2C479G3R; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a..0000000 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 8e3ca5d..0000000 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc1..0000000 --- a/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift deleted file mode 100644 index 6266644..0000000 --- a/example/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fa..0000000 --- a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 7353c41..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 797d452..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 6ed2d93..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cd7b00..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index fe73094..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 321773c..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 797d452..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 502f463..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 0ec3034..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 0ec3034..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index e9f5fea..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 84ac32a..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 8953cba..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 0467bf1..0000000 Binary files a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2..0000000 --- a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725..0000000 --- a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c..0000000 --- a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c2851..0000000 --- a/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist deleted file mode 100644 index 9cdbdf5..0000000 --- a/example/ios/Runner/Info.plist +++ /dev/null @@ -1,55 +0,0 @@ - - - - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Example - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - example - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - NSCameraUsageDescription - $(PRODUCT_NAME) would like to access your camera. - NSMicrophoneUsageDescription - $(PRODUCT_NAME) would like to access your microphone. - NSPhotoLibraryUsageDescription - $(PRODUCT_NAME) would like access to your photos. - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a5..0000000 --- a/example/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/example/ios/RunnerTests/RunnerTests.swift b/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 86a7c3b..0000000 --- a/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Flutter -import UIKit -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/example/lib/cupertino/cupertino.dart b/example/lib/cupertino/cupertino.dart deleted file mode 100644 index ee4eee2..0000000 --- a/example/lib/cupertino/cupertino.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Cupertino'; - - const App({super.key}); - - @override - Widget build(BuildContext context) => const CupertinoApp( - title: title, - home: ChatPage(), - ); -} - -class ChatPage extends StatelessWidget { - const ChatPage({super.key}); - - @override - Widget build(BuildContext context) => CupertinoPageScaffold( - navigationBar: CupertinoNavigationBar( - middle: Text(App.title), - ), - child: LlmChatView( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ), - ), - ); -} diff --git a/example/lib/custom_styles/custom_styles.dart b/example/lib/custom_styles/custom_styles.dart deleted file mode 100644 index 566e923..0000000 --- a/example/lib/custom_styles/custom_styles.dart +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Custom Styles'; - const App({super.key}); - - @override - Widget build(BuildContext context) => MaterialApp( - title: title, - theme: ThemeData.from( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange), - ), - debugShowCheckedModeBanner: false, - home: ChatPage(), - ); -} - -class ChatPage extends StatefulWidget { - const ChatPage({super.key}); - - @override - State createState() => _ChatPageState(); -} - -class _ChatPageState extends State - with SingleTickerProviderStateMixin { - late final _animationController = AnimationController( - duration: const Duration(seconds: 1), - vsync: this, - lowerBound: 0.25, - upperBound: 1.0, - ); - - final _chatController = LlmChatViewController( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ), - ); - - @override - void initState() { - super.initState(); - _reset(); - } - - void _reset() { - _chatController.clearHistory(); - _animationController.value = 1.0; - _animationController.reverse(); - } - - @override - void dispose() { - _animationController.dispose(); - _chatController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text(App.title), - actions: [ - IconButton( - onPressed: _reset, - icon: const Icon(Icons.edit_note), - ), - ], - ), - body: AnimatedBuilder( - animation: _animationController, - builder: (context, child) => Stack( - children: [ - SizedBox( - height: double.infinity, - width: double.infinity, - child: Image.asset( - 'assets/halloween-bg.png', - fit: BoxFit.cover, - opacity: _animationController, - ), - ), - LlmChatView( - controller: _chatController, - style: style, - ), - ], - ), - ), - ); - } - - LlmChatViewStyle get style { - final TextStyle halloweenTextStyle = GoogleFonts.hennyPenny( - color: Colors.white, - fontSize: 24, - ); - - final halloweenActionButtonStyle = ActionButtonStyle( - tooltipTextStyle: halloweenTextStyle, - iconColor: Colors.black, - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - ); - - final halloweenMenuButtonStyle = ActionButtonStyle( - tooltipTextStyle: halloweenTextStyle, - iconColor: Colors.orange, - iconDecoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.orange), - ), - ); - - return LlmChatViewStyle( - backgroundColor: Colors.transparent, - progressIndicatorColor: Colors.purple, - chatInputStyle: ChatInputStyle( - backgroundColor: _animationController.isAnimating - ? Colors.transparent - : Colors.black, - decoration: BoxDecoration( - color: Colors.yellow, - border: Border.all(color: Colors.orange), - ), - textStyle: halloweenTextStyle.copyWith(color: Colors.black), - hintText: 'good evening...', - hintStyle: - halloweenTextStyle.copyWith(color: Colors.orange.withOpacity(.5)), - ), - userMessageStyle: UserMessageStyle( - textStyle: halloweenTextStyle.copyWith(color: Colors.black), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.white, - Colors.grey.shade300, - Colors.grey.shade400, - ], - ), - borderRadius: BorderRadius.circular(20), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - blurRadius: 10, - spreadRadius: 2, - ), - ], - ), - ), - llmMessageStyle: LlmMessageStyle( - icon: Icons.sentiment_very_satisfied, - iconColor: Colors.black, - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(8), - bottomLeft: Radius.circular(8), - topRight: Radius.zero, - bottomRight: Radius.circular(8), - ), - border: Border.all(color: Colors.black), - ), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.deepOrange.shade900, - Colors.orange.shade800, - Colors.purple.shade900, - ], - ), - borderRadius: BorderRadius.only( - topLeft: Radius.zero, - bottomLeft: Radius.circular(20), - topRight: Radius.circular(20), - bottomRight: Radius.circular(20), - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.3), - blurRadius: 8, - offset: Offset(2, 2), - ), - ], - ), - markdownStyle: MarkdownStyleSheet( - p: halloweenTextStyle, - listBullet: halloweenTextStyle, - ), - ), - recordButtonStyle: halloweenActionButtonStyle, - stopButtonStyle: halloweenActionButtonStyle, - submitButtonStyle: halloweenActionButtonStyle, - addButtonStyle: halloweenActionButtonStyle, - attachFileButtonStyle: halloweenMenuButtonStyle, - cameraButtonStyle: halloweenMenuButtonStyle, - closeButtonStyle: halloweenActionButtonStyle, - closeMenuButtonStyle: halloweenActionButtonStyle, - copyButtonStyle: halloweenMenuButtonStyle, - editButtonStyle: halloweenMenuButtonStyle, - galleryButtonStyle: halloweenMenuButtonStyle, - actionButtonBarDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - fileAttachmentStyle: FileAttachmentStyle( - decoration: BoxDecoration( - color: Colors.black, - ), - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - filenameStyle: halloweenTextStyle, - filetypeStyle: halloweenTextStyle.copyWith( - color: Colors.green, - fontSize: 18, - ), - ), - ); - } -} diff --git a/example/lib/dark_mode/dark_mode.dart b/example/lib/dark_mode/dark_mode.dart deleted file mode 100644 index ceb9e60..0000000 --- a/example/lib/dark_mode/dark_mode.dart +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Dark Mode'; - static final themeMode = ValueNotifier(ThemeMode.dark); - - const App({super.key}); - - @override - Widget build(BuildContext context) => ValueListenableBuilder( - valueListenable: themeMode, - builder: (BuildContext context, ThemeMode mode, Widget? child) => - MaterialApp( - title: title, - theme: ThemeData.light(), - darkTheme: ThemeData.dark(), - themeMode: mode, - home: ChatPage(), - debugShowCheckedModeBanner: false, - ), - ); -} - -class ChatPage extends StatefulWidget { - const ChatPage({super.key}); - - @override - State createState() => _ChatPageState(); -} - -class _ChatPageState extends State { - final _provider = GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar( - title: const Text(App.title), - actions: [ - IconButton( - onPressed: () => App.themeMode.value = - App.themeMode.value == ThemeMode.light - ? ThemeMode.dark - : ThemeMode.light, - icon: const Icon(Icons.brightness_4_outlined), - ), - ], - ), - body: LlmChatView( - provider: _provider, - style: App.themeMode.value == ThemeMode.dark - ? LlmChatViewStyle.darkStyle() - : LlmChatViewStyle.lightStyle(), - ), - ); -} diff --git a/example/lib/demo/api_key_page.dart b/example/lib/demo/api_key_page.dart deleted file mode 100644 index 1378718..0000000 --- a/example/lib/demo/api_key_page.dart +++ /dev/null @@ -1,98 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:gap/gap.dart'; -import 'package:url_launcher/url_launcher.dart'; - -class GeminiApiKeyPage extends StatefulWidget { - const GeminiApiKeyPage({ - required this.title, - required this.onApiKey, - super.key, - }); - - final String title; - final void Function(String apiKey) onApiKey; - - @override - State createState() => _GeminiApiKeyPageState(); -} - -class _GeminiApiKeyPageState extends State { - static final url = Uri.parse('https://aistudio.google.com/app/apikey'); - final _controller = TextEditingController(); - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: Text(widget.title)), - body: Center( - child: ValueListenableBuilder( - valueListenable: _controller, - builder: (context, value, child) => Column( - children: [ - const Text('To run this sample, you need a Gemini API key.\n' - 'Get your Gemini API Key from the following URL:'), - GestureDetector( - onTap: () => launchUrl(url, webOnlyWindowName: '_blank'), - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: Text( - url.toString(), - style: const TextStyle( - color: Colors.blue, - decoration: TextDecoration.underline, - ), - ), - ), - ), - GestureDetector( - onTap: _copyUrl, - child: const MouseRegion( - cursor: SystemMouseCursors.click, - child: Text('(or copy the URL above by tapping HERE)'), - ), - ), - const Gap(16), - const Text('Paste your API key here:'), - SizedBox( - width: 300, - child: TextField( - controller: _controller, - decoration: InputDecoration( - labelText: 'Gemini API Key', - errorText: _isValidApiKey() - ? null - : 'API key must be 39 characters', - ), - onSubmitted: _isValidApiKey() - ? (apiKey) => widget.onApiKey(apiKey) - : null, - ), - ), - const Gap(16), - ElevatedButton( - onPressed: _isValidApiKey() - ? () => widget.onApiKey(_controller.text) - : null, - child: const Text('Submit'), - ), - ], - ), - ), - ), - ); - - bool _isValidApiKey() => _controller.text.length == 39; - - void _copyUrl() { - Clipboard.setData(ClipboardData(text: url.toString())); - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Copied URL to clipboard')), - ); - } -} diff --git a/example/lib/demo/demo.dart b/example/lib/demo/demo.dart deleted file mode 100644 index 011cce6..0000000 --- a/example/lib/demo/demo.dart +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import 'api_key_page.dart'; - -late final SharedPreferences prefs; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - final prefs = await SharedPreferences.getInstance(); - runApp(App(prefs: prefs)); -} - -class App extends StatefulWidget { - static const title = 'Demo: Flutter AI Toolkit'; - static final themeMode = ValueNotifier(ThemeMode.light); - - const App({super.key, required this.prefs}); - final SharedPreferences prefs; - - @override - State createState() => _AppState(); -} - -class _AppState extends State { - String? _geminiApiKey; - - @override - void initState() { - super.initState(); - _geminiApiKey = widget.prefs.getString('gemini_api_key'); - } - - @override - Widget build(BuildContext context) => ValueListenableBuilder( - valueListenable: App.themeMode, - builder: (context, mode, child) => MaterialApp( - title: App.title, - theme: ThemeData.light(), - darkTheme: ThemeData.dark(), - themeMode: mode, - home: _geminiApiKey == null - ? GeminiApiKeyPage( - title: App.title, - onApiKey: _setApiKey, - ) - : ChatPage( - geminiApiKey: _geminiApiKey!, - onResetApiKey: _resetApiKey, - ), - debugShowCheckedModeBanner: false, - ), - ); - - void _setApiKey(String apiKey) { - setState(() => _geminiApiKey = apiKey); - widget.prefs.setString('gemini_api_key', apiKey); - } - - void _resetApiKey() { - setState(() => _geminiApiKey = null); - widget.prefs.remove('gemini_api_key'); - } -} - -class ChatPage extends StatefulWidget { - const ChatPage({ - required this.geminiApiKey, - required this.onResetApiKey, - super.key, - }); - - final String geminiApiKey; - final void Function() onResetApiKey; - - @override - State createState() => _ChatPageState(); -} - -class _ChatPageState extends State - with SingleTickerProviderStateMixin { - late final _animationController = AnimationController( - duration: const Duration(seconds: 1), - vsync: this, - lowerBound: 0.25, - upperBound: 1.0, - ); - - late final _chatController = LlmChatViewController( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: widget.geminiApiKey, - ), - ), - ); - - final _halloweenMode = ValueNotifier(false); - - @override - void initState() { - super.initState(); - _resetAnimation(); - } - - void _resetAnimation() { - _animationController.value = 1.0; - _animationController.reverse(); - } - - @override - void dispose() { - _animationController.dispose(); - _chatController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar( - title: const Text(App.title), - actions: [ - IconButton( - onPressed: widget.onResetApiKey, - tooltip: 'Reset API Key', - icon: const Icon(Icons.key), - ), - IconButton( - onPressed: _clearHistory, - tooltip: 'Clear History', - icon: const Icon(Icons.history), - ), - IconButton( - onPressed: () => App.themeMode.value = - App.themeMode.value == ThemeMode.light - ? ThemeMode.dark - : ThemeMode.light, - tooltip: App.themeMode.value == ThemeMode.light - ? 'Dark Mode' - : 'Light Mode', - icon: const Icon(Icons.brightness_4_outlined), - ), - IconButton( - onPressed: () { - _halloweenMode.value = !_halloweenMode.value; - if (_halloweenMode.value) _resetAnimation(); - }, - tooltip: _halloweenMode.value ? 'Normal Mode' : 'Halloween Mode', - icon: Text('🎃'), - ), - ], - ), - body: ValueListenableBuilder( - valueListenable: _halloweenMode, - builder: (context, halloween, child) => AnimatedBuilder( - animation: _animationController, - builder: (context, child) => Stack( - children: [ - SizedBox( - height: double.infinity, - width: double.infinity, - child: Image.asset( - 'assets/halloween-bg.png', - fit: BoxFit.cover, - opacity: _animationController, - ), - ), - LlmChatView( - controller: _chatController, - style: style, - suggestions: [ - 'I\'m a Star Wars fan. What should I wear for Halloween?', - 'I\'m allergic to peanuts. What candy should I avoid at Halloween?', - 'What\'s the difference between a pumpkin and a squash?', - ], - ), - ], - ), - ), - ), - ); - - void _clearHistory() { - _chatController.clearHistory(); - _resetAnimation(); - } - - LlmChatViewStyle get style { - if (!_halloweenMode.value) { - return App.themeMode.value == ThemeMode.dark - ? LlmChatViewStyle.darkStyle() - : LlmChatViewStyle.lightStyle(); - } - - final TextStyle halloweenTextStyle = GoogleFonts.hennyPenny( - color: Colors.white, - fontSize: 24, - ); - - final halloweenActionButtonStyle = ActionButtonStyle( - tooltipTextStyle: halloweenTextStyle, - iconColor: Colors.black, - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - ); - - final halloweenMenuButtonStyle = ActionButtonStyle( - tooltipTextStyle: halloweenTextStyle, - iconColor: Colors.orange, - iconDecoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.orange), - ), - ); - - return LlmChatViewStyle( - backgroundColor: Colors.transparent, - progressIndicatorColor: Colors.purple, - chatInputStyle: ChatInputStyle( - backgroundColor: _animationController.isAnimating - ? Colors.transparent - : Colors.black, - decoration: BoxDecoration( - color: Colors.yellow, - border: Border.all(color: Colors.orange), - ), - textStyle: halloweenTextStyle.copyWith(color: Colors.black), - hintText: 'good evening...', - hintStyle: - halloweenTextStyle.copyWith(color: Colors.orange.withOpacity(.5)), - ), - userMessageStyle: UserMessageStyle( - textStyle: halloweenTextStyle.copyWith(color: Colors.black), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.white, - Colors.grey.shade300, - Colors.grey.shade400, - ], - ), - borderRadius: BorderRadius.circular(20), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - blurRadius: 10, - spreadRadius: 2, - ), - ], - ), - ), - llmMessageStyle: LlmMessageStyle( - icon: Icons.sentiment_very_satisfied, - iconColor: Colors.black, - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(8), - bottomLeft: Radius.circular(8), - topRight: Radius.zero, - bottomRight: Radius.circular(8), - ), - border: Border.all(color: Colors.black), - ), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.deepOrange.shade900, - Colors.orange.shade800, - Colors.purple.shade900, - ], - ), - borderRadius: BorderRadius.only( - topLeft: Radius.zero, - bottomLeft: Radius.circular(20), - topRight: Radius.circular(20), - bottomRight: Radius.circular(20), - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.3), - blurRadius: 8, - offset: Offset(2, 2), - ), - ], - ), - markdownStyle: MarkdownStyleSheet( - p: halloweenTextStyle, - listBullet: halloweenTextStyle, - ), - ), - recordButtonStyle: halloweenActionButtonStyle, - stopButtonStyle: halloweenActionButtonStyle, - submitButtonStyle: halloweenActionButtonStyle, - addButtonStyle: halloweenActionButtonStyle, - attachFileButtonStyle: halloweenMenuButtonStyle, - cameraButtonStyle: halloweenMenuButtonStyle, - closeButtonStyle: halloweenActionButtonStyle, - closeMenuButtonStyle: halloweenActionButtonStyle, - copyButtonStyle: halloweenMenuButtonStyle, - editButtonStyle: halloweenMenuButtonStyle, - galleryButtonStyle: halloweenMenuButtonStyle, - actionButtonBarDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - fileAttachmentStyle: FileAttachmentStyle( - decoration: BoxDecoration( - color: Colors.black, - ), - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - filenameStyle: halloweenTextStyle, - filetypeStyle: halloweenTextStyle.copyWith( - color: Colors.green, - fontSize: 18, - ), - ), - ); - } -} diff --git a/example/lib/echo/echo.dart b/example/lib/echo/echo.dart deleted file mode 100644 index ca8e6ba..0000000 --- a/example/lib/echo/echo.dart +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; - -void main() => runApp(App()); - -class App extends StatefulWidget { - static const title = 'Example: Echo Test'; - - const App({super.key}); - - @override - State createState() => _AppState(); -} - -class _AppState extends State { - final _provider = EchoProvider(); - - @override - Widget build(BuildContext context) => MaterialApp( - title: App.title, - home: Scaffold( - appBar: AppBar(title: const Text(App.title)), - body: LlmChatView(provider: _provider), - ), - ); -} diff --git a/example/lib/gemini/gemini.dart b/example/lib/gemini/gemini.dart deleted file mode 100644 index b085c39..0000000 --- a/example/lib/gemini/gemini.dart +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Google Gemini AI'; - - const App({super.key}); - - @override - Widget build(BuildContext context) => const MaterialApp( - title: title, - home: ChatPage(), - ); -} - -class ChatPage extends StatelessWidget { - const ChatPage({super.key}); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: const Text(App.title)), - body: LlmChatView( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ), - ), - ); -} diff --git a/example/lib/history/history.dart b/example/lib/history/history.dart deleted file mode 100644 index 58d2580..0000000 --- a/example/lib/history/history.dart +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:io' as io; - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; -import 'package:path/path.dart' as path; -import 'package:path_provider/path_provider.dart' as pp; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: History'; - - const App({super.key}); - - @override - Widget build(BuildContext context) => MaterialApp( - title: title, - home: ChatPage(), - debugShowCheckedModeBanner: false, - ); -} - -class ChatPage extends StatefulWidget { - const ChatPage({super.key}); - - @override - State createState() => _ChatPageState(); -} - -class _ChatPageState extends State { - final _controller = LlmChatViewController( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ), - ); - - @override - void initState() { - super.initState(); - _controller.addListener(_saveHistory); - _loadHistory(); - } - - @override - void dispose() { - _controller.removeListener(_saveHistory); - super.dispose(); - } - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar( - title: const Text(App.title), - actions: [ - IconButton( - onPressed: _clearHistory, - icon: const Icon(Icons.history), - ), - ], - ), - body: LlmChatView(controller: _controller), - ); - - io.Directory? _historyDir; - - final _welcomeMessage = ChatMessage.llmWelcome( - '# Welcome\n' - 'Hello and welcome to the chat! This sample shows off a simple way to use ' - 'the Flutter AI Toolkit to create a chat history that is saved to disk ' - 'and restored the next time the app is launched.\n\n' - '# Note\n' - '**Since this sample depends on the availability of a file system and ' - 'the ability to save and restore files, it will not work in an environment ' - 'that does not support these capabilities, such as a web browser.**', - ); - - Future _getHistoryDir() async { - if (_historyDir == null) { - final temp = await pp.getTemporaryDirectory(); - _historyDir = io.Directory(path.join(temp.path, 'chat-history')); - await _historyDir!.create(); - } - return _historyDir!; - } - - Future _messageFile(int messageNo) async { - final fileName = path.join( - (await _getHistoryDir()).path, - 'message-${messageNo.toString().padLeft(3, '0')}.json', - ); - return io.File(fileName); - } - - Future _loadHistory() async { - // read the history from disk - final history = []; - for (var i = 0;; ++i) { - final file = await _messageFile(i); - if (!file.existsSync()) break; - - debugPrint('Loading: ${file.path}'); - final map = jsonDecode(await file.readAsString()); - history.add(LlmChatViewController.messageFrom(map)); - } - - // put in a welcome message - if (history.isEmpty) history.add(_welcomeMessage); - - // set the history on the controller - _controller.history = history; - } - - Future _saveHistory() async { - // get the latest history - final history = _controller.history.toList(); - - // write the new messages - for (var i = 0; i != history.length; ++i) { - // skip if the file already exists - final file = await _messageFile(i); - if (file.existsSync()) continue; - - // write the new message to disk - debugPrint('Saving: ${file.path}'); - final map = LlmChatViewController.mapFrom(history[i]); - final json = JsonEncoder.withIndent(' ').convert(map); - await file.writeAsString(json); - } - } - - void _clearHistory() async { - final ok = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Clear history?'), - actions: [ - ElevatedButton( - onPressed: () => Navigator.pop(context, true), - child: const Text('Clear'), - ), - OutlinedButton( - onPressed: () => Navigator.pop(context, false), - child: const Text('Cancel'), - ), - ], - ), - ); - - if (ok != true) return; - - // delete any old messages - for (var i = 0;; ++i) { - final file = await _messageFile(i); - if (!file.existsSync()) break; - debugPrint('Deleting: ${file.path}'); - await file.delete(); - } - - _controller.history = [_welcomeMessage]; - } -} diff --git a/example/lib/main.dart b/example/lib/main.dart deleted file mode 100644 index b085c39..0000000 --- a/example/lib/main.dart +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Google Gemini AI'; - - const App({super.key}); - - @override - Widget build(BuildContext context) => const MaterialApp( - title: title, - home: ChatPage(), - ); -} - -class ChatPage extends StatelessWidget { - const ChatPage({super.key}); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: const Text(App.title)), - body: LlmChatView( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ), - ), - ); -} diff --git a/example/lib/recipes/data/recipe_data.dart b/example/lib/recipes/data/recipe_data.dart deleted file mode 100644 index 2823013..0000000 --- a/example/lib/recipes/data/recipe_data.dart +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; - -import 'package:uuid/uuid.dart'; - -class Recipe { - Recipe({ - required this.id, - required this.title, - required this.description, - required this.ingredients, - required this.instructions, - this.tags = const [], - this.notes = '', - }); - - Recipe.empty(String id) - : this( - id: id, - title: '', - description: '', - ingredients: [], - instructions: [], - tags: [], - notes: '', - ); - - factory Recipe.fromJson(Map json) => Recipe( - id: json['id'] ?? const Uuid().v4(), - title: json['title'], - description: json['description'], - ingredients: List.from(json['ingredients']), - instructions: List.from(json['instructions']), - tags: json['tags'] == null ? [] : List.from(json['tags']), - notes: json['notes'] ?? '', - ); - - final String id; - final String title; - final String description; - final List ingredients; - final List instructions; - final List tags; - final String notes; - - Map toJson() => { - 'id': id, - 'title': title, - 'description': description, - 'ingredients': ingredients, - 'instructions': instructions, - 'tags': tags, - 'notes': notes, - }; - - static Future> loadFrom(String json) async { - final jsonList = jsonDecode(json) as List; - return [for (final json in jsonList) Recipe.fromJson(json)]; - } - - @override - String toString() => '''# $title -$description - -## Ingredients -${ingredients.join('\n')} - -## Instructions -${instructions.join('\n')} -'''; -} - -class RecipeEmbedding { - RecipeEmbedding({ - required this.id, - required this.embedding, - }); - - factory RecipeEmbedding.fromJson(Map json) => - RecipeEmbedding( - id: json['id'], - embedding: List.from(json['embedding']), - ); - - final String id; - final List embedding; - - static Future> loadFrom(String json) async { - final jsonList = jsonDecode(json) as List; - return [for (final json in jsonList) RecipeEmbedding.fromJson(json)]; - } - - Map toJson() => { - 'id': id, - 'embedding': embedding, - }; -} diff --git a/example/lib/recipes/data/recipe_repository.dart b/example/lib/recipes/data/recipe_repository.dart deleted file mode 100644 index ac32802..0000000 --- a/example/lib/recipes/data/recipe_repository.dart +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:io' as io; - -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart' show rootBundle; -import 'package:path/path.dart' as path; -import 'package:path_provider/path_provider.dart' as pp; - -import 'recipe_data.dart'; - -class RecipeRepository { - static const newRecipeID = '__NEW_RECIPE__'; - static const _fileName = 'recipes.json'; - - static const _assetFileName = 'assets/recipes_default.json'; - - static List? _recipes; - static final items = ValueNotifier>([]); - - static Future init() async { - assert(_recipes == null, 'call init() only once'); - _recipes = await _loadRecipes(); - items.value = _recipes!; - } - - static Iterable get recipes { - assert(_recipes != null, 'call init() first'); - return _recipes!; - } - - static Recipe getRecipe(String recipeId) { - assert(_recipes != null, 'call init() first'); - if (recipeId == newRecipeID) return Recipe.empty(newRecipeID); - return _recipes!.singleWhere((r) => r.id == recipeId); - } - - static Future addNewRecipe(Recipe newRecipe) async { - assert(_recipes != null, 'call init() first'); - _recipes!.add(newRecipe); - await _saveRecipes(); - } - - static Future updateRecipe(Recipe recipe) async { - assert(_recipes != null, 'call init() first'); - final i = _recipes!.indexWhere((r) => r.id == recipe.id); - assert(i >= 0); - _recipes![i] = recipe; - await _saveRecipes(); - } - - static Future deleteRecipe(Recipe recipe) async { - assert(_recipes != null, 'call init() first'); - final removed = _recipes!.remove(recipe); - assert(removed); - await _saveRecipes(); - } - - static Future get _recipeFile async { - final directory = await pp.getApplicationSupportDirectory(); - return io.File(path.join(directory.path, _fileName)); - } - - static Future> _loadRecipes() async { - // seed empty recipe file w/ sample recipes; note: we're not loading from a - // file on the web; all recipes are in memory for the sessions only - late final String contents; - if (!kIsWeb) { - final recipeFile = await _recipeFile; - contents = await recipeFile.exists() - ? await recipeFile.readAsString() - : await rootBundle.loadString(_assetFileName); - } else { - contents = await rootBundle.loadString(_assetFileName); - } - - final jsonList = json.decode(contents) as List; - return jsonList.map((json) => Recipe.fromJson(json)).toList(); - } - - static Future _saveRecipes() async { - // note: we're not saving to a file on the web; all recipes are in memory - // for the sessions only - if (!kIsWeb) { - final file = await _recipeFile; - final jsonString = json.encode(recipes.map((r) => r.toJson()).toList()); - await file.writeAsString(jsonString); - } - - // notify listeners that the recipes have changed - items.value = []; - items.value = _recipes!; - } -} diff --git a/example/lib/recipes/data/settings.dart b/example/lib/recipes/data/settings.dart deleted file mode 100644 index 91ea1a3..0000000 --- a/example/lib/recipes/data/settings.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:shared_preferences/shared_preferences.dart'; - -class Settings { - Settings._(); - - static SharedPreferencesWithCache? _prefs; - - static Future init() async { - assert(_prefs == null, 'call Settings.init() exactly once'); - _prefs = await SharedPreferencesWithCache.create( - cacheOptions: SharedPreferencesWithCacheOptions(), - ); - } - - static String get foodPreferences { - assert(_prefs != null, 'call Settings.init() exactly once'); - return _prefs!.getString('foodPreferences') ?? ''; - } - - static Future setFoodPreferences(String value) async { - assert(_prefs != null, 'call Settings.init() exactly once'); - await _prefs!.setString('foodPreferences', value); - } -} diff --git a/example/lib/recipes/pages/edit_recipe_page.dart b/example/lib/recipes/pages/edit_recipe_page.dart deleted file mode 100644 index 5042072..0000000 --- a/example/lib/recipes/pages/edit_recipe_page.dart +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:gap/gap.dart'; -import 'package:go_router/go_router.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; -import 'package:uuid/uuid.dart'; - -import '../../gemini_api_key.dart'; -import '../data/recipe_data.dart'; -import '../data/recipe_repository.dart'; -import '../data/settings.dart'; - -class EditRecipePage extends StatefulWidget { - const EditRecipePage({ - super.key, - required this.recipe, - }); - - final Recipe recipe; - - @override - _EditRecipePageState createState() => _EditRecipePageState(); -} - -class _EditRecipePageState extends State { - final _formKey = GlobalKey(); - late final TextEditingController _titleController; - late final TextEditingController _descriptionController; - late final TextEditingController _ingredientsController; - late final TextEditingController _instructionsController; - - final _provider = GeminiProvider( - generativeModel: GenerativeModel( - model: "gemini-1.5-flash", - apiKey: geminiApiKey, - generationConfig: GenerationConfig( - responseMimeType: 'application/json', - responseSchema: Schema( - SchemaType.object, - properties: { - 'modifications': Schema( - description: 'The modifications to the recipe you made', - SchemaType.string, - ), - 'recipe': Schema( - SchemaType.object, - properties: { - 'title': Schema(SchemaType.string), - 'description': Schema(SchemaType.string), - 'ingredients': Schema( - SchemaType.array, - items: Schema(SchemaType.string), - ), - 'instructions': Schema( - SchemaType.array, - items: Schema(SchemaType.string), - ), - }, - ), - }, - ), - ), - systemInstruction: Content.system( - ''' -You are a helpful assistant that generates recipes based on the ingredients and -instructions provided: -${Settings.foodPreferences.isEmpty ? 'I don\'t have any food preferences' : Settings.foodPreferences} - -When you generate a recipe, you should generate a JSON object. -''', - ), - ), - ); - - @override - void initState() { - super.initState(); - - _titleController = TextEditingController( - text: widget.recipe.title, - ); - _descriptionController = TextEditingController( - text: widget.recipe.description, - ); - _ingredientsController = TextEditingController( - text: widget.recipe.ingredients.join('\n'), - ); - _instructionsController = TextEditingController( - text: widget.recipe.instructions.join('\n'), - ); - } - - @override - void dispose() { - _titleController.dispose(); - _descriptionController.dispose(); - _ingredientsController.dispose(); - _instructionsController.dispose(); - super.dispose(); - } - - bool get _isNewRecipe => widget.recipe.id == RecipeRepository.newRecipeID; - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: Text('${_isNewRecipe ? "Add" : "Edit"} Recipe')), - body: Form( - key: _formKey, - child: SingleChildScrollView( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - TextFormField( - controller: _titleController, - decoration: const InputDecoration( - labelText: 'Title', - hintText: 'Enter a name for your recipe...', - ), - validator: (value) => (value == null || value.isEmpty) - ? 'Recipe title is requires' - : null, - ), - TextField( - controller: _descriptionController, - decoration: const InputDecoration( - labelText: 'Description', - hintText: 'In a few words, describe your recipe...', - ), - maxLines: null, - ), - TextField( - controller: _ingredientsController, - decoration: const InputDecoration( - labelText: 'Ingredients🍎 (one per line)', - hintText: 'e.g., 2 cups flour\n1 tsp salt\n1 cup sugar', - ), - maxLines: null, - ), - TextField( - controller: _instructionsController, - decoration: const InputDecoration( - labelText: 'Instructions🥧 (one per line)', - hintText: 'e.g., Mix ingredients\nBake for 30 minutes', - ), - maxLines: null, - ), - const Gap(16), - OverflowBar( - spacing: 16, - children: [ - ElevatedButton( - onPressed: _onMagic, - child: const Text('Magic'), - ), - OutlinedButton( - onPressed: _onDone, - child: const Text('Done'), - ), - ], - ), - ], - ), - ), - ), - ); - - void _onDone() { - if (!_formKey.currentState!.validate()) return; - - final recipe = Recipe( - id: _isNewRecipe ? const Uuid().v4() : widget.recipe.id, - title: _titleController.text, - description: _descriptionController.text, - ingredients: _ingredientsController.text.split('\n'), - instructions: _instructionsController.text.split('\n'), - ); - - if (_isNewRecipe) { - RecipeRepository.addNewRecipe(recipe); - } else { - RecipeRepository.updateRecipe(recipe); - } - - if (context.mounted) context.goNamed('home'); - } - - Future _onMagic() async { - final stream = _provider.sendMessageStream( - 'Generate a modified version of this recipe based on my food preferences: ' - '${_ingredientsController.text}\n\n${_instructionsController.text}', - ); - var response = await stream.join(); - final json = jsonDecode(response); - - try { - final modifications = json['modifications']; - final recipe = Recipe.fromJson(json['recipe']); - - if (!context.mounted) return; - final accept = await showDialog( - // ignore: use_build_context_synchronously - context: context, - builder: (context) => AlertDialog( - title: Text(recipe.title), - content: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text('Modifications:'), - const Gap(16), - Text(_wrapText(modifications)), - ], - ), - actions: [ - TextButton( - onPressed: () => context.pop(true), - child: const Text('Accept'), - ), - TextButton( - onPressed: () => context.pop(false), - child: const Text('Reject'), - ), - ], - ), - ); - - if (accept == true) { - setState(() { - _titleController.text = recipe.title; - _descriptionController.text = recipe.description; - _ingredientsController.text = recipe.ingredients.join('\n'); - _instructionsController.text = recipe.instructions.join('\n'); - }); - } - } catch (ex) { - if (context.mounted) { - showDialog( - // ignore: use_build_context_synchronously - context: context, - builder: (context) => AlertDialog( - title: const Text('Error'), - content: Text(ex.toString()), - actions: [ - TextButton( - onPressed: () => context.pop(), - child: const Text('OK'), - ), - ], - ), - ); - } - } - } - - String _wrapText(String text, {int lineLength = 80}) { - final words = text.split(RegExp(r'\s+')); - final lines = []; - - var currentLine = ''; - for (final word in words) { - if (currentLine.isEmpty) { - currentLine = word; - } else if (('$currentLine $word').length <= lineLength) { - currentLine += ' $word'; - } else { - lines.add(currentLine); - currentLine = word; - } - } - - if (currentLine.isNotEmpty) lines.add(currentLine); - return lines.join('\n'); - } -} diff --git a/example/lib/recipes/pages/home_page.dart b/example/lib/recipes/pages/home_page.dart deleted file mode 100644 index 6bec320..0000000 --- a/example/lib/recipes/pages/home_page.dart +++ /dev/null @@ -1,247 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:go_router/go_router.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; -import 'package:split_view/split_view.dart'; - -import '../../gemini_api_key.dart'; -import '../data/recipe_repository.dart'; -import '../data/settings.dart'; -import '../views/recipe_list_view.dart'; -import '../views/recipe_response_view.dart'; -import '../views/search_box.dart'; - -class HomePage extends StatefulWidget { - const HomePage({super.key}); - - @override - _HomePageState createState() => _HomePageState(); -} - -class _HomePageState extends State - with SingleTickerProviderStateMixin { - String _searchText = ''; - - final _provider = GeminiProvider( - generativeModel: GenerativeModel( - model: "gemini-1.5-flash", - apiKey: geminiApiKey, - generationConfig: GenerationConfig( - responseMimeType: 'application/json', - responseSchema: Schema( - SchemaType.object, - properties: { - 'recipes': Schema( - SchemaType.array, - items: Schema( - SchemaType.object, - properties: { - 'text': Schema( - SchemaType.string, - ), - 'recipe': Schema( - SchemaType.object, - properties: { - 'title': Schema(SchemaType.string), - 'description': Schema(SchemaType.string), - 'ingredients': Schema( - SchemaType.array, - items: Schema(SchemaType.string), - ), - 'instructions': Schema( - SchemaType.array, - items: Schema(SchemaType.string), - ), - }, - ), - }, - ), - ), - 'text': Schema(SchemaType.string), - }, - ), - ), - systemInstruction: Content.system( - ''' -You are a helpful assistant that generates recipes based on the ingredients and -instructions provided as well as my food preferences, which are as follows: -${Settings.foodPreferences.isEmpty ? 'I don\'t have any food preferences' : Settings.foodPreferences} - -You should keep things casual and friendly. Feel free to mix in rich text -commentary with the recipes you generate. You may generate multiple recipes in -a single response, but only if asked. Generate each response in JSON format. -''', - ), - ), - history: [ - ChatMessage.llmWelcome( - 'Hello and welcome to the Recipes sample app! In this app, you can ' - 'generate recipes based on the ingredients and instructions provided ' - 'as well as your food preferences. It demonstrates several real-world ' - 'use cases for the Flutter AI Toolkit. Enjoy!', - ) - ], - ); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar( - title: const Text('Example: Recipes'), - actions: [ - IconButton( - onPressed: _onAdd, - tooltip: 'Add Recipe', - icon: const Icon(Icons.add), - ), - ], - ), - drawer: Builder(builder: (context) { - return _SettingsDrawer(); - }), - body: _SideBySideOrTabBar( - tabs: const [ - Tab(text: 'Recipes'), - Tab(text: 'Chat'), - ], - children: [ - Column( - children: [ - SearchBox(onSearchChanged: _updateSearchText), - Expanded( - child: RecipeListView(searchText: _searchText), - ), - ], - ), - LlmChatView( - provider: _provider, - responseBuilder: (context, response) => RecipeResponseView( - response, - ), - ), - ], - ), - ); - - void _updateSearchText(String text) => setState(() => _searchText = text); - - void _onAdd() => context.goNamed( - 'edit', - pathParameters: {'recipe': RecipeRepository.newRecipeID}, - ); -} - -class _SettingsDrawer extends StatelessWidget { - final controller = TextEditingController( - text: Settings.foodPreferences, - ); - - @override - Widget build(BuildContext context) => Drawer( - child: ListView( - children: [ - const DrawerHeader(child: Text('Food Preferences')), - Padding( - padding: const EdgeInsets.all(8.0), - child: TextField( - controller: controller, - maxLines: 5, - decoration: const InputDecoration( - hintText: 'Enter your food preferences...', - border: OutlineInputBorder( - borderSide: BorderSide(width: 1), - ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide(width: 1), - ), - focusedBorder: OutlineInputBorder( - borderSide: BorderSide(width: 1), - ), - ), - ), - ), - Align( - alignment: Alignment.centerRight, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: OverflowBar( - spacing: 8, - children: [ - ElevatedButton( - child: const Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - OutlinedButton( - child: const Text('Save'), - onPressed: () { - Settings.setFoodPreferences(controller.text); - Navigator.of(context).pop(); - }, - ), - ], - ), - ), - ), - ], - ), - ); -} - -class _SideBySideOrTabBar extends StatefulWidget { - const _SideBySideOrTabBar({required this.tabs, required this.children}); - final List tabs; - final List children; - - @override - State<_SideBySideOrTabBar> createState() => _SideBySideOrTabBarState(); -} - -class _SideBySideOrTabBarState extends State<_SideBySideOrTabBar> - with SingleTickerProviderStateMixin { - late TabController _tabController; - - @override - void initState() { - super.initState(); - _tabController = TabController(length: widget.tabs.length, vsync: this); - } - - @override - void dispose() { - _tabController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) => MediaQuery.of(context).size.width > 600 - ? SplitView( - viewMode: SplitViewMode.Horizontal, - gripColor: Colors.transparent, - indicator: SplitIndicator( - viewMode: SplitViewMode.Horizontal, - color: Colors.grey, - ), - gripColorActive: Colors.transparent, - activeIndicator: SplitIndicator( - viewMode: SplitViewMode.Horizontal, - isActive: true, - color: Colors.black, - ), - children: widget.children, - ) - : Column( - children: [ - TabBar( - controller: _tabController, - tabs: widget.tabs, - ), - Expanded( - child: TabBarView( - controller: _tabController, - children: widget.children, - ), - ), - ], - ); -} diff --git a/example/lib/recipes/recipes.dart b/example/lib/recipes/recipes.dart deleted file mode 100644 index aee85c5..0000000 --- a/example/lib/recipes/recipes.dart +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -import 'data/recipe_repository.dart'; -import 'data/settings.dart'; -import 'pages/edit_recipe_page.dart'; -import 'pages/home_page.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - await Settings.init(); - await RecipeRepository.init(); - runApp(App()); -} - -class App extends StatelessWidget { - App({super.key}); - - final _router = GoRouter( - routes: [ - GoRoute( - name: 'home', - path: '/', - builder: (BuildContext context, _) => const HomePage(), - routes: [ - GoRoute( - name: 'edit', - path: 'edit/:recipe', - builder: (context, state) { - final recipeId = state.pathParameters['recipe']!; - final recipe = RecipeRepository.getRecipe(recipeId); - return EditRecipePage(recipe: recipe); - }, - ), - ], - ), - ], - ); - - @override - Widget build(BuildContext context) => - MaterialApp.router(routerConfig: _router); -} diff --git a/example/lib/recipes/views/recipe_content_view.dart b/example/lib/recipes/views/recipe_content_view.dart deleted file mode 100644 index 2028b38..0000000 --- a/example/lib/recipes/views/recipe_content_view.dart +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:gap/gap.dart'; - -import '../data/recipe_data.dart'; - -class RecipeContentView extends StatelessWidget { - const RecipeContentView({ - super.key, - required this.recipe, - }); - - final Recipe recipe; - static const mobileBreakpoint = 600; - - @override - Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) => - constraints.maxWidth < mobileBreakpoint - ? SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _RecipeIngredientsView(recipe), - const Gap(16), - _RecipeInstructionsView(recipe), - ], - ), - ) - : Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded(child: _RecipeIngredientsView(recipe)), - const Gap(16), - Expanded(child: _RecipeInstructionsView(recipe)), - ], - ), - ), - ); -} - -class _RecipeIngredientsView extends StatelessWidget { - const _RecipeIngredientsView(this.recipe); - final Recipe recipe; - - @override - Widget build(BuildContext context) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Ingredients:🍎', - style: Theme.of(context).textTheme.titleMedium, - ), - ...[ - for (final ingredient in recipe.ingredients) Text('• $ingredient') - ], - ], - ); -} - -class _RecipeInstructionsView extends StatelessWidget { - const _RecipeInstructionsView(this.recipe); - final Recipe recipe; - - @override - Widget build(BuildContext context) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Instructions:🥧', - style: Theme.of(context).textTheme.titleMedium, - ), - ...[ - for (final entry in recipe.instructions.asMap().entries) - Text('${entry.key + 1}. ${entry.value}') - ], - ], - ); -} diff --git a/example/lib/recipes/views/recipe_list_view.dart b/example/lib/recipes/views/recipe_list_view.dart deleted file mode 100644 index 4937ef5..0000000 --- a/example/lib/recipes/views/recipe_list_view.dart +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -import '../data/recipe_data.dart'; -import '../data/recipe_repository.dart'; -import 'recipe_view.dart'; - -class RecipeListView extends StatefulWidget { - final String searchText; - - const RecipeListView({super.key, required this.searchText}); - - @override - _RecipeListViewState createState() => _RecipeListViewState(); -} - -class _RecipeListViewState extends State { - final _expanded = {}; - - Iterable _filteredRecipes(Iterable recipes) => recipes - .where((recipe) => - recipe.title - .toLowerCase() - .contains(widget.searchText.toLowerCase()) || - recipe.description - .toLowerCase() - .contains(widget.searchText.toLowerCase()) || - recipe.tags.any((tag) => - tag.toLowerCase().contains(widget.searchText.toLowerCase()))) - .toList() - ..sort((a, b) => a.title.toLowerCase().compareTo(b.title.toLowerCase())); - - @override - Widget build(BuildContext context) => - ValueListenableBuilder?>( - valueListenable: RecipeRepository.items, - builder: (context, recipes, child) { - if (recipes == null) { - return const Center(child: CircularProgressIndicator()); - } - - final displayedRecipes = _filteredRecipes(recipes).toList(); - return ListView.builder( - itemCount: displayedRecipes.length, - itemBuilder: (context, index) { - final recipe = displayedRecipes[index]; - final recipeId = recipe.id; - return RecipeView( - key: ValueKey(recipeId), - recipe: recipe, - expanded: _expanded[recipeId] == true, - onExpansionChanged: (expanded) => - _onExpand(recipe.id, expanded), - onEdit: () => _onEdit(recipe), - onDelete: () => _onDelete(recipe), - ); - }, - ); - }, - ); - - void _onExpand(String recipeId, bool expanded) => - _expanded[recipeId] = expanded; - - void _onEdit(Recipe recipe) => context.goNamed( - 'edit', - pathParameters: {'recipe': recipe.id}, - ); - - void _onDelete(Recipe recipe) async { - final shouldDelete = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: const Text('Delete Recipe'), - content: Text( - 'Are you sure you want to delete the recipe "${recipe.title}"?', - ), - actions: [ - TextButton( - onPressed: () => Navigator.pop(context, false), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () => Navigator.pop(context, true), - child: const Text('Delete'), - ), - ], - ), - ); - - if (shouldDelete == true) await RecipeRepository.deleteRecipe(recipe); - } -} diff --git a/example/lib/recipes/views/recipe_response_view.dart b/example/lib/recipes/views/recipe_response_view.dart deleted file mode 100644 index 64266a6..0000000 --- a/example/lib/recipes/views/recipe_response_view.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; -import 'package:gap/gap.dart'; - -import '../data/recipe_data.dart'; -import '../data/recipe_repository.dart'; -import 'recipe_content_view.dart'; - -class RecipeResponseView extends StatelessWidget { - const RecipeResponseView(this.response, {super.key}); - - final String response; - - @override - Widget build(BuildContext context) { - final children = []; - - try { - final map = jsonDecode(response); - final recipesWithText = map['recipes'] as List; - final finalText = map['text'] as String?; - - for (final recipeWithText in recipesWithText) { - // extract the text before the recipe - final text = recipeWithText['text'] as String?; - if (text != null && text.isNotEmpty) { - children.add(MarkdownBody(data: text)); - } - - // extract the recipe - final json = recipeWithText['recipe'] as Map; - final recipe = Recipe.fromJson(json); - children.add(const Gap(16)); - children.add(Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(recipe.title, style: Theme.of(context).textTheme.titleLarge), - Text(recipe.description), - RecipeContentView(recipe: recipe), - ], - )); - - // add a button to add the recipe to the list - children.add(const Gap(16)); - children.add(OutlinedButton( - onPressed: () => RecipeRepository.addNewRecipe(recipe), - child: const Text('Add Recipe'), - )); - children.add(const Gap(16)); - } - - // add the remaining text - if (finalText != null && finalText.isNotEmpty) { - children.add(MarkdownBody(data: finalText)); - } - } catch (e) { - children.add(Text('Error: $e')); - } - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: children, - ); - } -} diff --git a/example/lib/recipes/views/recipe_view.dart b/example/lib/recipes/views/recipe_view.dart deleted file mode 100644 index cd05cb5..0000000 --- a/example/lib/recipes/views/recipe_view.dart +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:gap/gap.dart'; - -import '../data/recipe_data.dart'; -import 'recipe_content_view.dart'; - -class RecipeView extends StatelessWidget { - const RecipeView({ - required this.recipe, - required this.expanded, - required this.onExpansionChanged, - required this.onEdit, - required this.onDelete, - super.key, - }); - - final Recipe recipe; - final bool expanded; - final ValueChanged? onExpansionChanged; - final Function() onEdit; - final Function() onDelete; - - @override - Widget build(BuildContext context) => Card( - child: Column( - children: [ - ExpansionTile( - title: Text(recipe.title), - subtitle: Text(recipe.description), - initiallyExpanded: expanded, - onExpansionChanged: onExpansionChanged, - children: [ - RecipeContentView(recipe: recipe), - Padding( - padding: const EdgeInsets.all(8.0), - child: OverflowBar( - spacing: 8, - alignment: MainAxisAlignment.end, - children: [ - ElevatedButton( - onPressed: onDelete, - child: const Text('Delete'), - ), - OutlinedButton( - onPressed: onEdit, - child: const Text('Edit'), - ), - ], - ), - ), - const Gap(16), - ], - ), - ], - ), - ); -} diff --git a/example/lib/recipes/views/search_box.dart b/example/lib/recipes/views/search_box.dart deleted file mode 100644 index 0f660d4..0000000 --- a/example/lib/recipes/views/search_box.dart +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; - -class SearchBox extends StatefulWidget { - final Function(String) onSearchChanged; - - const SearchBox({super.key, required this.onSearchChanged}); - - @override - _SearchBoxState createState() => _SearchBoxState(); -} - -class _SearchBoxState extends State - with AutomaticKeepAliveClientMixin { - @override - bool get wantKeepAlive => true; - - final TextEditingController _searchController = TextEditingController(); - - @override - void dispose() { - _searchController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - super.build(context); - return Padding( - padding: const EdgeInsets.all(8), - child: TextField( - controller: _searchController, - decoration: const InputDecoration( - labelText: 'Search recipes', - border: OutlineInputBorder(), - suffixIcon: Icon(Icons.search), - ), - onChanged: widget.onSearchChanged, - ), - ); - } -} diff --git a/example/lib/styles/styles.dart b/example/lib/styles/styles.dart deleted file mode 100644 index 450c18e..0000000 --- a/example/lib/styles/styles.dart +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Custom Styles'; - const App({super.key}); - - @override - Widget build(BuildContext context) => MaterialApp( - title: title, - theme: ThemeData.from( - colorScheme: ColorScheme.fromSeed(seedColor: Colors.orange), - ), - debugShowCheckedModeBanner: false, - home: ChatPage(), - ); -} - -class ChatPage extends StatefulWidget { - const ChatPage({super.key}); - - @override - State createState() => _ChatPageState(); -} - -class _ChatPageState extends State - with SingleTickerProviderStateMixin { - LlmProvider? _provider; - late final _controller = AnimationController( - duration: const Duration(seconds: 1), - vsync: this, - lowerBound: 0.25, - upperBound: 1.0, - ); - - @override - void initState() { - super.initState(); - reset(); - } - - void reset() { - _provider = GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ); - _controller.value = 1.0; - _controller.reverse(); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final TextStyle halloweenTextStyle = GoogleFonts.hennyPenny( - color: Colors.white, - fontSize: 24, - ); - - final halloweenActionButtonStyle = ActionButtonStyle( - tooltipTextStyle: halloweenTextStyle, - iconColor: Colors.black, - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - ); - - final halloweenMenuButtonStyle = ActionButtonStyle( - tooltipTextStyle: halloweenTextStyle, - iconColor: Colors.orange, - iconDecoration: BoxDecoration( - color: Colors.black, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.orange), - ), - ); - - return Scaffold( - appBar: AppBar( - title: const Text(App.title), - actions: [ - IconButton( - onPressed: reset, - icon: const Icon(Icons.edit_note), - ), - ], - ), - body: AnimatedBuilder( - animation: _controller, - builder: (context, child) => Stack( - children: [ - SizedBox( - height: double.infinity, - width: double.infinity, - child: Image.asset( - 'assets/halloween-bg.png', - fit: BoxFit.cover, - opacity: _controller, - ), - ), - LlmChatView( - provider: _provider!, - style: LlmChatViewStyle( - backgroundColor: Colors.transparent, - progressIndicatorColor: Colors.purple, - chatInputStyle: ChatInputStyle( - backgroundColor: _controller.isAnimating - ? Colors.transparent - : Colors.black, - decoration: BoxDecoration( - color: Colors.yellow, - border: Border.all(color: Colors.orange), - ), - textStyle: halloweenTextStyle.copyWith(color: Colors.black), - hintText: 'good evening...', - hintStyle: halloweenTextStyle.copyWith( - color: Colors.orange.withOpacity(.5)), - ), - userMessageStyle: UserMessageStyle( - textStyle: halloweenTextStyle.copyWith(color: Colors.black), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.white, - Colors.grey.shade300, - Colors.grey.shade400, - ], - ), - borderRadius: BorderRadius.circular(20), - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.5), - blurRadius: 10, - spreadRadius: 2, - ), - ], - ), - ), - llmMessageStyle: LlmMessageStyle( - icon: Icons.sentiment_very_satisfied, - iconColor: Colors.black, - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(8), - bottomLeft: Radius.circular(8), - topRight: Radius.zero, - bottomRight: Radius.circular(8), - ), - border: Border.all(color: Colors.black), - ), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.deepOrange.shade900, - Colors.orange.shade800, - Colors.purple.shade900, - ], - ), - borderRadius: BorderRadius.only( - topLeft: Radius.zero, - bottomLeft: Radius.circular(20), - topRight: Radius.circular(20), - bottomRight: Radius.circular(20), - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.3), - blurRadius: 8, - offset: Offset(2, 2), - ), - ], - ), - markdownStyle: MarkdownStyleSheet( - p: halloweenTextStyle, - listBullet: halloweenTextStyle, - ), - ), - recordButtonStyle: halloweenActionButtonStyle, - stopButtonStyle: halloweenActionButtonStyle, - submitButtonStyle: halloweenActionButtonStyle, - addButtonStyle: halloweenActionButtonStyle, - attachFileButtonStyle: halloweenMenuButtonStyle, - cameraButtonStyle: halloweenMenuButtonStyle, - closeButtonStyle: halloweenActionButtonStyle, - closeMenuButtonStyle: halloweenActionButtonStyle, - copyButtonStyle: halloweenMenuButtonStyle, - editButtonStyle: halloweenMenuButtonStyle, - galleryButtonStyle: halloweenMenuButtonStyle, - actionButtonBarDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - fileAttachmentStyle: FileAttachmentStyle( - decoration: BoxDecoration( - color: Colors.black, - ), - iconDecoration: BoxDecoration( - color: Colors.orange, - borderRadius: BorderRadius.circular(8), - ), - filenameStyle: halloweenTextStyle, - filetypeStyle: halloweenTextStyle.copyWith( - color: Colors.green, - fontSize: 18, - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/example/lib/suggestions/suggestions.dart b/example/lib/suggestions/suggestions.dart deleted file mode 100644 index 98fa91a..0000000 --- a/example/lib/suggestions/suggestions.dart +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Suggestions'; - static final themeMode = ValueNotifier(ThemeMode.light); - - const App({super.key}); - - @override - Widget build(BuildContext context) => ValueListenableBuilder( - valueListenable: themeMode, - builder: (BuildContext context, ThemeMode mode, Widget? child) => - MaterialApp( - title: title, - theme: ThemeData.light(), - darkTheme: ThemeData.dark(), - themeMode: mode, - home: ChatPage(), - debugShowCheckedModeBanner: false, - ), - ); -} - -class ChatPage extends StatefulWidget { - const ChatPage({super.key}); - - @override - State createState() => _ChatPageState(); -} - -class _ChatPageState extends State { - final _controller = LlmChatViewController( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - ), - ); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar( - title: const Text(App.title), - actions: [ - IconButton( - onPressed: _clearHistory, - icon: const Icon(Icons.history), - ), - IconButton( - onPressed: () => App.themeMode.value = - App.themeMode.value == ThemeMode.light - ? ThemeMode.dark - : ThemeMode.light, - icon: const Icon(Icons.brightness_4_outlined), - ), - ], - ), - body: LlmChatView( - controller: _controller, - style: App.themeMode.value == ThemeMode.dark - ? LlmChatViewStyle.darkStyle() - : LlmChatViewStyle.lightStyle(), - suggestions: const [ - 'Tell me a joke.', - 'Write me a limerick.', - 'Perform a haiku.', - ], - ), - ); - - void _clearHistory() => _controller.clearHistory(); -} diff --git a/example/lib/vertex/vertex.dart b/example/lib/vertex/vertex.dart deleted file mode 100644 index 547514c..0000000 --- a/example/lib/vertex/vertex.dart +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:firebase_core/firebase_core.dart'; -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; - -// from `flutterfire config`: https://firebase.google.com/docs/flutter/setup -import 'firebase_options.dart'; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); - runApp(const App()); -} - -class App extends StatelessWidget { - static const title = 'Example: Firebase Vertex AI'; - - const App({super.key}); - @override - Widget build(BuildContext context) => const MaterialApp( - title: title, - home: ChatPage(), - ); -} - -class ChatPage extends StatelessWidget { - const ChatPage({super.key}); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: const Text(App.title)), - body: LlmChatView( - provider: VertexProvider( - generativeModel: FirebaseVertexAI.instance.generativeModel( - model: 'gemini-1.5-flash', - ), - ), - ), - ); -} diff --git a/example/lib/welcome/welcome.dart b/example/lib/welcome/welcome.dart deleted file mode 100644 index 4957592..0000000 --- a/example/lib/welcome/welcome.dart +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../gemini_api_key.dart'; - -void main() => runApp(const App()); - -class App extends StatelessWidget { - static const title = 'Example: Welcome Message'; - - const App({super.key}); - - @override - Widget build(BuildContext context) => const MaterialApp( - title: title, - home: ChatPage(), - ); -} - -class ChatPage extends StatelessWidget { - const ChatPage({super.key}); - - @override - Widget build(BuildContext context) => Scaffold( - appBar: AppBar(title: const Text(App.title)), - body: LlmChatView( - provider: GeminiProvider( - generativeModel: GenerativeModel( - model: 'gemini-1.5-flash', - apiKey: geminiApiKey, - ), - history: [ - ChatMessage.llmWelcome( - 'Hello and welcome to the Flutter AI Toolkit!', - ) - ], - ), - ), - ); -} diff --git a/example/linux/.gitignore b/example/linux/.gitignore deleted file mode 100644 index d3896c9..0000000 --- a/example/linux/.gitignore +++ /dev/null @@ -1 +0,0 @@ -flutter/ephemeral diff --git a/example/linux/CMakeLists.txt b/example/linux/CMakeLists.txt deleted file mode 100644 index 9cb0d1d..0000000 --- a/example/linux/CMakeLists.txt +++ /dev/null @@ -1,145 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.10) -project(runner LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "example") -# The unique GTK application identifier for this application. See: -# https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.example.example") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(SET CMP0063 NEW) - -# Load bundled libraries from the lib/ directory relative to the binary. -set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") - -# Root filesystem for cross-building. -if(FLUTTER_TARGET_PLATFORM_SYSROOT) - set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) - set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -endif() - -# Define build configuration options. -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") -endif() - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_14) - target_compile_options(${TARGET} PRIVATE -Wall -Werror) - target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") - target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) - -add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") - -# Define the application target. To change its name, change BINARY_NAME above, -# not the value here, or `flutter run` will no longer work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} - "main.cc" - "my_application.cc" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add dependency libraries. Add any application-specific dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) - -# Only the install-generated bundle's copy of the executable will launch -# correctly, since the resources must in the right relative locations. To avoid -# people trying to run the unbundled copy, put it in a subdirectory instead of -# the default top-level location. -set_target_properties(${BINARY_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" -) - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# By default, "installing" just makes a relocatable bundle in the build -# directory. -set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -# Start with a clean build bundle directory every time. -install(CODE " - file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") - " COMPONENT Runtime) - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) - install(FILES "${bundled_library}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endforeach(bundled_library) - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") - install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() diff --git a/example/linux/flutter/CMakeLists.txt b/example/linux/flutter/CMakeLists.txt deleted file mode 100644 index d5bd016..0000000 --- a/example/linux/flutter/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.10) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. - -# Serves the same purpose as list(TRANSFORM ... PREPEND ...), -# which isn't available in 3.10. -function(list_prepend LIST_NAME PREFIX) - set(NEW_LIST "") - foreach(element ${${LIST_NAME}}) - list(APPEND NEW_LIST "${PREFIX}${element}") - endforeach(element) - set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) -endfunction() - -# === Flutter Library === -# System-level dependencies. -find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) -pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) -pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) - -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "fl_basic_message_channel.h" - "fl_binary_codec.h" - "fl_binary_messenger.h" - "fl_dart_project.h" - "fl_engine.h" - "fl_json_message_codec.h" - "fl_json_method_codec.h" - "fl_message_codec.h" - "fl_method_call.h" - "fl_method_channel.h" - "fl_method_codec.h" - "fl_method_response.h" - "fl_plugin_registrar.h" - "fl_plugin_registry.h" - "fl_standard_message_codec.h" - "fl_standard_method_codec.h" - "fl_string_codec.h" - "fl_value.h" - "fl_view.h" - "flutter_linux.h" -) -list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") -target_link_libraries(flutter INTERFACE - PkgConfig::GTK - PkgConfig::GLIB - PkgConfig::GIO -) -add_dependencies(flutter flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CMAKE_CURRENT_BINARY_DIR}/_phony_ - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" - ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} -) diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index adc5a9f..0000000 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,23 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include -#include - -void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); - file_selector_plugin_register_with_registrar(file_selector_linux_registrar); - g_autoptr(FlPluginRegistrar) record_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "RecordLinuxPlugin"); - record_linux_plugin_register_with_registrar(record_linux_registrar); - g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); - url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); -} diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h deleted file mode 100644 index e0f0a47..0000000 --- a/example/linux/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void fl_register_plugins(FlPluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 1262bd6..0000000 --- a/example/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,26 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - file_selector_linux - record_linux - url_launcher_linux -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/example/linux/main.cc b/example/linux/main.cc deleted file mode 100644 index e7c5c54..0000000 --- a/example/linux/main.cc +++ /dev/null @@ -1,6 +0,0 @@ -#include "my_application.h" - -int main(int argc, char** argv) { - g_autoptr(MyApplication) app = my_application_new(); - return g_application_run(G_APPLICATION(app), argc, argv); -} diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc deleted file mode 100644 index c0530d4..0000000 --- a/example/linux/my_application.cc +++ /dev/null @@ -1,124 +0,0 @@ -#include "my_application.h" - -#include -#ifdef GDK_WINDOWING_X11 -#include -#endif - -#include "flutter/generated_plugin_registrant.h" - -struct _MyApplication { - GtkApplication parent_instance; - char** dart_entrypoint_arguments; -}; - -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) - -// Implements GApplication::activate. -static void my_application_activate(GApplication* application) { - MyApplication* self = MY_APPLICATION(application); - GtkWindow* window = - GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); - - // Use a header bar when running in GNOME as this is the common style used - // by applications and is the setup most users will be using (e.g. Ubuntu - // desktop). - // If running on X and not using GNOME then just use a traditional title bar - // in case the window manager does more exotic layout, e.g. tiling. - // If running on Wayland assume the header bar will work (may need changing - // if future cases occur). - gboolean use_header_bar = TRUE; -#ifdef GDK_WINDOWING_X11 - GdkScreen* screen = gtk_window_get_screen(window); - if (GDK_IS_X11_SCREEN(screen)) { - const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); - if (g_strcmp0(wm_name, "GNOME Shell") != 0) { - use_header_bar = FALSE; - } - } -#endif - if (use_header_bar) { - GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); - gtk_widget_show(GTK_WIDGET(header_bar)); - gtk_header_bar_set_title(header_bar, "example"); - gtk_header_bar_set_show_close_button(header_bar, TRUE); - gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); - } else { - gtk_window_set_title(window, "example"); - } - - gtk_window_set_default_size(window, 1280, 720); - gtk_widget_show(GTK_WIDGET(window)); - - g_autoptr(FlDartProject) project = fl_dart_project_new(); - fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); - - FlView* view = fl_view_new(project); - gtk_widget_show(GTK_WIDGET(view)); - gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); - - fl_register_plugins(FL_PLUGIN_REGISTRY(view)); - - gtk_widget_grab_focus(GTK_WIDGET(view)); -} - -// Implements GApplication::local_command_line. -static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { - MyApplication* self = MY_APPLICATION(application); - // Strip out the first argument as it is the binary name. - self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); - - g_autoptr(GError) error = nullptr; - if (!g_application_register(application, nullptr, &error)) { - g_warning("Failed to register: %s", error->message); - *exit_status = 1; - return TRUE; - } - - g_application_activate(application); - *exit_status = 0; - - return TRUE; -} - -// Implements GApplication::startup. -static void my_application_startup(GApplication* application) { - //MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application startup. - - G_APPLICATION_CLASS(my_application_parent_class)->startup(application); -} - -// Implements GApplication::shutdown. -static void my_application_shutdown(GApplication* application) { - //MyApplication* self = MY_APPLICATION(object); - - // Perform any actions required at application shutdown. - - G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); -} - -// Implements GObject::dispose. -static void my_application_dispose(GObject* object) { - MyApplication* self = MY_APPLICATION(object); - g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); - G_OBJECT_CLASS(my_application_parent_class)->dispose(object); -} - -static void my_application_class_init(MyApplicationClass* klass) { - G_APPLICATION_CLASS(klass)->activate = my_application_activate; - G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; - G_APPLICATION_CLASS(klass)->startup = my_application_startup; - G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; - G_OBJECT_CLASS(klass)->dispose = my_application_dispose; -} - -static void my_application_init(MyApplication* self) {} - -MyApplication* my_application_new() { - return MY_APPLICATION(g_object_new(my_application_get_type(), - "application-id", APPLICATION_ID, - "flags", G_APPLICATION_NON_UNIQUE, - nullptr)); -} diff --git a/example/linux/my_application.h b/example/linux/my_application.h deleted file mode 100644 index 72271d5..0000000 --- a/example/linux/my_application.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FLUTTER_MY_APPLICATION_H_ -#define FLUTTER_MY_APPLICATION_H_ - -#include - -G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) - -/** - * my_application_new: - * - * Creates a new Flutter-based application. - * - * Returns: a new #MyApplication. - */ -MyApplication* my_application_new(); - -#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/example/macos/.gitignore b/example/macos/.gitignore deleted file mode 100644 index 746adbb..0000000 --- a/example/macos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/example/macos/Flutter/Flutter-Debug.xcconfig b/example/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b..0000000 --- a/example/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/example/macos/Flutter/Flutter-Release.xcconfig b/example/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d1..0000000 --- a/example/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/example/macos/Flutter/GeneratedPluginRegistrant.swift b/example/macos/Flutter/GeneratedPluginRegistrant.swift deleted file mode 100644 index 388dbf4..0000000 --- a/example/macos/Flutter/GeneratedPluginRegistrant.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// Generated file. Do not edit. -// - -import FlutterMacOS -import Foundation - -import file_selector_macos -import firebase_app_check -import firebase_auth -import firebase_core -import path_provider_foundation -import record_darwin -import shared_preferences_foundation -import url_launcher_macos - -func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { - FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) - FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin")) - FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) - FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin")) - SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) - UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) -} diff --git a/example/macos/Podfile b/example/macos/Podfile deleted file mode 100644 index b52666a..0000000 --- a/example/macos/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - use_modular_headers! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/example/macos/Podfile.lock b/example/macos/Podfile.lock deleted file mode 100644 index d403493..0000000 --- a/example/macos/Podfile.lock +++ /dev/null @@ -1,164 +0,0 @@ -PODS: - - AppCheckCore (11.0.0): - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) - - PromisesObjC (~> 2.4) - - file_selector_macos (0.0.1): - - FlutterMacOS - - Firebase/AppCheck (11.2.0): - - Firebase/CoreOnly - - FirebaseAppCheck (~> 11.2.0) - - Firebase/Auth (11.2.0): - - Firebase/CoreOnly - - FirebaseAuth (~> 11.2.0) - - Firebase/CoreOnly (11.2.0): - - FirebaseCore (= 11.2.0) - - firebase_app_check (0.3.1-4): - - Firebase/AppCheck (~> 11.2.0) - - Firebase/CoreOnly (~> 11.2.0) - - firebase_core - - FlutterMacOS - - firebase_auth (5.3.1): - - Firebase/Auth (~> 11.2.0) - - Firebase/CoreOnly (~> 11.2.0) - - firebase_core - - FlutterMacOS - - firebase_core (3.6.0): - - Firebase/CoreOnly (~> 11.2.0) - - FlutterMacOS - - FirebaseAppCheck (11.2.0): - - AppCheckCore (~> 11.0) - - FirebaseAppCheckInterop (~> 11.0) - - FirebaseCore (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/UserDefaults (~> 8.0) - - FirebaseAppCheckInterop (11.3.0) - - FirebaseAuth (11.2.0): - - FirebaseAppCheckInterop (~> 11.0) - - FirebaseAuthInterop (~> 11.0) - - FirebaseCore (~> 11.0) - - FirebaseCoreExtension (~> 11.0) - - GoogleUtilities/AppDelegateSwizzler (~> 8.0) - - GoogleUtilities/Environment (~> 8.0) - - GTMSessionFetcher/Core (~> 3.4) - - RecaptchaInterop (~> 100.0) - - FirebaseAuthInterop (11.3.0) - - FirebaseCore (11.2.0): - - FirebaseCoreInternal (~> 11.0) - - GoogleUtilities/Environment (~> 8.0) - - GoogleUtilities/Logger (~> 8.0) - - FirebaseCoreExtension (11.3.0): - - FirebaseCore (~> 11.0) - - FirebaseCoreInternal (11.3.0): - - "GoogleUtilities/NSData+zlib (~> 8.0)" - - FlutterMacOS (1.0.0) - - GoogleUtilities/AppDelegateSwizzler (8.0.2): - - GoogleUtilities/Environment - - GoogleUtilities/Logger - - GoogleUtilities/Network - - GoogleUtilities/Privacy - - GoogleUtilities/Environment (8.0.2): - - GoogleUtilities/Privacy - - GoogleUtilities/Logger (8.0.2): - - GoogleUtilities/Environment - - GoogleUtilities/Privacy - - GoogleUtilities/Network (8.0.2): - - GoogleUtilities/Logger - - "GoogleUtilities/NSData+zlib" - - GoogleUtilities/Privacy - - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (8.0.2)": - - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (8.0.2) - - GoogleUtilities/Reachability (8.0.2): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - GoogleUtilities/UserDefaults (8.0.2): - - GoogleUtilities/Logger - - GoogleUtilities/Privacy - - GTMSessionFetcher/Core (3.5.0) - - path_provider_foundation (0.0.1): - - Flutter - - FlutterMacOS - - PromisesObjC (2.4.0) - - record_darwin (1.0.0): - - Flutter - - FlutterMacOS - - shared_preferences_foundation (0.0.1): - - Flutter - - FlutterMacOS - - url_launcher_macos (0.0.1): - - FlutterMacOS - -DEPENDENCIES: - - file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`) - - firebase_app_check (from `Flutter/ephemeral/.symlinks/plugins/firebase_app_check/macos`) - - firebase_auth (from `Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos`) - - firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`) - - FlutterMacOS (from `Flutter/ephemeral`) - - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - - record_darwin (from `Flutter/ephemeral/.symlinks/plugins/record_darwin/macos`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`) - -SPEC REPOS: - trunk: - - AppCheckCore - - Firebase - - FirebaseAppCheck - - FirebaseAppCheckInterop - - FirebaseAuth - - FirebaseAuthInterop - - FirebaseCore - - FirebaseCoreExtension - - FirebaseCoreInternal - - GoogleUtilities - - GTMSessionFetcher - - PromisesObjC - -EXTERNAL SOURCES: - file_selector_macos: - :path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos - firebase_app_check: - :path: Flutter/ephemeral/.symlinks/plugins/firebase_app_check/macos - firebase_auth: - :path: Flutter/ephemeral/.symlinks/plugins/firebase_auth/macos - firebase_core: - :path: Flutter/ephemeral/.symlinks/plugins/firebase_core/macos - FlutterMacOS: - :path: Flutter/ephemeral - path_provider_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin - record_darwin: - :path: Flutter/ephemeral/.symlinks/plugins/record_darwin/macos - shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin - url_launcher_macos: - :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos - -SPEC CHECKSUMS: - AppCheckCore: e25aaaac234b333320b0bebb8fc21ed3576819ba - file_selector_macos: cc3858c981fe6889f364731200d6232dac1d812d - Firebase: 98e6bf5278170668a7983e12971a66b2cd57fc8c - firebase_app_check: 63d5807d5c8c091eaee743919ddf1f450a42b596 - firebase_auth: 877e19571bf76f0351087020b280e3cefc667b20 - firebase_core: e88f946a4601cb1854178cb07da241bba5a6508e - FirebaseAppCheck: a6a1c1ca169d795212b9e70b5cfb880083a28e7c - FirebaseAppCheckInterop: 7789a8adfb09e905ce02a76540b94b059029ea81 - FirebaseAuth: 2a198b8cdbbbd457f08d74df7040feb0a0e7777a - FirebaseAuthInterop: c453b7ba7c49b88b2f519bb8d2e29edf7ada4a2a - FirebaseCore: a282032ae9295c795714ded2ec9c522fc237f8da - FirebaseCoreExtension: 30bb063476ef66cd46925243d64ad8b2c8ac3264 - FirebaseCoreInternal: ac26d09a70c730e497936430af4e60fb0c68ec4e - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d - GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6 - path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 - PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 - record_darwin: df0a677188e5fed18472550298e675f19ddaffbe - shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 - url_launcher_macos: c82c93949963e55b228a30115bd219499a6fe404 - -PODFILE CHECKSUM: 9ebaf0ce3d369aaa26a9ea0e159195ed94724cf3 - -COCOAPODS: 1.15.2 diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 18350a0..0000000 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,805 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXAggregateTarget section */ - 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; - buildPhases = ( - 33CC111E2044C6BF0003C045 /* ShellScript */, - ); - dependencies = ( - ); - name = "Flutter Assemble"; - productName = FLX; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 0F0076023A7154B6644DD23A /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4DF3D81367B3171410D320C /* Pods_RunnerTests.framework */; }; - 100004D3378A0047528D212B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 834FF9386F6763BEC99CCA7A /* GoogleService-Info.plist */; }; - 12112B3F91686D50B2557BC6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1170A741A11CB9748472866 /* Pods_Runner.framework */; }; - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC10EC2044A3C60003C045; - remoteInfo = Runner; - }; - 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 33CC10E52044A3C60003C045 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 33CC111A2044C6BA0003C045; - remoteInfo = FLX; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 33CC110E2044A8840003C045 /* Bundle Framework */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Bundle Framework"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 13F273E4D26A174C6CD21037 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 1BD10D066500AE9A3187C8B8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; - 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; - 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; - 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; - 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 6574190FAD397292529BC8CA /* 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 = ""; }; - 6B6BA039641A07C6EBC1E4C1 /* 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 = ""; }; - 6CD544534B3649B776D362F9 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 834FF9386F6763BEC99CCA7A /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - C1170A741A11CB9748472866 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D08632FA71FD25306A7A276C /* 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 = ""; }; - D4DF3D81367B3171410D320C /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 331C80D2294CF70F00263BE5 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0F0076023A7154B6644DD23A /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EA2044A3C60003C045 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 12112B3F91686D50B2557BC6 /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 33BA886A226E78AF003329D5 /* Configs */ = { - isa = PBXGroup; - children = ( - 33E5194F232828860026EE4D /* AppInfo.xcconfig */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, - ); - path = Configs; - sourceTree = ""; - }; - 33CC10E42044A3C60003C045 = { - isa = PBXGroup; - children = ( - 33FAB671232836740065AC1E /* Runner */, - 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, - 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - B337B3F86092E189CAF5F58B /* Pods */, - 834FF9386F6763BEC99CCA7A /* GoogleService-Info.plist */, - ); - sourceTree = ""; - }; - 33CC10EE2044A3C60003C045 /* Products */ = { - isa = PBXGroup; - children = ( - 33CC10ED2044A3C60003C045 /* example.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 33CC11242044D66E0003C045 /* Resources */ = { - isa = PBXGroup; - children = ( - 33CC10F22044A3C60003C045 /* Assets.xcassets */, - 33CC10F42044A3C60003C045 /* MainMenu.xib */, - 33CC10F72044A3C60003C045 /* Info.plist */, - ); - name = Resources; - path = ..; - sourceTree = ""; - }; - 33CEB47122A05771004F2AC0 /* Flutter */ = { - isa = PBXGroup; - children = ( - 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, - 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, - 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, - 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, - ); - path = Flutter; - sourceTree = ""; - }; - 33FAB671232836740065AC1E /* Runner */ = { - isa = PBXGroup; - children = ( - 33CC10F02044A3C60003C045 /* AppDelegate.swift */, - 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, - 33E51913231747F40026EE4D /* DebugProfile.entitlements */, - 33E51914231749380026EE4D /* Release.entitlements */, - 33CC11242044D66E0003C045 /* Resources */, - 33BA886A226E78AF003329D5 /* Configs */, - ); - path = Runner; - sourceTree = ""; - }; - B337B3F86092E189CAF5F58B /* Pods */ = { - isa = PBXGroup; - children = ( - D08632FA71FD25306A7A276C /* Pods-Runner.debug.xcconfig */, - 6B6BA039641A07C6EBC1E4C1 /* Pods-Runner.release.xcconfig */, - 6574190FAD397292529BC8CA /* Pods-Runner.profile.xcconfig */, - 6CD544534B3649B776D362F9 /* Pods-RunnerTests.debug.xcconfig */, - 13F273E4D26A174C6CD21037 /* Pods-RunnerTests.release.xcconfig */, - 1BD10D066500AE9A3187C8B8 /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - C1170A741A11CB9748472866 /* Pods_Runner.framework */, - D4DF3D81367B3171410D320C /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 53978ECA397BCDAB1914E38B /* [CP] Check Pods Manifest.lock */, - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 33CC10EC2044A3C60003C045 /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 51C2F56BFDC2C924B8C53C24 /* [CP] Check Pods Manifest.lock */, - 33CC10E92044A3C60003C045 /* Sources */, - 33CC10EA2044A3C60003C045 /* Frameworks */, - 33CC10EB2044A3C60003C045 /* Resources */, - 33CC110E2044A8840003C045 /* Bundle Framework */, - 3399D490228B24CF009A79C7 /* ShellScript */, - D5034116E3D12B789A47C197 /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 33CC11202044C79F0003C045 /* PBXTargetDependency */, - ); - name = Runner; - productName = Runner; - productReference = 33CC10ED2044A3C60003C045 /* example.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 33CC10E52044A3C60003C045 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C80D4294CF70F00263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 33CC10EC2044A3C60003C045; - }; - 33CC10EC2044A3C60003C045 = { - CreatedOnToolsVersion = 9.2; - LastSwiftMigration = 1100; - ProvisioningStyle = Automatic; - SystemCapabilities = { - com.apple.Sandbox = { - enabled = 1; - }; - }; - }; - 33CC111A2044C6BA0003C045 = { - CreatedOnToolsVersion = 9.2; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 33CC10E42044A3C60003C045; - productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, - 33CC111A2044C6BA0003C045 /* Flutter Assemble */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C80D3294CF70F00263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10EB2044A3C60003C045 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, - 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, - 100004D3378A0047528D212B /* GoogleService-Info.plist in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; - }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, - ); - inputPaths = ( - Flutter/ephemeral/tripwire, - ); - outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; - }; - 51C2F56BFDC2C924B8C53C24 /* [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; - }; - 53978ECA397BCDAB1914E38B /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - D5034116E3D12B789A47C197 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C80D1294CF70F00263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 33CC10E92044A3C60003C045 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, - 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, - 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC10EC2044A3C60003C045 /* Runner */; - targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; - }; - 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; - targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - 33CC10F52044A3C60003C045 /* Base */, - ); - name = MainMenu.xib; - path = Runner; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 6CD544534B3649B776D362F9 /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 13F273E4D26A174C6CD21037 /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1BD10D066500AE9A3187C8B8 /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.example.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example"; - }; - name = Profile; - }; - 338D0CE9231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Profile; - }; - 338D0CEA231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Profile; - }; - 338D0CEB231458BD00FA5F75 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Profile; - }; - 33CC10F92044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 33CC10FA2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CODE_SIGN_IDENTITY = "-"; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - }; - name = Release; - }; - 33CC10FC2044A3C60003C045 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 33CC10FD2044A3C60003C045 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 33CC111C2044C6BA0003C045 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Manual; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 33CC111D2044C6BA0003C045 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10F92044A3C60003C045 /* Debug */, - 33CC10FA2044A3C60003C045 /* Release */, - 338D0CE9231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC10FC2044A3C60003C045 /* Debug */, - 33CC10FD2044A3C60003C045 /* Release */, - 338D0CEA231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 33CC111C2044C6BA0003C045 /* Debug */, - 33CC111D2044C6BA0003C045 /* Release */, - 338D0CEB231458BD00FA5F75 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 33CC10E52044A3C60003C045 /* Project object */; -} diff --git a/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index 15368ec..0000000 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/example/macos/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc1..0000000 --- a/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/example/macos/Runner/AppDelegate.swift b/example/macos/Runner/AppDelegate.swift deleted file mode 100644 index b3c1761..0000000 --- a/example/macos/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Cocoa -import FlutterMacOS - -@main -class AppDelegate: FlutterAppDelegate { - override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { - return true - } - - override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { - return true - } -} diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a2ec33f..0000000 --- a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" - }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png deleted file mode 100644 index 82b6f9d..0000000 Binary files a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and /dev/null differ diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png deleted file mode 100644 index 13b35eb..0000000 Binary files a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and /dev/null differ diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png deleted file mode 100644 index 0a3f5fa..0000000 Binary files a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and /dev/null differ diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png deleted file mode 100644 index bdb5722..0000000 Binary files a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and /dev/null differ diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png deleted file mode 100644 index f083318..0000000 Binary files a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and /dev/null differ diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png deleted file mode 100644 index 326c0e7..0000000 Binary files a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and /dev/null differ diff --git a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png deleted file mode 100644 index 2f1632c..0000000 Binary files a/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and /dev/null differ diff --git a/example/macos/Runner/Base.lproj/MainMenu.xib b/example/macos/Runner/Base.lproj/MainMenu.xib deleted file mode 100644 index 80e867a..0000000 --- a/example/macos/Runner/Base.lproj/MainMenu.xib +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/example/macos/Runner/Configs/AppInfo.xcconfig b/example/macos/Runner/Configs/AppInfo.xcconfig deleted file mode 100644 index 92fb3cd..0000000 --- a/example/macos/Runner/Configs/AppInfo.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -// Application-level settings for the Runner target. -// -// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the -// future. If not, the values below would default to using the project name when this becomes a -// 'flutter create' template. - -// The application's name. By default this is also the title of the Flutter window. -PRODUCT_NAME = example - -// The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.example - -// The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. diff --git a/example/macos/Runner/Configs/Debug.xcconfig b/example/macos/Runner/Configs/Debug.xcconfig deleted file mode 100644 index 36b0fd9..0000000 --- a/example/macos/Runner/Configs/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" -#include "Warnings.xcconfig" diff --git a/example/macos/Runner/Configs/Release.xcconfig b/example/macos/Runner/Configs/Release.xcconfig deleted file mode 100644 index dff4f49..0000000 --- a/example/macos/Runner/Configs/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include "../../Flutter/Flutter-Release.xcconfig" -#include "Warnings.xcconfig" diff --git a/example/macos/Runner/Configs/Warnings.xcconfig b/example/macos/Runner/Configs/Warnings.xcconfig deleted file mode 100644 index 42bcbf4..0000000 --- a/example/macos/Runner/Configs/Warnings.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings -GCC_WARN_UNDECLARED_SELECTOR = YES -CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES -CLANG_WARN_PRAGMA_PACK = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_COMMA = YES -GCC_WARN_STRICT_SELECTOR_MATCH = YES -CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -GCC_WARN_SHADOW = YES -CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/example/macos/Runner/DebugProfile.entitlements b/example/macos/Runner/DebugProfile.entitlements deleted file mode 100644 index 5a2ec64..0000000 --- a/example/macos/Runner/DebugProfile.entitlements +++ /dev/null @@ -1,18 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.cs.allow-jit - - com.apple.security.network.server - - com.apple.security.network.client - - com.apple.security.files.user-selected.read-only - - com.apple.security.device.audio-input - - - diff --git a/example/macos/Runner/Info.plist b/example/macos/Runner/Info.plist deleted file mode 100644 index 3895a14..0000000 --- a/example/macos/Runner/Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSMinimumSystemVersion - $(MACOSX_DEPLOYMENT_TARGET) - NSHumanReadableCopyright - $(PRODUCT_COPYRIGHT) - NSMainNibFile - MainMenu - NSPrincipalClass - NSApplication - NSMicrophoneUsageDescription - $(PRODUCT_NAME) would like to access your microphone. - - diff --git a/example/macos/Runner/MainFlutterWindow.swift b/example/macos/Runner/MainFlutterWindow.swift deleted file mode 100644 index 3cc05eb..0000000 --- a/example/macos/Runner/MainFlutterWindow.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Cocoa -import FlutterMacOS - -class MainFlutterWindow: NSWindow { - override func awakeFromNib() { - let flutterViewController = FlutterViewController() - let windowFrame = self.frame - self.contentViewController = flutterViewController - self.setFrame(windowFrame, display: true) - - RegisterGeneratedPlugins(registry: flutterViewController) - - super.awakeFromNib() - } -} diff --git a/example/macos/Runner/Release.entitlements b/example/macos/Runner/Release.entitlements deleted file mode 100644 index 4811e83..0000000 --- a/example/macos/Runner/Release.entitlements +++ /dev/null @@ -1,14 +0,0 @@ - - - - - com.apple.security.app-sandbox - - com.apple.security.network.client - - com.apple.security.files.user-selected.read-only - - com.apple.security.device.audio-input - - - diff --git a/example/macos/RunnerTests/RunnerTests.swift b/example/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index 61f3bd1..0000000 --- a/example/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Cocoa -import FlutterMacOS -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/example/pubspec.lock b/example/pubspec.lock deleted file mode 100644 index bf2a035..0000000 --- a/example/pubspec.lock +++ /dev/null @@ -1,953 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _flutterfire_internals: - dependency: transitive - description: - name: _flutterfire_internals - sha256: "5534e701a2c505fed1f0799e652dd6ae23bd4d2c4cf797220e5ced5764a7c1c2" - url: "https://pub.dev" - source: hosted - version: "1.3.44" - args: - dependency: transitive - description: - name: args - sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 - url: "https://pub.dev" - source: hosted - version: "2.6.0" - async: - dependency: transitive - description: - name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.dev" - source: hosted - version: "2.11.0" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.dev" - source: hosted - version: "2.1.1" - characters: - dependency: transitive - description: - name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - clock: - dependency: transitive - description: - name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.dev" - source: hosted - version: "1.1.1" - collection: - dependency: transitive - description: - name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a - url: "https://pub.dev" - source: hosted - version: "1.18.0" - cross_file: - dependency: transitive - description: - name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" - url: "https://pub.dev" - source: hosted - version: "0.3.4+2" - crypto: - dependency: transitive - description: - name: crypto - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.dev" - source: hosted - version: "3.0.6" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" - source: hosted - version: "1.0.8" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.dev" - source: hosted - version: "1.3.1" - fetch_api: - dependency: transitive - description: - name: fetch_api - sha256: "97f46c25b480aad74f7cc2ad7ccba2c5c6f08d008e68f95c1077286ce243d0e6" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - fetch_client: - dependency: transitive - description: - name: fetch_client - sha256: "9666ee14536778474072245ed5cba07db81ae8eb5de3b7bf4a2d1e2c49696092" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - ffi: - dependency: transitive - description: - name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" - url: "https://pub.dev" - source: hosted - version: "2.1.3" - file: - dependency: transitive - description: - name: file - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" - source: hosted - version: "7.0.1" - file_selector: - dependency: transitive - description: - name: file_selector - sha256: "5019692b593455127794d5718304ff1ae15447dea286cdda9f0db2a796a1b828" - url: "https://pub.dev" - source: hosted - version: "1.0.3" - file_selector_android: - dependency: transitive - description: - name: file_selector_android - sha256: ec439df07c4999faad319ce8ad9e971795c2f1d7132ad5a793b9370a863c6128 - url: "https://pub.dev" - source: hosted - version: "0.5.1+10" - file_selector_ios: - dependency: transitive - description: - name: file_selector_ios - sha256: "94b98ad950b8d40d96fee8fa88640c2e4bd8afcdd4817993bd04e20310f45420" - url: "https://pub.dev" - source: hosted - version: "0.5.3+1" - file_selector_linux: - dependency: transitive - description: - name: file_selector_linux - sha256: "712ce7fab537ba532c8febdb1a8f167b32441e74acd68c3ccb2e36dcb52c4ab2" - url: "https://pub.dev" - source: hosted - version: "0.9.3" - file_selector_macos: - dependency: transitive - description: - name: file_selector_macos - sha256: "271ab9986df0c135d45c3cdb6bd0faa5db6f4976d3e4b437cf7d0f258d941bfc" - url: "https://pub.dev" - source: hosted - version: "0.9.4+2" - file_selector_platform_interface: - dependency: transitive - description: - name: file_selector_platform_interface - sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b - url: "https://pub.dev" - source: hosted - version: "2.6.2" - file_selector_web: - dependency: transitive - description: - name: file_selector_web - sha256: c4c0ea4224d97a60a7067eca0c8fd419e708ff830e0c83b11a48faf566cec3e7 - url: "https://pub.dev" - source: hosted - version: "0.9.4+2" - file_selector_windows: - dependency: transitive - description: - name: file_selector_windows - sha256: "8f5d2f6590d51ecd9179ba39c64f722edc15226cc93dcc8698466ad36a4a85a4" - url: "https://pub.dev" - source: hosted - version: "0.9.3+3" - firebase_app_check: - dependency: transitive - description: - name: firebase_app_check - sha256: b5b3c1df2698d6b6bd183f27fb10fbf61f9a0a564d8ccba3d87d0e0760a9ffea - url: "https://pub.dev" - source: hosted - version: "0.3.1+4" - firebase_app_check_platform_interface: - dependency: transitive - description: - name: firebase_app_check_platform_interface - sha256: "8dbb826d99c67512212331331461ee142e46645740f1c1209706ca2f72958e57" - url: "https://pub.dev" - source: hosted - version: "0.1.0+38" - firebase_app_check_web: - dependency: transitive - description: - name: firebase_app_check_web - sha256: d9cf8d7e7eb904399784ecdc21ac66119ff2a93181bd7a3f8ab43e8220ad0be8 - url: "https://pub.dev" - source: hosted - version: "0.2.0" - firebase_auth: - dependency: transitive - description: - name: firebase_auth - sha256: d453acec0d958ba0e25d41a9901b32cb77d1535766903dea7a61b2788c304596 - url: "https://pub.dev" - source: hosted - version: "5.3.1" - firebase_auth_platform_interface: - dependency: transitive - description: - name: firebase_auth_platform_interface - sha256: "78966c2ef774f5bf2a8381a307222867e9ece3509110500f7a138c115926aa65" - url: "https://pub.dev" - source: hosted - version: "7.4.7" - firebase_auth_web: - dependency: transitive - description: - name: firebase_auth_web - sha256: "77ad3b252badedd3f08dfa21a4c7fe244be96c6da3a4067f253b13ea5d32424c" - url: "https://pub.dev" - source: hosted - version: "5.13.2" - firebase_core: - dependency: "direct main" - description: - name: firebase_core - sha256: "51dfe2fbf3a984787a2e7b8592f2f05c986bfedd6fdacea3f9e0a7beb334de96" - url: "https://pub.dev" - source: hosted - version: "3.6.0" - firebase_core_platform_interface: - dependency: transitive - description: - name: firebase_core_platform_interface - sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 - url: "https://pub.dev" - source: hosted - version: "5.3.0" - firebase_core_web: - dependency: transitive - description: - name: firebase_core_web - sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 - url: "https://pub.dev" - source: hosted - version: "2.18.1" - firebase_vertexai: - dependency: "direct main" - description: - name: firebase_vertexai - sha256: c7d7a67a0d3b84e0d2e1b5c68a58df7378a2fab5b6b0481fc4b5344b1ef5454d - url: "https://pub.dev" - source: hosted - version: "1.0.1" - fixnum: - dependency: transitive - description: - name: fixnum - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_ai_toolkit: - dependency: "direct main" - description: - path: ".." - relative: true - source: path - version: "0.4.2" - flutter_context_menu: - dependency: transitive - description: - name: flutter_context_menu - sha256: "4bc1dc30ae5aa705ed99ebbeb875898c6341a6d092397a566fecd5184b392380" - url: "https://pub.dev" - source: hosted - version: "0.2.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.dev" - source: hosted - version: "5.0.0" - flutter_markdown: - dependency: "direct main" - description: - name: flutter_markdown - sha256: f0e599ba89c9946c8e051780f0ec99aba4ba15895e0380a7ab68f420046fc44e - url: "https://pub.dev" - source: hosted - version: "0.7.4+1" - flutter_plugin_android_lifecycle: - dependency: transitive - description: - name: flutter_plugin_android_lifecycle - sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398" - url: "https://pub.dev" - source: hosted - version: "2.0.23" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - flutter_web_plugins: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - freezed_annotation: - dependency: transitive - description: - name: freezed_annotation - sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 - url: "https://pub.dev" - source: hosted - version: "2.4.4" - future_builder_ex: - dependency: "direct main" - description: - name: future_builder_ex - sha256: a6f1cbccd1ef39a842febf2d09b71da2c5d5f7aa75c0c798646d14c42100e244 - url: "https://pub.dev" - source: hosted - version: "4.0.0" - gap: - dependency: "direct main" - description: - name: gap - sha256: f19387d4e32f849394758b91377f9153a1b41d79513ef7668c088c77dbc6955d - url: "https://pub.dev" - source: hosted - version: "3.0.1" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: "6f1b756f6e863259a99135ff3c95026c3cdca17d10ebef2bba2261a25ddc8bbc" - url: "https://pub.dev" - source: hosted - version: "14.3.0" - google_fonts: - dependency: "direct main" - description: - name: google_fonts - sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82 - url: "https://pub.dev" - source: hosted - version: "6.2.1" - google_generative_ai: - dependency: "direct main" - description: - name: google_generative_ai - sha256: "81dae159c89e4d9bdc46955b6f4ee5ae0a291f9e8f990d76f43944e0d6041d4f" - url: "https://pub.dev" - source: hosted - version: "0.4.6" - http: - dependency: transitive - description: - name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 - url: "https://pub.dev" - source: hosted - version: "1.2.2" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" - source: hosted - version: "4.0.2" - image_picker: - dependency: transitive - description: - name: image_picker - sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - image_picker_android: - dependency: transitive - description: - name: image_picker_android - sha256: "8faba09ba361d4b246dc0a17cb4289b3324c2b9f6db7b3d457ee69106a86bd32" - url: "https://pub.dev" - source: hosted - version: "0.8.12+17" - image_picker_for_web: - dependency: transitive - description: - name: image_picker_for_web - sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83" - url: "https://pub.dev" - source: hosted - version: "3.0.6" - image_picker_ios: - dependency: transitive - description: - name: image_picker_ios - sha256: "4f0568120c6fcc0aaa04511cb9f9f4d29fc3d0139884b1d06be88dcec7641d6b" - url: "https://pub.dev" - source: hosted - version: "0.8.12+1" - image_picker_linux: - dependency: transitive - description: - name: image_picker_linux - sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" - url: "https://pub.dev" - source: hosted - version: "0.2.1+1" - image_picker_macos: - dependency: transitive - description: - name: image_picker_macos - sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" - url: "https://pub.dev" - source: hosted - version: "0.2.1+1" - image_picker_platform_interface: - dependency: transitive - description: - name: image_picker_platform_interface - sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80" - url: "https://pub.dev" - source: hosted - version: "2.10.0" - image_picker_windows: - dependency: transitive - description: - name: image_picker_windows - sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" - url: "https://pub.dev" - source: hosted - version: "0.2.1+1" - json_annotation: - dependency: transitive - description: - name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" - source: hosted - version: "4.9.0" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" - url: "https://pub.dev" - source: hosted - version: "10.0.5" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" - url: "https://pub.dev" - source: hosted - version: "3.0.5" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" - source: hosted - version: "3.0.1" - lints: - dependency: transitive - description: - name: lints - sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" - url: "https://pub.dev" - source: hosted - version: "5.0.0" - logger: - dependency: transitive - description: - name: logger - sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - logging: - dependency: transitive - description: - name: logging - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - markdown: - dependency: transitive - description: - name: markdown - sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 - url: "https://pub.dev" - source: hosted - version: "7.2.2" - matcher: - dependency: transitive - description: - name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://pub.dev" - source: hosted - version: "0.12.16+1" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" - source: hosted - version: "0.11.1" - meta: - dependency: transitive - description: - name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 - url: "https://pub.dev" - source: hosted - version: "1.15.0" - mime: - dependency: transitive - description: - name: mime - sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" - source: hosted - version: "2.0.0" - ollama_dart: - dependency: transitive - description: - name: ollama_dart - sha256: a48d3d6c7deeb035b2d42eb7f0b294f6f939ad00389e801d833a06d88ae36162 - url: "https://pub.dev" - source: hosted - version: "0.2.2" - path: - dependency: "direct main" - description: - name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.dev" - source: hosted - version: "1.9.0" - path_provider: - dependency: "direct main" - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a - url: "https://pub.dev" - source: hosted - version: "2.2.12" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 - url: "https://pub.dev" - source: hosted - version: "2.4.0" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" - source: hosted - version: "2.3.0" - platform: - dependency: transitive - description: - name: platform - sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" - source: hosted - version: "3.1.6" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - record: - dependency: transitive - description: - name: record - sha256: "4a5cf4d083d1ee49e0878823c4397d073f8eb0a775f31215d388e2bc47a9e867" - url: "https://pub.dev" - source: hosted - version: "5.1.2" - record_android: - dependency: transitive - description: - name: record_android - sha256: d7af0b3119725a0f561817c72b5f5eca4d7a76d441deef519ae04e4824c0734c - url: "https://pub.dev" - source: hosted - version: "1.2.6" - record_darwin: - dependency: transitive - description: - name: record_darwin - sha256: fe90d302acb1f3cee1ade5df9c150ca5cee33b48d8cdf1cf433bf577d7f00134 - url: "https://pub.dev" - source: hosted - version: "1.1.2" - record_linux: - dependency: transitive - description: - name: record_linux - sha256: "74d41a9ebb1eb498a38e9a813dd524e8f0b4fdd627270bda9756f437b110a3e3" - url: "https://pub.dev" - source: hosted - version: "0.7.2" - record_platform_interface: - dependency: transitive - description: - name: record_platform_interface - sha256: "11f8b03ea8a0e279b0e306571dbe0db0202c0b8e866495c9fa1ad2281d5e4c15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - record_web: - dependency: transitive - description: - name: record_web - sha256: "656b7a865f90651fab997c2a563364f5fd60a0b527d5dadbb915d62d84fc3867" - url: "https://pub.dev" - source: hosted - version: "1.1.3" - record_windows: - dependency: transitive - description: - name: record_windows - sha256: e653555aa3fda168aded7c34e11bd82baf0c6ac84e7624553def3c77ffefd36f - url: "https://pub.dev" - source: hosted - version: "1.0.3" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" - url: "https://pub.dev" - source: hosted - version: "2.3.3" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" - url: "https://pub.dev" - source: hosted - version: "2.5.3" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e - url: "https://pub.dev" - source: hosted - version: "2.4.2" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" - source: hosted - version: "2.4.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.dev" - source: hosted - version: "1.10.0" - split_view: - dependency: "direct main" - description: - name: split_view - sha256: "7ad0e1c40703901aa1175fd465dec5e965b55324f9cc8e51526479a4a96d01a4" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - sprintf: - dependency: transitive - description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" - url: "https://pub.dev" - source: hosted - version: "7.0.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" - url: "https://pub.dev" - source: hosted - version: "1.11.1" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.dev" - source: hosted - version: "2.1.2" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" - url: "https://pub.dev" - source: hosted - version: "1.2.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.dev" - source: hosted - version: "1.2.1" - test_api: - dependency: transitive - description: - name: test_api - sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" - url: "https://pub.dev" - source: hosted - version: "0.7.2" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - universal_platform: - dependency: transitive - description: - name: universal_platform - sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - url_launcher: - dependency: "direct main" - description: - name: url_launcher - sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" - url: "https://pub.dev" - source: hosted - version: "6.3.1" - url_launcher_android: - dependency: transitive - description: - name: url_launcher_android - sha256: "0dea215895a4d254401730ca0ba8204b29109a34a99fb06ae559a2b60988d2de" - url: "https://pub.dev" - source: hosted - version: "6.3.13" - url_launcher_ios: - dependency: transitive - description: - name: url_launcher_ios - sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e - url: "https://pub.dev" - source: hosted - version: "6.3.1" - url_launcher_linux: - dependency: transitive - description: - name: url_launcher_linux - sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af - url: "https://pub.dev" - source: hosted - version: "3.2.0" - url_launcher_macos: - dependency: transitive - description: - name: url_launcher_macos - sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" - url: "https://pub.dev" - source: hosted - version: "3.2.1" - url_launcher_platform_interface: - dependency: transitive - description: - name: url_launcher_platform_interface - sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" - source: hosted - version: "2.3.2" - url_launcher_web: - dependency: transitive - description: - name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" - url: "https://pub.dev" - source: hosted - version: "2.3.3" - url_launcher_windows: - dependency: transitive - description: - name: url_launcher_windows - sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" - url: "https://pub.dev" - source: hosted - version: "3.1.3" - uuid: - dependency: "direct main" - description: - name: uuid - sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff - url: "https://pub.dev" - source: hosted - version: "4.5.1" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" - url: "https://pub.dev" - source: hosted - version: "14.2.5" - waveform_flutter: - dependency: transitive - description: - name: waveform_flutter - sha256: "3b4362b47295930cc71ef147985fddfd28673a939b7996e1718fa7433f3bc7a9" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - waveform_recorder: - dependency: transitive - description: - name: waveform_recorder - sha256: daf0104b13c29277377bf7640f8dcca296cb244e7cb27ded0713b655ef750031 - url: "https://pub.dev" - source: hosted - version: "1.3.0" - web: - dependency: transitive - description: - name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb - url: "https://pub.dev" - source: hosted - version: "1.1.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" - source: hosted - version: "1.1.0" -sdks: - dart: ">=3.5.0 <4.0.0" - flutter: ">=3.24.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml deleted file mode 100644 index 98e5d9b..0000000 --- a/example/pubspec.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: flutter_ai_toolkit_example -description: "Sample apps showing off various features of the Flutter AI Toolkit." -publish_to: 'none' -version: 0.4.2 - -environment: - sdk: ^3.4.4 - -dependencies: - flutter: - sdk: flutter - flutter_ai_toolkit: - path: .. - cupertino_icons: ^1.0.8 - google_generative_ai: ^0.4.3 - firebase_core: ^3.4.0 - firebase_vertexai: ^1.0.1 - shared_preferences: ^2.3.2 - url_launcher: ^6.3.0 - gap: ^3.0.1 - go_router: ^14.2.8 - uuid: ^4.5.1 - path: ^1.9.0 - path_provider: ^2.1.4 - flutter_markdown: ^0.7.4+1 - google_fonts: ^6.2.1 - future_builder_ex: ^4.0.0 - split_view: ^3.2.1 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^5.0.0 - -flutter: - uses-material-design: true - assets: - - assets/recipes_default.json - - assets/halloween-bg.png diff --git a/example/web/favicon.png b/example/web/favicon.png deleted file mode 100644 index 8aaa46a..0000000 Binary files a/example/web/favicon.png and /dev/null differ diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png deleted file mode 100644 index b749bfe..0000000 Binary files a/example/web/icons/Icon-192.png and /dev/null differ diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png deleted file mode 100644 index 88cfd48..0000000 Binary files a/example/web/icons/Icon-512.png and /dev/null differ diff --git a/example/web/icons/Icon-maskable-192.png b/example/web/icons/Icon-maskable-192.png deleted file mode 100644 index eb9b4d7..0000000 Binary files a/example/web/icons/Icon-maskable-192.png and /dev/null differ diff --git a/example/web/icons/Icon-maskable-512.png b/example/web/icons/Icon-maskable-512.png deleted file mode 100644 index d69c566..0000000 Binary files a/example/web/icons/Icon-maskable-512.png and /dev/null differ diff --git a/example/web/index.html b/example/web/index.html deleted file mode 100644 index 1aa025d..0000000 --- a/example/web/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - example - - - - - - diff --git a/example/web/manifest.json b/example/web/manifest.json deleted file mode 100644 index 096edf8..0000000 --- a/example/web/manifest.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "example", - "short_name": "example", - "start_url": ".", - "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", - "orientation": "portrait-primary", - "prefer_related_applications": false, - "icons": [ - { - "src": "icons/Icon-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "icons/Icon-512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "icons/Icon-maskable-192.png", - "sizes": "192x192", - "type": "image/png", - "purpose": "maskable" - }, - { - "src": "icons/Icon-maskable-512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ] -} diff --git a/example/windows/.gitignore b/example/windows/.gitignore deleted file mode 100644 index d492d0d..0000000 --- a/example/windows/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -flutter/ephemeral/ - -# Visual Studio user-specific files. -*.suo -*.user -*.userosscache -*.sln.docstates - -# Visual Studio build-related files. -x64/ -x86/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ diff --git a/example/windows/CMakeLists.txt b/example/windows/CMakeLists.txt deleted file mode 100644 index d960948..0000000 --- a/example/windows/CMakeLists.txt +++ /dev/null @@ -1,108 +0,0 @@ -# Project-level configuration. -cmake_minimum_required(VERSION 3.14) -project(example LANGUAGES CXX) - -# The name of the executable created for the application. Change this to change -# the on-disk name of your application. -set(BINARY_NAME "example") - -# Explicitly opt in to modern CMake behaviors to avoid warnings with recent -# versions of CMake. -cmake_policy(VERSION 3.14...3.25) - -# Define build configuration option. -get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -if(IS_MULTICONFIG) - set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" - CACHE STRING "" FORCE) -else() - if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - set(CMAKE_BUILD_TYPE "Debug" CACHE - STRING "Flutter build mode" FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS - "Debug" "Profile" "Release") - endif() -endif() -# Define settings for the Profile build mode. -set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") -set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") -set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") -set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") - -# Use Unicode for all projects. -add_definitions(-DUNICODE -D_UNICODE) - -# Compilation settings that should be applied to most targets. -# -# Be cautious about adding new options here, as plugins use this function by -# default. In most cases, you should add new options to specific targets instead -# of modifying this function. -function(APPLY_STANDARD_SETTINGS TARGET) - target_compile_features(${TARGET} PUBLIC cxx_std_17) - target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") - target_compile_options(${TARGET} PRIVATE /EHsc) - target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") - target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") -endfunction() - -# Flutter library and tool build rules. -set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") -add_subdirectory(${FLUTTER_MANAGED_DIR}) - -# Application build; see runner/CMakeLists.txt. -add_subdirectory("runner") - - -# Generated plugin build rules, which manage building the plugins and adding -# them to the application. -include(flutter/generated_plugins.cmake) - - -# === Installation === -# Support files are copied into place next to the executable, so that it can -# run in place. This is done instead of making a separate bundle (as on Linux) -# so that building and running from within Visual Studio will work. -set(BUILD_BUNDLE_DIR "$") -# Make the "install" step default, as it's required to run. -set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) -if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) -endif() - -set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") -set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") - -install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - COMPONENT Runtime) - -install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -if(PLUGIN_BUNDLED_LIBRARIES) - install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) -endif() - -# Copy the native assets provided by the build.dart from all packages. -set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") -install(DIRECTORY "${NATIVE_ASSETS_DIR}" - DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" - COMPONENT Runtime) - -# Fully re-copy the assets directory on each build to avoid having stale files -# from a previous install. -set(FLUTTER_ASSET_DIR_NAME "flutter_assets") -install(CODE " - file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") - " COMPONENT Runtime) -install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" - DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) - -# Install the AOT library on non-Debug builds only. -install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" - CONFIGURATIONS Profile;Release - COMPONENT Runtime) diff --git a/example/windows/flutter/CMakeLists.txt b/example/windows/flutter/CMakeLists.txt deleted file mode 100644 index 903f489..0000000 --- a/example/windows/flutter/CMakeLists.txt +++ /dev/null @@ -1,109 +0,0 @@ -# This file controls Flutter-level build steps. It should not be edited. -cmake_minimum_required(VERSION 3.14) - -set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") - -# Configuration provided via flutter tool. -include(${EPHEMERAL_DIR}/generated_config.cmake) - -# TODO: Move the rest of this into files in ephemeral. See -# https://github.com/flutter/flutter/issues/57146. -set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") - -# Set fallback configurations for older versions of the flutter tool. -if (NOT DEFINED FLUTTER_TARGET_PLATFORM) - set(FLUTTER_TARGET_PLATFORM "windows-x64") -endif() - -# === Flutter Library === -set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") - -# Published to parent scope for install step. -set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) -set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) -set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) -set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) - -list(APPEND FLUTTER_LIBRARY_HEADERS - "flutter_export.h" - "flutter_windows.h" - "flutter_messenger.h" - "flutter_plugin_registrar.h" - "flutter_texture_registrar.h" -) -list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") -add_library(flutter INTERFACE) -target_include_directories(flutter INTERFACE - "${EPHEMERAL_DIR}" -) -target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") -add_dependencies(flutter flutter_assemble) - -# === Wrapper === -list(APPEND CPP_WRAPPER_SOURCES_CORE - "core_implementations.cc" - "standard_codec.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_PLUGIN - "plugin_registrar.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") -list(APPEND CPP_WRAPPER_SOURCES_APP - "flutter_engine.cc" - "flutter_view_controller.cc" -) -list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") - -# Wrapper sources needed for a plugin. -add_library(flutter_wrapper_plugin STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} -) -apply_standard_settings(flutter_wrapper_plugin) -set_target_properties(flutter_wrapper_plugin PROPERTIES - POSITION_INDEPENDENT_CODE ON) -set_target_properties(flutter_wrapper_plugin PROPERTIES - CXX_VISIBILITY_PRESET hidden) -target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) -target_include_directories(flutter_wrapper_plugin PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_plugin flutter_assemble) - -# Wrapper sources needed for the runner. -add_library(flutter_wrapper_app STATIC - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_APP} -) -apply_standard_settings(flutter_wrapper_app) -target_link_libraries(flutter_wrapper_app PUBLIC flutter) -target_include_directories(flutter_wrapper_app PUBLIC - "${WRAPPER_ROOT}/include" -) -add_dependencies(flutter_wrapper_app flutter_assemble) - -# === Flutter tool backend === -# _phony_ is a non-existent file to force this command to run every time, -# since currently there's no way to get a full input/output list from the -# flutter tool. -set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") -set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) -add_custom_command( - OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} - ${PHONY_OUTPUT} - COMMAND ${CMAKE_COMMAND} -E env - ${FLUTTER_TOOL_ENVIRONMENT} - "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - ${FLUTTER_TARGET_PLATFORM} $ - VERBATIM -) -add_custom_target(flutter_assemble DEPENDS - "${FLUTTER_LIBRARY}" - ${FLUTTER_LIBRARY_HEADERS} - ${CPP_WRAPPER_SOURCES_CORE} - ${CPP_WRAPPER_SOURCES_PLUGIN} - ${CPP_WRAPPER_SOURCES_APP} -) diff --git a/example/windows/flutter/generated_plugin_registrant.cc b/example/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 3c9a7f7..0000000 --- a/example/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,26 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - -#include -#include -#include -#include -#include - -void RegisterPlugins(flutter::PluginRegistry* registry) { - FileSelectorWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FileSelectorWindows")); - FirebaseAuthPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); - FirebaseCorePluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); - RecordWindowsPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("RecordWindowsPluginCApi")); - UrlLauncherWindowsRegisterWithRegistrar( - registry->GetRegistrarForPlugin("UrlLauncherWindows")); -} diff --git a/example/windows/flutter/generated_plugin_registrant.h b/example/windows/flutter/generated_plugin_registrant.h deleted file mode 100644 index dc139d8..0000000 --- a/example/windows/flutter/generated_plugin_registrant.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#ifndef GENERATED_PLUGIN_REGISTRANT_ -#define GENERATED_PLUGIN_REGISTRANT_ - -#include - -// Registers Flutter plugins. -void RegisterPlugins(flutter::PluginRegistry* registry); - -#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/windows/flutter/generated_plugins.cmake b/example/windows/flutter/generated_plugins.cmake deleted file mode 100644 index f2ab310..0000000 --- a/example/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST - file_selector_windows - firebase_auth - firebase_core - record_windows - url_launcher_windows -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/example/windows/runner/CMakeLists.txt b/example/windows/runner/CMakeLists.txt deleted file mode 100644 index 394917c..0000000 --- a/example/windows/runner/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.14) -project(runner LANGUAGES CXX) - -# Define the application target. To change its name, change BINARY_NAME in the -# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer -# work. -# -# Any new source files that you add to the application should be added here. -add_executable(${BINARY_NAME} WIN32 - "flutter_window.cpp" - "main.cpp" - "utils.cpp" - "win32_window.cpp" - "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" - "Runner.rc" - "runner.exe.manifest" -) - -# Apply the standard set of build settings. This can be removed for applications -# that need different build settings. -apply_standard_settings(${BINARY_NAME}) - -# Add preprocessor definitions for the build version. -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") -target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") - -# Disable Windows macros that collide with C++ standard library functions. -target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") - -# Add dependency libraries and include directories. Add any application-specific -# dependencies here. -target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) -target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") -target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") - -# Run the Flutter tool portions of the build. This must not be removed. -add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/example/windows/runner/Runner.rc b/example/windows/runner/Runner.rc deleted file mode 100644 index 687e6bd..0000000 --- a/example/windows/runner/Runner.rc +++ /dev/null @@ -1,121 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#pragma code_page(65001) -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP_ICON ICON "resources\\app_icon.ico" - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) -#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD -#else -#define VERSION_AS_NUMBER 1,0,0,0 -#endif - -#if defined(FLUTTER_VERSION) -#define VERSION_AS_STRING FLUTTER_VERSION -#else -#define VERSION_AS_STRING "1.0.0" -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION VERSION_AS_NUMBER - PRODUCTVERSION VERSION_AS_NUMBER - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG - FILEFLAGS VS_FF_DEBUG -#else - FILEFLAGS 0x0L -#endif - FILEOS VOS__WINDOWS32 - FILETYPE VFT_APP - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904e4" - BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "example" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" - VALUE "InternalName", "example" "\0" - VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" - VALUE "OriginalFilename", "example.exe" "\0" - VALUE "ProductName", "example" "\0" - VALUE "ProductVersion", VERSION_AS_STRING "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/example/windows/runner/flutter_window.cpp b/example/windows/runner/flutter_window.cpp deleted file mode 100644 index 955ee30..0000000 --- a/example/windows/runner/flutter_window.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "flutter_window.h" - -#include - -#include "flutter/generated_plugin_registrant.h" - -FlutterWindow::FlutterWindow(const flutter::DartProject& project) - : project_(project) {} - -FlutterWindow::~FlutterWindow() {} - -bool FlutterWindow::OnCreate() { - if (!Win32Window::OnCreate()) { - return false; - } - - RECT frame = GetClientArea(); - - // The size here must match the window dimensions to avoid unnecessary surface - // creation / destruction in the startup path. - flutter_controller_ = std::make_unique( - frame.right - frame.left, frame.bottom - frame.top, project_); - // Ensure that basic setup of the controller was successful. - if (!flutter_controller_->engine() || !flutter_controller_->view()) { - return false; - } - RegisterPlugins(flutter_controller_->engine()); - SetChildContent(flutter_controller_->view()->GetNativeWindow()); - - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); - - // Flutter can complete the first frame before the "show window" callback is - // registered. The following call ensures a frame is pending to ensure the - // window is shown. It is a no-op if the first frame hasn't completed yet. - flutter_controller_->ForceRedraw(); - - return true; -} - -void FlutterWindow::OnDestroy() { - if (flutter_controller_) { - flutter_controller_ = nullptr; - } - - Win32Window::OnDestroy(); -} - -LRESULT -FlutterWindow::MessageHandler(HWND hwnd, UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opportunity to handle window messages. - if (flutter_controller_) { - std::optional result = - flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, - lparam); - if (result) { - return *result; - } - } - - switch (message) { - case WM_FONTCHANGE: - flutter_controller_->engine()->ReloadSystemFonts(); - break; - } - - return Win32Window::MessageHandler(hwnd, message, wparam, lparam); -} diff --git a/example/windows/runner/flutter_window.h b/example/windows/runner/flutter_window.h deleted file mode 100644 index 6da0652..0000000 --- a/example/windows/runner/flutter_window.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RUNNER_FLUTTER_WINDOW_H_ -#define RUNNER_FLUTTER_WINDOW_H_ - -#include -#include - -#include - -#include "win32_window.h" - -// A window that does nothing but host a Flutter view. -class FlutterWindow : public Win32Window { - public: - // Creates a new FlutterWindow hosting a Flutter view running |project|. - explicit FlutterWindow(const flutter::DartProject& project); - virtual ~FlutterWindow(); - - protected: - // Win32Window: - bool OnCreate() override; - void OnDestroy() override; - LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, - LPARAM const lparam) noexcept override; - - private: - // The project to run. - flutter::DartProject project_; - - // The Flutter instance hosted by this window. - std::unique_ptr flutter_controller_; -}; - -#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/example/windows/runner/main.cpp b/example/windows/runner/main.cpp deleted file mode 100644 index a61bf80..0000000 --- a/example/windows/runner/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -#include "flutter_window.h" -#include "utils.h" - -int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { - // Attach to console when present (e.g., 'flutter run') or create a - // new console when running with a debugger. - if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { - CreateAndAttachConsole(); - } - - // Initialize COM, so that it is available for use in the library and/or - // plugins. - ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - - flutter::DartProject project(L"data"); - - std::vector command_line_arguments = - GetCommandLineArguments(); - - project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - - FlutterWindow window(project); - Win32Window::Point origin(10, 10); - Win32Window::Size size(1280, 720); - if (!window.Create(L"example", origin, size)) { - return EXIT_FAILURE; - } - window.SetQuitOnClose(true); - - ::MSG msg; - while (::GetMessage(&msg, nullptr, 0, 0)) { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - ::CoUninitialize(); - return EXIT_SUCCESS; -} diff --git a/example/windows/runner/resource.h b/example/windows/runner/resource.h deleted file mode 100644 index 66a65d1..0000000 --- a/example/windows/runner/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Runner.rc -// -#define IDI_APP_ICON 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/example/windows/runner/resources/app_icon.ico b/example/windows/runner/resources/app_icon.ico deleted file mode 100644 index c04e20c..0000000 Binary files a/example/windows/runner/resources/app_icon.ico and /dev/null differ diff --git a/example/windows/runner/runner.exe.manifest b/example/windows/runner/runner.exe.manifest deleted file mode 100644 index 153653e..0000000 --- a/example/windows/runner/runner.exe.manifest +++ /dev/null @@ -1,14 +0,0 @@ - - - - - PerMonitorV2 - - - - - - - - - diff --git a/example/windows/runner/utils.cpp b/example/windows/runner/utils.cpp deleted file mode 100644 index 3a0b465..0000000 --- a/example/windows/runner/utils.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "utils.h" - -#include -#include -#include -#include - -#include - -void CreateAndAttachConsole() { - if (::AllocConsole()) { - FILE *unused; - if (freopen_s(&unused, "CONOUT$", "w", stdout)) { - _dup2(_fileno(stdout), 1); - } - if (freopen_s(&unused, "CONOUT$", "w", stderr)) { - _dup2(_fileno(stdout), 2); - } - std::ios::sync_with_stdio(); - FlutterDesktopResyncOutputStreams(); - } -} - -std::vector GetCommandLineArguments() { - // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. - int argc; - wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - if (argv == nullptr) { - return std::vector(); - } - - std::vector command_line_arguments; - - // Skip the first argument as it's the binary name. - for (int i = 1; i < argc; i++) { - command_line_arguments.push_back(Utf8FromUtf16(argv[i])); - } - - ::LocalFree(argv); - - return command_line_arguments; -} - -std::string Utf8FromUtf16(const wchar_t* utf16_string) { - if (utf16_string == nullptr) { - return std::string(); - } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character - int input_length = (int)wcslen(utf16_string); - std::string utf8_string; - if (target_length == 0 || target_length > utf8_string.max_size()) { - return utf8_string; - } - utf8_string.resize(target_length); - int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); - if (converted_length == 0) { - return std::string(); - } - return utf8_string; -} diff --git a/example/windows/runner/utils.h b/example/windows/runner/utils.h deleted file mode 100644 index 3879d54..0000000 --- a/example/windows/runner/utils.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef RUNNER_UTILS_H_ -#define RUNNER_UTILS_H_ - -#include -#include - -// Creates a console for the process, and redirects stdout and stderr to -// it for both the runner and the Flutter library. -void CreateAndAttachConsole(); - -// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string -// encoded in UTF-8. Returns an empty std::string on failure. -std::string Utf8FromUtf16(const wchar_t* utf16_string); - -// Gets the command line arguments passed in as a std::vector, -// encoded in UTF-8. Returns an empty std::vector on failure. -std::vector GetCommandLineArguments(); - -#endif // RUNNER_UTILS_H_ diff --git a/example/windows/runner/win32_window.cpp b/example/windows/runner/win32_window.cpp deleted file mode 100644 index 60608d0..0000000 --- a/example/windows/runner/win32_window.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "win32_window.h" - -#include -#include - -#include "resource.h" - -namespace { - -/// Window attribute that enables dark mode window decorations. -/// -/// Redefined in case the developer's machine has a Windows SDK older than -/// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute -#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE -#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 -#endif - -constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; - -/// Registry key for app theme preference. -/// -/// A value of 0 indicates apps should use dark mode. A non-zero or missing -/// value indicates apps should use light mode. -constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; - -// The number of Win32Window objects that currently exist. -static int g_active_window_count = 0; - -using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); - -// Scale helper to convert logical scaler values to physical using passed in -// scale factor -int Scale(int source, double scale_factor) { - return static_cast(source * scale_factor); -} - -// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. -// This API is only needed for PerMonitor V1 awareness mode. -void EnableFullDpiSupportIfAvailable(HWND hwnd) { - HMODULE user32_module = LoadLibraryA("User32.dll"); - if (!user32_module) { - return; - } - auto enable_non_client_dpi_scaling = - reinterpret_cast( - GetProcAddress(user32_module, "EnableNonClientDpiScaling")); - if (enable_non_client_dpi_scaling != nullptr) { - enable_non_client_dpi_scaling(hwnd); - } - FreeLibrary(user32_module); -} - -} // namespace - -// Manages the Win32Window's window class registration. -class WindowClassRegistrar { - public: - ~WindowClassRegistrar() = default; - - // Returns the singleton registrar instance. - static WindowClassRegistrar* GetInstance() { - if (!instance_) { - instance_ = new WindowClassRegistrar(); - } - return instance_; - } - - // Returns the name of the window class, registering the class if it hasn't - // previously been registered. - const wchar_t* GetWindowClass(); - - // Unregisters the window class. Should only be called if there are no - // instances of the window. - void UnregisterWindowClass(); - - private: - WindowClassRegistrar() = default; - - static WindowClassRegistrar* instance_; - - bool class_registered_ = false; -}; - -WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; - -const wchar_t* WindowClassRegistrar::GetWindowClass() { - if (!class_registered_) { - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = kWindowClassName; - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = - LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = Win32Window::WndProc; - RegisterClass(&window_class); - class_registered_ = true; - } - return kWindowClassName; -} - -void WindowClassRegistrar::UnregisterWindowClass() { - UnregisterClass(kWindowClassName, nullptr); - class_registered_ = false; -} - -Win32Window::Win32Window() { - ++g_active_window_count; -} - -Win32Window::~Win32Window() { - --g_active_window_count; - Destroy(); -} - -bool Win32Window::Create(const std::wstring& title, - const Point& origin, - const Size& size) { - Destroy(); - - const wchar_t* window_class = - WindowClassRegistrar::GetInstance()->GetWindowClass(); - - const POINT target_point = {static_cast(origin.x), - static_cast(origin.y)}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); - UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); - double scale_factor = dpi / 96.0; - - HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW, - Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), - Scale(size.width, scale_factor), Scale(size.height, scale_factor), - nullptr, nullptr, GetModuleHandle(nullptr), this); - - if (!window) { - return false; - } - - UpdateTheme(window); - - return OnCreate(); -} - -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} - -// static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto window_struct = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(window_struct->lpCreateParams)); - - auto that = static_cast(window_struct->lpCreateParams); - EnableFullDpiSupportIfAvailable(window); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - switch (message) { - case WM_DESTROY: - window_handle_ = nullptr; - Destroy(); - if (quit_on_close_) { - PostQuitMessage(0); - } - return 0; - - case WM_DPICHANGED: { - auto newRectSize = reinterpret_cast(lparam); - LONG newWidth = newRectSize->right - newRectSize->left; - LONG newHeight = newRectSize->bottom - newRectSize->top; - - SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, - newHeight, SWP_NOZORDER | SWP_NOACTIVATE); - - return 0; - } - case WM_SIZE: { - RECT rect = GetClientArea(); - if (child_content_ != nullptr) { - // Size and position the child window. - MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, - rect.bottom - rect.top, TRUE); - } - return 0; - } - - case WM_ACTIVATE: - if (child_content_ != nullptr) { - SetFocus(child_content_); - } - return 0; - - case WM_DWMCOLORIZATIONCOLORCHANGED: - UpdateTheme(hwnd); - return 0; - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -void Win32Window::Destroy() { - OnDestroy(); - - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - if (g_active_window_count == 0) { - WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); - } -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -void Win32Window::SetChildContent(HWND content) { - child_content_ = content; - SetParent(content, window_handle_); - RECT frame = GetClientArea(); - - MoveWindow(content, frame.left, frame.top, frame.right - frame.left, - frame.bottom - frame.top, true); - - SetFocus(child_content_); -} - -RECT Win32Window::GetClientArea() { - RECT frame; - GetClientRect(window_handle_, &frame); - return frame; -} - -HWND Win32Window::GetHandle() { - return window_handle_; -} - -void Win32Window::SetQuitOnClose(bool quit_on_close) { - quit_on_close_ = quit_on_close; -} - -bool Win32Window::OnCreate() { - // No-op; provided for subclasses. - return true; -} - -void Win32Window::OnDestroy() { - // No-op; provided for subclasses. -} - -void Win32Window::UpdateTheme(HWND const window) { - DWORD light_mode; - DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); - - if (result == ERROR_SUCCESS) { - BOOL enable_dark_mode = light_mode == 0; - DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, - &enable_dark_mode, sizeof(enable_dark_mode)); - } -} diff --git a/example/windows/runner/win32_window.h b/example/windows/runner/win32_window.h deleted file mode 100644 index e901dde..0000000 --- a/example/windows/runner/win32_window.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef RUNNER_WIN32_WINDOW_H_ -#define RUNNER_WIN32_WINDOW_H_ - -#include - -#include -#include -#include - -// A class abstraction for a high DPI-aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling -class Win32Window { - public: - struct Point { - unsigned int x; - unsigned int y; - Point(unsigned int x, unsigned int y) : x(x), y(y) {} - }; - - struct Size { - unsigned int width; - unsigned int height; - Size(unsigned int width, unsigned int height) - : width(width), height(height) {} - }; - - Win32Window(); - virtual ~Win32Window(); - - // Creates a win32 window with |title| that is positioned and sized using - // |origin| and |size|. New windows are created on the default monitor. Window - // sizes are specified to the OS in physical pixels, hence to ensure a - // consistent size this function will scale the inputted width and height as - // as appropriate for the default monitor. The window is invisible until - // |Show| is called. Returns true if the window was created successfully. - bool Create(const std::wstring& title, const Point& origin, const Size& size); - - // Show the current window. Returns true if the window was successfully shown. - bool Show(); - - // Release OS resources associated with window. - void Destroy(); - - // Inserts |content| into the window tree. - void SetChildContent(HWND content); - - // Returns the backing Window handle to enable clients to set icon and other - // window properties. Returns nullptr if the window has been destroyed. - HWND GetHandle(); - - // If true, closing this window will quit the application. - void SetQuitOnClose(bool quit_on_close); - - // Return a RECT representing the bounds of the current client area. - RECT GetClientArea(); - - protected: - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Called when CreateAndShow is called, allowing subclass window-related - // setup. Subclasses should return false if setup fails. - virtual bool OnCreate(); - - // Called when Destroy is called. - virtual void OnDestroy(); - - private: - friend class WindowClassRegistrar; - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - - // Update the window frame's theme to match the system theme. - static void UpdateTheme(HWND const window); - - bool quit_on_close_ = false; - - // window handle for top level window. - HWND window_handle_ = nullptr; - - // window handle for hosted content. - HWND child_content_ = nullptr; -}; - -#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/font_svg/README.md b/font_svg/README.md deleted file mode 100644 index b903f5c..0000000 --- a/font_svg/README.md +++ /dev/null @@ -1,25 +0,0 @@ -`lib/fonts/FatIcons.ttf` is generated at [fluttericon.com](https://www.fluttericon.com/) from the following files: -- `font_svg/spark-icon.svg` -- `font_svg/submit-icon.svg` - -SVG sources: -- `font_svg/submit-icon.svg` was generated by flipping the svg in `reply_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg` horizontally - -- `font_svg/reply_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg` was generated by exporting the SVG from [the SVG of Google Symbols "reply" character](https://fonts.google.com/icons?icon.query=reply) - -- `font_svg/spark-icon.svg` was purchased at [the Noun Project](https://thenounproject.com/icon/spark-6645136/) - -Material icons: -The following icons will pulled in from Material and packaged into the FatIcons.ttf so that Material itself wasn't required for a Cupertino app: -- Icons.add -- Icons.attach_file -- Icons.stop -- Icons.mic -- Icons.close -- Icons.camera_alt -- Icons.image -- Icons.edit -- Icons.copy - -more info: -https://stackoverflow.com/a/75657218 diff --git a/font_svg/reply_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg b/font_svg/reply_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg deleted file mode 100644 index 9e29a55..0000000 --- a/font_svg/reply_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/font_svg/spark-icon.svg b/font_svg/spark-icon.svg deleted file mode 100644 index 1c6f763..0000000 --- a/font_svg/spark-icon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/font_svg/submit-icon.svg b/font_svg/submit-icon.svg deleted file mode 100644 index 4a95b6a..0000000 --- a/font_svg/submit-icon.svg +++ /dev/null @@ -1,9 +0,0 @@ - -Created with Fabric.js 3.5.0 - - - - - - - \ No newline at end of file diff --git a/lib/flutter_ai_toolkit.dart b/lib/flutter_ai_toolkit.dart deleted file mode 100644 index 54d4f5e..0000000 --- a/lib/flutter_ai_toolkit.dart +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/// A library for integrating AI-powered chat functionality into Flutter -/// applications. -/// -/// This library provides a set of tools and widgets to easily incorporate AI -/// language models into your Flutter app, enabling interactive chat experiences -/// with various AI providers. -/// -/// Key components: -/// - LLM providers: Interfaces and implementations for different AI services. -/// - Chat UI: Ready-to-use widgets for displaying chat interfaces. -library; - -export 'src/llm_chat_view_controller.dart'; -export 'src/providers/interface/chat_message.dart'; -export 'src/providers/providers.dart'; -export 'src/styles/styles.dart'; -export 'src/views/llm_chat_view/llm_chat_view.dart'; diff --git a/lib/fonts/FatIcons.ttf b/lib/fonts/FatIcons.ttf deleted file mode 100644 index 7411934..0000000 Binary files a/lib/fonts/FatIcons.ttf and /dev/null differ diff --git a/lib/src/chat_view_model/chat_view_model.dart b/lib/src/chat_view_model/chat_view_model.dart deleted file mode 100644 index 6b95e4c..0000000 --- a/lib/src/chat_view_model/chat_view_model.dart +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/foundation.dart'; - -import '../llm_chat_view_controller.dart'; -import '../styles/llm_chat_view_style.dart'; -import '../views/response_builder.dart'; - -/// A view model class that manages the state and configuration of a chat -/// interface. -/// -/// This class holds the controller and styling information needed to render and -/// manage a chat view. It works in conjunction with [LlmChatViewController] to -/// handle the business logic and state management of the chat interface. -@immutable -class ChatViewModel { - /// Creates a [ChatViewModel] with the required controller and style. - /// - /// The [controller] parameter must not be null and manages the chat state and - /// interactions. - /// - /// The [style] parameter allows customizing the visual appearance of the chat - /// interface. If null, default styling will be used. - const ChatViewModel({ - required this.controller, - required this.style, - this.responseBuilder, - }); - - /// The controller that manages the chat state and interactions. - /// - /// This controller handles operations like sending messages, managing the - /// chat history, and processing responses from the LLM provider. - final LlmChatViewController controller; - - /// The style configuration for the chat view. - /// - /// Defines visual properties like colors, decorations, and layout parameters - /// for the chat interface. If null, default styling will be applied. - final LlmChatViewStyle? style; - - /// The builder for the chat response. - final ResponseBuilder? responseBuilder; - - @override - bool operator ==(Object other) => - identical(this, other) || - (other is ChatViewModel && - other.controller == controller && - other.style == style); - - @override - int get hashCode => Object.hash( - controller, - style, - ); -} diff --git a/lib/src/chat_view_model/chat_view_model_client.dart b/lib/src/chat_view_model/chat_view_model_client.dart deleted file mode 100644 index 0d28c9b..0000000 --- a/lib/src/chat_view_model/chat_view_model_client.dart +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import 'chat_view_model.dart'; -import 'chat_view_model_provider.dart'; - -/// A widget that provides access to a [ChatViewModel] and builds its child -/// using a builder function. -/// -/// This widget is typically used in conjunction with [ChatViewModelProvider] -/// to access the [ChatViewModel] from the widget tree. -@immutable -class ChatViewModelClient extends StatelessWidget { - /// Creates a [ChatViewModelClient]. - /// - /// The [builder] argument must not be null. - const ChatViewModelClient({ - required this.builder, - this.child, - super.key, - }); - - /// A function that builds a widget tree based on the current [ChatViewModel]. - /// - /// This function is called with the current [BuildContext], the - /// [ChatViewModel] obtained from the nearest [ChatViewModelProvider] - /// ancestor, and the optional [child]. - final Widget Function( - BuildContext context, ChatViewModel viewModel, Widget? child) builder; - - /// An optional child widget that can be passed to the [builder] function. - /// - /// This is useful when part of the widget subtree does not depend on the - /// [ChatViewModel] and can be shared across multiple builds. - final Widget? child; - - @override - Widget build(BuildContext context) => - builder(context, ChatViewModelProvider.of(context), child); -} diff --git a/lib/src/chat_view_model/chat_view_model_provider.dart b/lib/src/chat_view_model/chat_view_model_provider.dart deleted file mode 100644 index 1b54862..0000000 --- a/lib/src/chat_view_model/chat_view_model_provider.dart +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import 'chat_view_model.dart'; - -/// A provider widget that makes a [ChatViewModel] available to its descendants. -/// -/// This widget uses the [InheritedWidget] mechanism to efficiently propagate -/// the [ChatViewModel] down the widget tree. -@immutable -class ChatViewModelProvider extends InheritedWidget { - /// Creates a [ChatViewModelProvider]. - /// - /// The [child] and [viewModel] arguments must not be null. - const ChatViewModelProvider({ - required super.child, - required this.viewModel, - super.key, - }); - - /// The [ChatViewModel] to be made available to descendants. - final ChatViewModel viewModel; - - /// Retrieves the [ChatViewModel] from the closest [ChatViewModelProvider] - /// ancestor in the widget tree. - /// - /// This method will assert if no [ChatViewModelProvider] is found in the - /// widget's ancestors. - /// - /// [context] must not be null. - static ChatViewModel of(BuildContext context) { - final viewModel = maybeOf(context); - assert(viewModel != null, 'No ChatViewModelProvider found in context'); - return viewModel!; - } - - /// Retrieves the [ChatViewModel] from the closest [ChatViewModelProvider] - /// ancestor in the widget tree, if one exists. - /// - /// Returns null if no [ChatViewModelProvider] is found. - /// - /// [context] must not be null. - static ChatViewModel? maybeOf(BuildContext context) => context - .dependOnInheritedWidgetOfExactType() - ?.viewModel; - - @override - bool updateShouldNotify(ChatViewModelProvider oldWidget) => - viewModel != oldWidget.viewModel; -} diff --git a/lib/src/dialogs/adaptive_dialog.dart b/lib/src/dialogs/adaptive_dialog.dart deleted file mode 100644 index 88d5101..0000000 --- a/lib/src/dialogs/adaptive_dialog.dart +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart' as cup; -import 'package:flutter/material.dart' as mat; -import 'package:flutter/widgets.dart'; - -import '../utility.dart'; - -/// A utility class for showing adaptive dialogs that match the current platform -/// style. -@immutable -class AdaptiveAlertDialog { - /// Shows an adaptive dialog with the given [content] widget as content. - /// - /// This method automatically chooses between a Cupertino-style dialog for iOS - /// and a Material-style dialog for other platforms. - /// - /// Parameters: - /// * [context]: The build context in which to show the dialog. - /// * [child]: The widget to display as the dialog's content. - /// - /// Returns a [Future] that completes with the result value when the dialog is - /// dismissed. - static Future show({ - required BuildContext context, - required Widget content, - bool barrierDismissible = false, - List actions = const [], - }) => - isCupertinoApp(context) - ? cup.showCupertinoDialog( - context: context, - barrierDismissible: barrierDismissible, - builder: (context) => cup.CupertinoAlertDialog( - content: content, - actions: actions, - ), - ) - : mat.showDialog( - context: context, - barrierDismissible: barrierDismissible, - builder: (context) => mat.AlertDialog( - // insetPadding: const EdgeInsets.all(48), - content: content, - actions: actions, - ), - ); -} diff --git a/lib/src/dialogs/adaptive_dialog_action.dart b/lib/src/dialogs/adaptive_dialog_action.dart deleted file mode 100644 index e0c7390..0000000 --- a/lib/src/dialogs/adaptive_dialog_action.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import '../utility.dart'; - -/// A button that adapts its appearance based on the design language, either -/// Material or Cupertino. -/// -/// The [AdaptiveDialogAction] widget is designed to provide a consistent user -/// experience across different platforms while adhering to platform-specific -/// design guidelines. -@immutable -class AdaptiveDialogAction extends StatelessWidget { - /// Creates an adaptive dialog action. - /// - /// The [onPressed] and [child] arguments must not be null. - const AdaptiveDialogAction({ - required this.onPressed, - required this.child, - super.key, - }); - - /// The callback that is called when the button is tapped or pressed. - final VoidCallback onPressed; - - /// The widget below this widget in the tree. - /// - /// Typically a [Text] widget. - final Widget child; - - @override - Widget build(BuildContext context) => isCupertinoApp(context) - ? CupertinoDialogAction( - onPressed: onPressed, - child: child, - ) - : TextButton(onPressed: onPressed, child: child); -} diff --git a/lib/src/dialogs/adaptive_snack_bar/adaptive_snack_bar.dart b/lib/src/dialogs/adaptive_snack_bar/adaptive_snack_bar.dart deleted file mode 100644 index e596acc..0000000 --- a/lib/src/dialogs/adaptive_snack_bar/adaptive_snack_bar.dart +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; - -import '../../utility.dart'; -import 'cupertino_snack_bar.dart'; - -/// A utility class for showing adaptive snack bars in Flutter applications. -/// -/// This class provides a static method to display snack bars that adapt to the -/// current application environment, showing either a Material Design snack bar -/// or a Cupertino-style snack bar based on the app's context. -@immutable -class AdaptiveSnackBar { - /// Shows an adaptive snack bar with the given message. - /// - /// This method determines whether the app is using Cupertino or Material - /// design and displays an appropriate snack bar. - /// - /// Parameters: - /// * [context]: The build context in which to show the snack bar. - /// * [message]: The text message to display in the snack bar. - static void show(BuildContext context, String message) { - if (isCupertinoApp(context)) { - _showCupertinoSnackBar(context: context, message: message); - } else { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text(message))); - } - } - - static void _showCupertinoSnackBar({ - required BuildContext context, - required String message, - int durationMillis = 4000, - }) { - const animationDurationMillis = 200; - final overlayEntry = OverlayEntry( - builder: (context) => CupertinoSnackBar( - message: message, - animationDurationMillis: animationDurationMillis, - waitDurationMillis: durationMillis, - ), - ); - Future.delayed( - Duration(milliseconds: durationMillis + 2 * animationDurationMillis), - overlayEntry.remove, - ); - Overlay.of(context).insert(overlayEntry); - } -} diff --git a/lib/src/dialogs/adaptive_snack_bar/cupertino_snack_bar.dart b/lib/src/dialogs/adaptive_snack_bar/cupertino_snack_bar.dart deleted file mode 100644 index fe102a8..0000000 --- a/lib/src/dialogs/adaptive_snack_bar/cupertino_snack_bar.dart +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart'; - -/// A widget that displays a Cupertino-style snack bar. -/// -/// This widget creates an animated snack bar that slides up from the bottom of -/// the screen, displays a message for a specified duration, and then slides -/// back down. -/// -/// The snack bar uses Cupertino styling to match iOS design guidelines. -@immutable -class CupertinoSnackBar extends StatefulWidget { - /// Creates a [CupertinoSnackBar]. - /// - /// All parameters are required: - /// * [message] is the text to display in the snack bar. - /// * [animationDurationMillis] defines how long the slide animations take. - /// * [waitDurationMillis] sets how long the snack bar stays visible before - /// dismissing. - const CupertinoSnackBar({ - required this.message, - required this.animationDurationMillis, - required this.waitDurationMillis, - super.key, - }); - - /// The message to display in the snack bar. - final String message; - - /// The duration of the slide-in and slide-out animations in milliseconds. - final int animationDurationMillis; - - /// The duration for which the snack bar remains visible in milliseconds. - final int waitDurationMillis; - - @override - State createState() => _CupertinoSnackBarState(); -} - -class _CupertinoSnackBarState extends State { - bool show = false; - - @override - void initState() { - super.initState(); - Future.microtask(() => setState(() => show = true)); - Future.delayed( - Duration( - milliseconds: widget.waitDurationMillis, - ), - () { - if (mounted) { - setState(() => show = false); - } - }, - ); - } - - @override - Widget build(BuildContext context) => AnimatedPositioned( - bottom: show ? 8.0 : -50.0, - left: 8, - right: 8, - curve: show ? Curves.linearToEaseOut : Curves.easeInToLinear, - duration: Duration(milliseconds: widget.animationDurationMillis), - child: CupertinoPopupSurface( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 8, - ), - child: Text( - widget.message, - style: const TextStyle( - fontSize: 14, - color: CupertinoColors.secondaryLabel, - ), - textAlign: TextAlign.center, - ), - ), - ), - ); -} diff --git a/lib/src/dialogs/image_preview_dialog.dart b/lib/src/dialogs/image_preview_dialog.dart deleted file mode 100644 index 541ebf2..0000000 --- a/lib/src/dialogs/image_preview_dialog.dart +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import '../providers/interface/attachments.dart'; - -/// Displays a dialog to preview the image when the user taps on an attached -/// image. -@immutable -class ImagePreviewDialog extends StatelessWidget { - /// Shows the [ImagePreviewDialog] for the given [attachment]. - const ImagePreviewDialog(this.attachment, {super.key}); - - /// The image file attachment to be previewed in the dialog. - final ImageFileAttachment attachment; - - @override - Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.all(8), - child: Center( - child: Image.memory(attachment.bytes, fit: BoxFit.contain), - ), - ); -} diff --git a/lib/src/llm_chat_view_controller.dart b/lib/src/llm_chat_view_controller.dart deleted file mode 100644 index 884ddf3..0000000 --- a/lib/src/llm_chat_view_controller.dart +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// using dynamic calls to translate to/from JSON -// ignore_for_file: avoid_dynamic_calls - -import 'dart:convert'; - -import 'package:flutter/widgets.dart'; - -import 'providers/interface/attachments.dart'; -import 'providers/interface/chat_message.dart'; -import 'providers/interface/llm_provider.dart'; -import 'providers/interface/message_origin.dart'; - -/// A controller class for managing LLM chat interactions and view updates. -/// -/// This class extends [ChangeNotifier] to provide a way to notify listeners -/// of changes in the chat state. -/// A controller class for managing LLM chat interactions and view updates. -/// -/// This class extends [ChangeNotifier] to provide a way to notify listeners -/// of changes in the chat state. -class LlmChatViewController extends ChangeNotifier { - /// Creates a new [LlmChatViewController]. - /// - /// [provider] is the required [LlmProvider] for handling LLM interactions. - /// [messageSender] is an optional [LlmStreamGenerator] for sending messages. - LlmChatViewController({ - required LlmProvider provider, - LlmStreamGenerator? messageSender, - }) : _provider = provider, - _messageSender = messageSender; - - final LlmProvider _provider; - final LlmStreamGenerator? _messageSender; - - /// Generates a stream of text from the LLM based on a prompt and attachments. - /// - /// [prompt] is the text prompt to send to the LLM. [attachments] is a - /// required list of file attachments to include with the prompt. - /// - /// Returns a [Stream] of [String] containing the LLM's generated response. - /// The response is streamed back as it is generated. - Stream generateStream( - String prompt, { - required List attachments, - }) => - _provider.generateStream(prompt, attachments: attachments); - - /// Sends a message to the LLM and returns a stream of the response. - /// - /// [prompt] is the message to send to the LLM. [attachments] is an optional - /// list of attachments to include with the message. - /// - /// Notifies listeners when a new message is added to the history and when the - /// full LLM response is available. - Stream sendMessageStream( - String prompt, { - Iterable attachments = const [], - }) async* { - if (_messageSender != null) { - yield* _messageSender(prompt, attachments: attachments); - } else { - yield* _provider.sendMessageStream(prompt, attachments: attachments); - notifyListeners(); - } - } - - /// Gets the current chat history. - Iterable get history => _provider.history; - - /// Sets the chat history and notifies listeners of the change. - set history(Iterable history) { - _provider.history = history; - notifyListeners(); - } - - /// Clears the chat history and notifies listeners of the change. - void clearHistory() => history = const []; - - /// Converts a [ChatMessage] to a map representation. - /// - /// The map contains the following keys: - /// - 'origin': The origin of the message (user or model). - /// - 'text': The text content of the message. - /// - 'attachments': A list of attachments, each represented as a map with: - /// - 'type': The type of the attachment ('file' or 'link'). - /// - 'name': The name of the attachment. - /// - 'mimeType': The MIME type of the attachment. - /// - 'data': The data of the attachment, either as a base64 encoded string - /// (for files) or a URL (for links). - static Map mapFrom(ChatMessage message) => { - 'origin': message.origin.name, - 'text': message.text, - 'attachments': [ - for (final attachment in message.attachments) - { - 'type': switch (attachment) { - (FileAttachment _) => 'file', - (LinkAttachment _) => 'link', - }, - 'name': attachment.name, - 'mimeType': switch (attachment) { - (final FileAttachment a) => a.mimeType, - (final LinkAttachment a) => a.mimeType, - }, - 'data': switch (attachment) { - (final FileAttachment a) => base64Encode(a.bytes), - (final LinkAttachment a) => a.url, - }, - }, - ], - }; - - /// Converts a map representation to a [ChatMessage]. - /// - /// The map should contain the following keys: - /// - 'origin': The origin of the message (user or model). - /// - 'text': The text content of the message. - /// - 'attachments': A list of attachments, each represented as a map with: - /// - 'type': The type of the attachment ('file' or 'link'). - /// - 'name': The name of the attachment. - /// - 'mimeType': The MIME type of the attachment. - /// - 'data': The data of the attachment, either as a base64 encoded string - /// (for files) or a URL (for links). - static ChatMessage messageFrom(Map map) => ChatMessage( - origin: MessageOrigin.values.byName(map['origin'] as String), - text: map['text'] as String, - attachments: [ - for (final attachment in map['attachments'] as List) - switch (attachment['type'] as String) { - 'file' => FileAttachment.fileOrImage( - name: attachment['name'] as String, - mimeType: attachment['mimeType'] as String, - bytes: base64Decode(attachment['data'] as String), - ), - 'link' => LinkAttachment( - name: attachment['name'] as String, - url: Uri.parse(attachment['data'] as String), - ), - _ => throw UnimplementedError(), - }, - ], - ); -} diff --git a/lib/src/llm_exception.dart b/lib/src/llm_exception.dart deleted file mode 100644 index be5b4c9..0000000 --- a/lib/src/llm_exception.dart +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/foundation.dart'; - -/// Exception class for LLM-related errors. -/// -/// This class is used to represent exceptions that occur during -/// LLM (Language Learning Model) operations. -@immutable -abstract class LlmException implements Exception { - /// Creates a new [LlmException] with the given error [message]. - /// - /// The [message] parameter is a string describing the error that occurred. - const LlmException._([this.message = '']); - - /// The message describing the error that occurred. - final String message; - - @override - String toString() => 'LlmException: $message'; -} - -/// Exception thrown when an LLM operation is cancelled. -/// -/// This exception is used to indicate that an LLM operation was -/// intentionally cancelled, typically by user action or a timeout. -@immutable -class LlmCancelException extends LlmException { - /// Creates a new [LlmCancelException]. - const LlmCancelException() : super._(); - - @override - String toString() => 'LlmCancelException'; -} - -/// Exception thrown when an LLM operation fails. -/// -/// This exception is used to represent failures in LLM operations -/// that are not due to cancellation, such as network errors or -/// invalid responses from the LLM provider. -@immutable -class LlmFailureException extends LlmException { - /// Creates a new [LlmFailureException] with the given error [message]. - /// - /// The [message] parameter is a string describing the failure that occurred. - const LlmFailureException([super.message]) : super._(); - - @override - String toString() => 'LlmFailureException: $message'; -} diff --git a/lib/src/platform_helper/platform_helper.dart b/lib/src/platform_helper/platform_helper.dart deleted file mode 100644 index 68e2e79..0000000 --- a/lib/src/platform_helper/platform_helper.dart +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -export 'platform_helper_web.dart' - if (dart.library.io) 'platform_helper_io.dart'; diff --git a/lib/src/platform_helper/platform_helper_io.dart b/lib/src/platform_helper/platform_helper_io.dart deleted file mode 100644 index 3ebb759..0000000 --- a/lib/src/platform_helper/platform_helper_io.dart +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:io'; - -import 'package:cross_file/cross_file.dart'; - -/// Deletes a file from the file system. -/// -/// This method takes an [XFile] object and deletes the corresponding file -/// from the file system. It uses the [File] class from dart:io to perform -/// the deletion. -/// -/// Parameters: -/// - file: An [XFile] object representing the file to be deleted. -/// -/// Returns: -/// A [Future] that completes when the file has been deleted. -/// -/// Throws: -/// - [FileSystemException] if the file cannot be deleted. -Future deleteFile(XFile file) async { - await File(file.path).delete(); -} diff --git a/lib/src/platform_helper/platform_helper_web.dart b/lib/src/platform_helper/platform_helper_web.dart deleted file mode 100644 index ea555db..0000000 --- a/lib/src/platform_helper/platform_helper_web.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:cross_file/cross_file.dart'; - -/// Deletes a file from the file system. -/// -/// This method is a no-op on web platforms, as web browsers do not have -/// direct access to the file system. The method is provided for API -/// compatibility with non-web platforms. -/// -/// Parameters: -/// - file: An [XFile] object representing the file to be deleted. -/// This parameter is ignored on web platforms. -/// -/// Returns: -/// A [Future] that completes immediately, as no actual deletion occurs. -Future deleteFile(XFile file) async {} diff --git a/lib/src/providers/implementations/echo_provider.dart b/lib/src/providers/implementations/echo_provider.dart deleted file mode 100644 index 724a7a2..0000000 --- a/lib/src/providers/implementations/echo_provider.dart +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/foundation.dart'; - -import '../../llm_exception.dart'; -import '../interface/attachments.dart'; -import '../interface/chat_message.dart'; -import '../interface/llm_provider.dart'; - -/// A simple LLM provider that echoes the input prompt and attachment -/// information. -/// -/// This provider is primarily used for testing and debugging purposes. -@immutable -class EchoProvider extends LlmProvider { - /// Creates an [EchoProvider] instance with an optional chat history. - /// - /// The [history] parameter is an optional iterable of [ChatMessage] objects - /// representing the chat history. If provided, it will be converted to a list - /// and stored internally. If not provided, an empty list will be used. - EchoProvider({Iterable? history}) - : _history = List.from(history ?? []); - - final List _history; - - @override - Future> getDocumentEmbedding(String document) => - throw UnimplementedError('EchoProvider.getDocumentEmbedding'); - - @override - Future> getQueryEmbedding(String query) => - throw UnimplementedError('EchoProvider.getQueryEmbedding'); - - @override - Stream generateStream( - String prompt, { - Iterable attachments = const [], - }) => - _generateStream(prompt, attachments: attachments); - - @override - Stream sendMessageStream( - String prompt, { - Iterable attachments = const [], - }) async* { - final userMessage = ChatMessage.user(prompt, attachments); - final llmMessage = ChatMessage.llm(); - _history.addAll([userMessage, llmMessage]); - final chunks = _generateStream(prompt, attachments: attachments); - await for (final chunk in chunks) { - llmMessage.append(chunk); - yield chunk; - } - } - - Stream _generateStream( - String prompt, { - Iterable attachments = const [], - }) async* { - if (prompt == 'FAILFAST') throw const LlmFailureException('Failing fast!'); - - await Future.delayed(const Duration(milliseconds: 1000)); - yield '# Echo\n'; - - switch (prompt) { - case 'CANCEL': - throw const LlmCancelException(); - case 'FAIL': - throw const LlmFailureException('User requested failure'); - } - - await Future.delayed(const Duration(milliseconds: 1000)); - yield prompt; - - yield '\n\n# Attachments\n${attachments.map(_stringFrom)}'; - } - - String _stringFrom(Attachment attachment) => attachment.toString(); - - @override - Iterable get history => _history; - - @override - set history(Iterable history) { - _history.clear(); - _history.addAll(history); - } -} diff --git a/lib/src/providers/implementations/gemini_provider.dart b/lib/src/providers/implementations/gemini_provider.dart deleted file mode 100644 index a5bc627..0000000 --- a/lib/src/providers/implementations/gemini_provider.dart +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/foundation.dart'; -import 'package:google_generative_ai/google_generative_ai.dart'; - -import '../interface/attachments.dart'; -import '../interface/chat_message.dart'; -import '../interface/llm_provider.dart'; - -/// A provider class for interacting with Google's Gemini AI language model. -/// -/// This class extends [LlmProvider] and implements the necessary methods to -/// generate text using the Gemini AI model. -class GeminiProvider extends LlmProvider { - /// Creates a new instance of [GeminiProvider]. - /// - /// [generativeModel] is an optional [GenerativeModel] instance for text - /// generation. If provided, it will be used for chat-based interactions and - /// text generation. - /// - /// [embeddingModel] is an optional [GenerativeModel] instance for creating - /// embeddings. If provided, it will be used for document and query embedding - /// operations. - /// - /// [history] is an optional list of previous chat messages to initialize the - /// chat session with. - /// - /// [safetySettings] is an optional list of safety settings to apply to the - /// model's responses. - /// - /// [generationConfig] is an optional configuration for controlling the - /// model's generation behavior. - @immutable - GeminiProvider({ - GenerativeModel? generativeModel, - GenerativeModel? embeddingModel, - Iterable? history, - List? safetySettings, - GenerationConfig? generationConfig, - }) : _generativeModel = generativeModel, - _embeddingModel = embeddingModel, - _history = history?.toList() ?? [], - _safetySettings = safetySettings, - _generationConfig = generationConfig { - _chat = _startChat(history?.map(_contentFrom).toList()); - } - - final GenerativeModel? _generativeModel; - final GenerativeModel? _embeddingModel; - final List? _safetySettings; - final GenerationConfig? _generationConfig; - List? _history; - ChatSession? _chat; - - ChatSession? _startChat(List? history) => - _generativeModel?.startChat( - history: history, - safetySettings: _safetySettings, - generationConfig: _generationConfig, - ); - - @override - Future> getDocumentEmbedding(String document) => - _getEmbedding(document, TaskType.retrievalDocument); - - @override - Future> getQueryEmbedding(String query) => - _getEmbedding(query, TaskType.retrievalQuery); - - Future> _getEmbedding(String s, TaskType embeddingTask) async { - _checkModel('embeddingModel', _embeddingModel); - assert(embeddingTask == TaskType.retrievalDocument || - embeddingTask == TaskType.retrievalQuery); - - final content = Content.text(s); - final result = await _embeddingModel!.embedContent( - content, - taskType: embeddingTask, - ); - - return result.embedding.values; - } - - @override - Stream generateStream( - String prompt, { - Iterable attachments = const [], - }) { - _checkModel('generativeModel', _generativeModel); - return _generateStream( - prompt: prompt, - attachments: attachments, - contentStreamGenerator: (c) => - _generativeModel!.generateContentStream([c]), - ); - } - - @override - Stream sendMessageStream( - String prompt, { - Iterable attachments = const [], - }) async* { - _checkModel('generativeModel', _generativeModel); - final userMessage = ChatMessage.user(prompt, attachments); - final llmMessage = ChatMessage.llm(); - _history!.addAll([userMessage, llmMessage]); - - final chunks = _generateStream( - prompt: prompt, - attachments: attachments, - contentStreamGenerator: _chat!.sendMessageStream, - ); - - await for (final chunk in chunks) { - llmMessage.append(chunk); - yield chunk; - } - } - - Stream _generateStream({ - required String prompt, - required Iterable attachments, - required Stream Function(Content) - contentStreamGenerator, - }) async* { - final content = Content('user', [ - TextPart(prompt), - ...attachments.map(_partFrom), - ]); - - final response = contentStreamGenerator(content); - await for (final chunk in response) { - final text = chunk.text; - if (text != null) yield text; - } - } - - @override - Iterable get history => _history ?? []; - - @override - set history(Iterable history) { - _history = history.toList(); - _chat = _startChat(history.map(_contentFrom).toList()); - } - - static Part _partFrom(Attachment attachment) => switch (attachment) { - (final FileAttachment a) => DataPart(a.mimeType, a.bytes), - (final LinkAttachment a) => FilePart(a.url), - }; - - static Content _contentFrom(ChatMessage message) => Content( - message.origin.isUser ? 'user' : 'model', - [ - TextPart(message.text ?? ''), - ...message.attachments.map(_partFrom), - ], - ); - - void _checkModel(String name, GenerativeModel? model) { - if (model == null) throw Exception('$name is not initialized'); - } -} diff --git a/lib/src/providers/implementations/vertex_provider.dart b/lib/src/providers/implementations/vertex_provider.dart deleted file mode 100644 index 21d0ab7..0000000 --- a/lib/src/providers/implementations/vertex_provider.dart +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:firebase_vertexai/firebase_vertexai.dart'; -import 'package:flutter/foundation.dart'; - -import '../interface/attachments.dart'; -import '../interface/chat_message.dart'; -import '../interface/llm_provider.dart'; - -/// A provider class for interacting with Firebase Vertex AI's language model. -/// -/// This class extends [LlmProvider] and implements the necessary methods to -/// generate text using Firebase Vertex AI's generative model. -class VertexProvider extends LlmProvider { - /// Creates a new instance of [VertexProvider]. - /// - /// [generativeModel] is an optional [GenerativeModel] instance for text - /// generation. If provided, it will be used for chat-based interactions and - /// text generation. - /// - /// [embeddingModel] is an optional [GenerativeModel] instance for creating - /// embeddings. If provided, it will be used for document and query embedding - /// operations. - /// - /// [history] is an optional list of previous chat messages to initialize the - /// chat session with. - /// - /// [safetySettings] is an optional list of safety settings to apply to the - /// model's responses. - /// - /// [generationConfig] is an optional configuration for controlling the - /// model's generation behavior. - @immutable - VertexProvider({ - GenerativeModel? generativeModel, - GenerativeModel? embeddingModel, - Iterable? history, - List? safetySettings, - GenerationConfig? generationConfig, - }) : _generativeModel = generativeModel, - _embeddingModel = embeddingModel, - _history = history?.toList() ?? [], - _safetySettings = safetySettings, - _generationConfig = generationConfig { - _chat = _startChat(history?.map(_contentFrom).toList()); - } - - final GenerativeModel? _generativeModel; - final GenerativeModel? _embeddingModel; - final List? _safetySettings; - final GenerationConfig? _generationConfig; - List? _history; - ChatSession? _chat; - - ChatSession? _startChat(List? history) => - _generativeModel?.startChat( - history: history, - safetySettings: _safetySettings, - generationConfig: _generationConfig, - ); - - @override - Future> getDocumentEmbedding(String document) => - _getEmbedding(document, TaskType.retrievalDocument); - - @override - Future> getQueryEmbedding(String query) => - _getEmbedding(query, TaskType.retrievalQuery); - - Future> _getEmbedding(String s, TaskType embeddingTask) async { - _checkModel('embeddingModel', _embeddingModel); - assert(embeddingTask == TaskType.retrievalDocument || - embeddingTask == TaskType.retrievalQuery); - - // waiting for: https://github.com/firebase/flutterfire/issues/13269 - throw UnimplementedError('VertexProvider${switch (embeddingTask) { - TaskType.retrievalDocument => 'getDocumentEmbedding', - TaskType.retrievalQuery => 'getQueryEmbedding', - _ => 'getEmbedding', - }}'); - } - - @override - Stream generateStream( - String prompt, { - Iterable attachments = const [], - }) { - _checkModel('generativeModel', _generativeModel); - return _generateStream( - prompt: prompt, - attachments: attachments, - contentStreamGenerator: (c) => - _generativeModel!.generateContentStream([c]), - ); - } - - @override - Stream sendMessageStream( - String prompt, { - Iterable attachments = const [], - }) async* { - _checkModel('generativeModel', _generativeModel); - final userMessage = ChatMessage.user(prompt, attachments); - final llmMessage = ChatMessage.llm(); - _history!.addAll([userMessage, llmMessage]); - - final chunks = _generateStream( - prompt: prompt, - attachments: attachments, - contentStreamGenerator: _chat!.sendMessageStream, - ); - - await for (final chunk in chunks) { - llmMessage.append(chunk); - yield chunk; - } - } - - Stream _generateStream({ - required String prompt, - required Iterable attachments, - required Stream Function(Content) - contentStreamGenerator, - }) async* { - final content = Content('user', [ - TextPart(prompt), - ...attachments.map(_partFrom), - ]); - - final response = contentStreamGenerator(content); - await for (final chunk in response) { - final text = chunk.text; - if (text != null) yield text; - } - } - - @override - Iterable get history => _history ?? []; - - @override - set history(Iterable history) { - _history = history.toList(); - _chat = _startChat(history.map(_contentFrom).toList()); - } - - static Part _partFrom(Attachment attachment) => switch (attachment) { - (final FileAttachment a) => InlineDataPart(a.mimeType, a.bytes), - (final LinkAttachment a) => FileData(a.mimeType, a.url.toString()), - }; - - static Content _contentFrom(ChatMessage message) => Content( - message.origin.isUser ? 'user' : 'model', - [ - TextPart(message.text ?? ''), - ...message.attachments.map(_partFrom), - ], - ); - - void _checkModel(String name, GenerativeModel? model) { - if (model == null) throw Exception('$name is not initialized'); - } -} diff --git a/lib/src/providers/interface/attachments.dart b/lib/src/providers/interface/attachments.dart deleted file mode 100644 index ae2087d..0000000 --- a/lib/src/providers/interface/attachments.dart +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:cross_file/cross_file.dart'; -import 'package:flutter/foundation.dart'; -import 'package:mime/mime.dart'; - -/// An abstract class representing an attachment in a chat message. -/// -/// This class serves as a base for different types of attachments -/// (e.g., files, images, links) that can be included in a chat message. -@immutable -sealed class Attachment { - /// Creates an [Attachment] with the given name. - /// - /// [name] is the name of the attachment, which must not be null. - const Attachment({required this.name}); - - /// The name of the attachment. - final String name; - - static String _mimeType(XFile file) => - file.mimeType ?? lookupMimeType(file.path) ?? 'application/octet-stream'; - - static bool _isImage(String mimeType) => - mimeType.toLowerCase().startsWith('image/'); -} - -/// Represents a file attachment in a chat message. -/// -/// This class extends [Attachment] and provides specific properties and methods -/// for handling file attachments. -@immutable -final class FileAttachment extends Attachment { - /// Creates a [FileAttachment] with the given name, MIME type, and bytes. - /// - /// [name] is the name of the file attachment. - /// [mimeType] is the MIME type of the file. - /// [bytes] is the binary content of the file. - const FileAttachment({ - required super.name, - required this.mimeType, - required this.bytes, - }); - - /// Factory constructor for creating either a [FileAttachment] or an - /// [ImageFileAttachment]. - /// - /// This factory method determines the type of attachment based on the MIME - /// type. If the MIME type indicates an image, it creates an - /// [ImageFileAttachment]. Otherwise, it creates a [FileAttachment]. - /// - /// [name] is the name of the attachment. [mimeType] is the MIME type of the - /// attachment. [bytes] is the binary content of the attachment. - /// - /// Returns an instance of either [FileAttachment] or [ImageFileAttachment]. - factory FileAttachment.fileOrImage({ - required String name, - required String mimeType, - required Uint8List bytes, - }) => - Attachment._isImage(mimeType) - ? ImageFileAttachment( - name: name, - mimeType: mimeType, - bytes: bytes, - ) - : FileAttachment( - name: name, - mimeType: mimeType, - bytes: bytes, - ); - - /// The MIME type of the file attachment. - final String mimeType; - - /// The binary content of the file attachment. - final Uint8List bytes; - - @override - String toString() => 'FileAttachment(' - 'name: $name, ' - 'mimeType: $mimeType, ' - // I want to avoid the trailing whitespace here for readability. - // ignore: missing_whitespace_between_adjacent_strings - 'bytes: ${bytes.length} bytes' - ')'; - - /// Creates a [FileAttachment] from an [XFile]. - /// - /// This factory method asynchronously reads the file content and determines - /// its MIME type. - /// - /// [file] is the XFile object representing the file to be attached. - /// - /// Returns a Future that completes with a [FileAttachment] instance. - static Future fromFile(XFile file) async => - FileAttachment.fileOrImage( - name: file.name, - mimeType: Attachment._mimeType(file), - bytes: await file.readAsBytes(), - ); -} - -/// Represents an image attachment in a chat message. -/// -/// This class extends [Attachment] and provides specific properties and methods -/// for handling image attachments. -@immutable -final class ImageFileAttachment extends FileAttachment { - /// Creates an [ImageFileAttachment] with the given name, MIME type, and - /// bytes. - /// - /// [name] is the name of the image attachment. [mimeType] is the MIME type of - /// the image. [bytes] is the binary content of the image. - ImageFileAttachment({ - required super.name, - required super.mimeType, - required super.bytes, - }) : assert(Attachment._isImage(mimeType)); - - @override - String toString() => 'ImageFileAttachment(' - 'name: $name, ' - 'mimeType: $mimeType, ' - // I want to avoid the trailing whitespace here for readability. - // ignore: missing_whitespace_between_adjacent_strings - 'bytes: ${bytes.length} bytes' - ')'; - - /// Creates an [ImageFileAttachment] from an [XFile]. - /// - /// This factory method asynchronously reads the file content and determines - /// its MIME type. It throws an exception if the file is not an image. - /// - /// [file] is the XFile object representing the image file to be attached. - /// - /// Returns a Future that completes with an [ImageFileAttachment] instance. - /// Throws an Exception if the file is not an image. - static Future fromFile(XFile file) async { - final mimeType = Attachment._mimeType(file); - if (!Attachment._isImage(mimeType)) { - throw Exception('Not an image: $mimeType'); - } - - return ImageFileAttachment( - name: file.name, - mimeType: mimeType, - bytes: await file.readAsBytes(), - ); - } -} - -/// Represents a link attachment in a chat message. -/// -/// This class extends [Attachment] and provides specific properties for -/// handling link attachments. -@immutable -final class LinkAttachment extends Attachment { - /// Creates a [LinkAttachment] with the given name and URL. - /// - /// [name] is the name of the link attachment. - /// [url] is the URI of the link. - LinkAttachment({ - required super.name, - required this.url, - }) : mimeType = lookupMimeType(url.path) ?? 'application/octet-stream'; - - /// The URL of the link attachment. - final Uri url; - - /// The MIME type of the linked content. - /// - /// This property specifies the media type of the resource pointed to by the - /// [url]. - final String mimeType; - - @override - String toString() => 'LinkAttachment(' - 'name: $name, ' - 'url: $url, ' - 'mimeType: $mimeType' - ')'; -} diff --git a/lib/src/providers/interface/chat_message.dart b/lib/src/providers/interface/chat_message.dart deleted file mode 100644 index 7c8859f..0000000 --- a/lib/src/providers/interface/chat_message.dart +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import '../../providers/interface/attachments.dart'; -import 'message_origin.dart'; - -/// Represents a message in a chat conversation. -/// -/// This class encapsulates the properties and behavior of a chat message, -/// including its unique identifier, origin (user or LLM), text content, -/// and any attachments. -class ChatMessage { - /// Constructs a [ChatMessage] instance. - /// - /// The [origin] parameter specifies the origin of the message (user or LLM). - /// The [text] parameter is the content of the message. It can be null or - /// empty if the message is from an LLM. For user-originated messages, [text] - /// must not be null or empty. The [attachments] parameter is a list of any - /// files or media attached to the message. - ChatMessage({ - required this.origin, - required String? text, - required this.attachments, - }) : _text = text, - assert( - origin.isUser && text != null && text.isNotEmpty || origin.isLlm); - - /// Factory constructor for creating an LLM-originated message. - /// - /// Creates a message with an empty text content and no attachments. - factory ChatMessage.llm() => ChatMessage( - origin: MessageOrigin.llm, - text: null, - attachments: [], - ); - - /// Factory constructor for creating an LLM-originated greeting message. - /// - /// [welcomeMessage] is the content of the greeting message. - factory ChatMessage.llmWelcome(String welcomeMessage) => ChatMessage( - origin: MessageOrigin.llm, - text: welcomeMessage, - attachments: [], - ); - - /// Factory constructor for creating a user-originated message. - /// - /// [text] is the content of the user's message. - /// [attachments] are any files or media the user has attached to the message. - factory ChatMessage.user(String text, Iterable attachments) => - ChatMessage( - origin: MessageOrigin.user, - text: text, - attachments: attachments, - ); - - String? _text; - - /// The origin of the message (user or LLM). - final MessageOrigin origin; - - /// Any attachments associated with the message. - final Iterable attachments; - - /// Getter for the text content of the message. - String? get text => _text?.trim(); - - /// Appends additional text to the existing message content. - /// - /// This is typically used for LLM messages that are streamed in parts. - void append(String text) => _text = (_text ?? '') + text; - - @override - String toString() => 'ChatMessage(' - 'origin: $origin, ' - 'text: $text, ' - 'attachments: $attachments' - ')'; -} diff --git a/lib/src/providers/interface/llm_provider.dart b/lib/src/providers/interface/llm_provider.dart deleted file mode 100644 index f390f0e..0000000 --- a/lib/src/providers/interface/llm_provider.dart +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'attachments.dart'; -import 'chat_message.dart'; - -/// An abstract class representing a Language Model (LLM) provider. -/// -/// This class defines the interface for interacting with different LLM -/// services. Implementations of this class should provide the logic for -/// generating text responses based on input prompts and optional attachments. -abstract class LlmProvider { - /// Generates an embedding for a given document. - /// - /// This method should be implemented to create a numerical representation - /// (embedding) of the input document, which can be used for tasks like - /// semantic search or document comparison. - /// - /// [document] is the text content of the document to be embedded. - /// - /// Returns a [Future] that resolves to a [List] representing the - /// document's embedding. - Future> getDocumentEmbedding(String document); - - /// Generates an embedding for a given query. - /// - /// This method should be implemented to create a numerical representation - /// (embedding) of the input query, which can be used for tasks like - /// semantic search or query-document matching. - /// - /// [query] is the text content of the query to be embedded. - /// - /// Returns a [Future] that resolves to a [List] representing the - /// query's embedding. - Future> getQueryEmbedding(String query); - - /// Generates a stream of text based on the given prompt and attachments. - /// This method does not interact with a chat or build on any chat history. - /// - /// [prompt] is the input text to generate a response for. - /// [attachments] is an optional iterable of [Attachment] objects to include - /// with the prompt. These can be images, files, or links that provide - /// additional context for the LLM. - /// - /// Returns a [Stream] of [String] containing the generated text chunks. This - /// allows for streaming responses as they are generated by the LLM. - Stream generateStream( - String prompt, { - Iterable attachments, - }); - - /// Generates a stream of text based on the given prompt and attachments. - /// Interacts with a chat and builds on the history of the chat associated - /// with the provider. - /// - /// This method should be implemented to interact with the specific LLM - /// service and generate text responses. - /// - /// [prompt] is the input text to generate a response for. [attachments] is an - /// optional iterable of [Attachment] objects to include with the prompt. - /// These can be images, files, or links that provide additional context for - /// the LLM. - /// - /// Returns a [Stream] of [String] containing the generated text chunks. This - /// allows for streaming responses as they are generated by the LLM. - Stream sendMessageStream( - String prompt, { - Iterable attachments, - }); - - /// Returns an iterable of [ChatMessage] objects representing the chat - /// history. - /// - /// This getter provides access to the conversation history maintained by the - /// LLM provider. The history typically includes both user messages and LLM - /// responses in chronological order. - /// - /// Returns an [Iterable] of [ChatMessage] objects. - Iterable get history; - - /// Sets the chat history to the provided messages. - /// - /// This setter allows updating the conversation history maintained by the LLM - /// provider. The provided [history] replaces the existing history with a new - /// set of messages. - /// - /// [history] is an [Iterable] of [ChatMessage] objects representing the new - /// chat history. - set history(Iterable history); -} - -/// A function that generates a stream of text based on a prompt and -/// attachments. -typedef LlmStreamGenerator = Stream Function( - String prompt, { - required Iterable attachments, -}); diff --git a/lib/src/providers/interface/message_origin.dart b/lib/src/providers/interface/message_origin.dart deleted file mode 100644 index e048577..0000000 --- a/lib/src/providers/interface/message_origin.dart +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/// Represents the origin of a chat message. -enum MessageOrigin { - /// Indicates that the message originated from the user. - user, - - /// Indicates that the message originated from the LLM. - llm; - - /// Checks if the message origin is from the user. - bool get isUser => this == MessageOrigin.user; - - /// Checks if the message origin is from the LLM. - bool get isLlm => this == MessageOrigin.llm; -} diff --git a/lib/src/providers/providers.dart b/lib/src/providers/providers.dart deleted file mode 100644 index b45cc87..0000000 --- a/lib/src/providers/providers.dart +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -export 'implementations/echo_provider.dart'; -export 'implementations/gemini_provider.dart'; -export 'implementations/vertex_provider.dart'; -export 'interface/llm_provider.dart'; diff --git a/lib/src/styles/action_button_style.dart b/lib/src/styles/action_button_style.dart deleted file mode 100644 index 5e4357c..0000000 --- a/lib/src/styles/action_button_style.dart +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import 'action_button_type.dart'; -import 'fat_colors.dart'; -import 'fat_icons.dart'; -import 'fat_text_styles.dart'; -import 'style_helpers.dart' as sh; - -/// Style for icon buttons. -@immutable -class ActionButtonStyle { - /// Creates an IconButtonStyle. - const ActionButtonStyle({ - this.icon, - this.iconColor, - this.iconDecoration, - this.tooltip, - this.tooltipTextStyle, - this.tooltipDecoration, - }); - - /// Resolves the provided [style] with the [defaultStyle]. - /// - /// This method returns a new [ActionButtonStyle] instance where each property - /// is taken from the provided [style] if it is not null, otherwise from the - /// [defaultStyle]. - /// - /// - [style]: The style to resolve. If null, the [defaultStyle] will be used. - /// - [defaultStyle]: The default style to use for any properties not provided - /// by the [style]. - factory ActionButtonStyle.resolve( - ActionButtonStyle? style, { - required ActionButtonStyle defaultStyle, - }) => - ActionButtonStyle( - icon: style?.icon ?? defaultStyle.icon, - iconColor: style?.iconColor ?? defaultStyle.iconColor, - iconDecoration: style?.iconDecoration ?? defaultStyle.iconDecoration, - tooltip: style?.tooltip ?? defaultStyle.tooltip, - tooltipTextStyle: - style?.tooltipTextStyle ?? defaultStyle.tooltipTextStyle, - tooltipDecoration: - style?.tooltipDecoration ?? defaultStyle.tooltipDecoration, - ); - - /// Provides default style for icon buttons. - factory ActionButtonStyle.defaultStyle(ActionButtonType type) => - ActionButtonStyle.lightStyle(type); - - /// Provides a default dark style. - factory ActionButtonStyle.darkStyle(ActionButtonType type) { - final style = ActionButtonStyle.lightStyle(type); - return ActionButtonStyle( - icon: style.icon, - iconColor: sh.invertColor(style.iconColor), - iconDecoration: switch (type) { - ActionButtonType.add || - ActionButtonType.record || - ActionButtonType.stop => - const BoxDecoration( - color: FatColors.greyBackground, - shape: BoxShape.circle, - ), - _ => sh.invertDecoration(style.iconDecoration), - }, - tooltip: style.tooltip, - tooltipTextStyle: sh.invertTextStyle(style.tooltipTextStyle), - tooltipDecoration: sh.invertDecoration(style.tooltipDecoration), - ); - } - - /// Provides default light style for icon buttons. - factory ActionButtonStyle.lightStyle(ActionButtonType type) { - IconData icon; - var color = FatColors.darkIcon; - var bgColor = FatColors.lightButtonBackground; - String tooltip; - final tooltipTextStyle = FatTextStyles.tooltip; - const tooltipDecoration = BoxDecoration( - color: FatColors.tooltipBackground, - borderRadius: BorderRadius.all(Radius.circular(4)), - ); - - switch (type) { - case ActionButtonType.add: - icon = FatIcons.add; - tooltip = 'Add Attachment'; - case ActionButtonType.attachFile: - icon = FatIcons.attach_file; - color = FatColors.whiteIcon; - bgColor = FatColors.darkButtonBackground; - tooltip = 'Attach File'; - case ActionButtonType.camera: - icon = FatIcons.camera_alt; - color = FatColors.whiteIcon; - bgColor = FatColors.darkButtonBackground; - tooltip = 'Take Photo'; - case ActionButtonType.stop: - icon = FatIcons.stop; - tooltip = 'Stop'; - case ActionButtonType.close: - icon = FatIcons.close; - color = FatColors.whiteIcon; - bgColor = FatColors.darkButtonBackground; - tooltip = 'Close'; - case ActionButtonType.copy: - icon = FatIcons.content_copy; - color = FatColors.whiteIcon; - bgColor = FatColors.darkButtonBackground; - tooltip = 'Copy to Clipboard'; - case ActionButtonType.edit: - icon = FatIcons.edit; - color = FatColors.whiteIcon; - bgColor = FatColors.darkButtonBackground; - tooltip = 'Edit Message'; - case ActionButtonType.gallery: - icon = FatIcons.image; - color = FatColors.whiteIcon; - bgColor = FatColors.darkButtonBackground; - tooltip = 'Image Gallery'; - case ActionButtonType.record: - icon = FatIcons.mic; - tooltip = 'Record Audio'; - case ActionButtonType.submit: - icon = FatIcons.submit_icon; - color = FatColors.whiteIcon; - bgColor = FatColors.darkButtonBackground; - tooltip = 'Submit Message'; - case ActionButtonType.closeMenu: - icon = FatIcons.close; - color = FatColors.whiteIcon; - bgColor = FatColors.greyBackground; - tooltip = 'Close Menu'; - } - - return ActionButtonStyle( - icon: icon, - iconColor: color, - iconDecoration: BoxDecoration(color: bgColor, shape: BoxShape.circle), - tooltip: tooltip, - tooltipTextStyle: tooltipTextStyle, - tooltipDecoration: tooltipDecoration, - ); - } - - /// The icon to display for the icon button. - final IconData? icon; - - /// The color of the icon. - final Color? iconColor; - - /// The decoration for the icon. - final Decoration? iconDecoration; - - /// The tooltip for the icon button. - final String? tooltip; - - /// The text style of the tooltip. - final TextStyle? tooltipTextStyle; - - /// The decoration of the tooltip. - final Decoration? tooltipDecoration; -} diff --git a/lib/src/styles/action_button_type.dart b/lib/src/styles/action_button_type.dart deleted file mode 100644 index 316d9bc..0000000 --- a/lib/src/styles/action_button_type.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/// Enum representing different types of action buttons in the chat view. -enum ActionButtonType { - /// Button to add content or initiate a new action. - add, - - /// Button to attach a file to the chat. - attachFile, - - /// Button to access the camera for taking photos or videos. - camera, - - /// Button to cancel an ongoing action or input. - stop, - - /// Button to close the current view or dialog. - close, - - /// Button to close an open menu. - closeMenu, - - /// Button to copy selected text or content. - copy, - - /// Button to edit existing content or settings. - edit, - - /// Button to access the device's photo gallery. - gallery, - - /// Button to start or stop audio recording. - record, - - /// Button to submit the current input or action. - submit, -} diff --git a/lib/src/styles/chat_input_style.dart b/lib/src/styles/chat_input_style.dart deleted file mode 100644 index 8728cea..0000000 --- a/lib/src/styles/chat_input_style.dart +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import 'fat_colors.dart'; -import 'fat_text_styles.dart'; -import 'style_helpers.dart' as sh; - -/// Style for the input text box. -@immutable -class ChatInputStyle { - /// Creates an InputBoxStyle. - const ChatInputStyle({ - this.textStyle, - this.hintStyle, - this.hintText, - this.backgroundColor, - this.decoration, - }); - - /// Merges the provided styles with the default styles. - factory ChatInputStyle.resolve( - ChatInputStyle? style, { - ChatInputStyle? defaultStyle, - }) { - defaultStyle ??= ChatInputStyle.defaultStyle(); - return ChatInputStyle( - textStyle: style?.textStyle ?? defaultStyle.textStyle, - hintStyle: style?.hintStyle ?? defaultStyle.hintStyle, - hintText: style?.hintText ?? defaultStyle.hintText, - backgroundColor: style?.backgroundColor ?? defaultStyle.backgroundColor, - decoration: style?.decoration ?? defaultStyle.decoration, - ); - } - - /// Provides a default dark style. - factory ChatInputStyle.darkStyle() { - final style = ChatInputStyle.lightStyle(); - return ChatInputStyle( - decoration: sh.invertDecoration(style.decoration), - textStyle: sh.invertTextStyle(style.textStyle), - // inversion doesn't look great here - // hintStyle: sh.invertTextStyle(style.hintStyle), - hintStyle: FatTextStyles.body2.copyWith( - color: FatColors.greyBackground, - ), - hintText: style.hintText, - backgroundColor: sh.invertColor(style.backgroundColor), - ); - } - - /// Provides a default style. - factory ChatInputStyle.defaultStyle() => ChatInputStyle.lightStyle(); - - /// Provides a default light style. - factory ChatInputStyle.lightStyle() => ChatInputStyle( - textStyle: FatTextStyles.body2, - hintStyle: FatTextStyles.body2.copyWith(color: FatColors.hintText), - hintText: 'Ask me anything...', - backgroundColor: FatColors.containerBackground, - decoration: BoxDecoration( - color: FatColors.containerBackground, - border: Border.all(width: 1, color: FatColors.outline), - borderRadius: BorderRadius.circular(24), - ), - ); - - /// The text style for the input text box. - final TextStyle? textStyle; - - /// The hint text style for the input text box. - final TextStyle? hintStyle; - - /// The hint text for the input text box. - final String? hintText; - - /// The background color of the input box. - final Color? backgroundColor; - - /// The decoration of the input box. - final Decoration? decoration; -} diff --git a/lib/src/styles/fat_colors.dart b/lib/src/styles/fat_colors.dart deleted file mode 100644 index 29005d4..0000000 --- a/lib/src/styles/fat_colors.dart +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -/// A collection of color constants used throughout the application. -@immutable -abstract final class FatColors { - /// Fully transparent color. - static const Color transparent = Color(0x00000000); - - /// Pure black color. - static const Color black = Color(0xFF000000); - - // Color 0 (#FFFFFF) - /// White color used for button backgrounds. - static const Color whiteButtonBackground = Color(0xFFFFFFFF); - - /// White color used for container backgrounds. - static const Color containerBackground = Color(0xFFFFFFFF); - - /// White color used for LLM message backgrounds. - static const Color llmMessageBackground = Color(0xFFFFFFFF); - - /// White color used for LLM message outlines. - static const Color llmMessageOutline = Color(0xFFFFFFFF); - - /// White color used for icons. - static const Color whiteIcon = Color(0xFFFFFFFF); - - /// White color used for tooltip text. - static const Color tooltipText = Color(0xFFFFFFFF); - - // Color 100 (#F5F5F5) - /// Light gray color used for user message backgrounds. - static const Color userMessageBackground = Color(0xFFF5F5F5); - - /// Light gray color used for file container backgrounds. - static const Color fileContainerBackground = Color(0xFFF5F5F5); - - /// Light gray color used for light button backgrounds. - static const Color lightButtonBackground = Color(0xFFF5F5F5); - - /// Light gray color used for dark button icons. - static const Color darkButtonIcon = Color(0xFFF5F5F5); - - // Color 200 (#E5E5E5) - /// Light gray color used for outlines. - static const Color outline = Color(0xFFE5E5E5); - - /// Light gray color used for LLM icon backgrounds. - static const Color llmIconBackground = Color(0xFFE5E5E5); - - /// Light gray color used for disabled buttons. - static const Color disabledButton = Color(0xFFE5E5E5); - - // Color 300 (#CACACA) - /// Gray color used for hint text. - static const Color hintText = Color(0xFFCACACA); - - /// Gray color used for file attachment icon backgrounds. - static const Color fileAttachmentIconBackground = Color(0xFFCACACA); - - /// Gray color used for grey button backgrounds. - static const Color greyButtonBackground = Color(0xFFCACACA); - - /// Gray color used for light icons. - static const Color lightIcon = Color(0xFFCACACA); - - /// Gray color used for image placeholders. - static const Color imagePlaceholder = Color(0xFFCACACA); - - /// Gray color used for light pagination circles. - static const Color lightPaginationCircle = Color(0xFFCACACA); - - /// Gray color used for light voice bar lines. - static const Color lightVoiceBarLine = Color(0xFFCACACA); - - // Color 400 (#535353) - /// Dark gray color used for grey backgrounds. - static const Color greyBackground = Color(0xFF535353); - - /// Dark gray color used for LLM name text. - static const Color llmNameText = Color(0xFF535353); - - /// Dark gray color used for tooltip backgrounds. - static const Color tooltipBackground = Color(0xFF535353); - - // Color 500 (#2F2F2F) - /// Very dark gray color used for dark button backgrounds. - static const Color darkButtonBackground = Color(0xFF2F2F2F); - - /// Very dark gray color used for dark icons. - static const Color darkIcon = Color(0xFF2F2F2F); - - /// Very dark gray color used for enabled text. - static const Color enabledText = Color(0xFF2F2F2F); -} diff --git a/lib/src/styles/fat_icons.dart b/lib/src/styles/fat_icons.dart deleted file mode 100644 index d64e696..0000000 --- a/lib/src/styles/fat_icons.dart +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// by convention, using the names of the icons as the constant names -// ignore_for_file: constant_identifier_names - -import 'package:flutter/widgets.dart'; - -/// A collection of custom icons used in the Fat application. -/// -/// This class provides a set of static [IconData] constants that can be used -/// to display custom icons in the application. These icons are part of a custom -/// font called 'FatIcons'. -/// Material Design Icons, Copyright (C) Google, Inc -/// Author: Google -/// License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) -/// Homepage: https://design.google.com/icons/ -/// -@immutable -class FatIcons { - const FatIcons._(); - - static const _kFontFam = 'FatIcons'; - static const String _kFontPkg = 'flutter_ai_toolkit'; - - /// Icon for submitting or sending. - static const IconData submit_icon = - IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon representing a spark or idea. - static const IconData spark_icon = - IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon for adding or creating new items. - static const IconData add = - IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon for attaching files. - static const IconData attach_file = - IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon for stopping or halting an action. - static const IconData stop = - IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon representing a microphone. - static const IconData mic = - IconData(0xe805, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon for closing or dismissing. - static const IconData close = - IconData(0xe806, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon representing a camera. - static const IconData camera_alt = - IconData(0xe807, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon representing an image or picture. - static const IconData image = - IconData(0xe808, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon for editing. - static const IconData edit = - IconData(0xe809, fontFamily: _kFontFam, fontPackage: _kFontPkg); - - /// Icon for copying content. - static const IconData content_copy = - IconData(0xe80a, fontFamily: _kFontFam, fontPackage: _kFontPkg); -} diff --git a/lib/src/styles/fat_text_styles.dart b/lib/src/styles/fat_text_styles.dart deleted file mode 100644 index a4c52d2..0000000 --- a/lib/src/styles/fat_text_styles.dart +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:google_fonts/google_fonts.dart'; - -import 'fat_colors.dart'; - -/// A utility class that defines text styles for the Fat design system. -@immutable -abstract final class FatTextStyles { - /// Large display text style. - /// - /// Used for the most prominent text elements, typically headers or titles. - static final TextStyle display = GoogleFonts.roboto( - color: FatColors.enabledText, - fontSize: 32, - fontWeight: FontWeight.w400, - ); - - /// Primary heading text style. - /// - /// Used for main section headings or important subheadings. - static final TextStyle heading1 = GoogleFonts.roboto( - color: FatColors.enabledText, - fontSize: 24, - fontWeight: FontWeight.w400, - ); - - /// Secondary heading text style. - /// - /// Used for subsection headings or less prominent titles. - static final TextStyle heading2 = GoogleFonts.roboto( - color: FatColors.enabledText, - fontSize: 20, - fontWeight: FontWeight.w400, - ); - - /// Primary body text style. - /// - /// Used for the main content text in the application. - static final TextStyle body1 = GoogleFonts.roboto( - color: FatColors.enabledText, - fontSize: 16, - fontWeight: FontWeight.w400, - ); - - /// Code text style. - /// - /// Used for displaying code snippets or monospaced text. - static final TextStyle code = GoogleFonts.robotoMono( - color: FatColors.enabledText, - fontSize: 16, - fontWeight: FontWeight.w400, - ); - - /// Secondary body text style. - /// - /// Used for less prominent body text or supporting information. - static final TextStyle body2 = GoogleFonts.roboto( - color: FatColors.enabledText, - fontSize: 14, - fontWeight: FontWeight.w400, - ); - - /// Tooltip text style. - /// - /// Used for the text of tooltips. - static final TextStyle tooltip = GoogleFonts.roboto( - color: FatColors.tooltipText.withOpacity(0.9), - fontSize: 14, - fontWeight: FontWeight.w400, - ); - - /// Filename text style. - /// - /// Used for the text of file attachments. - static final TextStyle filename = GoogleFonts.roboto( - color: FatColors.enabledText, - fontSize: 14, - fontWeight: FontWeight.w400, - ); - - /// File type text style. - /// - /// Used for displaying the file type or MIME type of attachments. - static final TextStyle filetype = GoogleFonts.roboto( - color: FatColors.hintText, - fontSize: 14, - fontWeight: FontWeight.w400, - ); - - /// Label text style. - /// - /// Used for small labels, captions, or helper text. - static final TextStyle label = GoogleFonts.roboto( - color: FatColors.enabledText, - fontSize: 12, - fontWeight: FontWeight.w400, - ); -} diff --git a/lib/src/styles/file_attachment_style.dart b/lib/src/styles/file_attachment_style.dart deleted file mode 100644 index 790e6bc..0000000 --- a/lib/src/styles/file_attachment_style.dart +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import 'fat_colors.dart'; -import 'fat_icons.dart'; -import 'fat_text_styles.dart'; -import 'style_helpers.dart' as sh; - -/// Style for file attachments in the chat view. -@immutable -class FileAttachmentStyle { - /// Creates a FileAttachmentStyle. - const FileAttachmentStyle({ - this.decoration, - this.icon, - this.iconColor, - this.iconDecoration, - this.filenameStyle, - this.filetypeStyle, - }); - - /// Resolves the FileAttachmentStyle by combining the provided style with - /// default values. - /// - /// This method takes an optional [style] and merges it with the - /// [defaultStyle]. If [defaultStyle] is not provided, it uses - /// [FileAttachmentStyle.defaultStyle]. - /// - /// [style] - The custom FileAttachmentStyle to apply. Can be null. - /// [defaultStyle] - The default FileAttachmentStyle to use as a base. If - /// null, uses [FileAttachmentStyle.defaultStyle]. - /// - /// Returns a new [FileAttachmentStyle] instance with resolved properties. - factory FileAttachmentStyle.resolve( - FileAttachmentStyle? style, { - FileAttachmentStyle? defaultStyle, - }) { - defaultStyle ??= FileAttachmentStyle.defaultStyle(); - return FileAttachmentStyle( - decoration: style?.decoration ?? defaultStyle.decoration, - icon: style?.icon ?? defaultStyle.icon, - iconColor: style?.iconColor ?? defaultStyle.iconColor, - iconDecoration: style?.iconDecoration ?? defaultStyle.iconDecoration, - filenameStyle: style?.filenameStyle ?? defaultStyle.filenameStyle, - filetypeStyle: style?.filetypeStyle ?? defaultStyle.filetypeStyle, - ); - } - - /// Provides a default dark style. - factory FileAttachmentStyle.darkStyle() { - final style = FileAttachmentStyle.lightStyle(); - return FileAttachmentStyle( - // inversion doesn't look great here - // decoration: sh.invertDecoration(style.decoration), - decoration: ShapeDecoration( - color: FatColors.greyBackground, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - icon: style.icon, - iconColor: sh.invertColor(style.iconColor), - iconDecoration: sh.invertDecoration(style.iconDecoration), - filenameStyle: sh.invertTextStyle(style.filenameStyle), - // inversion doesn't look great here - // filetypeStyle: sh.invertTextStyle(style.filetypeStyle), - filetypeStyle: style.filetypeStyle!.copyWith(color: FatColors.black), - ); - } - - /// Provides a default style. - factory FileAttachmentStyle.defaultStyle() => - FileAttachmentStyle.lightStyle(); - - /// Provides a default light style. - factory FileAttachmentStyle.lightStyle() => FileAttachmentStyle( - decoration: ShapeDecoration( - color: FatColors.fileContainerBackground, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - ), - icon: FatIcons.attach_file, - iconColor: FatColors.darkIcon, - iconDecoration: ShapeDecoration( - color: FatColors.fileAttachmentIconBackground, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - filenameStyle: FatTextStyles.filename, - filetypeStyle: FatTextStyles.filetype, - ); - - /// The decoration for the file attachment container. - final Decoration? decoration; - - /// The icon to display for the file attachment. - final IconData? icon; - - /// The color of the file attachment icon. - final Color? iconColor; - - /// The decoration for the file attachment icon container. - final Decoration? iconDecoration; - - /// The text style for the filename. - final TextStyle? filenameStyle; - - /// The text style for the filetype. - final TextStyle? filetypeStyle; -} diff --git a/lib/src/styles/llm_chat_view_style.dart b/lib/src/styles/llm_chat_view_style.dart deleted file mode 100644 index 9c5b31b..0000000 --- a/lib/src/styles/llm_chat_view_style.dart +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import 'action_button_style.dart'; -import 'action_button_type.dart'; -import 'chat_input_style.dart'; -import 'fat_colors.dart'; -import 'file_attachment_style.dart'; -import 'llm_message_style.dart'; -import 'style_helpers.dart' as sh; -import 'suggestion_style.dart'; -import 'user_message_style.dart'; - -/// Style for the entire chat widget. -@immutable -class LlmChatViewStyle { - /// Creates a style object for the chat widget. - const LlmChatViewStyle({ - this.backgroundColor, - this.progressIndicatorColor, - this.userMessageStyle, - this.llmMessageStyle, - this.chatInputStyle, - this.addButtonStyle, - this.attachFileButtonStyle, - this.cameraButtonStyle, - this.stopButtonStyle, - this.closeButtonStyle, - this.copyButtonStyle, - this.editButtonStyle, - this.galleryButtonStyle, - this.recordButtonStyle, - this.submitButtonStyle, - this.closeMenuButtonStyle, - this.actionButtonBarDecoration, - this.fileAttachmentStyle, - this.suggestionStyle, - }); - - /// Resolves the provided [style] with the [defaultStyle]. - /// - /// This method returns a new [LlmChatViewStyle] instance where each property - /// is taken from the provided [style] if it is not null, otherwise from the - /// [defaultStyle]. - /// - /// - [style]: The style to resolve. If null, the [defaultStyle] will be used. - /// - [defaultStyle]: The default style to use for any properties not provided - /// by the [style]. - factory LlmChatViewStyle.resolve( - LlmChatViewStyle? style, { - LlmChatViewStyle? defaultStyle, - }) { - defaultStyle ??= LlmChatViewStyle.defaultStyle(); - return LlmChatViewStyle( - backgroundColor: style?.backgroundColor ?? defaultStyle.backgroundColor, - progressIndicatorColor: - style?.progressIndicatorColor ?? defaultStyle.progressIndicatorColor, - userMessageStyle: UserMessageStyle.resolve(style?.userMessageStyle, - defaultStyle: defaultStyle.userMessageStyle), - llmMessageStyle: LlmMessageStyle.resolve(style?.llmMessageStyle, - defaultStyle: defaultStyle.llmMessageStyle), - chatInputStyle: ChatInputStyle.resolve(style?.chatInputStyle, - defaultStyle: defaultStyle.chatInputStyle), - addButtonStyle: ActionButtonStyle.resolve( - style?.addButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.add), - ), - attachFileButtonStyle: ActionButtonStyle.resolve( - style?.attachFileButtonStyle, - defaultStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.attachFile), - ), - cameraButtonStyle: ActionButtonStyle.resolve( - style?.cameraButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.camera), - ), - stopButtonStyle: ActionButtonStyle.resolve( - style?.stopButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.stop), - ), - closeButtonStyle: ActionButtonStyle.resolve( - style?.closeButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.close), - ), - copyButtonStyle: ActionButtonStyle.resolve( - style?.copyButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.copy), - ), - editButtonStyle: ActionButtonStyle.resolve( - style?.editButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.edit), - ), - galleryButtonStyle: ActionButtonStyle.resolve( - style?.galleryButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.gallery), - ), - recordButtonStyle: ActionButtonStyle.resolve( - style?.recordButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.record), - ), - submitButtonStyle: ActionButtonStyle.resolve( - style?.submitButtonStyle, - defaultStyle: ActionButtonStyle.defaultStyle(ActionButtonType.submit), - ), - closeMenuButtonStyle: ActionButtonStyle.resolve( - style?.closeMenuButtonStyle, - defaultStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.closeMenu), - ), - actionButtonBarDecoration: style?.actionButtonBarDecoration ?? - defaultStyle.actionButtonBarDecoration, - suggestionStyle: SuggestionStyle.resolve( - style?.suggestionStyle, - defaultStyle: defaultStyle.suggestionStyle, - ), - ); - } - - /// Provides default style if none is specified. - factory LlmChatViewStyle.defaultStyle() => LlmChatViewStyle.lightStyle(); - - /// Provides a default dark style. - factory LlmChatViewStyle.darkStyle() { - final style = LlmChatViewStyle.lightStyle(); - return LlmChatViewStyle( - backgroundColor: sh.invertColor(style.backgroundColor), - progressIndicatorColor: sh.invertColor(style.progressIndicatorColor), - userMessageStyle: UserMessageStyle.darkStyle(), - llmMessageStyle: LlmMessageStyle.darkStyle(), - chatInputStyle: ChatInputStyle.darkStyle(), - addButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.add), - attachFileButtonStyle: - ActionButtonStyle.darkStyle(ActionButtonType.attachFile), - cameraButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.camera), - stopButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.stop), - recordButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.record), - submitButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.submit), - closeMenuButtonStyle: - ActionButtonStyle.darkStyle(ActionButtonType.closeMenu), - actionButtonBarDecoration: - sh.invertDecoration(style.actionButtonBarDecoration), - fileAttachmentStyle: FileAttachmentStyle.darkStyle(), - suggestionStyle: SuggestionStyle.darkStyle(), - closeButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.close), - copyButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.copy), - editButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.edit), - galleryButtonStyle: ActionButtonStyle.darkStyle(ActionButtonType.gallery), - ); - } - - /// Provides a default light style. - factory LlmChatViewStyle.lightStyle() => LlmChatViewStyle( - backgroundColor: FatColors.containerBackground, - progressIndicatorColor: FatColors.black, - userMessageStyle: UserMessageStyle.defaultStyle(), - llmMessageStyle: LlmMessageStyle.defaultStyle(), - chatInputStyle: ChatInputStyle.defaultStyle(), - addButtonStyle: ActionButtonStyle.defaultStyle(ActionButtonType.add), - stopButtonStyle: ActionButtonStyle.defaultStyle(ActionButtonType.stop), - recordButtonStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.record), - submitButtonStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.submit), - closeMenuButtonStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.closeMenu), - attachFileButtonStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.attachFile), - galleryButtonStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.gallery), - cameraButtonStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.camera), - closeButtonStyle: - ActionButtonStyle.defaultStyle(ActionButtonType.close), - copyButtonStyle: ActionButtonStyle.defaultStyle(ActionButtonType.copy), - editButtonStyle: ActionButtonStyle.defaultStyle(ActionButtonType.edit), - actionButtonBarDecoration: BoxDecoration( - color: FatColors.darkButtonBackground, - borderRadius: BorderRadius.circular(20), - ), - fileAttachmentStyle: FileAttachmentStyle.defaultStyle(), - suggestionStyle: SuggestionStyle.defaultStyle(), - ); - - /// Background color of the entire chat widget. - final Color? backgroundColor; - - /// The color of the progress indicator. - final Color? progressIndicatorColor; - - /// Style for user messages. - final UserMessageStyle? userMessageStyle; - - /// Style for LLM messages. - final LlmMessageStyle? llmMessageStyle; - - /// Style for the input text box. - final ChatInputStyle? chatInputStyle; - - /// Style for the add button. - final ActionButtonStyle? addButtonStyle; - - /// Style for the attach file button. - final ActionButtonStyle? attachFileButtonStyle; - - /// Style for the camera button. - final ActionButtonStyle? cameraButtonStyle; - - /// Style for the stop button. - final ActionButtonStyle? stopButtonStyle; - - /// Style for the close button. - final ActionButtonStyle? closeButtonStyle; - - /// Style for the copy button. - final ActionButtonStyle? copyButtonStyle; - - /// Style for the edit button. - final ActionButtonStyle? editButtonStyle; - - /// Style for the gallery button. - final ActionButtonStyle? galleryButtonStyle; - - /// Style for the record button. - final ActionButtonStyle? recordButtonStyle; - - /// Style for the submit button. - final ActionButtonStyle? submitButtonStyle; - - /// Style for the close menu button. - final ActionButtonStyle? closeMenuButtonStyle; - - /// Decoration for the action button bar. - final Decoration? actionButtonBarDecoration; - - /// Style for file attachments. - final FileAttachmentStyle? fileAttachmentStyle; - - /// Style for suggestions. - final SuggestionStyle? suggestionStyle; -} diff --git a/lib/src/styles/llm_message_style.dart b/lib/src/styles/llm_message_style.dart deleted file mode 100644 index 0c750d3..0000000 --- a/lib/src/styles/llm_message_style.dart +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; - -import 'fat_colors.dart'; -import 'fat_icons.dart'; -import 'fat_text_styles.dart'; -import 'style_helpers.dart' as sh; - -/// Style for LLM messages. -@immutable -class LlmMessageStyle { - /// Creates an LlmMessageStyle. - const LlmMessageStyle({ - this.icon, - this.iconColor, - this.iconDecoration, - this.decoration, - this.markdownStyle, - }); - - /// Resolves the provided style with the default style. - /// - /// This method creates a new [LlmMessageStyle] by combining the provided - /// [style] with the [defaultStyle]. If a property is not specified in the - /// provided [style], it falls back to the corresponding property in the - /// [defaultStyle]. - /// - /// If [defaultStyle] is not provided, it uses [LlmMessageStyle.defaultStyle]. - /// - /// Parameters: - /// - [style]: The custom style to apply. Can be null. - /// - [defaultStyle]: The default style to use as a fallback. If null, uses - /// [LlmMessageStyle.defaultStyle]. - /// - /// Returns: A new [LlmMessageStyle] instance with resolved properties. - factory LlmMessageStyle.resolve( - LlmMessageStyle? style, { - LlmMessageStyle? defaultStyle, - }) { - defaultStyle ??= LlmMessageStyle.defaultStyle(); - return LlmMessageStyle( - icon: style?.icon ?? defaultStyle.icon, - iconColor: style?.iconColor ?? defaultStyle.iconColor, - iconDecoration: style?.iconDecoration ?? defaultStyle.iconDecoration, - markdownStyle: style?.markdownStyle ?? defaultStyle.markdownStyle, - decoration: style?.decoration ?? defaultStyle.decoration, - ); - } - - /// Provides a default style. - factory LlmMessageStyle.defaultStyle() => LlmMessageStyle.lightStyle(); - - /// Provides a default dark style. - factory LlmMessageStyle.darkStyle() { - final style = LlmMessageStyle.lightStyle(); - return LlmMessageStyle( - icon: style.icon, - iconColor: sh.invertColor(style.iconColor), - // inversion doesn't look great here - // iconDecoration: sh.invertDecoration(style.iconDecoration), - iconDecoration: const BoxDecoration( - color: FatColors.greyBackground, - shape: BoxShape.circle, - ), - markdownStyle: _invertMarkdownStyle(style.markdownStyle), - decoration: sh.invertDecoration(style.decoration), - ); - } - - /// Provides a default light style. - factory LlmMessageStyle.lightStyle() => LlmMessageStyle( - icon: FatIcons.spark_icon, - iconColor: FatColors.darkIcon, - iconDecoration: const BoxDecoration( - color: FatColors.llmIconBackground, - shape: BoxShape.circle, - ), - markdownStyle: MarkdownStyleSheet( - a: FatTextStyles.body1, - blockquote: FatTextStyles.body1, - checkbox: FatTextStyles.body1, - code: FatTextStyles.code, - del: FatTextStyles.body1, - em: FatTextStyles.body1.copyWith(fontStyle: FontStyle.italic), - h1: FatTextStyles.heading1, - h2: FatTextStyles.heading2, - h3: FatTextStyles.body1.copyWith(fontWeight: FontWeight.bold), - h4: FatTextStyles.body1, - h5: FatTextStyles.body1, - h6: FatTextStyles.body1, - listBullet: FatTextStyles.body1, - img: FatTextStyles.body1, - strong: FatTextStyles.body1.copyWith(fontWeight: FontWeight.bold), - p: FatTextStyles.body1, - tableBody: FatTextStyles.body1, - tableHead: FatTextStyles.body1, - ), - decoration: BoxDecoration( - color: FatColors.llmMessageBackground, - border: Border.all( - color: FatColors.llmMessageOutline, - ), - borderRadius: const BorderRadius.only( - topLeft: Radius.zero, - topRight: Radius.circular(20), - bottomLeft: Radius.circular(20), - bottomRight: Radius.circular(20), - ), - ), - ); - - /// The icon to display for the LLM messages. - final IconData? icon; - - /// The color of the icon. - final Color? iconColor; - - /// The decoration for the icon. - final Decoration? iconDecoration; - - /// The decoration for LLM message bubbles. - final Decoration? decoration; - - /// The markdown style sheet for LLM messages. - final MarkdownStyleSheet? markdownStyle; - - static MarkdownStyleSheet? _invertMarkdownStyle( - MarkdownStyleSheet? markdownStyle, - ) => - markdownStyle?.copyWith( - a: sh.invertTextStyle(markdownStyle.a), - blockquote: sh.invertTextStyle(markdownStyle.blockquote), - checkbox: sh.invertTextStyle(markdownStyle.checkbox), - code: sh.invertTextStyle(markdownStyle.code), - del: sh.invertTextStyle(markdownStyle.del), - em: sh.invertTextStyle(markdownStyle.em), - strong: sh.invertTextStyle(markdownStyle.strong), - p: sh.invertTextStyle(markdownStyle.p), - tableBody: sh.invertTextStyle(markdownStyle.tableBody), - tableHead: sh.invertTextStyle(markdownStyle.tableHead), - h1: sh.invertTextStyle(markdownStyle.h1), - h2: sh.invertTextStyle(markdownStyle.h2), - h3: sh.invertTextStyle(markdownStyle.h3), - h4: sh.invertTextStyle(markdownStyle.h4), - h5: sh.invertTextStyle(markdownStyle.h5), - h6: sh.invertTextStyle(markdownStyle.h6), - listBullet: sh.invertTextStyle(markdownStyle.listBullet), - img: sh.invertTextStyle(markdownStyle.img), - ); -} diff --git a/lib/src/styles/style_helpers.dart b/lib/src/styles/style_helpers.dart deleted file mode 100644 index 0449dc2..0000000 --- a/lib/src/styles/style_helpers.dart +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -/// Inverts the color. -Color invertColor(Color? color) => Color.fromARGB( - color!.alpha, - 255 - color.red, - 255 - color.green, - 255 - color.blue, - ); - -/// Inverts the color of a [Decoration] if it's a [BoxDecoration] or -/// [ShapeDecoration]. -/// -/// This function takes a [Decoration] and attempts to invert its color: -/// - For [BoxDecoration], it creates a new instance with the inverted color. -/// - For [ShapeDecoration], it creates a new instance with the inverted color -/// while preserving other properties. -/// - For other types of decorations, it returns the original decoration -/// unchanged. -/// -/// Parameters: -/// * [decoration]: The [Decoration] to invert. Can be null. -/// -/// Returns: A new [Decoration] with inverted color if applicable, or the -/// original decoration. Returns null if the input is null. -Decoration invertDecoration(Decoration? decoration) => switch (decoration!) { - final BoxDecoration d => d.copyWith(color: invertColor(d.color)), - final ShapeDecoration d => ShapeDecoration( - color: invertColor(d.color), - shape: d.shape, - shadows: d.shadows, - image: d.image, - gradient: d.gradient, - ), - _ => decoration, - }; - -/// Inverts the color of a [TextStyle]. -/// -/// This function takes a [TextStyle] and creates a new instance with the -/// inverted color. If the input style is null, it returns null. -/// -/// Parameters: -/// * [style]: The [TextStyle] to invert. Can be null. -/// -/// Returns: A new [TextStyle] with inverted color if the input is not null, -/// otherwise null. -TextStyle invertTextStyle(TextStyle? style) => - style!.copyWith(color: invertColor(style.color)); diff --git a/lib/src/styles/styles.dart b/lib/src/styles/styles.dart deleted file mode 100644 index f6e9de2..0000000 --- a/lib/src/styles/styles.dart +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -export 'action_button_style.dart'; -export 'chat_input_style.dart'; -export 'file_attachment_style.dart'; -export 'llm_chat_view_style.dart'; -export 'llm_message_style.dart'; -export 'user_message_style.dart'; diff --git a/lib/src/styles/suggestion_style.dart b/lib/src/styles/suggestion_style.dart deleted file mode 100644 index 26f3312..0000000 --- a/lib/src/styles/suggestion_style.dart +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; - -import 'fat_colors.dart'; -import 'fat_text_styles.dart'; -import 'style_helpers.dart' as sh; - -@immutable - -/// A class that defines the style for suggestions. -class SuggestionStyle { - /// Creates a [SuggestionStyle]. - /// - /// The [textStyle] and [decoration] parameters can be used to customize - /// the appearance of the suggestion. - const SuggestionStyle({ - this.textStyle, - this.decoration, - }); - - /// Resolves the [SuggestionStyle] by merging the provided [style] with the - /// [defaultStyle]. - /// - /// If [style] is null, the [defaultStyle] is used. If [defaultStyle] is not - /// provided, the [defaultStyle] is obtained from - /// [SuggestionStyle.defaultStyle]. - factory SuggestionStyle.resolve( - SuggestionStyle? style, { - SuggestionStyle? defaultStyle, - }) { - defaultStyle ??= SuggestionStyle.defaultStyle(); - return SuggestionStyle( - textStyle: style?.textStyle ?? defaultStyle.textStyle, - decoration: style?.decoration ?? defaultStyle.decoration, - ); - } - - /// Provides a default style. - /// - /// This style is typically used as the base style for suggestions. - factory SuggestionStyle.defaultStyle() => SuggestionStyle.lightStyle(); - - /// Provides a default dark style. - /// - /// This style is typically used for suggestions in dark mode. - factory SuggestionStyle.darkStyle() { - final style = SuggestionStyle.lightStyle(); - return SuggestionStyle( - textStyle: sh.invertTextStyle(style.textStyle), - decoration: const BoxDecoration( - color: FatColors.greyBackground, - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - ); - } - - /// Provides a default light style. - /// - /// This style is typically used for suggestions in light mode. - factory SuggestionStyle.lightStyle() => SuggestionStyle( - textStyle: FatTextStyles.body1, - decoration: const BoxDecoration( - color: FatColors.userMessageBackground, - borderRadius: BorderRadius.all(Radius.circular(8)), - ), - ); - - /// The text style for the suggestion. - final TextStyle? textStyle; - - /// The decoration for the suggestion. - final Decoration? decoration; -} diff --git a/lib/src/styles/user_message_style.dart b/lib/src/styles/user_message_style.dart deleted file mode 100644 index cf879ea..0000000 --- a/lib/src/styles/user_message_style.dart +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import 'fat_colors.dart'; -import 'fat_text_styles.dart'; -import 'style_helpers.dart' as sh; - -/// Style for user messages. -@immutable -class UserMessageStyle { - /// Creates a UserMessageStyle. - const UserMessageStyle({ - this.textStyle, - this.decoration, - }); - - /// Resolves the UserMessageStyle by combining the provided style with default - /// values. - /// - /// This method takes an optional [style] and merges it with the - /// [defaultStyle]. If [defaultStyle] is not provided, it uses - /// [UserMessageStyle.defaultStyle]. - /// - /// [style] - The custom UserMessageStyle to apply. Can be null. - /// [defaultStyle] - The default UserMessageStyle to use as a base. If null, - /// uses [UserMessageStyle.defaultStyle]. - /// - /// Returns a new [UserMessageStyle] instance with resolved properties. - factory UserMessageStyle.resolve( - UserMessageStyle? style, { - UserMessageStyle? defaultStyle, - }) { - defaultStyle ??= UserMessageStyle.defaultStyle(); - return UserMessageStyle( - textStyle: style?.textStyle ?? defaultStyle.textStyle, - decoration: style?.decoration ?? defaultStyle.decoration, - ); - } - - /// Provides a default dark style. - factory UserMessageStyle.darkStyle() { - final style = UserMessageStyle.lightStyle(); - return UserMessageStyle( - textStyle: sh.invertTextStyle(style.textStyle), - // inversion doesn't look great here - // decoration: sh.invertDecoration(style.decoration), - decoration: (style.decoration! as BoxDecoration).copyWith( - color: FatColors.greyBackground, - ), - ); - } - - /// Provides default style data for user messages. - factory UserMessageStyle.defaultStyle() => UserMessageStyle.lightStyle(); - - /// Provides a default light style. - factory UserMessageStyle.lightStyle() => UserMessageStyle( - textStyle: FatTextStyles.body1, - decoration: const BoxDecoration( - color: FatColors.userMessageBackground, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.zero, - bottomLeft: Radius.circular(20), - bottomRight: Radius.circular(20), - ), - ), - ); - - /// The text style for user messages. - final TextStyle? textStyle; - - /// The decoration for user message bubbles. - final Decoration? decoration; -} diff --git a/lib/src/utility.dart b/lib/src/utility.dart deleted file mode 100644 index 4bbaa9b..0000000 --- a/lib/src/utility.dart +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart'; -import 'package:universal_platform/universal_platform.dart'; - -bool? _isCupertinoApp; - -/// Determines if the current application is a Cupertino-style app. -/// -/// This function checks the widget tree for the presence of a [CupertinoApp] -/// widget. If found, it indicates that the app is using Cupertino (iOS-style) -/// widgets. -/// -/// Parameters: -/// * [context]: The [BuildContext] used to search the widget tree. -/// -/// Returns: A [bool] value. `true` if a [CupertinoApp] is found in the widget -/// tree, `false` otherwise. -bool isCupertinoApp(BuildContext context) { - // caching the result to avoid recomputing it on every call; it's not likely - // to change during the lifetime of the app - _isCupertinoApp ??= - context.findAncestorWidgetOfExactType() != null; - return _isCupertinoApp!; -} - -/// Determines if the current platform is a mobile device (Android or iOS). -/// -/// This constant uses the [UniversalPlatform] package to check the platform. -/// -/// Returns: -/// A [bool] value. `true` if the platform is either Android or iOS, -/// `false` otherwise. -final isMobile = UniversalPlatform.isAndroid || UniversalPlatform.isIOS; diff --git a/lib/src/views/action_button/action_button.dart b/lib/src/views/action_button/action_button.dart deleted file mode 100644 index 2f8802b..0000000 --- a/lib/src/views/action_button/action_button.dart +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart' show Tooltip; -import 'package:flutter/widgets.dart'; - -import '../../styles/action_button_style.dart'; -import '../../utility.dart'; - -/// A button widget with an icon. -/// -/// This widget creates a button with a customizable icon, size, decoration, and -/// color. It can be enabled or disabled based on the presence of an [onPressed] -/// callback. -@immutable -class ActionButton extends StatelessWidget { - /// Creates an [ActionButton]. - /// - /// The [onPressed] and [style] parameters must not be null. - /// The [size] parameter defaults to 40 if not provided. - const ActionButton({ - required this.onPressed, - required this.style, - super.key, - this.size = 40, - }); - - /// The callback that is called when the button is tapped. - /// If null, the button will be disabled. - final VoidCallback onPressed; - - /// The style of the button. - final ActionButtonStyle style; - - /// The diameter of the circular button. - final double size; - - @override - Widget build(BuildContext context) => GestureDetector( - onTap: onPressed, - child: Container( - width: size, - height: size, - decoration: style.iconDecoration, - // tooltips aren't a thing in cupertino, so skip it - child: isCupertinoApp(context) - ? Icon( - style.icon, - color: style.iconColor, - size: size * 0.6, - ) - : Tooltip( - message: style.tooltip, - textStyle: style.tooltipTextStyle, - decoration: style.tooltipDecoration, - child: Icon( - style.icon, - color: style.iconColor, - size: size * 0.6, - ), - ), - ), - ); -} diff --git a/lib/src/views/action_button/action_button_bar.dart b/lib/src/views/action_button/action_button_bar.dart deleted file mode 100644 index 1940096..0000000 --- a/lib/src/views/action_button/action_button_bar.dart +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import '../../styles/styles.dart'; -import 'action_button.dart'; - -/// A widget that displays a horizontal bar of [ActionButton]s. -/// -/// This widget creates a container with rounded corners that houses a series of -/// [ActionButton]s. The buttons are laid out horizontally and can overflow if -/// there's not enough space. -@immutable -class ActionButtonBar extends StatelessWidget { - /// Creates a [ActionButtonBar]. - /// - /// The [buttons] parameter is required and specifies the list of - /// [ActionButton]s to be displayed in the bar. - const ActionButtonBar( - this.buttons, { - required this.style, - super.key, - }); - - /// The list of [ActionButton]s to be displayed in the bar. - final List buttons; - - /// The style of the action button bar. - final LlmChatViewStyle style; - - @override - Widget build(BuildContext context) => DecoratedBox( - decoration: style.actionButtonBarDecoration!, - child: OverflowBar( - children: buttons, - ), - ); -} diff --git a/lib/src/views/adaptive_progress_indicator.dart b/lib/src/views/adaptive_progress_indicator.dart deleted file mode 100644 index 11b32ee..0000000 --- a/lib/src/views/adaptive_progress_indicator.dart +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import '../utility.dart'; - -/// A progress indicator that adapts to the current platform. -/// -@immutable -class AdaptiveCircularProgressIndicator extends StatelessWidget { - /// Creates an adaptive circular progress indicator. - /// - /// This widget will display a [CupertinoActivityIndicator] on iOS - /// and a [CircularProgressIndicator] on other platforms. - /// - /// The [key] parameter is optional and is used to control how one widget - /// replaces another widget in the tree. - const AdaptiveCircularProgressIndicator({required this.color, super.key}); - - /// The color of the progress indicator. - final Color color; - - @override - Widget build(BuildContext context) => isCupertinoApp(context) - ? CupertinoActivityIndicator(color: color) - : CircularProgressIndicator(color: color); -} diff --git a/lib/src/views/attachment_view/attachment_view.dart b/lib/src/views/attachment_view/attachment_view.dart deleted file mode 100644 index fa4fbe1..0000000 --- a/lib/src/views/attachment_view/attachment_view.dart +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import '../../providers/interface/attachments.dart'; -import 'file_attatchment_view.dart'; -import 'image_attachment_view.dart'; - -/// A widget that displays an attachment based on its type. -/// -/// This widget determines the appropriate view for the given [attachment] -/// and renders it accordingly. It supports file attachments and image -/// attachments, but throws an exception for link attachments. -@immutable -class AttachmentView extends StatelessWidget { - /// Creates an AttachmentView. - /// - /// The [attachment] parameter must not be null. - const AttachmentView(this.attachment, {super.key}); - - /// The attachment to be displayed. - final Attachment attachment; - - /// The style for the attachment view. - - @override - Widget build(BuildContext context) => switch (attachment) { - (final ImageFileAttachment a) => ImageAttachmentView(a), - (final FileAttachment a) => FileAttachmentView(a), - (LinkAttachment _) => throw Exception('Link attachments not supported'), - }; -} diff --git a/lib/src/views/attachment_view/file_attatchment_view.dart b/lib/src/views/attachment_view/file_attatchment_view.dart deleted file mode 100644 index 3423250..0000000 --- a/lib/src/views/attachment_view/file_attatchment_view.dart +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; -import 'package:gap/gap.dart'; - -import '../../chat_view_model/chat_view_model_client.dart'; -import '../../providers/interface/attachments.dart'; -import '../../styles/file_attachment_style.dart'; - -/// A widget that displays a file attachment. -/// -/// This widget creates a container with a file icon and information about the -/// attached file, such as its name and MIME type. -@immutable -class FileAttachmentView extends StatelessWidget { - /// Creates a FileAttachmentView. - /// - /// The [attachment] parameter must not be null and represents the - /// file attachment to be displayed. - const FileAttachmentView(this.attachment, {super.key}); - - /// The file attachment to be displayed. - final FileAttachment attachment; - - @override - Widget build(BuildContext context) => ChatViewModelClient( - builder: (context, viewModel, child) { - final attachmentStyle = FileAttachmentStyle.resolve( - viewModel.style?.fileAttachmentStyle, - ); - - return Container( - height: 80, - padding: const EdgeInsets.all(8), - decoration: attachmentStyle.decoration, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - height: 64, - padding: const EdgeInsets.all(10), - decoration: attachmentStyle.iconDecoration, - child: Icon( - attachmentStyle.icon, - color: attachmentStyle.iconColor, - size: 24, - ), - ), - const Gap(8), - Flexible( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - attachment.name, - style: attachmentStyle.filenameStyle, - overflow: TextOverflow.ellipsis, - ), - Text( - attachment.mimeType, - style: attachmentStyle.filetypeStyle, - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - ], - ), - ); - }, - ); -} diff --git a/lib/src/views/attachment_view/image_attachment_view.dart b/lib/src/views/attachment_view/image_attachment_view.dart deleted file mode 100644 index d755948..0000000 --- a/lib/src/views/attachment_view/image_attachment_view.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; - -import 'package:flutter/widgets.dart'; - -import '../../dialogs/adaptive_dialog.dart'; -import '../../dialogs/image_preview_dialog.dart'; -import '../../providers/interface/attachments.dart'; - -/// A widget that displays an image attachment. -/// -/// This widget aligns the image to the center-right of its parent and -/// allows the user to tap on the image to open a preview dialog. -@immutable -class ImageAttachmentView extends StatelessWidget { - /// Creates an ImageAttachmentView. - /// - /// The [attachment] parameter must not be null and represents the - /// image file attachment to be displayed. - const ImageAttachmentView(this.attachment, {super.key}); - - /// The image file attachment to be displayed. - final ImageFileAttachment attachment; - - @override - Widget build(BuildContext context) => Align( - alignment: Alignment.centerRight, - child: GestureDetector( - onTap: () => unawaited(_showPreviewDialog(context)), - child: Image.memory(attachment.bytes)), - ); - - Future _showPreviewDialog(BuildContext context) async => - AdaptiveAlertDialog.show( - context: context, - barrierDismissible: true, - content: ImagePreviewDialog(attachment), - ); -} diff --git a/lib/src/views/chat_history_view.dart b/lib/src/views/chat_history_view.dart deleted file mode 100644 index 45ddcec..0000000 --- a/lib/src/views/chat_history_view.dart +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import '../chat_view_model/chat_view_model_client.dart'; -import '../providers/interface/chat_message.dart'; -import 'chat_message_view/llm_message_view.dart'; -import 'chat_message_view/user_message_view.dart'; - -/// A widget that displays a history of chat messages. -/// -/// This widget renders a scrollable list of chat messages, supporting -/// selection and editing of messages. It displays messages in reverse -/// chronological order (newest at the bottom). -@immutable -class ChatHistoryView extends StatefulWidget { - /// Creates a [ChatHistoryView]. - /// - /// If [onEditMessage] is provided, it will be called when a user initiates an - /// edit action on an editable message (typically the last user message in the - /// history). - const ChatHistoryView({ - this.onEditMessage, - super.key, - }); - - /// Optional callback function for editing a message. - /// - /// If provided, this function will be called when a user initiates an edit - /// action on an editable message (typically the last user message in the - /// history). The function receives the [ChatMessage] to be edited as its - /// parameter. - final void Function(ChatMessage message)? onEditMessage; - - @override - State createState() => _ChatHistoryViewState(); -} - -class _ChatHistoryViewState extends State { - @override - Widget build(BuildContext context) => Padding( - padding: const EdgeInsets.all(16), - child: ChatViewModelClient( - builder: (context, viewModel, child) => ListenableBuilder( - listenable: viewModel.controller, - builder: (context, child) { - final history = viewModel.controller.history.toList(); - return ListView.builder( - reverse: true, - itemCount: history.length, - itemBuilder: (context, index) { - final messageIndex = history.length - index - 1; - final message = history[messageIndex]; - final isLastUserMessage = message.origin.isUser && - messageIndex >= history.length - 2; - final canEdit = - isLastUserMessage && widget.onEditMessage != null; - final isUser = message.origin.isUser; - - return Padding( - padding: const EdgeInsets.only(top: 6), - child: isUser - ? UserMessageView( - message, - onEdit: canEdit - ? () => widget.onEditMessage?.call(message) - : null, - ) - : LlmMessageView(message), - ); - }, - ); - }, - ), - ), - ); -} diff --git a/lib/src/views/chat_input/attachments_action_bar.dart b/lib/src/views/chat_input/attachments_action_bar.dart deleted file mode 100644 index eddc59d..0000000 --- a/lib/src/views/chat_input/attachments_action_bar.dart +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; - -import 'package:file_selector/file_selector.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; -import 'package:image_picker/image_picker.dart'; - -import '../../chat_view_model/chat_view_model_client.dart'; -import '../../dialogs/adaptive_snack_bar/adaptive_snack_bar.dart'; -import '../../providers/interface/attachments.dart'; -import '../../styles/llm_chat_view_style.dart'; -import '../action_button/action_button.dart'; -import '../action_button/action_button_bar.dart'; - -/// A widget that provides an action bar for attaching files or images. -@immutable -class AttachmentActionBar extends StatefulWidget { - /// Creates an [AttachmentActionBar]. - /// - /// The [onAttachments] parameter is required and is called when attachments - /// are selected. - const AttachmentActionBar({required this.onAttachments, super.key}); - - /// Callback function that is called when attachments are selected. - /// - /// The selected [Attachment]s are passed as an argument to this function. - final Function(Iterable attachments) onAttachments; - - @override - State createState() => _AttachmentActionBarState(); -} - -class _AttachmentActionBarState extends State { - var _expanded = false; - late final bool _canCamera; - late final bool _canFile; - - @override - void initState() { - super.initState(); - _canCamera = ImagePicker().supportsImageSource(ImageSource.camera); - - // _canFile is a temporary work around for this bug: - // https://github.com/csells/flutter_ai_toolkit/issues/18 - _canFile = !kIsWeb; - } - - @override - Widget build(BuildContext context) => ChatViewModelClient( - builder: (context, viewModel, child) { - final chatStyle = LlmChatViewStyle.resolve(viewModel.style); - return _expanded - ? ActionButtonBar(style: chatStyle, [ - ActionButton( - onPressed: _onToggleMenu, - style: chatStyle.closeMenuButtonStyle!, - ), - if (_canCamera) - ActionButton( - onPressed: _onCamera, - style: chatStyle.cameraButtonStyle!, - ), - ActionButton( - onPressed: _onGallery, - style: chatStyle.galleryButtonStyle!, - ), - if (_canFile) - ActionButton( - onPressed: _onFile, - style: chatStyle.attachFileButtonStyle!, - ), - ]) - : ActionButton( - onPressed: _onToggleMenu, - style: chatStyle.addButtonStyle!, - ); - }, - ); - - void _onToggleMenu() => setState(() => _expanded = !_expanded); - void _onCamera() => unawaited(_pickImage(ImageSource.camera)); - void _onGallery() => unawaited(_pickImage(ImageSource.gallery)); - - Future _pickImage(ImageSource source) async { - _onToggleMenu(); // close the menu - - final picker = ImagePicker(); - try { - if (source == ImageSource.gallery) { - final pics = await picker.pickMultiImage(); - final attachments = await Future.wait(pics.map( - ImageFileAttachment.fromFile, - )); - widget.onAttachments(attachments); - } else { - final pic = await picker.pickImage(source: source); - if (pic == null) return; - widget.onAttachments([await ImageFileAttachment.fromFile(pic)]); - } - } on Exception catch (ex) { - if (context.mounted) { - // I just checked this! ^^^ - // ignore: use_build_context_synchronously - AdaptiveSnackBar.show(context, 'Unable to pick an image: $ex'); - } - } - } - - Future _onFile() async { - _onToggleMenu(); // close the menu - - try { - final files = await openFiles(); - final attachments = await Future.wait(files.map(FileAttachment.fromFile)); - widget.onAttachments(attachments); - } on Exception catch (ex) { - if (context.mounted) { - // I just checked this! ^^^ - // ignore: use_build_context_synchronously - AdaptiveSnackBar.show(context, 'Unable to pick a file: $ex'); - } - } - } -} diff --git a/lib/src/views/chat_input/attachments_view.dart b/lib/src/views/chat_input/attachments_view.dart deleted file mode 100644 index 58bf60d..0000000 --- a/lib/src/views/chat_input/attachments_view.dart +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import '../../providers/interface/attachments.dart'; -import 'removable_attachment.dart'; - -/// A widget that displays a horizontal list of attachments with the ability to -/// remove them. -@immutable -class AttachmentsView extends StatelessWidget { - /// Creates an [AttachmentsView]. - /// - /// The [attachments] parameter is required and represents the list of - /// attachments to display. The [onRemove] parameter is a callback function - /// that is called when an attachment is removed. - const AttachmentsView({ - required this.attachments, - required this.onRemove, - super.key, - }); - - /// The list of attachments to display. - final Iterable attachments; - - /// Callback function that is called when an attachment is removed. - /// - /// The removed [Attachment] is passed as an argument to this function. - final Function(Attachment) onRemove; - - @override - Widget build(BuildContext context) => Container( - height: attachments.isNotEmpty ? 104 : 0, - padding: const EdgeInsets.only(top: 12, bottom: 12, left: 12), - child: attachments.isNotEmpty - ? ListView( - scrollDirection: Axis.horizontal, - children: [ - for (final a in attachments) - RemovableAttachment(attachment: a, onRemove: onRemove), - ], - ) - : const SizedBox(), - ); -} diff --git a/lib/src/views/chat_input/chat_input.dart b/lib/src/views/chat_input/chat_input.dart deleted file mode 100644 index 5c2fd73..0000000 --- a/lib/src/views/chat_input/chat_input.dart +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:file_selector/file_selector.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; -import 'package:gap/gap.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:waveform_recorder/waveform_recorder.dart'; - -import '../../chat_view_model/chat_view_model_client.dart'; -import '../../dialogs/adaptive_snack_bar/adaptive_snack_bar.dart'; -import '../../providers/interface/attachments.dart'; -import '../../providers/interface/chat_message.dart'; -import '../../styles/chat_input_style.dart'; -import '../../styles/llm_chat_view_style.dart'; -import '../../utility.dart'; -import '../chat_text_field.dart'; -import 'attachments_action_bar.dart'; -import 'attachments_view.dart'; -import 'input_button.dart'; -import 'input_state.dart'; - -/// A widget that provides a chat input interface with support for text input, -/// speech-to-text, and attachments. -@immutable -class ChatInput extends StatefulWidget { - /// Creates a [ChatInput] widget. - /// - /// The [onSendMessage] and [onTranslateStt] parameters are required. - /// - /// [initialMessage] can be provided to pre-populate the input field. - /// - /// [onCancelMessage] and [onCancelStt] are optional callbacks for cancelling - /// message submission or speech-to-text translation respectively. - const ChatInput({ - required this.onSendMessage, - required this.onTranslateStt, - this.initialMessage, - this.onCancelMessage, - this.onCancelStt, - super.key, - }) : assert( - !(onCancelMessage != null && onCancelStt != null), - 'Cannot be submitting a prompt and doing stt at the same time', - ); - - /// Callback function triggered when a message is sent. - /// - /// Takes a [String] for the message text and an [`Iterable`] for - /// any attachments. - final void Function(String, Iterable) onSendMessage; - - /// Callback function triggered when speech-to-text translation is requested. - /// - /// Takes an [XFile] representing the audio file to be translated. - final void Function(XFile file) onTranslateStt; - - /// Optional callback function to cancel an ongoing message submission. - final void Function()? onCancelMessage; - - /// Optional callback function to cancel an ongoing speech-to-text - /// translation. - final void Function()? onCancelStt; - - /// The initial message to populate the input field, if any. - final ChatMessage? initialMessage; - - @override - State createState() => _ChatInputState(); -} - -class _ChatInputState extends State { - // Notes on the way focus works in this widget: - // - we use a focus node to request focus when the input is submitted or - // cancelled - // - we leave the text field enabled so that it never artifically loses focus - // (you can't have focus on a disabled widget) - // - this means we're not taking back focus after a submission or a - // cancellation is complete from another widget in the app that might have - // it, e.g. if we attempted to take back focus in didUpdateWidget - // - this also means that we don't need any complicated logic to request focus - // in didUpdateWidget only the first time after a submission or cancellation - // that would be required to keep from stealing focus from other widgets in - // the app - // - also, if the user is submitting and they press Enter while inside the - // text field, we want to put the focus back in the text field but otherwise - // ignore the Enter key; it doesn't make sense for Enter to cancel - they - // can use the Cancel button for that. - // - the reason we need to request focus in the onSubmitted function of the - // TextField is because apparently it gives up focus as part of its - // implementation somehow (just how is something to discover) - // - the reason we need to request focus in the implementation of the - // separate submit/cancel button is because apparently clicking on another - // widget when the TextField is focused causes it to lose focus (which makes - // sense) - final _focusNode = FocusNode(); - - final _textController = TextEditingController(); - final _waveController = WaveformRecorderController(); - final _attachments = []; - static const _minInputHeight = 48.0; - - @override - void didUpdateWidget(covariant ChatInput oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.initialMessage != null) { - _textController.text = widget.initialMessage!.text ?? ''; - _attachments.clear(); - _attachments.addAll(widget.initialMessage!.attachments); - } - } - - @override - void dispose() { - _textController.dispose(); - _waveController.dispose(); - _focusNode.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) => ChatViewModelClient( - builder: (context, viewModel, child) { - final chatStyle = LlmChatViewStyle.resolve(viewModel.style); - final inputStyle = ChatInputStyle.resolve( - viewModel.style?.chatInputStyle, - ); - - return Container( - color: inputStyle.backgroundColor, - padding: const EdgeInsets.all(16), - child: Column( - children: [ - AttachmentsView( - attachments: _attachments, - onRemove: onRemoveAttachment, - ), - const Gap(6), - ValueListenableBuilder( - valueListenable: _textController, - builder: (context, value, child) => ListenableBuilder( - listenable: _waveController, - builder: (context, child) => Row( - children: [ - AttachmentActionBar(onAttachments: onAttachments), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), - child: DecoratedBox( - decoration: inputStyle.decoration!, - child: ConstrainedBox( - constraints: const BoxConstraints( - minHeight: _minInputHeight, - ), - child: _waveController.isRecording - ? WaveformRecorder( - controller: _waveController, - height: _minInputHeight, - onRecordingStopped: onRecordingStopped, - ) - : ChatTextField( - minLines: 1, - maxLines: 1024, - controller: _textController, - autofocus: true, - focusNode: _focusNode, - textInputAction: isMobile - ? TextInputAction.newline - : TextInputAction.done, - onSubmitted: _inputState == - InputState.canSubmitPrompt - ? (_) => onSubmitPrompt() - : (_) => _focusNode.requestFocus(), - style: inputStyle.textStyle!, - hintText: inputStyle.hintText!, - hintStyle: inputStyle.hintStyle!, - hintPadding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - ), - ), - ), - ), - ), - InputButton( - inputState: _inputState, - chatStyle: chatStyle, - onSubmitPrompt: onSubmitPrompt, - onCancelPrompt: onCancelPrompt, - onStartRecording: onStartRecording, - onStopRecording: onStopRecording, - ), - ], - ), - ), - ), - ], - ), - ); - }, - ); - - InputState get _inputState { - if (_waveController.isRecording) return InputState.isRecording; - if (widget.onCancelMessage != null) return InputState.canCancelPrompt; - if (widget.onCancelStt != null) return InputState.canCancelStt; - if (_textController.text.trim().isEmpty) return InputState.canStt; - return InputState.canSubmitPrompt; - } - - void onSubmitPrompt() { - assert(_inputState == InputState.canSubmitPrompt); - - // the mobile vkb can still cause a submission even if there is no text - final text = _textController.text.trim(); - if (text.isEmpty) return; - - widget.onSendMessage(text, List.from(_attachments)); - _attachments.clear(); - _textController.clear(); - _focusNode.requestFocus(); - } - - void onCancelPrompt() { - assert(_inputState == InputState.canCancelPrompt); - widget.onCancelMessage!(); - _focusNode.requestFocus(); - } - - Future onStartRecording() async { - await _waveController.startRecording(); - } - - Future onStopRecording() async { - await _waveController.stopRecording(); - } - - Future onRecordingStopped() async { - final file = _waveController.file; - - if (file == null) { - AdaptiveSnackBar.show(context, 'Unable to record audio'); - return; - } - - // will come back as initialMessage - widget.onTranslateStt(file); - } - - void onAttachments(Iterable attachments) => - setState(() => _attachments.addAll(attachments)); - - void onRemoveAttachment(Attachment attachment) => - setState(() => _attachments.remove(attachment)); -} diff --git a/lib/src/views/chat_input/chat_suggestion_view.dart b/lib/src/views/chat_input/chat_suggestion_view.dart deleted file mode 100644 index d45d5db..0000000 --- a/lib/src/views/chat_input/chat_suggestion_view.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:flutter/widgets.dart'; - -import '../../chat_view_model/chat_view_model_client.dart'; -import '../../styles/suggestion_style.dart'; - -/// A widget that displays a list of chat suggestions. -/// -/// This widget takes a list of suggestions and a callback function that is -/// triggered when a suggestion is selected. Each suggestion is displayed -/// as a tappable container with padding and a background color. -@immutable -class ChatSuggestionsView extends StatelessWidget { - /// Creates a [ChatSuggestionsView] widget. - /// - /// The [suggestions] parameter is a list of suggestion strings to display. - /// The [onSelectSuggestion] parameter is a callback function that is called - /// when a suggestion is tapped. - const ChatSuggestionsView({ - required this.suggestions, - required this.onSelectSuggestion, - super.key, - }); - - /// The list of suggestions to display. - final List suggestions; - - /// The callback function to call when a suggestion is selected. - final void Function(String suggestion) onSelectSuggestion; - - @override - Widget build(BuildContext context) => ChatViewModelClient( - builder: (context, viewModel, child) { - final suggestionStyle = SuggestionStyle.resolve( - viewModel.style?.suggestionStyle, - ); - return Wrap( - direction: Axis.vertical, - alignment: WrapAlignment.spaceEvenly, - children: [ - for (final suggestion in suggestions) - GestureDetector( - onTap: () => onSelectSuggestion(suggestion), - child: Padding( - padding: const EdgeInsets.all(8), - child: Container( - padding: const EdgeInsets.all(8), - decoration: suggestionStyle.decoration, - child: Wrap(children: [ - Text( - suggestion, - style: suggestionStyle.textStyle, - ) - ]), - ), - ), - ), - ], - ); - }, - ); -} diff --git a/lib/src/views/chat_input/input_button.dart b/lib/src/views/chat_input/input_button.dart deleted file mode 100644 index 8a3bfbf..0000000 --- a/lib/src/views/chat_input/input_button.dart +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -import '../../styles/llm_chat_view_style.dart'; -import '../action_button/action_button.dart'; -import '../adaptive_progress_indicator.dart'; -import 'input_state.dart'; - -/// A button widget that adapts its appearance and behavior based on the current -/// input state. -@immutable -class InputButton extends StatelessWidget { - /// Creates an [InputButton]. - /// - /// All parameters are required: - /// - [inputState]: The current state of the input. - /// - [chatStyle]: The style configuration for the chat interface. - /// - [onSubmitPrompt]: Callback function when submitting a prompt. - /// - [onCancelPrompt]: Callback function when cancelling a prompt. - /// - [onStartRecording]: Callback function when starting audio recording. - /// - [onStopRecording]: Callback function when stopping audio recording. - const InputButton({ - required this.inputState, - required this.chatStyle, - required this.onSubmitPrompt, - required this.onCancelPrompt, - required this.onStartRecording, - required this.onStopRecording, - super.key, - }); - - /// The current state of the input. - final InputState inputState; - - /// The style configuration for the chat interface. - final LlmChatViewStyle chatStyle; - - /// Callback function when submitting a prompt. - final void Function() onSubmitPrompt; - - /// Callback function when cancelling a prompt. - final void Function() onCancelPrompt; - - /// Callback function when starting audio recording. - final void Function() onStartRecording; - - /// Callback function when stopping audio recording. - final void Function() onStopRecording; - - @override - Widget build(BuildContext context) => switch (inputState) { - InputState.canSubmitPrompt => ActionButton( - style: chatStyle.submitButtonStyle!, - onPressed: onSubmitPrompt, - ), - InputState.canCancelPrompt => ActionButton( - style: chatStyle.stopButtonStyle!, - onPressed: onCancelPrompt, - ), - InputState.canStt => ActionButton( - style: chatStyle.recordButtonStyle!, - onPressed: onStartRecording, - ), - InputState.isRecording => ActionButton( - style: chatStyle.stopButtonStyle!, - onPressed: onStopRecording, - ), - InputState.canCancelStt => AdaptiveCircularProgressIndicator( - color: chatStyle.progressIndicatorColor!, - ), - }; -} diff --git a/lib/src/views/chat_input/input_state.dart b/lib/src/views/chat_input/input_state.dart deleted file mode 100644 index cdfab21..0000000 --- a/lib/src/views/chat_input/input_state.dart +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/// Represents the different states of the chat input. -enum InputState { - /// The input has text and the submit button is enabled. - canSubmitPrompt, - - /// A prompt is being submitted and the cancel button is enabled. - canCancelPrompt, - - /// The input is empty and the microphone button for speech-to-text is - /// enabled. - canStt, - - /// Speech is being recorded and the stop button is enabled. - isRecording, - - /// Speech is being translated to text and a progress indicator is shown. - canCancelStt, -} diff --git a/lib/src/views/chat_input/removable_attachment.dart b/lib/src/views/chat_input/removable_attachment.dart deleted file mode 100644 index fcea2d7..0000000 --- a/lib/src/views/chat_input/removable_attachment.dart +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; - -import 'package:flutter/widgets.dart'; - -import '../../chat_view_model/chat_view_model_client.dart'; -import '../../dialogs/adaptive_dialog.dart'; -import '../../dialogs/image_preview_dialog.dart'; -import '../../providers/interface/attachments.dart'; -import '../../styles/llm_chat_view_style.dart'; -import '../action_button/action_button.dart'; -import '../attachment_view/attachment_view.dart'; - -/// A widget that displays an attachment with a remove button. -@immutable -class RemovableAttachment extends StatelessWidget { - /// Creates a [RemovableAttachment]. - /// - /// The [attachment] parameter is required and represents the attachment to - /// display. The [onRemove] parameter is a callback function that is called - /// when the remove button is pressed. - const RemovableAttachment({ - required this.attachment, - required this.onRemove, - super.key, - }); - - /// The attachment to display. - final Attachment attachment; - - /// Callback function that is called when the remove button is pressed. - /// - /// The [Attachment] to be removed is passed as an argument to this function. - final Function(Attachment) onRemove; - - @override - Widget build(BuildContext context) => Stack( - children: [ - GestureDetector( - onTap: attachment is ImageFileAttachment - ? () => unawaited(_showPreviewDialog(context)) - : null, - child: Container( - padding: const EdgeInsets.only(right: 12), - height: 80, - child: AttachmentView(attachment), - ), - ), - Padding( - padding: const EdgeInsets.all(2), - child: ChatViewModelClient( - builder: (context, viewModel, child) { - final chatStyle = LlmChatViewStyle.resolve(viewModel.style); - return ActionButton( - style: chatStyle.closeButtonStyle!, - size: 20, - onPressed: () => onRemove(attachment), - ); - }, - ), - ), - ], - ); - - Future _showPreviewDialog(BuildContext context) async => - AdaptiveAlertDialog.show( - context: context, - barrierDismissible: true, - content: ImagePreviewDialog(attachment as ImageFileAttachment), - ); -} diff --git a/lib/src/views/chat_message_view/adaptive_copy_text.dart b/lib/src/views/chat_message_view/adaptive_copy_text.dart deleted file mode 100644 index a036f72..0000000 --- a/lib/src/views/chat_message_view/adaptive_copy_text.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart' - show DefaultMaterialLocalizations, SelectionArea; -import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart'; -import 'package:flutter_context_menu/flutter_context_menu.dart'; - -import '../../dialogs/adaptive_snack_bar/adaptive_snack_bar.dart'; -import '../../styles/llm_chat_view_style.dart'; -import '../../utility.dart'; - -/// A widget that displays text with adaptive copy functionality. -/// -/// This widget provides a context menu for copying text to the clipboard on -/// mobile devices, and a selection area for mouse-driven selection on desktop -/// and web platforms. -@immutable -class AdaptiveCopyText extends StatelessWidget { - /// Creates an [AdaptiveCopyText] widget. - /// - /// The [clipboardText] parameter is required and contains the text to be - /// copied to the clipboard. The [child] parameter is required and contains - /// the widget to be displayed. The [chatStyle] parameter is required and - /// contains the style information for the chat. The [onEdit] parameter is - /// optional and contains the callback to be invoked when the text is edited. - const AdaptiveCopyText({ - required this.clipboardText, - required this.child, - required this.chatStyle, - this.onEdit, - super.key, - }); - - /// The text to be copied to the clipboard. - final String clipboardText; - - /// The widget to be displayed. - final Widget child; - - /// The callback to be invoked when the text is edited. - final VoidCallback? onEdit; - - /// The style information for the chat. - final LlmChatViewStyle chatStyle; - - @override - Widget build(BuildContext context) { - final contextMenu = ContextMenu( - entries: [ - if (onEdit != null) - MenuItem( - label: 'Edit', - icon: chatStyle.editButtonStyle!.icon, - onSelected: onEdit, - ), - MenuItem( - label: 'Copy', - icon: chatStyle.copyButtonStyle!.icon, - onSelected: () => unawaited(_onCopy(context, clipboardText)), - ), - ], - ); - - // On mobile, show the context menu for long-press; - // on desktop and web, show the selection area for mouse-driven selection. - return isMobile - ? ContextMenuRegion(contextMenu: contextMenu, child: child) - : Localizations( - locale: Localizations.localeOf(context), - delegates: const [ - DefaultWidgetsLocalizations.delegate, - DefaultMaterialLocalizations.delegate, - ], - child: SelectionArea(child: child), - ); - } - - Future _onCopy(BuildContext context, String text) async { - await Clipboard.setData(ClipboardData(text: text)); - if (context.mounted) { - AdaptiveSnackBar.show(context, 'Message copied to clipboard'); - } - } -} diff --git a/lib/src/views/chat_message_view/llm_message_view.dart b/lib/src/views/chat_message_view/llm_message_view.dart deleted file mode 100644 index 350da11..0000000 --- a/lib/src/views/chat_message_view/llm_message_view.dart +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; -import 'package:flutter_markdown/flutter_markdown.dart'; - -import '../../chat_view_model/chat_view_model_client.dart'; -import '../../providers/interface/chat_message.dart'; -import '../../styles/llm_chat_view_style.dart'; -import '../../styles/llm_message_style.dart'; -import '../jumping_dots_progress_indicator/jumping_dots_progress_indicator.dart'; -import 'adaptive_copy_text.dart'; - -/// A widget that displays an LLM (Language Model) message in a chat interface. -@immutable -class LlmMessageView extends StatelessWidget { - /// Creates an [LlmMessageView]. - /// - /// The [message] parameter is required and represents the LLM chat message to - /// be displayed. - const LlmMessageView(this.message, {super.key}); - - /// The LLM chat message to be displayed. - final ChatMessage message; - - @override - Widget build(BuildContext context) => Row( - children: [ - Flexible( - flex: 6, - child: Column( - children: [ - ChatViewModelClient( - builder: (context, viewModel, child) { - final chatStyle = LlmChatViewStyle.resolve(viewModel.style); - final llmStyle = LlmMessageStyle.resolve( - viewModel.style?.llmMessageStyle, - ); - final isWelcomeMessage = identical( - viewModel.controller.history.first, - message, - ); - - return Stack( - children: [ - Container( - height: 20, - width: 20, - decoration: llmStyle.iconDecoration, - child: Icon( - llmStyle.icon, - color: llmStyle.iconColor, - size: 12, - ), - ), - Container( - decoration: llmStyle.decoration, - margin: const EdgeInsets.only(left: 28), - padding: const EdgeInsets.all(8), - child: message.text == null - ? SizedBox( - width: 24, - child: JumpingDotsProgressIndicator( - fontSize: 24, - color: chatStyle.progressIndicatorColor!, - ), - ) - : AdaptiveCopyText( - clipboardText: message.text!, - chatStyle: chatStyle, - child: !isWelcomeMessage && - viewModel.responseBuilder != null - ? viewModel.responseBuilder!( - context, - message.text!, - ) - : MarkdownBody( - data: message.text!, - selectable: false, - styleSheet: llmStyle.markdownStyle, - ), - ), - ), - ], - ); - }, - ), - ], - ), - ), - const Flexible(flex: 2, child: SizedBox()), - ], - ); -} diff --git a/lib/src/views/chat_message_view/user_message_view.dart b/lib/src/views/chat_message_view/user_message_view.dart deleted file mode 100644 index 31d2f22..0000000 --- a/lib/src/views/chat_message_view/user_message_view.dart +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/material.dart'; - -import '../../chat_view_model/chat_view_model_client.dart'; -import '../../providers/interface/chat_message.dart'; -import '../../styles/styles.dart'; -import '../attachment_view/attachment_view.dart'; -import 'adaptive_copy_text.dart'; - -/// A widget that displays a user's message in a chat interface. -/// -/// This widget is responsible for rendering the user's message, including any -/// attachments, in a right-aligned layout. It uses a [Row] and [Column] to -/// structure the content, with the message text displayed in a styled -/// container. -@immutable -class UserMessageView extends StatelessWidget { - /// Creates a [UserMessageView]. - /// - /// The [message] parameter is required and contains the [ChatMessage] to be - /// displayed. - const UserMessageView(this.message, {super.key, this.onEdit}); - - /// The chat message to be displayed. - final ChatMessage message; - - /// The callback to be invoked when the message is edited. - final VoidCallback? onEdit; - - @override - Widget build(BuildContext context) => Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - const Flexible(flex: 2, child: SizedBox()), - Flexible( - flex: 6, - child: Column( - children: [ - ...[ - for (final attachment in message.attachments) - Padding( - padding: const EdgeInsets.only(bottom: 6), - child: Align( - alignment: Alignment.topRight, - child: SizedBox( - height: 80, - width: 200, - child: AttachmentView(attachment), - ), - ), - ), - ], - ChatViewModelClient( - builder: (context, viewModel, child) { - final chatStyle = LlmChatViewStyle.resolve(viewModel.style); - final userStyle = UserMessageStyle.resolve( - viewModel.style?.userMessageStyle, - ); - final text = message.text ?? ''; - - return Align( - alignment: Alignment.topRight, - child: DecoratedBox( - decoration: userStyle.decoration!, - child: Padding( - padding: const EdgeInsets.only( - left: 16, - right: 16, - top: 12, - bottom: 12, - ), - child: AdaptiveCopyText( - chatStyle: chatStyle, - clipboardText: text, - onEdit: onEdit, - child: Text(text, style: userStyle.textStyle), - ), - ), - ), - ); - }, - ), - ], - ), - ), - ], - ); -} diff --git a/lib/src/views/chat_text_field.dart b/lib/src/views/chat_text_field.dart deleted file mode 100644 index 9f38b67..0000000 --- a/lib/src/views/chat_text_field.dart +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import '../utility.dart'; - -/// A text field that adapts to the current app style (Material or Cupertino). -/// -/// This widget will render either a [CupertinoTextField] or a [TextField] -/// depending on whether the app is using Cupertino or Material design. -@immutable -class ChatTextField extends StatelessWidget { - /// Creates an adaptive text field. - /// - /// Many of the parameters are required to ensure consistent behavior - /// across both Cupertino and Material designs. - const ChatTextField({ - required this.minLines, - required this.maxLines, - required this.autofocus, - required this.style, - required this.textInputAction, - required this.controller, - required this.focusNode, - required this.onSubmitted, - required this.hintText, - required this.hintStyle, - required this.hintPadding, - super.key, - }); - - /// The minimum number of lines to show. - final int minLines; - - /// The maximum number of lines to show. - final int maxLines; - - /// Whether the text field should be focused initially. - final bool autofocus; - - /// The style to use for the text being edited. - final TextStyle style; - - /// The type of action button to use for the keyboard. - final TextInputAction textInputAction; - - /// Controls the text being edited. - final TextEditingController controller; - - /// Defines the keyboard focus for this widget. - final FocusNode focusNode; - - /// The text to show when the text field is empty. - final String hintText; - - /// The style to use for the hint text. - final TextStyle hintStyle; - - /// The padding to use for the hint text. - final EdgeInsetsGeometry? hintPadding; - - /// Called when the user submits editable content. - final void Function(String text) onSubmitted; - - @override - Widget build(BuildContext context) => isCupertinoApp(context) - ? CupertinoTextField( - minLines: minLines, - maxLines: maxLines, - controller: controller, - autofocus: autofocus, - focusNode: focusNode, - onSubmitted: onSubmitted, - style: style, - placeholder: hintText, - placeholderStyle: hintStyle, - padding: hintPadding ?? EdgeInsets.zero, - decoration: BoxDecoration( - border: Border.all(width: 0, color: Colors.transparent), - ), - textInputAction: textInputAction, - ) - : TextField( - minLines: minLines, - maxLines: maxLines, - controller: controller, - autofocus: autofocus, - focusNode: focusNode, - textInputAction: textInputAction, - onSubmitted: onSubmitted, - style: style, - decoration: InputDecoration( - border: InputBorder.none, - hintText: hintText, - hintStyle: hintStyle, - contentPadding: hintPadding, - ), - ); -} diff --git a/lib/src/views/jumping_dots_progress_indicator/jumping_dot.dart b/lib/src/views/jumping_dots_progress_indicator/jumping_dot.dart deleted file mode 100644 index 5174984..0000000 --- a/lib/src/views/jumping_dots_progress_indicator/jumping_dot.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -/// A widget that represents a single jumping dot in the progress indicator. -@immutable -class JumpingDot extends AnimatedWidget { - /// Creates a [JumpingDot] widget. - /// - /// The [animation] parameter is required and controls the vertical movement - /// of the dot. The [color] parameter sets the color of the dot. The - /// [fontSize] parameter determines the size of the dot. - const JumpingDot({ - required Animation animation, - required this.color, - required this.fontSize, - super.key, - }) : super(listenable: animation); - - /// The color of the dot. - final Color color; - - /// The font size of the dot. - final double fontSize; - - Animation get _animation => listenable as Animation; - - @override - Widget build(BuildContext context) => SizedBox( - height: _animation.value + fontSize, - child: Text( - '.', - style: TextStyle( - color: color, - fontSize: fontSize, - height: 1, // Center the text vertically within its line height - ), - ), - ); -} diff --git a/lib/src/views/jumping_dots_progress_indicator/jumping_dots_progress_indicator.dart b/lib/src/views/jumping_dots_progress_indicator/jumping_dots_progress_indicator.dart deleted file mode 100644 index 57123d9..0000000 --- a/lib/src/views/jumping_dots_progress_indicator/jumping_dots_progress_indicator.dart +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// this file forked from https://github.com/wal33d006/progress_indicators due to -// lack of activity - -import 'package:flutter/widgets.dart'; - -import 'jumping_dot.dart'; - -/// Creates a list with [numberOfDots] text dots, with 3 dots as default -/// default [fontSize] of 10.0, default [color] as black, [dotSpacing] (gap -/// between each dot) as 0.0 and default time for one cycle of animation -/// [milliseconds] as 250. -/// One cycle of animation is one complete round of a dot animating up and back -/// to its original position. -@immutable -class JumpingDotsProgressIndicator extends StatefulWidget { - /// Creates a jumping dot progress indicator. - const JumpingDotsProgressIndicator({ - required this.color, - super.key, - this.numberOfDots = 3, - this.fontSize = 10.0, - this.dotSpacing = 0.0, - this.milliseconds = 250, - }); - - /// Number of dots that are added in a horizontal list, default = 3. - final int numberOfDots; - - /// Font size of each dot, default = 10.0. - final double fontSize; - - /// Spacing between each dot, default 0.0. - final double dotSpacing; - - /// Color of the dots, default black. - final Color color; - - /// Time of one complete cycle of animation, default 250 milliseconds. - final int milliseconds; - - @override - _JumpingDotsProgressIndicatorState createState() => - _JumpingDotsProgressIndicatorState(); -} - -class _JumpingDotsProgressIndicatorState - extends State with TickerProviderStateMixin { - final _controllers = []; - final _animations = >[]; - final _widgets = []; - static const double _beginTweenValue = 0; - static const double _endTweenValue = 8; - - @override - void initState() { - super.initState(); - - // for each dot... - for (var dot = 0; dot < widget.numberOfDots; dot++) { - // add an animation controller for the dot - _controllers.add(AnimationController( - duration: Duration(milliseconds: widget.milliseconds), - vsync: this, - )); - - // build an animation for the dot using the controller - _animations.add( - Tween(begin: _beginTweenValue, end: _endTweenValue) - .animate(_controllers[dot]) - ..addStatusListener((status) => _dotListener(status, dot)), - ); - - // add a dot widget with that animation - _widgets.add( - Padding( - padding: EdgeInsets.only(right: widget.dotSpacing), - child: JumpingDot( - animation: _animations[dot], - fontSize: widget.fontSize, - color: widget.color, - ), - ), - ); - } - - // start the animation - _controllers[0].forward(); - } - - void _dotListener(AnimationStatus status, int dot) { - if (status == AnimationStatus.completed) { - _controllers[dot].reverse(); - } - - if (dot == widget.numberOfDots - 1 && status == AnimationStatus.dismissed) { - _controllers[0].forward(); - } - - if (_animations[dot].value > _endTweenValue / 2 && - dot < widget.numberOfDots - 1) { - _controllers[dot + 1].forward(); - } - } - - @override - Widget build(BuildContext context) => SizedBox( - height: widget.fontSize + (widget.fontSize * 0.5), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: _widgets, - ), - ); - - @override - void dispose() { - for (var i = 0; i < widget.numberOfDots; i++) { - _controllers[i].dispose(); - } - - super.dispose(); - } -} diff --git a/lib/src/views/llm_chat_view/llm_chat_view.dart b/lib/src/views/llm_chat_view/llm_chat_view.dart deleted file mode 100644 index 86ef724..0000000 --- a/lib/src/views/llm_chat_view/llm_chat_view.dart +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; - -import 'package:cross_file/cross_file.dart'; -import 'package:flutter/widgets.dart'; - -import '../../chat_view_model/chat_view_model.dart'; -import '../../chat_view_model/chat_view_model_provider.dart'; -import '../../dialogs/adaptive_dialog.dart'; -import '../../dialogs/adaptive_dialog_action.dart'; -import '../../dialogs/adaptive_snack_bar/adaptive_snack_bar.dart'; -import '../../llm_chat_view_controller.dart'; -import '../../llm_exception.dart'; -import '../../platform_helper/platform_helper.dart' as ph; -import '../../providers/interface/attachments.dart'; -import '../../providers/interface/chat_message.dart'; -import '../../providers/interface/llm_provider.dart'; -import '../../styles/llm_chat_view_style.dart'; -import '../chat_history_view.dart'; -import '../chat_input/chat_input.dart'; -import '../chat_input/chat_suggestion_view.dart'; -import '../response_builder.dart'; -import 'llm_response.dart'; - -/// A widget that displays a chat interface for interacting with an LLM -/// (Language Model). -/// -/// This widget provides a complete chat interface, including a message history -/// view and an input area for sending new messages. It can be configured with -/// either an [LlmProvider] or an [LlmChatViewController] to manage the chat -/// interactions. -/// -/// Example usage: -/// ```dart -/// LlmChatView( -/// provider: MyLlmProvider(), -/// style: LlmChatViewStyle( -/// backgroundColor: Colors.white, -/// // ... other style properties -/// ), -/// ) -/// ``` -@immutable -class LlmChatView extends StatefulWidget { - /// Creates an [LlmChatView] widget. - /// - /// You must provide either a [provider] or a [controller], but not both. If - /// [provider] is provided, a new [LlmChatViewController] will be created - /// internally. - /// - /// The [style] parameter can be used to customize the appearance of the chat - /// view. The [responseBuilder] allows custom rendering of chat responses. - /// - /// Throws an [ArgumentError] if both [provider] and [controller] are - /// provided, or if neither is provided. - LlmChatView({ - LlmProvider? provider, - LlmChatViewController? controller, - LlmChatViewStyle? style, - ResponseBuilder? responseBuilder, - this.suggestions = const [], - super.key, - }) { - if (provider != null && controller != null) { - throw ArgumentError('Cannot provide both provider and controller'); - } - - if (provider == null && controller == null) { - throw ArgumentError('Must provide either provider or controller'); - } - - viewModel = ChatViewModel( - controller: controller ?? LlmChatViewController(provider: provider!), - responseBuilder: responseBuilder, - style: style, - ); - } - - /// The list of suggestions to display in the chat interface. - /// - /// This list contains predefined suggestions that can be shown to the user - /// when the chat history is empty. The user can select any of these - /// suggestions to quickly start a conversation with the LLM. - final List suggestions; - - /// The view model containing the chat state and configuration. - /// - /// This [ChatViewModel] instance holds the LLM provider, transcript, - /// response builder, welcome message, and LLM icon for the chat interface. - /// It encapsulates the core data and functionality needed for the chat view. - late final ChatViewModel viewModel; - - @override - State createState() => _LlmChatViewState(); -} - -class _LlmChatViewState extends State - with AutomaticKeepAliveClientMixin { - @override - bool get wantKeepAlive => true; - - LlmResponse? _pendingPromptResponse; - ChatMessage? _initialMessage; - LlmResponse? _pendingSttResponse; - - @override - void initState() { - super.initState(); - widget.viewModel.controller.addListener(_onHistoryChanged); - } - - @override - void dispose() { - super.dispose(); - widget.viewModel.controller.removeListener(_onHistoryChanged); - } - - @override - Widget build(BuildContext context) { - super.build(context); // for AutomaticKeepAliveClientMixin - - final chatStyle = LlmChatViewStyle.resolve(widget.viewModel.style); - return ListenableBuilder( - listenable: widget.viewModel.controller, - builder: (context, child) => ChatViewModelProvider( - viewModel: widget.viewModel, - child: Container( - color: chatStyle.backgroundColor, - child: Column( - children: [ - Expanded( - child: Stack( - children: [ - ChatHistoryView( - onEditMessage: _pendingPromptResponse == null - ? _onEditMessage - : null, - ), - if (widget.suggestions.isNotEmpty && - widget.viewModel.controller.history.isEmpty) - Align( - alignment: Alignment.bottomCenter, - child: ChatSuggestionsView( - suggestions: widget.suggestions, - onSelectSuggestion: _onSelectSuggestion, - ), - ), - ], - ), - ), - ChatInput( - initialMessage: _initialMessage, - onSendMessage: _onSendMessage, - onCancelMessage: - _pendingPromptResponse == null ? null : _onCancelMessage, - onTranslateStt: _onTranslateStt, - onCancelStt: _pendingSttResponse == null ? null : _onCancelStt, - ), - ], - ), - ), - ), - ); - } - - Future _onSendMessage( - String prompt, - Iterable attachments, - ) async { - _initialMessage = null; - - _pendingPromptResponse = LlmResponse( - stream: widget.viewModel.controller.sendMessageStream( - prompt, - attachments: attachments, - ), - // update during the streaming response input; the controller will notify - // listeners only when the response is complete - onUpdate: (_) => setState(() {}), - onDone: _onPromptDone, - ); - - setState(() {}); - } - - void _onPromptDone(LlmException? error) { - setState(() => _pendingPromptResponse = null); - unawaited(_showLlmException(error)); - } - - void _onCancelMessage() => _pendingPromptResponse?.cancel(); - - void _onEditMessage(ChatMessage message) { - assert(_pendingPromptResponse == null); - - // remove the last llm message - final history = widget.viewModel.controller.history.toList(); - assert(history.last.origin.isLlm); - history.removeLast(); - - // remove the last user message - assert(history.last.origin.isUser); - final userMessage = history.removeLast(); - - // set the history to the new history - widget.viewModel.controller.history = history; - - //set the text of the controller to the last userMessage to provide initial - //prompt and attachments for the user to edit - setState(() => _initialMessage = userMessage); - } - - Future _onTranslateStt(XFile file) async { - _initialMessage = null; - - // use the LLM to translate the attached audio to text - const prompt = - 'translate the attached audio to text; provide the result of that ' - 'translation as just the text of the translation itself. be careful to ' - 'separate the background audio from the foreground audio and only ' - 'provide the result of translating the foreground audio.'; - final attachments = [await FileAttachment.fromFile(file)]; - - var response = ''; - _pendingSttResponse = LlmResponse( - stream: widget.viewModel.controller.generateStream( - prompt, - attachments: attachments, - ), - onUpdate: (text) => response += text, - onDone: (error) async => _onSttDone(error, response, file), - ); - - setState(() {}); - } - - Future _onSttDone( - LlmException? error, - String response, - XFile file, - ) async { - assert(_pendingSttResponse != null); - setState(() { - _initialMessage = ChatMessage.user(response, []); - _pendingSttResponse = null; - }); - - // delete the file now that the LLM has translated it - unawaited(ph.deleteFile(file)); - - // show any error that occurred - unawaited(_showLlmException(error)); - } - - void _onCancelStt() => _pendingSttResponse?.cancel(); - - Future _showLlmException(LlmException? error) async { - if (error == null) return; - - switch (error) { - case LlmCancelException(): - AdaptiveSnackBar.show(context, 'LLM operation canceled by user'); - case LlmFailureException(): - case LlmException(): - // stop from the progress from indicating in case there was a failure - // before any text response happened; the progress indicator uses a null - // text message to keep progressing. plus we don't want to just show an - // empty LLM message. - final llmMessage = widget.viewModel.controller.history.last; - if (llmMessage.text == null) llmMessage.append('ERROR'); - - await AdaptiveAlertDialog.show( - context: context, - content: Text(error.toString()), - actions: [ - AdaptiveDialogAction( - onPressed: () => Navigator.pop(context), - child: const Text('OK'), - ), - ], - ); - } - } - - void _onSelectSuggestion(String suggestion) => - setState(() => _initialMessage = ChatMessage.user(suggestion, [])); - - void _onHistoryChanged() { - // if the history is cleared, clear the initial message - if (widget.viewModel.controller.history.isEmpty) { - setState(() => _initialMessage = null); - } - } -} diff --git a/lib/src/views/llm_chat_view/llm_response.dart b/lib/src/views/llm_chat_view/llm_response.dart deleted file mode 100644 index c829a15..0000000 --- a/lib/src/views/llm_chat_view/llm_response.dart +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; - -import '../../llm_exception.dart'; - -/// Represents a response from an LLM (Language Learning Model). -/// -/// This class manages the streaming of LLM responses, error handling, and -/// cleanup. -class LlmResponse { - /// Creates an LlmResponse. - /// - /// [stream] is the stream of text chunks from the LLM. [onDone] is an - /// optional callback for when the response is complete or encounters an - /// error. - LlmResponse({ - required Stream stream, - required this.onUpdate, - required this.onDone, - }) { - _subscription = stream.listen( - onUpdate, - onDone: () => onDone(null), - cancelOnError: true, - onError: (err) => _close(_exception(err)), - ); - } - - /// Callback function to be called when a new chunk is received from the - /// response stream. - final void Function(String text) onUpdate; - - /// Callback function to be called when the response is complete or encounters - /// an error. - final void Function(LlmException? error) onDone; - - /// Cancels the response stream. - void cancel() => _close(const LlmCancelException()); - - StreamSubscription? _subscription; - - LlmException _exception(dynamic err) => switch (err) { - (LlmCancelException _) => const LlmCancelException(), - (final LlmFailureException ex) => ex, - _ => LlmFailureException(err.toString()), - }; - - void _close(LlmException error) { - assert(_subscription != null); - unawaited(_subscription!.cancel()); - _subscription = null; - onDone.call(error); - } -} diff --git a/lib/src/views/response_builder.dart b/lib/src/views/response_builder.dart deleted file mode 100644 index 4add43c..0000000 --- a/lib/src/views/response_builder.dart +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2024 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:flutter/widgets.dart'; - -/// A function type that defines how to build a widget for displaying a response -/// in the chat interface. -/// -/// [context] is the build context, which can be used to access theme data and -/// other contextual information. -/// -/// [response] is the text of the response from the LLM. -/// -/// The function should return a [Widget] that represents the formatted response -/// in the chat interface. -typedef ResponseBuilder = Widget Function( - BuildContext context, - String response, -); diff --git a/pubspec.yaml b/pubspec.yaml deleted file mode 100644 index b9b8e25..0000000 --- a/pubspec.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: flutter_ai_toolkit -description: "A set of AI chat-related widgets for your Flutter app targeting mobile, desktop and web." -version: 0.4.2 -homepage: https://github.com/csells/flutter_ai_toolkit - -environment: - sdk: '>=3.4.0 <4.0.0' - flutter: ">=1.17.0" - -dependencies: - cross_file: ^0.3.4+2 - file_selector: ^1.0.3 - firebase_vertexai: ^1.0.1 - flutter: - sdk: flutter - flutter_context_menu: ^0.2.0 - flutter_markdown: ^0.7.4 - gap: ^3.0.1 - google_fonts: ^6.2.1 - google_generative_ai: ^0.4.3 - image_picker: ^1.1.2 - mime: ^2.0.0 - ollama_dart: ^0.2.1 - universal_platform: ^1.1.0 - uuid: ^4.4.2 - waveform_recorder: ^1.3.0 - -dev_dependencies: - all_lint_rules_community: ^0.0.42 - flutter_test: - sdk: flutter - -flutter: - fonts: - - family: FatIcons - fonts: - - asset: lib/fonts/FatIcons.ttf