├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── README.zh-Hans.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── bapaws
│ │ │ │ └── answer
│ │ │ │ └── MainActivity.java
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ └── splash.png
│ │ │ ├── drawable-mdpi
│ │ │ └── splash.png
│ │ │ ├── drawable-v21
│ │ │ ├── background.png
│ │ │ └── launch_background.xml
│ │ │ ├── drawable-xhdpi
│ │ │ └── splash.png
│ │ │ ├── drawable-xxhdpi
│ │ │ └── splash.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ └── splash.png
│ │ │ ├── drawable
│ │ │ ├── background.png
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── launcher_icon.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── files
│ ├── request_parameters.json
│ ├── service_providers.json
│ ├── service_tokens.json
│ └── service_vendors.json
└── images
│ ├── ai_avatar.png
│ ├── logo-green.png
│ ├── logo-white.png
│ ├── open_ai.svg
│ ├── open_ai_chat_gpt.svg
│ └── open_ai_gpt_4.svg
├── img
├── Icon-App-1024x1024@1x.png
├── android-screen-dark.png
├── android-screen-light.png
├── app-store.svg
├── google-play-badge.png
├── ios-screen-dark.png
├── ios-screen-light.png
└── testflight.png
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-50x50@1x.png
│ │ ├── Icon-App-50x50@2x.png
│ │ ├── Icon-App-57x57@1x.png
│ │ ├── Icon-App-57x57@2x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-72x72@1x.png
│ │ ├── Icon-App-72x72@2x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ ├── LaunchBackground.imageset
│ │ ├── Contents.json
│ │ └── background.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── Runner-Bridging-Header.h
│ ├── en.lproj
│ └── InfoPlist.strings
│ └── zh-Hans.lproj
│ └── InfoPlist.strings
├── lib
├── app
│ ├── app.dart
│ ├── app_translation.dart
│ ├── core
│ │ ├── app
│ │ │ ├── app_controller_mixin.dart
│ │ │ ├── app_hive_keys.dart
│ │ │ ├── app_http.dart
│ │ │ ├── app_http_overrides.dart
│ │ │ ├── app_manager.dart
│ │ │ ├── app_model.dart
│ │ │ ├── app_plugin.dart
│ │ │ ├── app_plugin_manager.dart
│ │ │ ├── app_progress_hud.dart
│ │ │ ├── app_theme.dart
│ │ │ ├── app_toast.dart
│ │ │ ├── app_urls.dart
│ │ │ └── app_view_mixin.dart
│ │ ├── binding
│ │ │ └── initial_binding.dart
│ │ └── mixin
│ │ │ └── refresh_mixin.dart
│ ├── data
│ │ ├── db
│ │ │ ├── app_database.dart
│ │ │ ├── app_uuid.dart
│ │ │ ├── conversations_dao.dart
│ │ │ ├── groups_dao.dart
│ │ │ ├── messages_dao.dart
│ │ │ ├── prompt_dao.dart
│ │ │ ├── request_parameters_dao.dart
│ │ │ ├── service_providers_dao.dart
│ │ │ ├── service_tokens_dao.dart
│ │ │ └── service_vendors_dao.dart
│ │ └── models
│ │ │ ├── conversation.dart
│ │ │ ├── group.dart
│ │ │ ├── message.dart
│ │ │ ├── prompt.dart
│ │ │ ├── request_parameter.dart
│ │ │ ├── service_token.dart
│ │ │ └── value_serializer.dart
│ ├── modules
│ │ ├── conversation
│ │ │ ├── bindings
│ │ │ │ └── conversation_binding.dart
│ │ │ ├── controllers
│ │ │ │ └── conversation_controller.dart
│ │ │ └── views
│ │ │ │ ├── conversation_view.dart
│ │ │ │ └── services_item_view.dart
│ │ ├── home
│ │ │ ├── bindings
│ │ │ │ └── home_binding.dart
│ │ │ ├── controllers
│ │ │ │ └── home_controller.dart
│ │ │ └── views
│ │ │ │ ├── home_bar.dart
│ │ │ │ ├── home_body.dart
│ │ │ │ ├── home_drawer.dart
│ │ │ │ └── home_view.dart
│ │ ├── new_prompt
│ │ │ ├── bindings
│ │ │ │ └── new_prompt_binding.dart
│ │ │ ├── controllers
│ │ │ │ └── new_prompt_controller.dart
│ │ │ └── views
│ │ │ │ └── new_prompt_view.dart
│ │ ├── prompt
│ │ │ ├── bindings
│ │ │ │ └── prompt_binding.dart
│ │ │ ├── controllers
│ │ │ │ └── prompt_controller.dart
│ │ │ └── views
│ │ │ │ └── prompt_view.dart
│ │ ├── service
│ │ │ ├── bindings
│ │ │ │ └── service_binding.dart
│ │ │ ├── controllers
│ │ │ │ └── service_controller.dart
│ │ │ └── views
│ │ │ │ ├── service_info.dart
│ │ │ │ ├── service_token_item_view.dart
│ │ │ │ └── service_view.dart
│ │ ├── settings
│ │ │ ├── bindings
│ │ │ │ └── settings_binding.dart
│ │ │ ├── controllers
│ │ │ │ └── settings_controller.dart
│ │ │ └── views
│ │ │ │ └── settings_view.dart
│ │ └── vendor
│ │ │ ├── bindings
│ │ │ └── vendor_binding.dart
│ │ │ ├── controllers
│ │ │ └── vendor_controller.dart
│ │ │ └── views
│ │ │ └── vendor_view.dart
│ ├── providers
│ │ ├── open_ai
│ │ │ ├── chat_gpt.dart
│ │ │ ├── chat_gpt_3.dart
│ │ │ ├── chat_gpt_4.dart
│ │ │ ├── chat_gpt_api.dart
│ │ │ └── chat_gpt_model.dart
│ │ ├── service_provider.dart
│ │ ├── service_provider_manager.dart
│ │ └── service_vendor.dart
│ ├── routes
│ │ ├── app_pages.dart
│ │ └── app_routes.dart
│ └── views
│ │ ├── app_cell.dart
│ │ ├── app_section.dart
│ │ ├── chat_avatar.dart
│ │ ├── chat_base_item_view.dart
│ │ ├── chat_input.dart
│ │ ├── chat_loading_item_view.dart
│ │ ├── chat_text_receive_item_view.dart
│ │ ├── chat_view.dart
│ │ ├── code_element_builder.dart
│ │ └── code_highlight_view.dart
├── flavors
│ ├── build_config.dart
│ ├── env_config.dart
│ └── environment.dart
└── main.dart
├── linux
├── .gitignore
├── CMakeLists.txt
├── flutter
│ ├── CMakeLists.txt
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ └── generated_plugins.cmake
├── main.cc
├── my_application.cc
└── my_application.h
├── macos
├── .gitignore
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── app_icon_1024.png
│ │ │ ├── app_icon_128.png
│ │ │ ├── app_icon_16.png
│ │ │ ├── app_icon_256.png
│ │ │ ├── app_icon_32.png
│ │ │ ├── app_icon_512.png
│ │ │ └── app_icon_64.png
│ ├── Base.lproj
│ │ └── MainMenu.xib
│ ├── Configs
│ │ ├── AppInfo.xcconfig
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── Warnings.xcconfig
│ ├── DebugProfile.entitlements
│ ├── Info.plist
│ ├── MainFlutterWindow.swift
│ └── Release.entitlements
└── firebase_app_id_file.json
├── pubspec.lock
├── pubspec.yaml
├── test
└── widget_test.dart
├── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
├── manifest.json
└── splash
│ ├── img
│ ├── dark-1x.png
│ ├── dark-2x.png
│ ├── dark-3x.png
│ ├── dark-4x.png
│ ├── light-1x.png
│ ├── light-2x.png
│ ├── light-3x.png
│ └── light-4x.png
│ ├── splash.js
│ └── style.css
└── windows
├── .gitignore
├── CMakeLists.txt
├── flutter
├── CMakeLists.txt
├── generated_plugin_registrant.cc
├── generated_plugin_registrant.h
└── generated_plugins.cmake
└── runner
├── CMakeLists.txt
├── Runner.rc
├── flutter_window.cpp
├── flutter_window.h
├── main.cpp
├── resource.h
├── resources
└── app_icon.ico
├── runner.exe.manifest
├── utils.cpp
├── utils.h
├── win32_window.cpp
└── win32_window.h
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | .vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 | main_dev.dart
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Android Studio will place build artifacts here
43 | /android/app/debug
44 | /android/app/profile
45 | /android/app/release
46 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
17 | base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
18 | - platform: android
19 | create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
20 | base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
21 | - platform: ios
22 | create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
23 | base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
24 | - platform: linux
25 | create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
26 | base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
27 | - platform: macos
28 | create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
29 | base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
30 | - platform: web
31 | create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
32 | base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
33 | - platform: windows
34 | create_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
35 | base_revision: 12cb4eb7a009f52b347b62ade7cb4854b926af72
36 |
37 | # User provided section
38 |
39 | # List of Local paths (relative to this file) that should be
40 | # ignored by the migrate tool.
41 | #
42 | # Files that are not part of the templates will be ignored by default.
43 | unmanaged_files:
44 | - 'lib/main.dart'
45 | - 'ios/Runner.xcodeproj/project.pbxproj'
46 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Chat Answer
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Chat Answer is an open source app based on ChatGPT API.
22 |
23 | ## iOS App
24 |
25 | ### Download
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ### Screen
34 | 
35 |
36 | ## Android App
37 |
38 | ### Download
39 | #### Google Play
40 |
41 |
42 |
43 |
44 | #### GitHub
45 | 1. GitHub Latest Release
46 | 2. Download "app-release.apk".
47 |
48 | ### Screen
49 | 
50 |
51 | ## Roadmap
52 |
53 | - [x] ChatGPT Service
54 | - [x] ChatGPT API Key & API URL setting
55 | - [x] Conversations local storage
56 | - [x] Add or delete conversations
57 | - [x] Messages local storage
58 | - [x] Support markdown
59 | - [x] Support code block highlight
60 | - [x] Support conversation settings
61 | - [x] Support quote message
62 | - [x] Support add prompts
63 | - [x] Support system message
64 | - [ ] Support delete message
65 | - [ ] Add App level settings
66 | - [ ] Support for code replication
67 | - [ ] Support more chat scenarios
68 | - [ ] Support chat stream output
69 | - [ ] Add App level prompts manager
70 | - [ ] Add prompts quick send button on chat page
71 |
72 | ## License
73 |
74 | [GNU General Public License v3.0](./LICENSE)
--------------------------------------------------------------------------------
/README.zh-Hans.md:
--------------------------------------------------------------------------------
1 | # 小答
2 |
3 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | 小答是一款基于 ChatGPT API 的开源客户端。
22 |
23 | ## iOS App
24 |
25 | ### 下载
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ### 预览
34 | 
35 | 
36 |
37 | ## Android App
38 |
39 | ### 下载
40 | #### Google Play
41 |
42 |
43 |
44 |
45 | #### GitHub
46 | 1. 点击 GitHub Latest Release
47 | 2. 点击页面中的 "app-release.apk" 开始下载。
48 |
49 | ### 预览
50 | 
51 |
52 | ## Roadmap
53 |
54 | - [x] ChatGPT 服务
55 | - [x] ChatGPT API Key 和 API URL 设置
56 | - [x] 会话本地存储
57 | - [x] 新增及删除会话
58 | - [x] 消息本地存储
59 | - [x] 消息支持 Markdown
60 | - [x] 支持代码块高亮显示
61 | - [x] 支持会话设置
62 | - [x] 支持引用消息设置上下文
63 | - [x] 支持系统角色设置
64 | - [x] 支持系统消息
65 | - [ ] 支持删除消息
66 | - [ ] 应用设置,支持语言、外观切换
67 | - [ ] 代码块的复制按钮
68 | - [ ] 支持更多聊天场景
69 |
70 | ## License
71 |
72 | [GNU General Public License v3.0](./LICENSE)
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
2 | linter:
3 | rules:
4 |
5 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/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 | signingConfigs {
30 | release {
31 | storeFile file('/Users/zhangminchao/Documents/Google Play/upload-keystore.jks')
32 | storePassword '8Paws.com'
33 | keyAlias 'upload'
34 | keyPassword '8Paws.com'
35 | }
36 | }
37 | compileSdkVersion flutter.compileSdkVersion
38 | ndkVersion flutter.ndkVersion
39 |
40 | compileOptions {
41 | sourceCompatibility JavaVersion.VERSION_1_8
42 | targetCompatibility JavaVersion.VERSION_1_8
43 | }
44 |
45 | defaultConfig {
46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
47 | applicationId "com.bapaws.answer"
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-gradle-build-configuration.
50 | minSdkVersion flutter.minSdkVersion
51 | targetSdkVersion flutter.targetSdkVersion
52 | versionCode flutterVersionCode.toInteger()
53 | versionName flutterVersionName
54 | signingConfig signingConfigs.release
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.release
62 | }
63 | }
64 | }
65 |
66 | flutter {
67 | source '../..'
68 | }
69 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
16 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
31 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/bapaws/answer/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.bapaws.answer;
2 |
3 | import io.flutter.embedding.android.FlutterActivity;
4 |
5 | public class MainActivity extends FlutterActivity {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-hdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/drawable-hdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-mdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/drawable-mdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/drawable-v21/background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/drawable-xhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/drawable-xxhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxxhdpi/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/drawable-xxxhdpi/splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/drawable/background.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/mipmap-hdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/mipmap-mdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.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 |
13 |
19 |
22 |
23 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.7.10'
3 | repositories {
4 | maven { url 'https://maven.aliyun.com/repository/public/' }
5 | maven { url 'https://maven.aliyun.com/repository/central' }
6 | maven { url 'https://maven.aliyun.com/repository/google' }
7 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
8 | google()
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | classpath 'com.android.tools.build:gradle:7.2.0'
14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | maven { url 'https://maven.aliyun.com/repository/public/' }
21 | maven { url 'https://maven.aliyun.com/repository/central' }
22 | maven { url 'https://maven.aliyun.com/repository/google' }
23 | maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
24 | google()
25 | mavenCentral()
26 | }
27 | }
28 |
29 | rootProject.buildDir = '../build'
30 | subprojects {
31 | project.buildDir = "${rootProject.buildDir}/${project.name}"
32 | }
33 | subprojects {
34 | project.evaluationDependsOn(':app')
35 | }
36 |
37 | task clean(type: Delete) {
38 | delete rootProject.buildDir
39 | }
40 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/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.5-all.zip
6 |
--------------------------------------------------------------------------------
/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/files/request_parameters.json:
--------------------------------------------------------------------------------
1 | W3sia2V5IjoibWF4X3Rva2VucyIsInZhbHVlIjoiODAwIiwidmFsdWVfdHlwZSI6MCwidmVuZG9yX2lkIjoib3Blbl9haV9jaGF0X2dwdCJ9LHsia2V5IjoidGltZW91dCIsInZhbHVlIjoiNjAiLCJ2YWx1ZV90eXBlIjowLCJ2ZW5kb3JfaWQiOiJvcGVuX2FpX2NoYXRfZ3B0In1d
--------------------------------------------------------------------------------
/assets/files/service_providers.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "open_ai_chat_gpt",
4 | "name": "Chat GPT",
5 | "avatar": "assets/images/open_ai_chat_gpt.svg",
6 | "group_id": 0,
7 | "official_url": "https://api.openai.com/v1/chat/completions",
8 | "api_url": "",
9 | "help": "Help",
10 | "help_url": "Help",
11 | "tokens": [
12 | {
13 | "name": "API Key",
14 | "service_provider_id": "open_ai_chat_gpt"
15 | }
16 | ]
17 | },
18 | {
19 | "id": "open_ai_chat_gpt_secret_api",
20 | "name": "Chat GPT Secret API",
21 | "avatar": "assets/images/open_ai_chat_gpt.svg",
22 | "group_id": 0,
23 | "official_url": "https://api.openai.com/v1/chat/completions",
24 | "api_url": "https://chat.openai.com/chat",
25 | "help": "Help",
26 | "help_url": "Help",
27 | "tokens": [
28 | {
29 | "name": "Session Token",
30 | "service_provider_id": "open_ai_chat_gpt_secret_api"
31 | }
32 | ]
33 | }
34 | ]
--------------------------------------------------------------------------------
/assets/files/service_tokens.json:
--------------------------------------------------------------------------------
1 | W3siaWQiOiJjaGF0X2dwdF9hcGlfa2V5IiwibmFtZSI6IkFQSSBLZXkiLCJzZXJ2aWNlX3Byb3ZpZGVyX2lkIjoib3Blbl9haV9jaGF0X2dwdCJ9XQ==
--------------------------------------------------------------------------------
/assets/files/service_vendors.json:
--------------------------------------------------------------------------------
1 | W3siaWQiOiJvcGVuX2FpX2NoYXRfZ3B0IiwibmFtZSI6Ik9wZW5BSSIsImF2YXRhciI6ImFzc2V0cy9pbWFnZXMvb3Blbl9haS5zdmciLCJvZmZpY2lhbF91cmwiOiJodHRwczovL29wZW5haS5jb20vIiwiYXBpX3VybCI6Imh0dHBzOi8vYXBpLm9wZW5haS5jb20vdjEvY2hhdC9jb21wbGV0aW9ucyIsImhlbHAiOiJjaGF0X2dwdF9oZWxwIiwiaGVscF91cmwiOiJodHRwczovL3d3dy5iYXBhd3MuY29tL2Fuc3dlci9oZWxwL2NoYXRfZ3B0Lmh0bWwiLCJoZWxsbyI6Im9wZW5fYWlfaGVsbG8ifV0=
--------------------------------------------------------------------------------
/assets/images/ai_avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/assets/images/ai_avatar.png
--------------------------------------------------------------------------------
/assets/images/logo-green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/assets/images/logo-green.png
--------------------------------------------------------------------------------
/assets/images/logo-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/assets/images/logo-white.png
--------------------------------------------------------------------------------
/assets/images/open_ai.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/images/open_ai_gpt_4.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/img/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/img/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/img/android-screen-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/img/android-screen-dark.png
--------------------------------------------------------------------------------
/img/android-screen-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/img/android-screen-light.png
--------------------------------------------------------------------------------
/img/google-play-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/img/google-play-badge.png
--------------------------------------------------------------------------------
/img/ios-screen-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/img/ios-screen-dark.png
--------------------------------------------------------------------------------
/img/ios-screen-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/img/ios-screen-light.png
--------------------------------------------------------------------------------
/img/testflight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/img/testflight.png
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '11.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 | - flutter_mailer (0.0.1):
4 | - Flutter
5 | - flutter_native_splash (0.0.1):
6 | - Flutter
7 | - fluttertoast (0.0.2):
8 | - Flutter
9 | - Toast
10 | - FMDB (2.7.5):
11 | - FMDB/standard (= 2.7.5)
12 | - FMDB/standard (2.7.5)
13 | - in_app_review (0.2.0):
14 | - Flutter
15 | - path_provider_foundation (0.0.1):
16 | - Flutter
17 | - FlutterMacOS
18 | - share_plus (0.0.1):
19 | - Flutter
20 | - shared_preferences_foundation (0.0.1):
21 | - Flutter
22 | - FlutterMacOS
23 | - sqflite (0.0.2):
24 | - Flutter
25 | - FMDB (>= 2.7.5)
26 | - Toast (4.0.0)
27 | - url_launcher_ios (0.0.1):
28 | - Flutter
29 |
30 | DEPENDENCIES:
31 | - Flutter (from `Flutter`)
32 | - flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`)
33 | - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
34 | - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
35 | - in_app_review (from `.symlinks/plugins/in_app_review/ios`)
36 | - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
37 | - share_plus (from `.symlinks/plugins/share_plus/ios`)
38 | - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
39 | - sqflite (from `.symlinks/plugins/sqflite/ios`)
40 | - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
41 |
42 | SPEC REPOS:
43 | trunk:
44 | - FMDB
45 | - Toast
46 |
47 | EXTERNAL SOURCES:
48 | Flutter:
49 | :path: Flutter
50 | flutter_mailer:
51 | :path: ".symlinks/plugins/flutter_mailer/ios"
52 | flutter_native_splash:
53 | :path: ".symlinks/plugins/flutter_native_splash/ios"
54 | fluttertoast:
55 | :path: ".symlinks/plugins/fluttertoast/ios"
56 | in_app_review:
57 | :path: ".symlinks/plugins/in_app_review/ios"
58 | path_provider_foundation:
59 | :path: ".symlinks/plugins/path_provider_foundation/ios"
60 | share_plus:
61 | :path: ".symlinks/plugins/share_plus/ios"
62 | shared_preferences_foundation:
63 | :path: ".symlinks/plugins/shared_preferences_foundation/ios"
64 | sqflite:
65 | :path: ".symlinks/plugins/sqflite/ios"
66 | url_launcher_ios:
67 | :path: ".symlinks/plugins/url_launcher_ios/ios"
68 |
69 | SPEC CHECKSUMS:
70 | Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
71 | flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
72 | flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
73 | fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
74 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
75 | in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
76 | path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
77 | share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
78 | shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
79 | sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
80 | Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
81 | url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
82 |
83 | PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
84 |
85 | COCOAPODS: 1.11.3
86 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "background.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "author" : "xcode",
19 | "version" : 1
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "LaunchImage.png",
5 | "idiom" : "universal",
6 | "scale" : "1x"
7 | },
8 | {
9 | "filename" : "LaunchImage@2x.png",
10 | "idiom" : "universal",
11 | "scale" : "2x"
12 | },
13 | {
14 | "filename" : "LaunchImage@3x.png",
15 | "idiom" : "universal",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "author" : "xcode",
21 | "version" : 1
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
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 |
29 |
30 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Answer
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | Answer
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UIViewControllerBasedStatusBarAppearance
45 |
46 | CADisableMinimumFrameDurationOnPhone
47 |
48 | UIApplicationSupportsIndirectInputEvents
49 |
50 | UIStatusBarHidden
51 |
52 | ITSAppUsesNonExemptEncryption
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/Runner/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /*
2 | InfoPlist.strings
3 | Runner
4 |
5 | Created by 张敏超 on 2023/3/12.
6 |
7 | */
8 |
9 | "CFBundleDisplayName" = "Answer";
10 | "CFBundleName" = "Chat Answer";
11 |
--------------------------------------------------------------------------------
/ios/Runner/zh-Hans.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /*
2 | InfoPlist.strings
3 | Runner
4 |
5 | Created by 张敏超 on 2023/3/12.
6 |
7 | */
8 |
9 | "CFBundleDisplayName" = "小答";
10 | "CFBundleName" = "小答";
11 |
--------------------------------------------------------------------------------
/lib/app/app.dart:
--------------------------------------------------------------------------------
1 | import 'package:answer/app/core/app/app_theme.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 |
5 | import 'app_translation.dart';
6 | import 'core/app/app_manager.dart';
7 | import 'core/app/app_progress_hud.dart';
8 | import 'core/binding/initial_binding.dart';
9 | import 'routes/app_pages.dart';
10 |
11 | class App extends StatefulWidget {
12 | const App({Key? key}) : super(key: key);
13 |
14 | @override
15 | State createState() => _AppState();
16 | }
17 |
18 | class _AppState extends State {
19 | final AppTheme theme = AppTheme();
20 |
21 | @override
22 | void initState() {
23 | super.initState();
24 | }
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return GetMaterialApp(
29 | theme: theme.light,
30 | darkTheme: theme.dark,
31 | themeMode: AppManager.to.themeMode,
32 | initialRoute: AppPages.initial,
33 | initialBinding: InitialBinding(),
34 | getPages: AppPages.routes,
35 | fallbackLocale: const Locale('en', 'US'),
36 | locale: Get.deviceLocale ?? const Locale('en', 'US'),
37 | // locale: AppManager.to.locale ?? const Locale('zh', 'CN'),
38 | translations: AppTranslation(),
39 | builder: AppProgressHud.init(),
40 | debugShowCheckedModeBanner: false,
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_controller_mixin.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | mixin AppControllerMixin on GetxController {
4 | @override
5 | void onClose() {
6 | super.onClose();
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_hive_keys.dart:
--------------------------------------------------------------------------------
1 | abstract class AppHiveKeys {
2 | static const fontSize = '_fontSize';
3 | static const openAIApiKey = '_openAIApiKey';
4 | static const plugin = '_pluginKey';
5 | static const currentConversationIndex = '_currentConversationIndex';
6 | static const currentGroupIndex = '_currentGroupIndex';
7 | static const serviceProviderIsSendWelcome = '_serviceProviderIsSendWelcome_';
8 | static const serviceProviderIsSendHello = '_serviceProviderIsSendHello_';
9 | static const conversationPromptId = '_conversationPromptId_';
10 | }
11 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_http.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:dio/dio.dart';
4 | import 'package:flutter/foundation.dart';
5 | import 'package:get/get.dart' hide Response;
6 | import 'package:pretty_dio_logger/pretty_dio_logger.dart';
7 |
8 | class AppHttp {
9 | late final Dio _dio;
10 |
11 | bool _lock = false;
12 |
13 | static final AppHttp instance = AppHttp._internal();
14 | AppHttp._internal();
15 |
16 | static Future instantiate({
17 | HttpOverrides? httpOverrides,
18 | }) async {
19 | if (instance._lock) return instance;
20 | instance._lock = true;
21 |
22 | if (kDebugMode) HttpOverrides.global = httpOverrides;
23 |
24 | final options = BaseOptions(
25 | connectTimeout: const Duration(seconds: 60),
26 | receiveTimeout: const Duration(seconds: 60),
27 | sendTimeout: const Duration(seconds: 60),
28 | headers: {
29 | 'Content-Type': 'application/json',
30 | },
31 | );
32 | instance._dio = Dio(options);
33 | instance._dio.interceptors.add(PrettyDioLogger(
34 | requestHeader: true,
35 | requestBody: true,
36 | ));
37 |
38 | return instance;
39 | }
40 |
41 | static String get networkError => 'network_error'.tr;
42 |
43 | static Future get(
44 | String path, {
45 | Object? data,
46 | Map? queryParameters,
47 | Options? options,
48 | CancelToken? cancelToken,
49 | ProgressCallback? onReceiveProgress,
50 | }) async {
51 | Response res = await instance._dio.get(
52 | path,
53 | data: data,
54 | queryParameters: queryParameters,
55 | options: options,
56 | cancelToken: cancelToken,
57 | onReceiveProgress: onReceiveProgress,
58 | );
59 | return res.data;
60 | }
61 |
62 | static Future> post(
63 | String path, {
64 | Object? data,
65 | Map? queryParameters,
66 | Options? options,
67 | CancelToken? cancelToken,
68 | ProgressCallback? onSendProgress,
69 | ProgressCallback? onReceiveProgress,
70 | }) async {
71 | return await instance._dio.post(
72 | path,
73 | data: data,
74 | queryParameters: queryParameters,
75 | options: options,
76 | cancelToken: cancelToken,
77 | onSendProgress: onSendProgress,
78 | onReceiveProgress: onReceiveProgress,
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_http_overrides.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | class AppHttpOverrides extends HttpOverrides {
4 | @override
5 | HttpClient createHttpClient(SecurityContext? context) {
6 | return super.createHttpClient(context)
7 | ..connectionTimeout = const Duration(seconds: 15)
8 | ..maxConnectionsPerHost = 5
9 | ..badCertificateCallback =
10 | ((X509Certificate cert, String host, int port) => true)
11 | // ..findProxy = ((url) => 'PROXY localhost:1081')
12 | ..findProxy = (url) => HttpClient.findProxyFromEnvironment(
13 | url,
14 | environment: {
15 | "http_proxy": "http://127.0.0.1:7890",
16 | "https_proxy": "http://127.0.0.1:7890",
17 | "ALL_PROXY": "socks5://127.0.0.1:7890",
18 | "HTTP_PROXY": "http://127.0.0.1:7890",
19 | "HTTPS_PROXY": "http://127.0.0.1:7890",
20 | },
21 | );
22 | // ..badCertificateCallback =
23 | // ((X509Certificate cert, String host, int port) => true);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_manager.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/scheduler.dart';
3 | import 'package:get/get.dart';
4 | import 'package:hive_flutter/hive_flutter.dart';
5 |
6 | import 'app_controller_mixin.dart';
7 |
8 | class AppManager extends GetxController with AppControllerMixin {
9 | static AppManager get to => Get.find();
10 | static const String _appManagerBox = 'AppManager';
11 |
12 | late final Box _box;
13 |
14 | static const _themeModeKey = '_themeMode';
15 | ThemeMode? _themeMode;
16 | ThemeMode get themeMode => _themeMode ?? ThemeMode.system;
17 | set themeMode(ThemeMode themeMode) {
18 | if (_themeMode == themeMode) return;
19 | _themeMode = themeMode;
20 | Get.changeThemeMode(themeMode);
21 |
22 | _box.put(_themeModeKey, themeMode.index);
23 | }
24 |
25 | bool get isLightMode =>
26 | themeMode == ThemeMode.light ||
27 | (themeMode == ThemeMode.system &&
28 | SchedulerBinding.instance.window.platformBrightness ==
29 | Brightness.light);
30 |
31 | static const _localeKey = '_locale';
32 | Locale? _locale;
33 | Locale? get locale => _locale;
34 | set locale(Locale? locale) {
35 | if (_locale == locale) return;
36 | _locale = locale;
37 |
38 | if (locale == null) {
39 | Get.updateLocale(
40 | Get.deviceLocale ?? const Locale('zh', 'CN'),
41 | );
42 | _box.delete(_localeKey);
43 | } else {
44 | Get.updateLocale(locale);
45 | _box.put(
46 | _localeKey,
47 | '${locale.languageCode}&${locale.countryCode ?? ''}',
48 | );
49 | }
50 | }
51 |
52 | final Map _map = {};
53 | T? get({required String key}) {
54 | final value = _map[key];
55 | if (value != null) return value;
56 | return _map[key] = _box.get(key);
57 | }
58 |
59 | void set({required String key, T? value}) {
60 | final oldValue = _map[key];
61 | if (oldValue == value) return;
62 | if (value == null) {
63 | _map.remove(key);
64 | _box.delete(key);
65 | } else {
66 | _map[key] = value;
67 | _box.put(key, value);
68 | }
69 | update();
70 | }
71 |
72 | AppManager._({required Box box}) : _box = box;
73 |
74 | static Future initialize() async {
75 | await Hive.initFlutter();
76 |
77 | final box = await Hive.openBox(_appManagerBox);
78 | final manager = AppManager._(box: box);
79 | Get.put(manager);
80 | }
81 |
82 | @override
83 | void onInit() {
84 | final int? index = _box.get(_themeModeKey);
85 | if (index != null) {
86 | _themeMode = ThemeMode.values[index];
87 | }
88 |
89 | final String? languageCode = _box.get(_localeKey);
90 | if (languageCode != null) {
91 | final codes = languageCode.split('&');
92 | _locale = Locale.fromSubtags(
93 | languageCode: codes[0],
94 | countryCode: codes[1].isEmpty ? null : codes[1],
95 | );
96 | }
97 |
98 | super.onInit();
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_model.dart:
--------------------------------------------------------------------------------
1 | class AppModel {}
2 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_plugin.dart:
--------------------------------------------------------------------------------
1 | import '../../data/models/message.dart';
2 |
3 | typedef AppPluginCallback = Future Function(Message message);
4 |
5 | abstract class AppPlugin {
6 | String get key;
7 | String get title;
8 | AppPluginCallback get onReceived;
9 |
10 | Future send({required Message message});
11 | }
12 |
13 | abstract class AppServicePlugin {}
14 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_plugin_manager.dart:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bapaws/answer/6c65fced23f96186f330d7704ff5b49107f83a83/lib/app/core/app/app_plugin_manager.dart
--------------------------------------------------------------------------------
/lib/app/core/app/app_progress_hud.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_easyloading/flutter_easyloading.dart';
3 |
4 | abstract class AppProgressHud {
5 | static TransitionBuilder init() => EasyLoading.init();
6 | static Future show() => EasyLoading.show(
7 | maskType: EasyLoadingMaskType.clear,
8 | );
9 |
10 | static Future dismiss() => EasyLoading.dismiss();
11 | }
12 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_toast.dart:
--------------------------------------------------------------------------------
1 | import 'package:fluttertoast/fluttertoast.dart';
2 |
3 | abstract class AppToast {
4 | static Future show({required String msg}) async {
5 | await Fluttertoast.showToast(
6 | msg: msg,
7 | gravity: ToastGravity.CENTER,
8 | );
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_urls.dart:
--------------------------------------------------------------------------------
1 | class AppUrls {
2 | static const chat = '/chat/completions';
3 | }
4 |
--------------------------------------------------------------------------------
/lib/app/core/app/app_view_mixin.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:fluttertoast/fluttertoast.dart';
4 | import 'package:get/get.dart';
5 |
6 | import 'app_controller_mixin.dart';
7 |
8 | mixin AppViewMixin {
9 | BuildContext get context => Get.context!;
10 |
11 | String? get tag => null;
12 | Controller get controller => GetInstance().find(tag: tag);
13 |
14 | String? get title => null;
15 | Color? get backgroundColor => null;
16 | Color? get statusBarColor => Colors.transparent;
17 | Color? get systemNavigationBarColor =>
18 | Theme.of(context).scaffoldBackgroundColor;
19 |
20 | bool get topSafeArea => false;
21 | bool get bottomSafeArea => false;
22 |
23 | Widget buildBody(BuildContext context);
24 |
25 | Widget build(BuildContext context) {
26 | return buildAnnotatedRegion(context);
27 | }
28 |
29 | Widget buildAnnotatedRegion(BuildContext context) {
30 | return AnnotatedRegion(
31 | value: SystemUiOverlayStyle(
32 | statusBarColor: statusBarColor,
33 | systemNavigationBarColor: systemNavigationBarColor,
34 | ),
35 | child: Material(
36 | color: Colors.transparent,
37 | child: buildScaffold(context),
38 | ),
39 | );
40 | }
41 |
42 | Widget buildScaffold(BuildContext context) {
43 | return GetBuilder(
44 | builder: (controller) => Scaffold(
45 | backgroundColor: backgroundColor,
46 | appBar: buildAppBar(context),
47 | body: buildPage(context),
48 | floatingActionButton: buildFloatingActionButton(context),
49 | bottomNavigationBar: buildBottomNavigationBar(context),
50 | drawer: buildDrawer(),
51 | ),
52 | );
53 | }
54 |
55 | PreferredSizeWidget? buildAppBar(BuildContext context) {
56 | if (title == null) return null;
57 |
58 | return AppBar(title: Text(title!));
59 | }
60 |
61 | Widget buildPage(BuildContext context) {
62 | return SafeArea(
63 | top: topSafeArea,
64 | bottom: bottomSafeArea,
65 | child: buildBody(context),
66 | );
67 | }
68 |
69 | Widget? buildFloatingActionButton(BuildContext context) => null;
70 | Widget? buildBottomNavigationBar(BuildContext context) => null;
71 |
72 | void showErrorSnackBar(String message) {
73 | final snackBar = SnackBar(content: Text(message));
74 | WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
75 | ScaffoldMessenger.of(Get.context!).showSnackBar(snackBar);
76 | });
77 | }
78 |
79 | void showToast(String message) {
80 | Fluttertoast.showToast(
81 | msg: message,
82 | toastLength: Toast.LENGTH_SHORT,
83 | timeInSecForIosWeb: 1,
84 | );
85 | }
86 |
87 | Widget? buildDrawer() {
88 | return null;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib/app/core/binding/initial_binding.dart:
--------------------------------------------------------------------------------
1 | import 'package:answer/app/providers/service_provider_manager.dart';
2 | import 'package:get/get.dart';
3 |
4 | class InitialBinding extends Bindings {
5 | @override
6 | void dependencies() {
7 | // Get.lazyPut(
8 | // () => ServiceProviderManager(),
9 | // );
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/lib/app/core/mixin/refresh_mixin.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:get/get.dart';
3 |
4 | mixin RefreshMixin on GetLifeCycleBase {
5 | ScrollController get scroll;
6 |
7 | @override
8 | void onInit() {
9 | super.onInit();
10 | scroll.addListener(_listener);
11 | }
12 |
13 | bool canFetchBottom = true;
14 |
15 | bool canFetchTop = true;
16 |
17 | void _listener() {
18 | final position = scroll.position;
19 | if (position.pixels < position.minScrollExtent + 16 ||
20 | position.pixels > position.maxScrollExtent - 16) {
21 | _checkIfCanLoadMore();
22 | }
23 | }
24 |
25 | Future _checkIfCanLoadMore() async {
26 | if (scroll.position.pixels == 0) {
27 | if (!canFetchTop) return;
28 | canFetchTop = false;
29 | await onTopScroll();
30 | canFetchTop = true;
31 | } else {
32 | if (!canFetchBottom) return;
33 | canFetchBottom = false;
34 | await onEndScroll();
35 | canFetchBottom = true;
36 | }
37 | }
38 |
39 | Future onEndScroll();
40 |
41 | Future onTopScroll();
42 |
43 | @override
44 | void onClose() {
45 | scroll.removeListener(_listener);
46 | super.onClose();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/app/data/db/app_database.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:answer/app/data/db/prompt_dao.dart';
4 | import 'package:answer/app/data/db/request_parameters_dao.dart';
5 | import 'package:answer/app/data/db/service_providers_dao.dart';
6 | import 'package:answer/app/data/db/service_tokens_dao.dart';
7 | import 'package:answer/app/data/db/service_vendors_dao.dart';
8 | import 'package:flutter/foundation.dart';
9 | import 'package:path/path.dart';
10 | import 'package:sqflite/sqflite.dart';
11 |
12 | import 'conversations_dao.dart';
13 | import 'messages_dao.dart';
14 |
15 | class AppDatabase {
16 | static const defaultLimit = 16;
17 |
18 | static final AppDatabase instance = AppDatabase._internal();
19 | AppDatabase._internal();
20 |
21 | late final Database database;
22 |
23 | late final ConversationsDao conversationsDao = ConversationsDao(database);
24 | late final MessagesDao messagesDao = MessagesDao(database);
25 | late final ServiceProvidersDao serviceProvidersDao =
26 | ServiceProvidersDao(database);
27 | late final ServiceVendorsDao serviceVendorsDao = ServiceVendorsDao(database);
28 | late final ServiceTokensDao serviceTokensDao = ServiceTokensDao(database);
29 | late final PromptDao promptDao = PromptDao(database);
30 | late final RequestParametersDao requestParametersDao =
31 | RequestParametersDao(database);
32 |
33 | static Future initialize({
34 | required String dbName,
35 | }) async {
36 | var databasesPath = await getDatabasesPath();
37 | var path = join(databasesPath, dbName);
38 |
39 | if (kDebugMode) {
40 | print(path);
41 | }
42 |
43 | instance.database = await openDatabase(
44 | path,
45 | onCreate: instance._onCreate,
46 | onUpgrade: instance._onUpgrade,
47 | version: 4,
48 | );
49 | }
50 |
51 | FutureOr _onCreate(Database db, int version) async {
52 | await PromptDao.onCreate(db);
53 | await ServiceTokensDao.onCreate(db);
54 | await ServiceVendorsDao.onCreate(db);
55 | await ServiceProvidersDao.onCreate(db);
56 | await ConversationsDao.onCreate(db);
57 | await RequestParametersDao.onCreate(db);
58 | }
59 |
60 | FutureOr _onUpgrade(Database db, int oldVersion, int newVersion) async {
61 | if (oldVersion < 3) {
62 | await ServiceVendorsDao.onCreate(db);
63 | await PromptDao.onCreate(db);
64 | }
65 | if (oldVersion < 4) {
66 | await RequestParametersDao.onCreate(db);
67 | } else {
68 | await RequestParametersDao.onUpgrade(db, oldVersion, newVersion);
69 | }
70 | await ServiceTokensDao.onUpgrade(db, oldVersion, newVersion);
71 | await ServiceVendorsDao.onUpgrade(db, oldVersion, newVersion);
72 | await PromptDao.onUpgrade(db, oldVersion, newVersion);
73 | await ServiceProvidersDao.onUpgrade(db, oldVersion, newVersion);
74 | await MessagesDao.onUpgrade(db, oldVersion, newVersion);
75 | await ConversationsDao.onUpgrade(db, oldVersion, newVersion);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/app/data/db/app_uuid.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/foundation.dart';
4 |
5 | class AppUuid {
6 | AppUuid();
7 |
8 | @override
9 | String toString() =>
10 | shortHash(this) + Random().nextInt(0xFFFFFF).toRadixString(16);
11 |
12 | static String get value => AppUuid().toString();
13 | }
14 |
--------------------------------------------------------------------------------
/lib/app/data/db/conversations_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:answer/app/data/models/conversation.dart';
2 | import 'package:sqflite/sqflite.dart';
3 |
4 | class ConversationsDao {
5 | static const table = 'conversations';
6 |
7 | final Database db;
8 | ConversationsDao(this.db);
9 |
10 | static Future onCreate(Database db) => db.execute('''
11 | CREATE TABLE $table (
12 | id TEXT NOT NULL PRIMARY KEY,
13 | name TEXT,
14 | edit_name TEXT,
15 | group_id INTEGER,
16 | auto_quote INTEGER,
17 | prompt_id String,
18 | max_tokens INTEGER DEFAULT 800,
19 | timeout INTEGER DEFAULT 60,
20 | message_version INTEGER DEFAULT 0
21 | );
22 | ''');
23 |
24 | static Future onUpgrade(
25 | Database db,
26 | int oldVersion,
27 | int newVersion,
28 | ) async {
29 | // version 3
30 | final result = await db.rawQuery(
31 | 'SELECT * FROM sqlite_master WHERE name="$table" AND sql LIKE "%prompt_id%";',
32 | );
33 | if (result.isEmpty) {
34 | await db.execute('ALTER TABLE $table ADD COLUMN auto_quote INTEGER;');
35 |
36 | await db.execute('ALTER TABLE $table ADD COLUMN prompt_id TEXT;');
37 | await db.execute('ALTER TABLE $table ADD COLUMN max_tokens INTEGER;');
38 | await db.execute('ALTER TABLE $table ADD COLUMN timeout INTEGER;');
39 | }
40 | }
41 |
42 | Future> getAll({required int groupId}) async {
43 | return (await db.query(
44 | table,
45 | where: 'group_id = ?',
46 | whereArgs: [groupId],
47 | ))
48 | .map((e) => Conversation.fromJson(e));
49 | }
50 |
51 | Future create(Conversation chat) async {
52 | return await db.insert(
53 | table,
54 | chat.toJson(),
55 | conflictAlgorithm: ConflictAlgorithm.replace,
56 | );
57 | }
58 |
59 | Future update(Conversation chat) async {
60 | return await db.update(
61 | table,
62 | chat.toJson(),
63 | where: 'id = ?',
64 | whereArgs: [chat.id],
65 | );
66 | }
67 |
68 | Future delete(String id) async {
69 | await db.delete(table, where: 'id = ?', whereArgs: [id]);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/lib/app/data/db/groups_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:answer/app/data/models/group.dart';
2 | import 'package:sqflite/sqflite.dart';
3 |
4 | class GroupsDao {
5 | static const table = 'groups';
6 |
7 | final Database db;
8 | GroupsDao(this.db);
9 |
10 | Future> getAll() async {
11 | return (await db.query(table)).map((e) => Group.fromJson(e));
12 | }
13 |
14 | Future create(Group chat) async {
15 | return await db.insert(table, chat.toJson());
16 | }
17 |
18 | Future update(Group chat) async {
19 | return await db.update(
20 | table,
21 | chat.toJson(),
22 | where: 'id = ?',
23 | whereArgs: [chat.id],
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/app/data/db/messages_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:answer/app/data/db/conversations_dao.dart';
2 | import 'package:sqflite/sqflite.dart';
3 |
4 | import '../models/message.dart';
5 |
6 | class MessagesDao {
7 | static const table = 'messages_';
8 |
9 | final Database db;
10 | MessagesDao(this.db);
11 |
12 | Future onCreate({required String conversationId}) async {
13 | await db.execute('''
14 | CREATE TABLE IF NOT EXISTS $table$conversationId (
15 | id TEXT NOT NULL PRIMARY KEY,
16 | type INTEGER,
17 | from_type INTEGER,
18 | service_name TEXT,
19 | service_avatar TEXT,
20 | content TEXT,
21 | create_at DATETIME,
22 | request_message TEXT,
23 | quote_message TEXT,
24 | response_data TEXT,
25 | conversation_id TEXT REFERENCES ${ConversationsDao.table} (id),
26 | service_id TEXT
27 | );
28 | ''');
29 | }
30 |
31 | static Future onUpgrade(
32 | Database db,
33 | int oldVersion,
34 | int newVersion,
35 | ) async {
36 | // new version is 3
37 | final tables = await db.rawQuery(
38 | 'SELECT * FROM sqlite_master WHERE name LIKE "$table%";',
39 | );
40 | for (final item in tables) {
41 | final tableName = item['name'];
42 | final quoteMessage = await db.rawQuery(
43 | 'SELECT * FROM sqlite_master WHERE name LIKE "$tableName" AND sql LIKE "%quote_message%";',
44 | );
45 | if (quoteMessage.isEmpty) {
46 | await db.execute(
47 | 'ALTER TABLE $tableName ADD COLUMN quote_message TEXT;',
48 | );
49 | }
50 | }
51 | }
52 |
53 | Future dropTable({required String conversationId}) {
54 | return db.execute('DROP TABLE $table$conversationId');
55 | }
56 |
57 | Future> get({
58 | required String conversationId,
59 | String? serviceId,
60 | MessageType? type,
61 | int offset = 0,
62 | int limit = 16,
63 | }) async {
64 | return (await db.rawQuery(
65 | 'SELECT * FROM $table$conversationId ${_buildWhere(
66 | serviceId: serviceId,
67 | type: type,
68 | )}ORDER BY create_at DESC LIMIT $limit OFFSET $offset',
69 | ))
70 | .map((e) => Message.fromJson(e));
71 | }
72 |
73 | String _buildWhere({
74 | String? serviceId,
75 | MessageType? type,
76 | }) {
77 | List where = [];
78 | if (serviceId != null) {
79 | where.add('service_id = "$serviceId"');
80 | }
81 | if (type != null) {
82 | where.add('type = ${type.index}');
83 | }
84 | return where.isEmpty ? '' : 'WHERE ${where.join(' AND ')} ';
85 | }
86 |
87 | Future create(Message message) async {
88 | return await db.insert('$table${message.conversationId}', message.toJson());
89 | }
90 |
91 | Future delete(Message message) async {
92 | return await db.delete(
93 | '$table${message.conversationId}',
94 | where: 'id = ?',
95 | whereArgs: [message.id],
96 | );
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/lib/app/data/db/prompt_dao.dart:
--------------------------------------------------------------------------------
1 | import 'package:answer/app/data/models/prompt.dart';
2 | import 'package:collection/collection.dart';
3 | import 'package:sqflite/sqflite.dart';
4 |
5 | class PromptDao {
6 | static const table = 'prompts';
7 |
8 | final Database db;
9 | PromptDao(this.db);
10 |
11 | static Future onCreate(Database db) async {
12 | await db.execute('''
13 | CREATE TABLE IF NOT EXISTS ${PromptDao.table} (
14 | id TEXT NOT NULL PRIMARY KEY,
15 | title TEXT,
16 | content TEXT
17 | );
18 | ''');
19 | }
20 |
21 | static Future onUpgrade(
22 | Database db,
23 | int oldVersion,
24 | int newVersion,
25 | ) async {}
26 |
27 | Future> getAll() async {
28 | List