├── .flutter-plugins ├── .flutter-plugins-dependencies ├── .gitignore ├── .idea ├── .gitignore ├── Viki-2-OpenAI.iml ├── libraries │ ├── Dart_Packages.xml │ ├── Dart_SDK.xml │ └── Flutter_Plugins.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── io │ │ │ │ └── flutter │ │ │ │ └── plugins │ │ │ │ └── GeneratedPluginRegistrant.java │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── chatgpt │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── chatgpt_android.iml ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties └── settings.gradle ├── assets ├── Viki 2 AI.png ├── openai.svg └── searching.json ├── chatgpt.iml ├── lib ├── errors │ └── exceptions.dart ├── main.dart ├── models │ ├── chat.dart │ ├── images.dart │ └── model.dart ├── network │ ├── api_services.dart │ ├── error_message.dart │ └── network_client.dart ├── providers │ ├── error_message.dart │ ├── get_images_provider.dart │ ├── get_message_provider.dart │ └── get_models_provider.dart ├── src │ └── pages │ │ ├── chat_page.dart │ │ ├── dalle_page.dart │ │ ├── full_screen.dart │ │ ├── home_page.dart │ │ └── splash_page.dart └── utils │ ├── change_theme_button.dart │ ├── constants.dart │ ├── routes.dart │ └── theme_provider.dart ├── pubspec.lock ├── pubspec.yaml ├── test └── widget_test.dart └── update_version.json /.flutter-plugins: -------------------------------------------------------------------------------- 1 | # This is a generated file; do not edit or check into version control. 2 | image_downloader=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\image_downloader-0.31.0\\ 3 | path_provider=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider-2.0.14\\ 4 | path_provider_android=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_android-2.0.24\\ 5 | path_provider_foundation=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_foundation-2.2.1\\ 6 | path_provider_linux=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_linux-2.1.10\\ 7 | path_provider_windows=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_windows-2.1.5\\ 8 | shared_preferences=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences-2.1.0\\ 9 | shared_preferences_android=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_android-2.1.0\\ 10 | shared_preferences_foundation=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_foundation-2.2.0\\ 11 | shared_preferences_linux=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_linux-2.2.0\\ 12 | shared_preferences_web=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_web-2.1.0\\ 13 | shared_preferences_windows=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\shared_preferences_windows-2.2.0\\ 14 | sqflite=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\sqflite-2.2.6\\ 15 | url_launcher=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher-6.1.10\\ 16 | url_launcher_android=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_android-6.0.26\\ 17 | url_launcher_ios=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_ios-6.1.4\\ 18 | url_launcher_linux=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_linux-3.0.4\\ 19 | url_launcher_macos=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_macos-3.0.4\\ 20 | url_launcher_web=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_web-2.0.16\\ 21 | url_launcher_windows=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\url_launcher_windows-3.0.5\\ 22 | -------------------------------------------------------------------------------- /.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"image_downloader","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_downloader-0.31.0\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.2.1\\\\","native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.2.0\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\sqflite-2.2.6\\\\","native_build":true,"dependencies":[]},{"name":"url_launcher_ios","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_ios-6.1.4\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"image_downloader","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\image_downloader-0.31.0\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.0.24\\\\","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.1.0\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\sqflite-2.2.6\\\\","native_build":true,"dependencies":[]},{"name":"url_launcher_android","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_android-6.0.26\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.2.1\\\\","native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.2.0\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\sqflite-2.2.6\\\\","native_build":true,"dependencies":[]},{"name":"url_launcher_macos","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_macos-3.0.4\\\\","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.1.10\\\\","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.2.0\\\\","native_build":false,"dependencies":["path_provider_linux"]},{"name":"url_launcher_linux","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_linux-3.0.4\\\\","native_build":true,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.1.5\\\\","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.2.0\\\\","native_build":false,"dependencies":["path_provider_windows"]},{"name":"url_launcher_windows","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_windows-3.0.5\\\\","native_build":true,"dependencies":[]}],"web":[{"name":"shared_preferences_web","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.1.0\\\\","dependencies":[]},{"name":"url_launcher_web","path":"C:\\\\Users\\\\VIKRAMADITYA\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\url_launcher_web-2.0.16\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"image_downloader","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"sqflite","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2023-04-08 10:12:21.827462","version":"3.7.7"} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | build/ 7 | # If you're building an application, you may want to check-in your pubspec.lock 8 | pubspec.lock 9 | 10 | # Directory created by dartdoc 11 | # If you don't generate documentation locally you can remove this line. 12 | doc/api/ 13 | 14 | # Avoid committing generated Javascript files: 15 | *.dart.js 16 | *.info.json # Produced by the --dump-info flag. 17 | *.js # When generated by dart2js. Don't specify *.js if your 18 | # project includes source files written in JavaScript. 19 | *.js_ 20 | *.js.deps 21 | *.js.map 22 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/Viki-2-OpenAI.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_Packages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Vikramaditya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Viki-2-OpenAI 2 |

3 | A Chatbot chat app built using the Flutter framework and OpenAI's ChatGPT-3 and Dall.E 2 language model. 4 |

5 | 6 | 7 | Get Release: [Download](https://github.com/VikramadityaDev/Viki-2-OpenAI/releases) 8 | 9 | 10 | ### Show some :heart: and star the repo. 11 | 12 | 13 | ## Features 14 | 15 | - Natural language understanding. 16 | - Human-like conversation. 17 | - Customizable to fit your use-case. 18 | - Lightweight, easy to integrate with other apps. 19 | - Open-source. 20 | - High quality images. 21 | - Text to image. 22 | - Light and Dark Mode Enabled. 23 | - Image Downloadable. 24 | 25 | ## Replacing API Key 26 | 27 | ``` 28 | You need to use your own OpenAI API key. 29 | Just replace the OPEN_AI_API_KEY_HERE found in /lib/utils/constants.dart, with your own key. 30 | ``` 31 | 32 | ## Prerequisites 33 | 34 | - Flutter SDK 35 | - API key for OpenAI GPT-3 [Available here](https://beta.openai.com/account/api-keys) 36 | 37 | 38 | ### Development by 39 | 40 | - OpenAI - https://openai.com 41 | - Flutter - https://flutter.dev/ 42 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 33 30 | ndkVersion flutter.ndkVersion 31 | 32 | compileOptions { 33 | sourceCompatibility JavaVersion.VERSION_1_8 34 | targetCompatibility JavaVersion.VERSION_1_8 35 | } 36 | 37 | kotlinOptions { 38 | jvmTarget = '1.8' 39 | } 40 | 41 | sourceSets { 42 | main.java.srcDirs += 'src/main/kotlin' 43 | } 44 | 45 | defaultConfig { 46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 47 | applicationId "com.example.chatgpt" 48 | // You can update the following values to match your application needs. 49 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. 50 | minSdkVersion 19 51 | targetSdkVersion flutter.targetSdkVersion 52 | versionCode flutterVersionCode.toInteger() 53 | versionName flutterVersionName 54 | multiDexEnabled true 55 | } 56 | 57 | buildTypes { 58 | release { 59 | // TODO: Add your own signing config for the release build. 60 | // Signing with the debug keys for now, so `flutter run --release` works. 61 | signingConfig signingConfigs.debug 62 | } 63 | } 64 | } 65 | 66 | flutter { 67 | source '../..' 68 | } 69 | 70 | dependencies { 71 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 72 | } 73 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 11 | 19 | 23 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java: -------------------------------------------------------------------------------- 1 | package io.flutter.plugins; 2 | 3 | import androidx.annotation.Keep; 4 | import androidx.annotation.NonNull; 5 | import io.flutter.Log; 6 | 7 | import io.flutter.embedding.engine.FlutterEngine; 8 | 9 | /** 10 | * Generated file. Do not edit. 11 | * This file is generated by the Flutter tool based on the 12 | * plugins that support the Android platform. 13 | */ 14 | @Keep 15 | public final class GeneratedPluginRegistrant { 16 | private static final String TAG = "GeneratedPluginRegistrant"; 17 | public static void registerWith(@NonNull FlutterEngine flutterEngine) { 18 | try { 19 | flutterEngine.getPlugins().add(new com.ko2ic.imagedownloader.ImageDownloaderPlugin()); 20 | } catch(Exception e) { 21 | Log.e(TAG, "Error registering plugin image_downloader, com.ko2ic.imagedownloader.ImageDownloaderPlugin", e); 22 | } 23 | try { 24 | flutterEngine.getPlugins().add(new io.flutter.plugins.pathprovider.PathProviderPlugin()); 25 | } catch(Exception e) { 26 | Log.e(TAG, "Error registering plugin path_provider_android, io.flutter.plugins.pathprovider.PathProviderPlugin", e); 27 | } 28 | try { 29 | flutterEngine.getPlugins().add(new io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin()); 30 | } catch(Exception e) { 31 | Log.e(TAG, "Error registering plugin shared_preferences_android, io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin", e); 32 | } 33 | try { 34 | flutterEngine.getPlugins().add(new com.tekartik.sqflite.SqflitePlugin()); 35 | } catch(Exception e) { 36 | Log.e(TAG, "Error registering plugin sqflite, com.tekartik.sqflite.SqflitePlugin", e); 37 | } 38 | try { 39 | flutterEngine.getPlugins().add(new io.flutter.plugins.urllauncher.UrlLauncherPlugin()); 40 | } catch(Exception e) { 41 | Log.e(TAG, "Error registering plugin url_launcher_android, io.flutter.plugins.urllauncher.UrlLauncherPlugin", e); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/chatgpt/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.chatgpt 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VikramadityaDev/Viki-2-OpenAI/b8f070be80ac7e489ae6eccf3011cf368a1a3285/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VikramadityaDev/Viki-2-OpenAI/b8f070be80ac7e489ae6eccf3011cf368a1a3285/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VikramadityaDev/Viki-2-OpenAI/b8f070be80ac7e489ae6eccf3011cf368a1a3285/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VikramadityaDev/Viki-2-OpenAI/b8f070be80ac7e489ae6eccf3011cf368a1a3285/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VikramadityaDev/Viki-2-OpenAI/b8f070be80ac7e489ae6eccf3011cf368a1a3285/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/chatgpt_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VikramadityaDev/Viki-2-OpenAI/b8f070be80ac7e489ae6eccf3011cf368a1a3285/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/local.properties: -------------------------------------------------------------------------------- 1 | sdk.dir=C:\\Users\\VIKRAMADITYA\\AppData\\Local\\Android\\sdk 2 | flutter.sdk=C:\\src\\flutter 3 | flutter.buildMode=release 4 | flutter.versionName=1.0.0 5 | flutter.versionCode=1 -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /assets/Viki 2 AI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VikramadityaDev/Viki-2-OpenAI/b8f070be80ac7e489ae6eccf3011cf368a1a3285/assets/Viki 2 AI.png -------------------------------------------------------------------------------- /assets/openai.svg: -------------------------------------------------------------------------------- 1 | OpenAI icon -------------------------------------------------------------------------------- /chatgpt.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/errors/exceptions.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | 3 | // Represent exceptions from Server/Remote data source. 4 | class RemoteException implements Exception { 5 | DioError dioError; 6 | 7 | RemoteException({required this.dioError}); 8 | } 9 | 10 | // Represent exceptions from Cache. 11 | class LocalException implements Exception { 12 | String error; 13 | 14 | LocalException(this.error); 15 | } 16 | 17 | class RouteException implements Exception { 18 | final String message; 19 | RouteException(this.message); 20 | } 21 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatgpt/src/pages/splash_page.dart'; 2 | import 'package:chatgpt/utils/theme_provider.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:provider/provider.dart'; 6 | 7 | void main() async { 8 | WidgetsFlutterBinding.ensureInitialized(); 9 | SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( 10 | statusBarColor: Colors.transparent, 11 | )); 12 | runApp(const MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | const MyApp({super.key}); 17 | 18 | @override 19 | Widget build(BuildContext context) => ChangeNotifierProvider( 20 | create: (context) => ThemeProvider(), 21 | builder: (context, _) { 22 | final themeProvider = Provider.of(context); 23 | return MaterialApp( 24 | title: 'Viki-2 A.I', 25 | debugShowCheckedModeBanner: false, 26 | themeMode: themeProvider.themeMode, 27 | theme: MyThemes.lightTheme, 28 | darkTheme: MyThemes.darkTheme, 29 | home: const SplashPage(), 30 | ); 31 | }, 32 | ); 33 | } 34 | 35 | 36 | // Code Updated to latest version. -------------------------------------------------------------------------------- /lib/models/chat.dart: -------------------------------------------------------------------------------- 1 | class Chat { 2 | final String msg; 3 | final int chat; 4 | Chat({ 5 | required this.msg, 6 | required this.chat, 7 | }); 8 | 9 | factory Chat.fromJson(Map json) => Chat( 10 | chat: json['chat'], 11 | msg: json['msg'], 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /lib/models/images.dart: -------------------------------------------------------------------------------- 1 | class Images { 2 | final String url; 3 | 4 | Images({ 5 | required this.url, 6 | }); 7 | 8 | factory Images.fromJson(Map json) => Images( 9 | url: json['url'], 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /lib/models/model.dart: -------------------------------------------------------------------------------- 1 | class Model { 2 | final String id; 3 | final int created; 4 | final String root; 5 | 6 | Model({ 7 | required this.id, 8 | required this.root, 9 | required this.created, 10 | }); 11 | 12 | factory Model.fromJson(Map json) => Model( 13 | id: json['id'], 14 | root: json['root'], 15 | created: json['created'], 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /lib/network/api_services.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:logger/logger.dart'; 5 | 6 | import '../errors/exceptions.dart'; 7 | import '../models/chat.dart'; 8 | import '../models/images.dart'; 9 | import '../models/model.dart'; 10 | 11 | import '../utils/constants.dart'; 12 | import 'error_message.dart'; 13 | import 'network_client.dart'; 14 | 15 | Future> submitGetImagesForm({ 16 | required BuildContext context, 17 | required String prompt, 18 | required int n, 19 | }) async { 20 | // 21 | NetworkClient networkClient = NetworkClient(); 22 | List imagesList = []; 23 | try { 24 | final res = await networkClient.post( 25 | '${BASE_URL}images/generations', 26 | {"prompt": prompt, "n": n, "size": "256x256"}, 27 | token: OPEN_API_KEY, 28 | ); 29 | Map mp = jsonDecode(res.toString()); 30 | debugPrint(mp.toString()); 31 | if (mp['data'].length > 0) { 32 | imagesList = List.generate(mp['data'].length, (i) { 33 | return Images.fromJson({ 34 | 'url': mp['data'][i]['url'], 35 | }); 36 | }); 37 | debugPrint(imagesList.toString()); 38 | } 39 | } on RemoteException catch (e) { 40 | Logger().e(e.dioError); 41 | errorMessage(context); 42 | } 43 | return imagesList; 44 | } 45 | 46 | Future> submitGetChatsForm({ 47 | required BuildContext context, 48 | required String prompt, 49 | required int tokenValue, 50 | String? model, 51 | }) async { 52 | // 53 | NetworkClient networkClient = NetworkClient(); 54 | List chatList = []; 55 | try { 56 | final res = await networkClient.post( 57 | "${BASE_URL}completions", 58 | { 59 | "model": model ?? "text-davinci-003", 60 | "prompt": prompt, 61 | "temperature": 0, 62 | "max_tokens": tokenValue 63 | }, 64 | token: OPEN_API_KEY, 65 | ); 66 | Map mp = jsonDecode(res.toString()); 67 | debugPrint(mp.toString()); 68 | if (mp['choices'].length > 0) { 69 | chatList = List.generate(mp['choices'].length, (i) { 70 | return Chat.fromJson({ 71 | 'msg': mp['choices'][i]['text'], 72 | 'chat': 1, 73 | }); 74 | }); 75 | debugPrint(chatList.toString()); 76 | } 77 | } on RemoteException catch (e) { 78 | Logger().e(e.dioError); 79 | errorMessage(context); 80 | } 81 | return chatList; 82 | } 83 | 84 | Future> submitGetModelsForm({ 85 | required BuildContext context, 86 | }) async { 87 | // 88 | NetworkClient networkClient = NetworkClient(); 89 | List modelsList = []; 90 | try { 91 | final res = await networkClient.get( 92 | "${BASE_URL}models", 93 | token: OPEN_API_KEY, 94 | ); 95 | Map mp = jsonDecode(res.toString()); 96 | debugPrint(mp.toString()); 97 | if (mp['data'].length > 0) { 98 | modelsList = List.generate(mp['data'].length, (i) { 99 | return Model.fromJson({ 100 | 'id': mp['data'][i]['id'], 101 | 'created': mp['data'][i]['created'], 102 | 'root': mp['data'][i]['root'], 103 | }); 104 | }); 105 | debugPrint(modelsList.toString()); 106 | } 107 | } on RemoteException catch (e) { 108 | Logger().e(e.dioError); 109 | errorMessage(context); 110 | } 111 | return modelsList; 112 | } 113 | -------------------------------------------------------------------------------- /lib/network/error_message.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void errorMessage(BuildContext context) { 4 | ScaffoldMessenger.of(context).showSnackBar( 5 | const SnackBar( 6 | content: Text("Something went wrong. please try again later"), 7 | backgroundColor: Colors.lightBlue, 8 | ), 9 | ); 10 | Navigator.pop(context); 11 | } 12 | -------------------------------------------------------------------------------- /lib/network/network_client.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | 3 | import '../errors/exceptions.dart'; 4 | 5 | class NetworkClient { 6 | Dio _dio = Dio(); 7 | NetworkClient({String? baseUrl}) { 8 | baseUrl ??= ""; 9 | BaseOptions baseOptions = BaseOptions( 10 | // receiveTimeout: 20000, 11 | // connectTimeout: 30000, 12 | baseUrl: baseUrl, 13 | maxRedirects: 2, 14 | ); 15 | _dio = Dio(baseOptions); 16 | // adding logging interceptor. 17 | _dio.interceptors.add(LogInterceptor( 18 | requestBody: false, 19 | error: true, 20 | request: false, 21 | requestHeader: false, 22 | responseBody: true, 23 | responseHeader: false, 24 | )); 25 | } 26 | 27 | // for HTTP.GET Request. 28 | Future get(String url, 29 | {Map? params, String? token}) async { 30 | Response response; 31 | try { 32 | Map map = {"Accept": "application/json"}; 33 | if (token != null) map.addAll({"Authorization": "Bearer $token"}); 34 | 35 | response = await _dio.get(url, 36 | queryParameters: params, 37 | options: Options( 38 | headers: map, 39 | )); 40 | } on DioError catch (exception) { 41 | throw RemoteException(dioError: exception); 42 | } 43 | return response; 44 | } 45 | 46 | // for HTTP.POST Request. 47 | Future post(String url, Map params, 48 | {String? token}) async { 49 | Response response; 50 | try { 51 | Map map = {"Accept": "application/json"}; 52 | if (token != null) { 53 | map.addAll({"Authorization": "Bearer $token"}); 54 | } 55 | response = await _dio.post(url, 56 | data: params, 57 | options: Options( 58 | headers: map, 59 | responseType: ResponseType.json, 60 | validateStatus: (_) => true, 61 | )); 62 | } on DioError catch (exception) { 63 | throw RemoteException(dioError: exception); 64 | } 65 | return response; 66 | } 67 | 68 | // for HTTP.POST Request. 69 | Future put(String url, Map params, 70 | {String? token}) async { 71 | Response response; 72 | try { 73 | Map map = {"Accept": "application/json"}; 74 | if (token != null) { 75 | map.addAll({"Authorization": "Bearer $token"}); 76 | } 77 | response = await _dio.put(url, 78 | data: params, 79 | options: Options( 80 | headers: map, 81 | responseType: ResponseType.json, 82 | validateStatus: (_) => true, 83 | )); 84 | } on DioError catch (exception) { 85 | throw RemoteException(dioError: exception); 86 | } 87 | return response; 88 | } 89 | 90 | // for HTTP.PATCH Request. 91 | Future patch(String url, Map params) async { 92 | Response response; 93 | try { 94 | response = await _dio.patch(url, 95 | data: params, 96 | options: Options( 97 | responseType: ResponseType.json, 98 | )); 99 | } on DioError catch (exception) { 100 | throw RemoteException(dioError: exception); 101 | } 102 | return response; 103 | } 104 | 105 | // for download Request. 106 | Future download(String url, String pathName, 107 | void Function(int, int)? onReceiveProgress) async { 108 | Response response; 109 | try { 110 | response = await _dio.download( 111 | url, 112 | pathName, 113 | onReceiveProgress: onReceiveProgress, 114 | ); 115 | } on DioError catch (exception) { 116 | throw RemoteException(dioError: exception); 117 | } 118 | return response; 119 | } 120 | 121 | // for fileUpload Request. 122 | Future fileUpload(String url, FormData params) async { 123 | Response response; 124 | try { 125 | response = await _dio.post(url, 126 | data: params, 127 | options: Options( 128 | responseType: ResponseType.json, 129 | )); 130 | } on DioError catch (exception) { 131 | throw RemoteException(dioError: exception); 132 | } 133 | return response; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /lib/providers/error_message.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void errorMessage(BuildContext context) { 4 | ScaffoldMessenger.of(context).showSnackBar( 5 | const SnackBar( 6 | content: Text("Something went wrong. please try again later"), 7 | backgroundColor: Colors.lightBlue, 8 | ), 9 | ); 10 | Navigator.pop(context); 11 | } 12 | -------------------------------------------------------------------------------- /lib/providers/get_images_provider.dart: -------------------------------------------------------------------------------- 1 | // import 'dart:convert'; 2 | 3 | // import 'package:chatgpt/models/images.dart'; 4 | // import 'package:flutter/material.dart'; 5 | // import 'package:logger/logger.dart'; 6 | 7 | // import '../errors/exceptions.dart'; 8 | // import '../networks/network_client.dart'; 9 | // import '../utils/constants.dart'; 10 | // import 'error_message.dart'; 11 | 12 | // Future> submitGetImagesForm({ 13 | // required BuildContext context, 14 | // required String prompt, 15 | // required int n, 16 | // }) async { 17 | // // 18 | // NetworkClient networkClient = NetworkClient(); 19 | // List imagesList = []; 20 | // try { 21 | // final res = await networkClient.post( 22 | // 'https://api.openai.com/v1/images/generations', 23 | // {"prompt": prompt, "n": n, "size": "1024x1024"}, 24 | // token: OPEN_API_KEY, 25 | // ); 26 | // Map mp = jsonDecode(res.toString()); 27 | // debugPrint(mp.toString()); 28 | // if (mp['data'].length > 0) { 29 | // imagesList = List.generate(mp['data'].length, (i) { 30 | // return Images.fromJson({ 31 | // 'url': mp['data'][i]['url'], 32 | // }); 33 | // }); 34 | // debugPrint(imagesList.toString()); 35 | // } 36 | // } on RemoteException catch (e) { 37 | // Logger().e(e.dioError); 38 | // errorMessage(context); 39 | // } 40 | // return imagesList; 41 | // } 42 | -------------------------------------------------------------------------------- /lib/providers/get_message_provider.dart: -------------------------------------------------------------------------------- 1 | // import 'dart:convert'; 2 | 3 | // import 'package:chatgpt/models/chat.dart'; 4 | // import 'package:flutter/material.dart'; 5 | // import 'package:logger/logger.dart'; 6 | 7 | // import '../errors/exceptions.dart'; 8 | // import '../networks/network_client.dart'; 9 | // import '../utils/constants.dart'; 10 | // import 'error_message.dart'; 11 | 12 | // Future> submitGetChatsForm({ 13 | // required BuildContext context, 14 | // required String prompt, 15 | // required int tokenValue, 16 | // String? model, 17 | // }) async { 18 | // // 19 | // NetworkClient networkClient = NetworkClient(); 20 | // List chatList = []; 21 | // try { 22 | // final res = await networkClient.post( 23 | // "https://api.openai.com/v1/completions", 24 | // { 25 | // "model": model ?? "text-davinci-003", 26 | // "prompt": prompt, 27 | // "temperature": 0, 28 | // "max_tokens": tokenValue 29 | // }, 30 | // token: OPEN_API_KEY, 31 | // ); 32 | // Map mp = jsonDecode(res.toString()); 33 | // debugPrint(mp.toString()); 34 | // if (mp['choices'].length > 0) { 35 | // chatList = List.generate(mp['choices'].length, (i) { 36 | // return Chat.fromJson({ 37 | // 'msg': mp['choices'][i]['text'], 38 | // 'chat': 1, 39 | // }); 40 | // }); 41 | // debugPrint(chatList.toString()); 42 | // } 43 | // } on RemoteException catch (e) { 44 | // Logger().e(e.dioError); 45 | // errorMessage(context); 46 | // } 47 | // return chatList; 48 | // } 49 | -------------------------------------------------------------------------------- /lib/providers/get_models_provider.dart: -------------------------------------------------------------------------------- 1 | // import 'dart:convert'; 2 | 3 | // import 'package:chatgpt/models/model.dart'; 4 | // import 'package:flutter/material.dart'; 5 | // import 'package:logger/logger.dart'; 6 | 7 | // import '../errors/exceptions.dart'; 8 | // import '../networks/network_client.dart'; 9 | // import '../utils/constants.dart'; 10 | // import 'error_message.dart'; 11 | 12 | // Future> submitGetModelsForm({ 13 | // required BuildContext context, 14 | // }) async { 15 | // // 16 | // NetworkClient networkClient = NetworkClient(); 17 | // List modelsList = []; 18 | // try { 19 | // final res = await networkClient.get( 20 | // "https://api.openai.com/v1/models", 21 | // token: OPEN_API_KEY, 22 | // ); 23 | // Map mp = jsonDecode(res.toString()); 24 | // debugPrint(mp.toString()); 25 | // if (mp['data'].length > 0) { 26 | // modelsList = List.generate(mp['data'].length, (i) { 27 | // return Model.fromJson({ 28 | // 'id': mp['data'][i]['id'], 29 | // 'created': mp['data'][i]['created'], 30 | // 'root': mp['data'][i]['root'], 31 | // }); 32 | // }); 33 | // debugPrint(modelsList.toString()); 34 | // } 35 | // } on RemoteException catch (e) { 36 | // Logger().e(e.dioError); 37 | // errorMessage(context); 38 | // } 39 | // return modelsList; 40 | // } 41 | -------------------------------------------------------------------------------- /lib/src/pages/chat_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:animated_text_kit/animated_text_kit.dart'; 2 | import 'package:chatgpt/models/model.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:shared_preferences/shared_preferences.dart'; 6 | 7 | import '../../models/chat.dart'; 8 | import '../../network/api_services.dart'; 9 | 10 | class ChatPage extends StatefulWidget { 11 | const ChatPage({super.key}); 12 | 13 | @override 14 | State createState() => _ChatPageState(); 15 | } 16 | 17 | class _ChatPageState extends State { 18 | String messagePrompt = ''; 19 | int tokenValue = 500; 20 | List chatList = []; 21 | List modelsList = []; 22 | late SharedPreferences prefs; 23 | @override 24 | void initState() { 25 | super.initState(); 26 | getModels(); 27 | initPrefs(); 28 | } 29 | 30 | void getModels() async { 31 | modelsList = await submitGetModelsForm(context: context); 32 | } 33 | 34 | List> get models { 35 | List> menuItems = 36 | List.generate(modelsList.length, (i) { 37 | return DropdownMenuItem( 38 | value: modelsList[i].id, 39 | child: Text(modelsList[i].id), 40 | ); 41 | }); 42 | return menuItems; 43 | } 44 | 45 | void initPrefs() async { 46 | prefs = await SharedPreferences.getInstance(); 47 | tokenValue = prefs.getInt("token") ?? 500; 48 | } 49 | 50 | TextEditingController mesageController = TextEditingController(); 51 | @override 52 | Widget build(BuildContext context) { 53 | return Scaffold( 54 | backgroundColor: Theme.of(context).scaffoldBackgroundColor, 55 | body: SafeArea( 56 | child: Stack( 57 | children: [ 58 | Column( 59 | children: [ 60 | _topChat(), 61 | _bodyChat(), 62 | const SizedBox( 63 | height: 75, 64 | ) 65 | ], 66 | ), 67 | _formChat(), 68 | ], 69 | ), 70 | ), 71 | ); 72 | } 73 | 74 | void saveData(int value) { 75 | prefs.setInt("token", value); 76 | } 77 | 78 | int getData() { 79 | return prefs.getInt("token") ?? 1; 80 | } 81 | 82 | _topChat() { 83 | return Container( 84 | padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), 85 | child: Row( 86 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 87 | children: [ 88 | Row( 89 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 90 | children: [ 91 | GestureDetector( 92 | onTap: () => Navigator.of(context).pop(), 93 | child: const Icon( 94 | Icons.arrow_back_ios, 95 | size: 20, 96 | ), 97 | ), 98 | const Text(''), 99 | const Text(''), 100 | const Text( 101 | 'Chat GPT', 102 | style: TextStyle( 103 | fontSize: 20, 104 | fontWeight: FontWeight.bold, 105 | ), 106 | ), 107 | ], 108 | ), 109 | GestureDetector( 110 | onTap: () { 111 | showModalBottomSheet( 112 | context: context, 113 | backgroundColor: Colors.transparent, 114 | builder: (BuildContext context) { 115 | return StatefulBuilder( 116 | builder: (BuildContext context, StateSetter state) { 117 | return Container( 118 | height: 400, 119 | decoration: const BoxDecoration( 120 | // color: Colors.white, 121 | borderRadius: BorderRadius.only( 122 | topLeft: Radius.circular(20), 123 | topRight: Radius.circular(20), 124 | )), 125 | child: Column( 126 | mainAxisAlignment: MainAxisAlignment.start, 127 | mainAxisSize: MainAxisSize.min, 128 | children: [ 129 | const Padding( 130 | padding: EdgeInsets.symmetric(vertical: 15.0), 131 | child: Text( 132 | 'Settings', 133 | style: TextStyle( 134 | // color: Colors.black, 135 | fontWeight: FontWeight.bold, 136 | ), 137 | ), 138 | ), 139 | Divider( 140 | color: Colors.grey.shade700, 141 | ), 142 | Padding( 143 | padding: const EdgeInsets.fromLTRB(20, 2, 20, 2), 144 | child: DropdownButtonFormField( 145 | items: models, 146 | borderRadius: const BorderRadius.only(), 147 | focusColor: Colors.amber, 148 | onChanged: (String? s) {}, 149 | decoration: const InputDecoration( 150 | hintText: "Select Model"), 151 | ), 152 | ), 153 | const Padding( 154 | padding: EdgeInsets.fromLTRB(20, 20, 20, 2), 155 | child: Align( 156 | alignment: Alignment.topLeft, 157 | child: Text("Token")), 158 | ), 159 | Slider( 160 | min: 0, 161 | max: 1000, 162 | activeColor: Colors.black54, 163 | inactiveColor: Colors.grey.shade300, 164 | value: tokenValue.toDouble(), 165 | onChanged: (value) { 166 | state(() { 167 | tokenValue = value.round(); 168 | }); 169 | }, 170 | ), 171 | Padding( 172 | padding: const EdgeInsets.symmetric(vertical: 10.0), 173 | child: Row( 174 | mainAxisAlignment: MainAxisAlignment.spaceAround, 175 | children: [ 176 | InkWell( 177 | onTap: () { 178 | Navigator.of(context).pop(false); 179 | }, 180 | child: Container( 181 | width: 182 | MediaQuery.of(context).size.width / 2.2, 183 | decoration: BoxDecoration( 184 | color: Colors.grey.shade200, 185 | borderRadius: BorderRadius.circular(40), 186 | ), 187 | padding: const EdgeInsets.symmetric( 188 | vertical: 15, horizontal: 20), 189 | child: const Center( 190 | child: Text( 191 | 'Cancel', 192 | style: TextStyle( 193 | color: Colors.black, 194 | fontWeight: FontWeight.bold, 195 | ), 196 | ), 197 | ), 198 | ), 199 | ), 200 | InkWell( 201 | onTap: () { 202 | saveData(tokenValue); 203 | Navigator.of(context).pop(false); 204 | }, 205 | child: Container( 206 | width: 207 | MediaQuery.of(context).size.width / 2.2, 208 | decoration: BoxDecoration( 209 | color: const Color(0xFFE58500), 210 | borderRadius: BorderRadius.circular(40), 211 | ), 212 | padding: const EdgeInsets.symmetric( 213 | vertical: 15, horizontal: 20), 214 | child: const Center( 215 | child: Text( 216 | 'Save', 217 | style: TextStyle( 218 | color: Colors.black, 219 | fontWeight: FontWeight.bold, 220 | ), 221 | ), 222 | ), 223 | ), 224 | ) 225 | ], 226 | ), 227 | ), 228 | ], 229 | ), 230 | ); 231 | }); 232 | }, 233 | ); 234 | }, 235 | child: const Icon( 236 | Icons.more_vert_rounded, 237 | size: 25, 238 | // color: Colors.white, 239 | ), 240 | ), 241 | ], 242 | ), 243 | ); 244 | } 245 | 246 | Widget chats() { 247 | return ListView.builder( 248 | shrinkWrap: true, 249 | physics: const NeverScrollableScrollPhysics(), 250 | scrollDirection: Axis.vertical, 251 | itemCount: chatList.length, 252 | itemBuilder: (context, index) => _itemChat( 253 | chat: chatList[index].chat, 254 | message: chatList[index].msg, 255 | ), 256 | ); 257 | } 258 | 259 | Widget _bodyChat() { 260 | return Expanded( 261 | child: Container( 262 | padding: const EdgeInsets.only(left: 10, right: 10, top: 10), 263 | width: double.infinity, 264 | decoration: BoxDecoration( 265 | border: Border.all(color: Colors.grey), 266 | borderRadius: const BorderRadius.only( 267 | topLeft: Radius.circular(45), topRight: Radius.circular(45)), 268 | // color: Colors.white, 269 | ), 270 | child: ListView( 271 | shrinkWrap: true, 272 | scrollDirection: Axis.vertical, 273 | physics: const BouncingScrollPhysics(), 274 | children: [ 275 | chats(), 276 | ], 277 | ), 278 | ), 279 | ); 280 | } 281 | 282 | _itemChat({required int chat, required String message}) { 283 | return Row( 284 | mainAxisAlignment: 285 | chat == 0 ? MainAxisAlignment.end : MainAxisAlignment.start, 286 | crossAxisAlignment: CrossAxisAlignment.end, 287 | children: [ 288 | Flexible( 289 | child: Container( 290 | margin: const EdgeInsets.only( 291 | left: 10, 292 | right: 10, 293 | top: 10, 294 | ), 295 | padding: const EdgeInsets.symmetric( 296 | vertical: 10, 297 | horizontal: 10, 298 | ), 299 | decoration: BoxDecoration( 300 | color: chat == 0 ? Colors.indigo.shade100 : Colors.indigo.shade50, 301 | borderRadius: chat == 0 302 | ? const BorderRadius.only( 303 | topLeft: Radius.circular(10), 304 | topRight: Radius.circular(10), 305 | bottomLeft: Radius.circular(10), 306 | ) 307 | : const BorderRadius.only( 308 | topLeft: Radius.circular(10), 309 | topRight: Radius.circular(10), 310 | bottomRight: Radius.circular(10), 311 | ), 312 | ), 313 | child: chatWidget(message), 314 | ), 315 | ), 316 | ], 317 | ); 318 | } 319 | 320 | Widget chatWidget(String text) { 321 | return SizedBox( 322 | width: 250.0, 323 | child: DefaultTextStyle( 324 | style: const TextStyle( 325 | color: Colors.black, 326 | fontSize: 16, 327 | ), 328 | child: AnimatedTextKit( 329 | animatedTexts: [ 330 | TyperAnimatedText( 331 | text.replaceFirst('\n\n', ''), 332 | ), 333 | ], 334 | repeatForever: false, 335 | totalRepeatCount: 1, 336 | ), 337 | ), 338 | ); 339 | } 340 | 341 | Widget _formChat() { 342 | return Positioned( 343 | child: Align( 344 | alignment: Alignment.bottomCenter, 345 | child: Container( 346 | padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), 347 | // color: Colors.white, 348 | child: TextField( 349 | cursorColor: Colors.black87, 350 | style: const TextStyle(color: Colors.black), 351 | controller: mesageController, 352 | decoration: InputDecoration( 353 | hintText: 'Type your message...', 354 | hintStyle: const TextStyle(color: Colors.grey), 355 | suffixIcon: InkWell( 356 | onTap: (() async { 357 | messagePrompt = mesageController.text.toString(); 358 | setState(() { 359 | chatList.add(Chat(msg: messagePrompt, chat: 0)); 360 | mesageController.clear(); 361 | }); 362 | chatList.addAll(await submitGetChatsForm( 363 | context: context, 364 | prompt: messagePrompt, 365 | tokenValue: tokenValue, 366 | )); 367 | setState(() {}); 368 | }), 369 | child: Container( 370 | decoration: BoxDecoration( 371 | borderRadius: BorderRadius.circular(10), 372 | color: Colors.black 373 | ), 374 | padding: const EdgeInsets.all(10), 375 | margin: const EdgeInsets.all(5), 376 | child: const Icon( 377 | Icons.send_rounded, 378 | color: Colors.white, 379 | size: 28, 380 | ), 381 | ), 382 | ), 383 | filled: true, 384 | fillColor: Colors.grey.shade100, 385 | labelStyle: const TextStyle(fontSize: 12), 386 | contentPadding: const EdgeInsets.all(20), 387 | enabledBorder: OutlineInputBorder( 388 | borderSide: BorderSide(color: Colors.grey.shade100,), 389 | borderRadius: BorderRadius.circular(10), 390 | ), 391 | focusedBorder: OutlineInputBorder( 392 | borderSide: BorderSide(color: Colors.grey.shade100,), 393 | borderRadius: BorderRadius.circular(10), 394 | ), 395 | ), 396 | ), 397 | ), 398 | ), 399 | ); 400 | } 401 | } 402 | -------------------------------------------------------------------------------- /lib/src/pages/dalle_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:cached_network_image/cached_network_image.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; 4 | import 'package:shimmer/shimmer.dart'; 5 | 6 | import '../../models/images.dart'; 7 | import '../../network/api_services.dart'; 8 | import 'full_screen.dart'; 9 | 10 | class DallePage extends StatefulWidget { 11 | const DallePage({ 12 | super.key, 13 | }); 14 | 15 | @override 16 | State createState() => _DallePageState(); 17 | } 18 | 19 | class _DallePageState extends State { 20 | TextEditingController searchController = TextEditingController(); 21 | bool imagesAvailable = false; 22 | bool searching = false; 23 | final double _value = 10; 24 | List imagesList = []; 25 | @override 26 | void initState() { 27 | super.initState(); 28 | imagesAvailable = imagesList.isNotEmpty ? true : false; 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return Scaffold( 34 | backgroundColor: Theme.of(context).scaffoldBackgroundColor, 35 | appBar: AppBar( 36 | backgroundColor: Colors.transparent, 37 | elevation: 0, 38 | leading: GestureDetector( 39 | onTap: () => Navigator.of(context).pop(), 40 | child: Icon( 41 | Icons.arrow_back_ios, 42 | size: 22, 43 | color: Theme.of(context).primaryColor, 44 | ), 45 | ), 46 | title: Text( 47 | 'DALL·E 2', 48 | style: TextStyle( 49 | fontSize: 20, 50 | fontWeight: FontWeight.bold, 51 | color: Theme.of(context).primaryColor, 52 | ), 53 | ), 54 | centerTitle: true, 55 | ), 56 | body: SafeArea( 57 | child: Container( 58 | margin: const EdgeInsets.symmetric( 59 | horizontal: 15, 60 | vertical: 5, 61 | ), 62 | child: Column( 63 | children: [ 64 | _formChat(), 65 | Expanded( 66 | child: imagesAvailable 67 | ? MasonryGridView.count( 68 | crossAxisCount: 3, 69 | mainAxisSpacing: 10, 70 | itemCount: imagesList.length, 71 | crossAxisSpacing: 10, 72 | semanticChildCount: 6, 73 | itemBuilder: (context, index) { 74 | return InkWell( 75 | onTap: () { 76 | Navigator.of(context).push( 77 | CustomPageRoute( 78 | builder: (context) => 79 | ImageView(imgPath: imagesList[index].url), 80 | ), 81 | ); 82 | }, 83 | child: Hero( 84 | tag: imagesList[index].url, 85 | child: Container( 86 | decoration: BoxDecoration( 87 | borderRadius: BorderRadius.circular(6)), 88 | height: index % 2 == 0 ? 180 : 250, 89 | width: MediaQuery.of(context).size.width / 3, 90 | child: ImageCard( 91 | imageData: imagesList[index].url, 92 | ), 93 | ), 94 | ), 95 | ); 96 | }, 97 | ) 98 | : Center( 99 | child: searchingWidget(), 100 | ), 101 | ), 102 | ], 103 | ), 104 | ), 105 | ), 106 | ); 107 | } 108 | 109 | Widget searchingWidget() { 110 | if (searching) { 111 | return const CircularProgressIndicator( 112 | color: Color(0x88000000), 113 | ); 114 | } else { 115 | return const Text( 116 | "Search for any image", 117 | style: TextStyle(color: Colors.white), 118 | ); 119 | } 120 | } 121 | 122 | Widget _formChat() { 123 | return Container( 124 | padding: const EdgeInsets.symmetric( 125 | vertical: 10, 126 | ), 127 | child: TextField( 128 | cursorColor: Colors.black87, 129 | controller: searchController, 130 | style: const TextStyle(color: Colors.black), 131 | decoration: InputDecoration( 132 | hintText: 'Type your message...', 133 | hintStyle: const TextStyle(color: Colors.grey), 134 | suffixIcon: InkWell( 135 | onTap: () async { 136 | setState(() { 137 | searching = true; 138 | }); 139 | imagesList = await submitGetImagesForm( 140 | context: context, 141 | prompt: searchController.text.toString(), 142 | n: _value.round(), 143 | ); 144 | setState(() { 145 | imagesAvailable = imagesList.isNotEmpty ? true : false; 146 | }); 147 | }, 148 | child: Container( 149 | decoration: BoxDecoration( 150 | borderRadius: BorderRadius.circular(10), 151 | color: Colors.black, 152 | ), 153 | padding: const EdgeInsets.all(10), 154 | margin: const EdgeInsets.all(5), 155 | child: const Icon( 156 | Icons.search, 157 | color: Colors.white, 158 | size: 28, 159 | ), 160 | ), 161 | ), 162 | filled: true, 163 | fillColor: Colors.grey.shade100, 164 | labelStyle: const TextStyle(fontSize: 12), 165 | contentPadding: const EdgeInsets.all(20), 166 | enabledBorder: OutlineInputBorder( 167 | borderSide: BorderSide( 168 | color: Colors.grey.shade100, 169 | ), 170 | borderRadius: BorderRadius.circular(10), 171 | ), 172 | focusedBorder: OutlineInputBorder( 173 | borderSide: BorderSide( 174 | color: Colors.grey.shade100, 175 | ), 176 | borderRadius: BorderRadius.circular(10), 177 | ), 178 | ), 179 | ), 180 | ); 181 | } 182 | } 183 | 184 | class ImageCard extends StatelessWidget { 185 | const ImageCard({super.key, required this.imageData}); 186 | 187 | final String imageData; 188 | 189 | @override 190 | Widget build(BuildContext context) { 191 | return ClipRRect( 192 | borderRadius: BorderRadius.circular(6.0), 193 | child: CachedNetworkImage( 194 | imageUrl: imageData, 195 | fit: BoxFit.cover, 196 | progressIndicatorBuilder: (context, url, downloadProgress) => SizedBox( 197 | height: 150, 198 | width: 150, 199 | child: Shimmer.fromColors( 200 | baseColor: Colors.grey.shade100, 201 | highlightColor: Colors.white, 202 | child: Container( 203 | height: 220, 204 | width: 130, 205 | decoration: BoxDecoration( 206 | color: Colors.white, 207 | borderRadius: BorderRadius.circular(4)), 208 | ), 209 | )), 210 | ), 211 | ); 212 | } 213 | } 214 | 215 | class CustomPageRoute extends MaterialPageRoute { 216 | @override 217 | Duration get transitionDuration => const Duration(milliseconds: 500); 218 | 219 | CustomPageRoute({builder}) : super(builder: builder); 220 | } 221 | -------------------------------------------------------------------------------- /lib/src/pages/full_screen.dart: -------------------------------------------------------------------------------- 1 | import 'package:cached_network_image/cached_network_image.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:image_downloader/image_downloader.dart'; 4 | 5 | class ImageView extends StatefulWidget { 6 | final String imgPath; 7 | 8 | const ImageView({super.key, required this.imgPath}); 9 | 10 | @override 11 | State createState() => _ImageViewState(); 12 | } 13 | 14 | class _ImageViewState extends State { 15 | @override 16 | Widget build(BuildContext context) { 17 | return Scaffold( 18 | body: Stack( 19 | children: [ 20 | Hero( 21 | tag: widget.imgPath, 22 | child: SizedBox( 23 | height: MediaQuery.of(context).size.height, 24 | width: MediaQuery.of(context).size.width, 25 | child: CachedNetworkImage( 26 | imageUrl: widget.imgPath, 27 | placeholder: (context, url) => Container( 28 | color: const Color(0xfff5f8fd), 29 | ), 30 | fit: BoxFit.cover), 31 | ), 32 | ), 33 | Container( 34 | height: MediaQuery.of(context).size.height, 35 | width: MediaQuery.of(context).size.width, 36 | alignment: Alignment.bottomCenter, 37 | child: Column( 38 | mainAxisSize: MainAxisSize.min, 39 | children: [ 40 | InkWell( 41 | onTap: () async { 42 | await ImageDownloader.downloadImage(widget.imgPath); 43 | }, 44 | child: Stack( 45 | children: [ 46 | Container( 47 | width: MediaQuery.of(context).size.width / 2, 48 | height: 50, 49 | decoration: BoxDecoration( 50 | color: const Color(0xff1C1B1B).withOpacity(0.8), 51 | borderRadius: BorderRadius.circular(40), 52 | ), 53 | ), 54 | Container( 55 | width: MediaQuery.of(context).size.width / 2, 56 | height: 50, 57 | alignment: Alignment.center, 58 | decoration: BoxDecoration( 59 | border: 60 | Border.all(color: Colors.white24, width: 1), 61 | borderRadius: BorderRadius.circular(40), 62 | gradient: const LinearGradient( 63 | colors: [ 64 | Color(0x36FFFFFF), 65 | Color(0x0FFFFFFF) 66 | ], 67 | begin: FractionalOffset.topLeft, 68 | end: FractionalOffset.bottomRight)), 69 | child: const Text( 70 | "Download", 71 | style: TextStyle( 72 | color: Colors.white70, 73 | fontSize: 15, 74 | fontWeight: FontWeight.w500), 75 | ), 76 | ), 77 | ], 78 | )), 79 | const SizedBox( 80 | height: 50, 81 | ) 82 | ], 83 | ), 84 | ) 85 | ], 86 | ), 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/src/pages/home_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatgpt/src/pages/chat_page.dart'; 2 | import 'package:chatgpt/src/pages/dalle_page.dart'; 3 | import 'package:chatgpt/utils/change_theme_button.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:url_launcher/url_launcher.dart'; 6 | 7 | class HomePage extends StatefulWidget { 8 | const HomePage({super.key}); 9 | 10 | @override 11 | State createState() => _HomePageState(); 12 | } 13 | 14 | class _HomePageState extends State { 15 | @override 16 | Widget build(BuildContext context) { 17 | return Scaffold( 18 | appBar: AppBar( 19 | title: Text( 20 | 'Viki-2 A.I', 21 | style: TextStyle( 22 | color: Theme.of(context).primaryColor, 23 | ), 24 | ), 25 | backgroundColor: Theme.of(context).scaffoldBackgroundColor, 26 | elevation: 0, 27 | centerTitle: true, 28 | actions: [ 29 | ChangeThemeButtonWidget(), 30 | ], 31 | ), 32 | body: Padding( 33 | padding: const EdgeInsets.only(bottom: 50), 34 | child: Column( 35 | mainAxisAlignment: MainAxisAlignment.center, 36 | children: [ 37 | SizedBox( 38 | height: 110, 39 | width: 115, 40 | child: Image.asset('assets/Viki 2 AI.png', fit: BoxFit.cover,), 41 | ), 42 | const SizedBox( 43 | height: 20, 44 | ), 45 | buttonWidget('DALL·E 2 By OpenAI', () { 46 | // _showInterstitialAd(); 47 | Navigator.push( 48 | context, 49 | MaterialPageRoute( 50 | builder: (context) => const DallePage(), 51 | ), 52 | ); 53 | }), 54 | buttonWidget( 55 | 'ChatGPT By OpenAI', 56 | () { 57 | // _showInterstitialAd(); 58 | Navigator.push( 59 | context, 60 | MaterialPageRoute( 61 | builder: (context) => const ChatPage(), 62 | ), 63 | ); 64 | }, 65 | ), 66 | buttonWidget("Join Telegram", () { 67 | _launchUrl( 68 | Uri.parse( 69 | 'http://telegram.me/VikiMediaOfficial/', 70 | ), 71 | ); 72 | } 73 | ), 74 | ], 75 | ), 76 | ), 77 | bottomNavigationBar: Container( 78 | alignment: Alignment.center, 79 | width: double.infinity, 80 | height: 50, 81 | child: const Text('Powered By VikiMedia Official'), 82 | ), 83 | ); 84 | } 85 | 86 | Widget buttonWidget(String text, VoidCallback onTap) { 87 | return InkWell( 88 | onTap: onTap, 89 | child: Container( 90 | decoration: BoxDecoration( 91 | borderRadius: BorderRadius.circular(8), 92 | border: Border.all( 93 | color: Colors.grey.shade400, 94 | ), 95 | ), 96 | padding: const EdgeInsets.symmetric( 97 | vertical: 40, 98 | ), 99 | margin: const EdgeInsets.symmetric( 100 | horizontal: 10, 101 | vertical: 5, 102 | ), 103 | child: Center( 104 | child: Text( 105 | text, 106 | ), 107 | ), 108 | ), 109 | ); 110 | } 111 | 112 | Future _launchUrl(Uri url) async { 113 | if (!await launchUrl( 114 | url, 115 | mode: LaunchMode.externalApplication, 116 | )) throw 'Could not launch $url'; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /lib/src/pages/splash_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatgpt/src/pages/home_page.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_svg/svg.dart'; 4 | 5 | class SplashPage extends StatefulWidget { 6 | const SplashPage({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _SplashPageState(); 10 | } 11 | 12 | class _SplashPageState extends State { 13 | @override 14 | void initState() { 15 | super.initState(); 16 | Future.delayed(const Duration(milliseconds: 1600), () { 17 | setState(() { 18 | // Here we are going to the City List Screen 19 | // we can make isProduction : true for showing active=true cities 20 | // we can make isProduction : false for showing active=false cities 21 | Navigator.pushReplacement( 22 | context, 23 | MaterialPageRoute( 24 | builder: (context) => const HomePage(), 25 | ), 26 | ); 27 | }); 28 | }); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return Scaffold( 34 | body: Center( 35 | child: SvgPicture.asset( 36 | 'assets/openai.svg', 37 | height: 130, 38 | ), 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/utils/change_theme_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatgpt/utils/theme_provider.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:provider/provider.dart'; 4 | 5 | 6 | class ChangeThemeButtonWidget extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | final themeProvider = Provider.of(context); 10 | 11 | return Switch.adaptive( 12 | value: themeProvider.isDarkMode, 13 | onChanged: (value){ 14 | final provider = Provider.of(context, listen: false); 15 | provider.toggleTheme(value); 16 | } 17 | ); 18 | } 19 | } -------------------------------------------------------------------------------- /lib/utils/constants.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | String OPEN_API_KEY = 'OPEN_AI_API_KEY_HERE'; 4 | 5 | String BASE_URL = 'https://api.openai.com/v1/'; 6 | -------------------------------------------------------------------------------- /lib/utils/routes.dart: -------------------------------------------------------------------------------- 1 | import 'package:chatgpt/src/pages/chat_page.dart'; 2 | import 'package:chatgpt/src/pages/dalle_page.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../errors/exceptions.dart'; 6 | 7 | class RouteGenerator { 8 | static const String dalle = 'dalle'; 9 | static const String chat = 'chat'; 10 | RouteGenerator._(); 11 | 12 | static Route generateRoute(RouteSettings settings) { 13 | switch (settings.name) { 14 | case dalle: 15 | return MaterialPageRoute(builder: (_) => const DallePage()); 16 | case chat: 17 | return MaterialPageRoute(builder: (_) => const ChatPage()); 18 | 19 | default: 20 | throw RouteException('Route not found'); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/utils/theme_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ThemeProvider extends ChangeNotifier { 4 | ThemeMode themeMode = ThemeMode.dark; 5 | bool get isDarkMode => themeMode == ThemeMode.dark; 6 | 7 | void toggleTheme(bool isOn){ 8 | themeMode = isOn ? ThemeMode.dark : ThemeMode.light; 9 | notifyListeners(); 10 | } 11 | } 12 | 13 | class MyThemes { 14 | static final darkTheme = ThemeData( 15 | scaffoldBackgroundColor: Colors.grey.shade900, 16 | primaryColor: Colors.white, 17 | colorScheme: const ColorScheme.dark(), 18 | ); 19 | 20 | static final lightTheme = ThemeData( 21 | scaffoldBackgroundColor: Colors.white, 22 | primaryColor: Colors.black87, 23 | colorScheme: const ColorScheme.light(), 24 | ); 25 | } -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | animated_text_kit: 5 | dependency: "direct main" 6 | description: 7 | name: animated_text_kit 8 | sha256: "37392a5376c9a1a503b02463c38bc0342ef814ddbb8f9977bc90f2a84b22fa92" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "4.2.2" 12 | archive: 13 | dependency: transitive 14 | description: 15 | name: archive 16 | sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "3.3.6" 20 | args: 21 | dependency: transitive 22 | description: 23 | name: args 24 | sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "2.4.0" 28 | async: 29 | dependency: transitive 30 | description: 31 | name: async 32 | sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "2.10.0" 36 | boolean_selector: 37 | dependency: transitive 38 | description: 39 | name: boolean_selector 40 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "2.1.1" 44 | cached_network_image: 45 | dependency: "direct main" 46 | description: 47 | name: cached_network_image 48 | sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "3.2.3" 52 | cached_network_image_platform_interface: 53 | dependency: transitive 54 | description: 55 | name: cached_network_image_platform_interface 56 | sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "2.0.0" 60 | cached_network_image_web: 61 | dependency: transitive 62 | description: 63 | name: cached_network_image_web 64 | sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.0.2" 68 | characters: 69 | dependency: transitive 70 | description: 71 | name: characters 72 | sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "1.2.1" 76 | clock: 77 | dependency: transitive 78 | description: 79 | name: clock 80 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "1.1.1" 84 | collection: 85 | dependency: transitive 86 | description: 87 | name: collection 88 | sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "1.17.0" 92 | convert: 93 | dependency: transitive 94 | description: 95 | name: convert 96 | sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" 97 | url: "https://pub.dev" 98 | source: hosted 99 | version: "3.1.1" 100 | crypto: 101 | dependency: transitive 102 | description: 103 | name: crypto 104 | sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 105 | url: "https://pub.dev" 106 | source: hosted 107 | version: "3.0.2" 108 | cupertino_icons: 109 | dependency: "direct main" 110 | description: 111 | name: cupertino_icons 112 | sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be 113 | url: "https://pub.dev" 114 | source: hosted 115 | version: "1.0.5" 116 | dio: 117 | dependency: "direct main" 118 | description: 119 | name: dio 120 | sha256: "0894a098594263fe1caaba3520e3016d8a855caeb010a882273189cca10f11e9" 121 | url: "https://pub.dev" 122 | source: hosted 123 | version: "5.1.1" 124 | fake_async: 125 | dependency: transitive 126 | description: 127 | name: fake_async 128 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 129 | url: "https://pub.dev" 130 | source: hosted 131 | version: "1.3.1" 132 | ffi: 133 | dependency: transitive 134 | description: 135 | name: ffi 136 | sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 137 | url: "https://pub.dev" 138 | source: hosted 139 | version: "2.0.1" 140 | file: 141 | dependency: transitive 142 | description: 143 | name: file 144 | sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" 145 | url: "https://pub.dev" 146 | source: hosted 147 | version: "6.1.4" 148 | flutter: 149 | dependency: "direct main" 150 | description: flutter 151 | source: sdk 152 | version: "0.0.0" 153 | flutter_blurhash: 154 | dependency: transitive 155 | description: 156 | name: flutter_blurhash 157 | sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" 158 | url: "https://pub.dev" 159 | source: hosted 160 | version: "0.7.0" 161 | flutter_cache_manager: 162 | dependency: transitive 163 | description: 164 | name: flutter_cache_manager 165 | sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" 166 | url: "https://pub.dev" 167 | source: hosted 168 | version: "3.3.0" 169 | flutter_lints: 170 | dependency: "direct dev" 171 | description: 172 | name: flutter_lints 173 | sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c 174 | url: "https://pub.dev" 175 | source: hosted 176 | version: "2.0.1" 177 | flutter_staggered_grid_view: 178 | dependency: "direct main" 179 | description: 180 | name: flutter_staggered_grid_view 181 | sha256: "1312314293acceb65b92754298754801b0e1f26a1845833b740b30415bbbcf07" 182 | url: "https://pub.dev" 183 | source: hosted 184 | version: "0.6.2" 185 | flutter_svg: 186 | dependency: "direct main" 187 | description: 188 | name: flutter_svg 189 | sha256: "12006889e2987c549c4c1ec1a5ba4ec4b24d34d2469ee5f9476c926dcecff266" 190 | url: "https://pub.dev" 191 | source: hosted 192 | version: "2.0.4" 193 | flutter_test: 194 | dependency: "direct dev" 195 | description: flutter 196 | source: sdk 197 | version: "0.0.0" 198 | flutter_web_plugins: 199 | dependency: transitive 200 | description: flutter 201 | source: sdk 202 | version: "0.0.0" 203 | http: 204 | dependency: transitive 205 | description: 206 | name: http 207 | sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "0.13.5" 211 | http_parser: 212 | dependency: transitive 213 | description: 214 | name: http_parser 215 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" 216 | url: "https://pub.dev" 217 | source: hosted 218 | version: "4.0.2" 219 | image_downloader: 220 | dependency: "direct main" 221 | description: 222 | name: image_downloader 223 | sha256: "2b1c1d1fcfb6677175d009af3fc86914aee07684c12ea061f380ef1f44cae8df" 224 | url: "https://pub.dev" 225 | source: hosted 226 | version: "0.31.0" 227 | js: 228 | dependency: transitive 229 | description: 230 | name: js 231 | sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" 232 | url: "https://pub.dev" 233 | source: hosted 234 | version: "0.6.5" 235 | lints: 236 | dependency: transitive 237 | description: 238 | name: lints 239 | sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" 240 | url: "https://pub.dev" 241 | source: hosted 242 | version: "2.0.1" 243 | logger: 244 | dependency: "direct main" 245 | description: 246 | name: logger 247 | sha256: db2ff852ed77090ba9f62d3611e4208a3d11dfa35991a81ae724c113fcb3e3f7 248 | url: "https://pub.dev" 249 | source: hosted 250 | version: "1.3.0" 251 | lottie: 252 | dependency: "direct main" 253 | description: 254 | name: lottie 255 | sha256: "23522951540d20a57a60202ed7022e6376bed206a4eee1c347a91f58bd57eb9f" 256 | url: "https://pub.dev" 257 | source: hosted 258 | version: "2.3.2" 259 | matcher: 260 | dependency: transitive 261 | description: 262 | name: matcher 263 | sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" 264 | url: "https://pub.dev" 265 | source: hosted 266 | version: "0.12.13" 267 | material_color_utilities: 268 | dependency: transitive 269 | description: 270 | name: material_color_utilities 271 | sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 272 | url: "https://pub.dev" 273 | source: hosted 274 | version: "0.2.0" 275 | meta: 276 | dependency: transitive 277 | description: 278 | name: meta 279 | sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" 280 | url: "https://pub.dev" 281 | source: hosted 282 | version: "1.8.0" 283 | nested: 284 | dependency: transitive 285 | description: 286 | name: nested 287 | sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" 288 | url: "https://pub.dev" 289 | source: hosted 290 | version: "1.0.0" 291 | octo_image: 292 | dependency: transitive 293 | description: 294 | name: octo_image 295 | sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" 296 | url: "https://pub.dev" 297 | source: hosted 298 | version: "1.0.2" 299 | path: 300 | dependency: transitive 301 | description: 302 | name: path 303 | sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b 304 | url: "https://pub.dev" 305 | source: hosted 306 | version: "1.8.2" 307 | path_parsing: 308 | dependency: transitive 309 | description: 310 | name: path_parsing 311 | sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf 312 | url: "https://pub.dev" 313 | source: hosted 314 | version: "1.0.1" 315 | path_provider: 316 | dependency: transitive 317 | description: 318 | name: path_provider 319 | sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4 320 | url: "https://pub.dev" 321 | source: hosted 322 | version: "2.0.14" 323 | path_provider_android: 324 | dependency: transitive 325 | description: 326 | name: path_provider_android 327 | sha256: "019f18c9c10ae370b08dce1f3e3b73bc9f58e7f087bb5e921f06529438ac0ae7" 328 | url: "https://pub.dev" 329 | source: hosted 330 | version: "2.0.24" 331 | path_provider_foundation: 332 | dependency: transitive 333 | description: 334 | name: path_provider_foundation 335 | sha256: "818b2dc38b0f178e0ea3f7cf3b28146faab11375985d815942a68eee11c2d0f7" 336 | url: "https://pub.dev" 337 | source: hosted 338 | version: "2.2.1" 339 | path_provider_linux: 340 | dependency: transitive 341 | description: 342 | name: path_provider_linux 343 | sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" 344 | url: "https://pub.dev" 345 | source: hosted 346 | version: "2.1.10" 347 | path_provider_platform_interface: 348 | dependency: transitive 349 | description: 350 | name: path_provider_platform_interface 351 | sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" 352 | url: "https://pub.dev" 353 | source: hosted 354 | version: "2.0.6" 355 | path_provider_windows: 356 | dependency: transitive 357 | description: 358 | name: path_provider_windows 359 | sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 360 | url: "https://pub.dev" 361 | source: hosted 362 | version: "2.1.5" 363 | pedantic: 364 | dependency: transitive 365 | description: 366 | name: pedantic 367 | sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" 368 | url: "https://pub.dev" 369 | source: hosted 370 | version: "1.11.1" 371 | petitparser: 372 | dependency: transitive 373 | description: 374 | name: petitparser 375 | sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" 376 | url: "https://pub.dev" 377 | source: hosted 378 | version: "5.1.0" 379 | platform: 380 | dependency: transitive 381 | description: 382 | name: platform 383 | sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" 384 | url: "https://pub.dev" 385 | source: hosted 386 | version: "3.1.0" 387 | plugin_platform_interface: 388 | dependency: transitive 389 | description: 390 | name: plugin_platform_interface 391 | sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" 392 | url: "https://pub.dev" 393 | source: hosted 394 | version: "2.1.4" 395 | pointycastle: 396 | dependency: transitive 397 | description: 398 | name: pointycastle 399 | sha256: c3120a968135aead39699267f4c74bc9a08e4e909e86bc1b0af5bfd78691123c 400 | url: "https://pub.dev" 401 | source: hosted 402 | version: "3.7.2" 403 | process: 404 | dependency: transitive 405 | description: 406 | name: process 407 | sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" 408 | url: "https://pub.dev" 409 | source: hosted 410 | version: "4.2.4" 411 | provider: 412 | dependency: "direct main" 413 | description: 414 | name: provider 415 | sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f 416 | url: "https://pub.dev" 417 | source: hosted 418 | version: "6.0.5" 419 | rxdart: 420 | dependency: transitive 421 | description: 422 | name: rxdart 423 | sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" 424 | url: "https://pub.dev" 425 | source: hosted 426 | version: "0.27.7" 427 | shared_preferences: 428 | dependency: "direct main" 429 | description: 430 | name: shared_preferences 431 | sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b" 432 | url: "https://pub.dev" 433 | source: hosted 434 | version: "2.1.0" 435 | shared_preferences_android: 436 | dependency: transitive 437 | description: 438 | name: shared_preferences_android 439 | sha256: "8304d8a1f7d21a429f91dee552792249362b68a331ac5c3c1caf370f658873f6" 440 | url: "https://pub.dev" 441 | source: hosted 442 | version: "2.1.0" 443 | shared_preferences_foundation: 444 | dependency: transitive 445 | description: 446 | name: shared_preferences_foundation 447 | sha256: cf2a42fb20148502022861f71698db12d937c7459345a1bdaa88fc91a91b3603 448 | url: "https://pub.dev" 449 | source: hosted 450 | version: "2.2.0" 451 | shared_preferences_linux: 452 | dependency: transitive 453 | description: 454 | name: shared_preferences_linux 455 | sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" 456 | url: "https://pub.dev" 457 | source: hosted 458 | version: "2.2.0" 459 | shared_preferences_platform_interface: 460 | dependency: transitive 461 | description: 462 | name: shared_preferences_platform_interface 463 | sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d 464 | url: "https://pub.dev" 465 | source: hosted 466 | version: "2.2.0" 467 | shared_preferences_web: 468 | dependency: transitive 469 | description: 470 | name: shared_preferences_web 471 | sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" 472 | url: "https://pub.dev" 473 | source: hosted 474 | version: "2.1.0" 475 | shared_preferences_windows: 476 | dependency: transitive 477 | description: 478 | name: shared_preferences_windows 479 | sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" 480 | url: "https://pub.dev" 481 | source: hosted 482 | version: "2.2.0" 483 | shimmer: 484 | dependency: "direct main" 485 | description: 486 | name: shimmer 487 | sha256: "1f1009b5845a1f88f1c5630212279540486f97409e9fc3f63883e71070d107bf" 488 | url: "https://pub.dev" 489 | source: hosted 490 | version: "2.0.0" 491 | sky_engine: 492 | dependency: transitive 493 | description: flutter 494 | source: sdk 495 | version: "0.0.99" 496 | source_span: 497 | dependency: transitive 498 | description: 499 | name: source_span 500 | sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 501 | url: "https://pub.dev" 502 | source: hosted 503 | version: "1.9.1" 504 | sqflite: 505 | dependency: transitive 506 | description: 507 | name: sqflite 508 | sha256: "500d6fec583d2c021f2d25a056d96654f910662c64f836cd2063167b8f1fa758" 509 | url: "https://pub.dev" 510 | source: hosted 511 | version: "2.2.6" 512 | sqflite_common: 513 | dependency: transitive 514 | description: 515 | name: sqflite_common 516 | sha256: "963dad8c4aa2f814ce7d2d5b1da2f36f31bd1a439d8f27e3dc189bb9d26bc684" 517 | url: "https://pub.dev" 518 | source: hosted 519 | version: "2.4.3" 520 | stack_trace: 521 | dependency: transitive 522 | description: 523 | name: stack_trace 524 | sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 525 | url: "https://pub.dev" 526 | source: hosted 527 | version: "1.11.0" 528 | stream_channel: 529 | dependency: transitive 530 | description: 531 | name: stream_channel 532 | sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" 533 | url: "https://pub.dev" 534 | source: hosted 535 | version: "2.1.1" 536 | string_scanner: 537 | dependency: transitive 538 | description: 539 | name: string_scanner 540 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 541 | url: "https://pub.dev" 542 | source: hosted 543 | version: "1.2.0" 544 | synchronized: 545 | dependency: transitive 546 | description: 547 | name: synchronized 548 | sha256: "33b31b6beb98100bf9add464a36a8dd03eb10c7a8cf15aeec535e9b054aaf04b" 549 | url: "https://pub.dev" 550 | source: hosted 551 | version: "3.0.1" 552 | term_glyph: 553 | dependency: transitive 554 | description: 555 | name: term_glyph 556 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 557 | url: "https://pub.dev" 558 | source: hosted 559 | version: "1.2.1" 560 | test_api: 561 | dependency: transitive 562 | description: 563 | name: test_api 564 | sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 565 | url: "https://pub.dev" 566 | source: hosted 567 | version: "0.4.16" 568 | typed_data: 569 | dependency: transitive 570 | description: 571 | name: typed_data 572 | sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" 573 | url: "https://pub.dev" 574 | source: hosted 575 | version: "1.3.1" 576 | url_launcher: 577 | dependency: "direct main" 578 | description: 579 | name: url_launcher 580 | sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e" 581 | url: "https://pub.dev" 582 | source: hosted 583 | version: "6.1.10" 584 | url_launcher_android: 585 | dependency: transitive 586 | description: 587 | name: url_launcher_android 588 | sha256: dd729390aa936bf1bdf5cd1bc7468ff340263f80a2c4f569416507667de8e3c8 589 | url: "https://pub.dev" 590 | source: hosted 591 | version: "6.0.26" 592 | url_launcher_ios: 593 | dependency: transitive 594 | description: 595 | name: url_launcher_ios 596 | sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" 597 | url: "https://pub.dev" 598 | source: hosted 599 | version: "6.1.4" 600 | url_launcher_linux: 601 | dependency: transitive 602 | description: 603 | name: url_launcher_linux 604 | sha256: "206fb8334a700ef7754d6a9ed119e7349bc830448098f21a69bf1b4ed038cabc" 605 | url: "https://pub.dev" 606 | source: hosted 607 | version: "3.0.4" 608 | url_launcher_macos: 609 | dependency: transitive 610 | description: 611 | name: url_launcher_macos 612 | sha256: "0ef2b4f97942a16523e51256b799e9aa1843da6c60c55eefbfa9dbc2dcb8331a" 613 | url: "https://pub.dev" 614 | source: hosted 615 | version: "3.0.4" 616 | url_launcher_platform_interface: 617 | dependency: transitive 618 | description: 619 | name: url_launcher_platform_interface 620 | sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" 621 | url: "https://pub.dev" 622 | source: hosted 623 | version: "2.1.2" 624 | url_launcher_web: 625 | dependency: transitive 626 | description: 627 | name: url_launcher_web 628 | sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" 629 | url: "https://pub.dev" 630 | source: hosted 631 | version: "2.0.16" 632 | url_launcher_windows: 633 | dependency: transitive 634 | description: 635 | name: url_launcher_windows 636 | sha256: a83ba3607a507758669cfafb03f9de09bf6e6280c14d9b9cb18f013e406dcacd 637 | url: "https://pub.dev" 638 | source: hosted 639 | version: "3.0.5" 640 | uuid: 641 | dependency: transitive 642 | description: 643 | name: uuid 644 | sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" 645 | url: "https://pub.dev" 646 | source: hosted 647 | version: "3.0.7" 648 | vector_graphics: 649 | dependency: transitive 650 | description: 651 | name: vector_graphics 652 | sha256: "4cf8e60dbe4d3a693d37dff11255a172594c0793da542183cbfe7fe978ae4aaa" 653 | url: "https://pub.dev" 654 | source: hosted 655 | version: "1.1.4" 656 | vector_graphics_codec: 657 | dependency: transitive 658 | description: 659 | name: vector_graphics_codec 660 | sha256: "278ad5f816f58b1967396d1f78ced470e3e58c9fe4b27010102c0a595c764468" 661 | url: "https://pub.dev" 662 | source: hosted 663 | version: "1.1.4" 664 | vector_graphics_compiler: 665 | dependency: transitive 666 | description: 667 | name: vector_graphics_compiler 668 | sha256: "0bf61ad56e6fd6688a2865d3ceaea396bc6a0a90ea0d7ad5049b1b76c09d6163" 669 | url: "https://pub.dev" 670 | source: hosted 671 | version: "1.1.4" 672 | vector_math: 673 | dependency: transitive 674 | description: 675 | name: vector_math 676 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 677 | url: "https://pub.dev" 678 | source: hosted 679 | version: "2.1.4" 680 | win32: 681 | dependency: transitive 682 | description: 683 | name: win32 684 | sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4 685 | url: "https://pub.dev" 686 | source: hosted 687 | version: "3.1.4" 688 | xdg_directories: 689 | dependency: transitive 690 | description: 691 | name: xdg_directories 692 | sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 693 | url: "https://pub.dev" 694 | source: hosted 695 | version: "1.0.0" 696 | xml: 697 | dependency: transitive 698 | description: 699 | name: xml 700 | sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" 701 | url: "https://pub.dev" 702 | source: hosted 703 | version: "6.2.2" 704 | sdks: 705 | dart: ">=2.19.0-0 <3.0.0" 706 | flutter: ">=3.7.0-0" 707 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: chatgpt 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | # In Windows, build-name is used as the major, minor, and patch parts 19 | # of the product and file versions while build-number is used as the build suffix. 20 | version: 1.0.2+3 21 | 22 | environment: 23 | sdk: '>=2.18.6 <3.0.0' 24 | 25 | # Dependencies specify other packages that your package needs in order to work. 26 | # To automatically upgrade your package dependencies to the latest versions 27 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 28 | # dependencies can be manually updated by changing the version numbers below to 29 | # the latest version available on pub.dev. To see which dependencies have newer 30 | # versions available, run `flutter pub outdated`. 31 | dependencies: 32 | animated_text_kit: ^4.2.2 33 | cached_network_image: ^3.2.3 34 | cupertino_icons: ^1.0.2 35 | dio: ^5.1.1 36 | flutter: 37 | sdk: flutter 38 | flutter_staggered_grid_view: ^0.6.2 39 | flutter_svg: ^2.0.4 40 | image_downloader: ^0.31.0 41 | logger: ^1.1.0 42 | lottie: ^2.1.0 43 | provider: ^6.0.5 44 | shared_preferences: ^2.0.15 45 | shimmer: ^2.0.0 46 | url_launcher: ^6.1.7 47 | 48 | dev_dependencies: 49 | flutter_lints: ^2.0.0 50 | flutter_test: 51 | sdk: flutter 52 | 53 | # For information on the generic Dart part of this file, see the 54 | # following page: https://dart.dev/tools/pub/pubspec 55 | # The following section is specific to Flutter packages. 56 | flutter: 57 | 58 | # The following line ensures that the Material Icons font is 59 | # included with your application, so that you can use the icons in 60 | # the material Icons class. 61 | uses-material-design: true 62 | # To add assets to your application, add an assets section, like this: 63 | assets: 64 | - assets/openai.svg 65 | - assets/Viki 2 AI.png 66 | # - images/a_dot_ham.jpeg 67 | # An image asset can refer to one or more resolution-specific "variants", see 68 | # https://flutter.dev/assets-and-images/#resolution-aware 69 | # For details regarding adding assets from package dependencies, see 70 | # https://flutter.dev/assets-and-images/#from-packages 71 | # To add custom fonts to your application, add a fonts section here, 72 | # in this "flutter" section. Each entry in this list should have a 73 | # "family" key with the font family name, and a "fonts" key with a 74 | # list giving the asset and other descriptors for the font. For 75 | # example: 76 | # fonts: 77 | # - family: Schyler 78 | # fonts: 79 | # - asset: fonts/Schyler-Regular.ttf 80 | # - asset: fonts/Schyler-Italic.ttf 81 | # style: italic 82 | # - family: Trajan Pro 83 | # fonts: 84 | # - asset: fonts/TrajanPro.ttf 85 | # - asset: fonts/TrajanPro_Bold.ttf 86 | # weight: 700 87 | # 88 | # For details regarding fonts from package dependencies, 89 | # see https://flutter.dev/custom-fonts/#from-packages 90 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:chatgpt/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /update_version.json: -------------------------------------------------------------------------------- 1 | { 2 | "versionCode":2, 3 | "versionName":"1.0.0", 4 | "contentText":"Please update your app", 5 | "minSupport":2, 6 | "url":"https://github.com/VikramadityaDev/Viki-2-OpenAI/releases/download/v1.0.1/app-armeabi-v7a-release.apk" 7 | } 8 | --------------------------------------------------------------------------------