Merge pull request #1 from quaxlyqueen/gui

Gui
This commit is contained in:
Josh Ashton
2024-07-11 15:26:54 -06:00
committed by GitHub
173 changed files with 12007 additions and 4 deletions
+3
View File
@@ -0,0 +1,3 @@
[submodule "one-ai-mobile"]
path = one-ai-mobile
url = https://github.com/quaxlyqueen/one-ai-mobile
+17 -4
View File
@@ -1,7 +1,20 @@
Dependencies:
<h1>One AI</h1>
<h2>Description:</h2>
End-to-end solution for self-deploying a secure and private AI. Ideally, always using the latest and greatest open-source technologies available and optimizing the connection between them.
<h3>Dependencies:</h3>
```
pip install scipy pydub torch torchaudio wavio silero sounddevice;
```
Create output.txt file, TODO: Implement error handling.
touch output.txt;
<h3>Usage:</h3>
Currently, you have 5 seconds to record a prompt. It will automatically place "in 50 words or less" at the start of your prompt for faster testing. The Text To Speech (TTS) engine is not great quality, at least at first. Just getting the basic structure together, more to come...
<p>Currently, you have 5 seconds to record a prompt. It will automatically place "in 50 words or less" at the start of your prompt for faster testing. The Text To Speech (TTS) engine is not great quality, at least at first. Just getting the basic structure together, more to come...</p>
<h3>TODO:</h3>
- [ ] Installation script, preferably need some kind of pipeline to auto-inject dependencies into the install script.
- [ ] Send and receive text files over USB
- [ ] GUI in flutter
+43
View File
@@ -0,0 +1,43 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
+45
View File
@@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "761747bfc538b5af34aa0d3fac380f1bc331ec49"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: android
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: ios
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: linux
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: macos
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: web
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: windows
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
+18
View File
@@ -0,0 +1,18 @@
# app
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# TODO
+28
View File
@@ -0,0 +1,28 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
+13
View File
@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
+58
View File
@@ -0,0 +1,58 @@
plugins {
id "com.android.application"
id "kotlin-android"
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader("UTF-8") { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) {
flutterVersionCode = "1"
}
def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0"
}
android {
namespace = "quaxlyqueen.dev.oneai"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "quaxlyqueen.dev.oneai"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.debug
}
}
}
flutter {
source = "../.."
}
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
@@ -0,0 +1,45 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="app"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
@@ -0,0 +1,5 @@
package com.example.app
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity()
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
+18
View File
@@ -0,0 +1,18 @@
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
+3
View File
@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
+25
View File
@@ -0,0 +1,25 @@
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.7.10" apply false
}
include ":app"
+3
View File
@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:
+34
View File
@@ -0,0 +1,34 @@
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>
+2
View File
@@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
+2
View File
@@ -0,0 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
+44
View File
@@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
+174
View File
@@ -0,0 +1,174 @@
PODS:
- apivideo_live_stream (0.0.1):
- ApiVideoLiveStream (= 1.2.2)
- Flutter
- HaishinKit (= 1.3.0)
- ApiVideoLiveStream (1.2.2):
- HaishinKit (= 1.3.0)
- camera_avfoundation (0.0.1):
- Flutter
- DKImagePickerController/Core (4.3.9):
- DKImagePickerController/ImageDataManager
- DKImagePickerController/Resource
- DKImagePickerController/ImageDataManager (4.3.9)
- DKImagePickerController/PhotoGallery (4.3.9):
- DKImagePickerController/Core
- DKPhotoGallery
- DKImagePickerController/Resource (4.3.9)
- DKPhotoGallery (0.0.19):
- DKPhotoGallery/Core (= 0.0.19)
- DKPhotoGallery/Model (= 0.0.19)
- DKPhotoGallery/Preview (= 0.0.19)
- DKPhotoGallery/Resource (= 0.0.19)
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Core (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Preview
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Model (0.0.19):
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Preview (0.0.19):
- DKPhotoGallery/Model
- DKPhotoGallery/Resource
- SDWebImage
- SwiftyGif
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- Flutter (1.0.0)
- flutter_credit_card (0.0.1):
- Flutter
- HaishinKit (1.3.0):
- Logboard (~> 2.3.0)
- image_picker_ios (0.0.1):
- Flutter
- Logboard (2.3.1)
- native_device_orientation (0.0.1):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- pointer_interceptor_ios (0.0.1):
- Flutter
- rive_common (0.0.1):
- Flutter
- SDWebImage (5.19.4):
- SDWebImage/Core (= 5.19.4)
- SDWebImage/Core (5.19.4)
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- speech_to_text (0.0.1):
- Flutter
- Try
- sqflite (0.0.3):
- Flutter
- FlutterMacOS
- SwiftyGif (5.4.5)
- Try (2.1.1)
- url_launcher_ios (0.0.1):
- Flutter
- video_player_avfoundation (0.0.1):
- Flutter
- FlutterMacOS
- webview_flutter_wkwebview (0.0.1):
- Flutter
DEPENDENCIES:
- apivideo_live_stream (from `.symlinks/plugins/apivideo_live_stream/ios`)
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
- flutter_credit_card (from `.symlinks/plugins/flutter_credit_card/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- native_device_orientation (from `.symlinks/plugins/native_device_orientation/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- pointer_interceptor_ios (from `.symlinks/plugins/pointer_interceptor_ios/ios`)
- rive_common (from `.symlinks/plugins/rive_common/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- speech_to_text (from `.symlinks/plugins/speech_to_text/ios`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
SPEC REPOS:
trunk:
- ApiVideoLiveStream
- DKImagePickerController
- DKPhotoGallery
- HaishinKit
- Logboard
- SDWebImage
- SwiftyGif
- Try
EXTERNAL SOURCES:
apivideo_live_stream:
:path: ".symlinks/plugins/apivideo_live_stream/ios"
camera_avfoundation:
:path: ".symlinks/plugins/camera_avfoundation/ios"
file_picker:
:path: ".symlinks/plugins/file_picker/ios"
Flutter:
:path: Flutter
flutter_credit_card:
:path: ".symlinks/plugins/flutter_credit_card/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
native_device_orientation:
:path: ".symlinks/plugins/native_device_orientation/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
pointer_interceptor_ios:
:path: ".symlinks/plugins/pointer_interceptor_ios/ios"
rive_common:
:path: ".symlinks/plugins/rive_common/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
speech_to_text:
:path: ".symlinks/plugins/speech_to_text/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
video_player_avfoundation:
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
apivideo_live_stream: 64fa696699cfc531e07f5d5d701c7e3cd5ce5e9d
ApiVideoLiveStream: 5842571806a2ed26671597dadd370ec38d9b9ba4
camera_avfoundation: dd002b0330f4981e1bbcb46ae9b62829237459a4
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_credit_card: 48fb35065294868bc6a3e7f18a42f28929b84f48
HaishinKit: 013229683accc4abe46630b04629da3ff90428b7
image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
Logboard: 3d98bb85de6a36b255ab637e8178eb5671c5c3a6
native_device_orientation: 3b4cfc9565a7b879cc4fde282b3e27745e852d0d
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
pointer_interceptor_ios: 508241697ff0947f853c061945a8b822463947c1
rive_common: 3a4c254c6e4db7e4b9e05daeb3d1f47ae4f7bf76
SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
webview_flutter_wkwebview: be0f0d33777f1bfd0c9fdcb594786704dbf65f36
PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796
COCOAPODS: 1.15.2
@@ -0,0 +1,730 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
1A842A08FCF2E60F2DC38967 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72D644A2E498C9BA5622C54F /* Pods_RunnerTests.framework */; };
23394E45189304C0C8B7B28E /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 56C8C7368AE78ACE8607CD9E /* Pods_Runner.framework */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0151E46117D4D747AD6AC5CA /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2B088EE7CCB52F9F9F771147 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
4A35B625628A126CB966D9D3 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
55D68109A360AC60F8F453F3 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
56C8C7368AE78ACE8607CD9E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
72D644A2E498C9BA5622C54F /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
85190F9D33FFEE471AA1BBDF /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E93E580DD876AE87CAF169F7 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
23394E45189304C0C8B7B28E /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
F46E2B0305A6E6E475DD5131 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1A842A08FCF2E60F2DC38967 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1DADEF4AA78CE7076F315AFE /* Pods */ = {
isa = PBXGroup;
children = (
0151E46117D4D747AD6AC5CA /* Pods-Runner.debug.xcconfig */,
2B088EE7CCB52F9F9F771147 /* Pods-Runner.release.xcconfig */,
85190F9D33FFEE471AA1BBDF /* Pods-Runner.profile.xcconfig */,
4A35B625628A126CB966D9D3 /* Pods-RunnerTests.debug.xcconfig */,
E93E580DD876AE87CAF169F7 /* Pods-RunnerTests.release.xcconfig */,
55D68109A360AC60F8F453F3 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
1DADEF4AA78CE7076F315AFE /* Pods */,
A3D098F5CC733F52B6D01ACB /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
A3D098F5CC733F52B6D01ACB /* Frameworks */ = {
isa = PBXGroup;
children = (
56C8C7368AE78ACE8607CD9E /* Pods_Runner.framework */,
72D644A2E498C9BA5622C54F /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
CF8C5EF2CFE445B8DBBA7041 /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
F46E2B0305A6E6E475DD5131 /* Frameworks */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
46398C21E369343F3454DAF3 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
86B1E22AB537DC186C27C01C /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
46398C21E369343F3454DAF3 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
86B1E22AB537DC186C27C01C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
CF8C5EF2CFE445B8DBBA7041 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 6G5TWS2YU7;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = quaxlyqueen.dev.oneai;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4A35B625628A126CB966D9D3 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.app.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E93E580DD876AE87CAF169F7 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.app.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 55D68109A360AC60F8F453F3 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.example.app.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 6G5TWS2YU7;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = quaxlyqueen.dev.oneai;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 6G5TWS2YU7;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = quaxlyqueen.dev.oneai;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
+13
View File
@@ -0,0 +1,13 @@
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
@@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
+59
View File
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>This app needs access to camera when used</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>TODO: Better description</string>
<key>LSApplicationCategoryType</key>
<string>Productivity</string>
<key>NSMicrophoneUsageDescription</key>
<string>Required for on-device speech recognition.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>On-device speech-to-text.</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>App</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>app</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
@@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"
@@ -0,0 +1,12 @@
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}
@@ -0,0 +1,25 @@
import '/components/options_dialog/options_dialog_widget.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'conversation_details_overlay_widget.dart'
show ConversationDetailsOverlayWidget;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class ConversationDetailsOverlayModel
extends FlutterFlowModel<ConversationDetailsOverlayWidget> {
/// State fields for stateful widgets in this component.
// Model for OptionsDialog component.
late PopupModel optionsDialogModel;
@override
void initState(BuildContext context) {
optionsDialogModel = createModel(context, () => PopupModel());
}
@override
void dispose() {
optionsDialogModel.dispose();
}
}
@@ -0,0 +1,208 @@
import '/components/options_dialog/options_dialog_widget.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
import 'conversation_details_overlay_model.dart';
export 'conversation_details_overlay_model.dart';
class ConversationDetailsOverlayWidget extends StatefulWidget {
const ConversationDetailsOverlayWidget({super.key});
@override
State<ConversationDetailsOverlayWidget> createState() =>
_ConversationDetailsOverlayWidgetState();
}
class _ConversationDetailsOverlayWidgetState
extends State<ConversationDetailsOverlayWidget> {
late ConversationDetailsOverlayModel _model;
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => ConversationDetailsOverlayModel());
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(0),
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 4,
sigmaY: 4,
),
child: Container(
width: double.infinity,
height: double.infinity,
decoration: const BoxDecoration(),
child: Align(
alignment: const AlignmentDirectional(0, -1),
child: Container(
width: double.infinity,
height: double.infinity,
constraints: const BoxConstraints(
maxWidth: 700,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0),
),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 70, 0, 0),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Padding(
padding: EdgeInsetsDirectional.fromSTEB(16, 0, 0, 0),
child: Text(
'Chat Details',
style: AppTheme.headlineSmall,
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 16, 0),
child: FlutterFlowIconButton(
borderColor: AppTheme.alternate,
borderRadius: 12,
borderWidth: 1,
buttonSize: 40,
fillColor: AppTheme.accent4,
icon: const Icon(
Icons.close_rounded,
color: AppTheme.primaryTextColor,
size: 24,
),
onPressed: () async {
Navigator.pop(context);
},
),
),
],
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16, 4, 0, 4),
child: RichText(
textScaler: MediaQuery.of(context).textScaler,
text: const TextSpan(
children: [
TextSpan(
text: 'Group Chat ID: ',
style: TextStyle(),
),
TextSpan(
text: 'Hello World ',
style: TextStyle(
color: AppTheme.primary,
fontWeight: FontWeight.bold,
),
)
],
style: AppTheme.labelMedium,
),
),
),
const Expanded(
child: Align(
alignment: AlignmentDirectional(0, 0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Divider(
thickness: 1,
color: AppTheme.tertiary,
),
],
),
),
),
Align(
alignment: const AlignmentDirectional(0, -1),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16, 0, 16, 0),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Container(
decoration: BoxDecoration(
color: AppTheme
.secondaryBackground,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppTheme.alternate,
),
),
child: wrapWithModel(
model: _model.optionsDialogModel,
updateCallback: () => setState(() {}),
updateOnChange: true,
child: const PopupWidget(),
),
),
),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16, 16, 16, 44),
child: FFButtonWidget(
onPressed: () async {
Navigator.pop(context);
},
text: 'Close',
options: FFButtonOptions(
width: double.infinity,
height: 52,
padding: const EdgeInsetsDirectional.fromSTEB(44, 0, 44, 0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color:
AppTheme.secondaryBackground,
textStyle: AppTheme.titleLarge,
elevation: 0,
borderSide: const BorderSide(
color: AppTheme.alternate,
width: 2,
),
borderRadius: BorderRadius.circular(12),
hoverColor: AppTheme.alternate,
hoverBorderSide: const BorderSide(
color: AppTheme.alternate,
width: 2,
),
hoverTextColor: AppTheme.primaryTextColor,
hoverElevation: 3,
),
),
),
],
),
),
),
),
),
),
);
}
}
@@ -0,0 +1,34 @@
import 'package:app/components/conversation_thread/conversation.dart';
import '/components/conversation_thread/conversation_thread_widget.dart';
import '/components/model_item/model_item_widget.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'conversation_widget.dart' show ConversationWidget;
import 'package:flutter/material.dart';
class ConversationModel extends FlutterFlowModel<ConversationWidget> {
/// State fields for stateful widgets in this page.
final unfocusNode = FocusNode();
// Model for ConversationThread component.
late ConversationThreadModel conversationThreadModel;
// Model for ModelItem component.
late ModelItemModel modelItemModel;
late Conversation conversation;
ConversationModel(this.conversation);
@override
void initState(BuildContext context) {
conversationThreadModel = createModel(context, () => ConversationThreadModel(conversation)); // TODO
modelItemModel = createModel(context, () => ModelItemModel());
}
@override
void dispose() {
unfocusNode.dispose();
conversationThreadModel.dispose();
modelItemModel.dispose();
}
}
@@ -0,0 +1,14 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'conversation_options_widget.dart' show ConversationOptionsWidget;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class ConversationOptionsModel
extends FlutterFlowModel<ConversationOptionsWidget> {
@override
void initState(BuildContext context) {}
@override
void dispose() {}
}
@@ -0,0 +1,235 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
import 'conversation_options_model.dart';
export 'conversation_options_model.dart';
class ConversationOptionsWidget extends StatefulWidget {
const ConversationOptionsWidget({super.key});
@override
State<ConversationOptionsWidget> createState() =>
_ConversationOptionsWidgetState();
}
class _ConversationOptionsWidgetState extends State<ConversationOptionsWidget> {
late ConversationOptionsModel _model;
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => ConversationOptionsModel());
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
decoration: const BoxDecoration(
color: AppTheme.secondaryBackground,
),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 12, 0, 24),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: double.infinity,
height: 60,
decoration: const BoxDecoration(),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 8, 12, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
color: AppTheme.primaryBackground,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Icon(
Icons.share_rounded,
color: AppTheme.secondaryText,
size: 20,
),
),
),
const Expanded(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(12, 0, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Share',
style: AppTheme.labelLarge,
),
],
),
),
),
],
),
),
),
Container(
width: double.infinity,
height: 60,
decoration: const BoxDecoration(),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 8, 12, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
color: AppTheme.primaryBackground,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Icon(
Icons.insert_link,
color: AppTheme.secondaryText,
size: 20,
),
),
),
const Expanded(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(12, 0, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Get Link',
style: AppTheme.labelLarge,
),
],
),
),
),
],
),
),
),
Container(
width: double.infinity,
height: 60,
decoration: const BoxDecoration(),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 8, 12, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
color: AppTheme.primaryBackground,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Icon(
Icons.mode_edit,
color: AppTheme.secondaryText,
size: 20,
),
),
),
const Expanded(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(12, 0, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Model selection',
style: AppTheme.labelLarge,
),
],
),
),
),
],
),
),
),
Container(
width: double.infinity,
height: 60,
decoration: const BoxDecoration(),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 8, 12, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Card(
clipBehavior: Clip.antiAliasWithSaveLayer,
color: AppTheme.primaryBackground,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Icon(
Icons.hide_source,
color: AppTheme.secondaryText,
size: 20,
),
),
),
const Expanded(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(12, 0, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Private',
style: AppTheme.labelLarge,
),
],
),
),
),
],
),
),
),
],
),
),
);
}
}
@@ -0,0 +1,33 @@
class Chat {
final String content;
final bool role;
int chatType = 0;
// Most basic chat, text from server or from user.
Chat(this.content, this.role, this.chatType);
// A chat with an included image.
Chat.image(this.content, this.role, this.chatType);
// A chat with an included file.
Chat.file(this.content, this.role, this.chatType);
}
// TODO: Add proper filetype support. File should either be parsed on-device, or uploaded to the server.
// TODO: See https://github.com/adithya-s-k/omniparse
// TODO: Implement dynamic pathing based upon filetypes.
enum Filetype {
pdf,
doc,
docx,
pages,
note,
todo,
cal,
calendar,
event,
contact,
mp3,
mp4,
wav,
}
@@ -0,0 +1,18 @@
import 'chat_bubble_widget.dart';
import 'chat.dart';
import 'package:flutter/material.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
class ChatBubbleModel extends FlutterFlowModel<ChatBubbleWidget>{
late final Chat c;
ChatBubbleModel(this.c);
@override
void dispose() {} // TODO: Need to implement for prompt/response deletion.
@override
void initState(BuildContext context) {} // TODO: Need to implement for loading in media and editing.
}
@@ -0,0 +1,53 @@
import 'dart:convert';
import 'package:app/components/util/backend.dart';
import 'package:app/theme.dart';
import 'package:flutter/material.dart';
import 'chat.dart';
class ChatBubbleWidget extends StatelessWidget{
late Chat c;
ChatBubbleWidget({super.key, required this.c});
@override
Widget build(BuildContext context) {
double max_width = MediaQuery.of(context).size.width*0.65;
return Row(
mainAxisAlignment: c.role ? MainAxisAlignment.end : MainAxisAlignment.start,
children: [
Container(
width: max_width,
padding: const EdgeInsets.all(16.0),
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(12.0),
topRight: const Radius.circular(12.0),
bottomLeft: c.role ? const Radius.circular(12.0) : const Radius
.circular(0.0),
bottomRight: c.role ? const Radius.circular(12.0) : const Radius
.circular(0.0),
),
color: c.role ? AppTheme.darkest : AppTheme.dark,
),
child:
// TODO: Properly display filetypes in the thread.
c.chatType == 0 ? Text(
c.content,
style: AppTheme.bodyMedium,
)
: c.chatType == 1 ? Image(image: Backend.convertFromBase64(c.content))
: c.chatType == 2 ? const Icon(
Icons.file_copy,
) : const Text("null"),
// Text(
// c.content,
// style: AppTheme.bodyMedium,
// ),
),
],
);
}
}
@@ -0,0 +1,57 @@
import 'package:app/components/util/backend.dart';
import 'package:flutter/material.dart';
import 'chat.dart';
class Conversation with ChangeNotifier {
int conversationID;
String conversationLabel;
String conversationSubLabel;
// TODO: Fix history, very, verry strange behavior when disabled.
bool history = true; // History is disabled by default. This means chats are auto-deleted once the user exits that conversation.\
bool conversationContext = true; // The prior prompts and responses are used as additional context for the next prompt and response.
late bool stream = false; // Update the UI with a stream of characters as received from the server, or as one text.
var lastAccessTime = DateTime.timestamp(); // Used to sort conversations based on most recent usage.
List<Chat> chats = [];
Conversation(this.conversationID, this.conversationLabel, this.conversationSubLabel);
Conversation.completeConversation(this.conversationID, this.conversationLabel, this.conversationSubLabel, this.chats);
void toggleHistory() => history = !history;
void toggleConversationContext() => conversationContext = !conversationContext;
void toggleStream() => stream = !stream;
void add(Chat message) {
lastAccessTime = DateTime.timestamp();
chats.add(message);
notifyListeners();
}
void loadChats() {
lastAccessTime = DateTime.timestamp();
Backend.loadConversation;
chats = Backend.loadedChats;
}
void setLabel() {
// TODO: Need to implement
}
void setSubLabel() {
// TODO: Need to implement
}
List<Chat> getChats() {
lastAccessTime = DateTime.timestamp();
return chats;
}
void setLabels(String cLabel, String cSubLabel) {
lastAccessTime = DateTime.timestamp();
conversationLabel = cLabel;
conversationSubLabel = cSubLabel;
}
}
@@ -0,0 +1,31 @@
import 'package:app/components/conversation_thread/chat_bubble_model.dart';
import 'package:app/components/conversation_thread/chat.dart';
import 'package:app/components/conversation_thread/conversation.dart';
import 'package:app/components/util/backend.dart';
import 'package:app/components/prompt_box/prompt_box_widget.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'conversation_thread_widget.dart' show ConversationThreadWidget;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:cached_network_image/cached_network_image.dart';
class ConversationThreadModel extends FlutterFlowModel<ConversationThreadWidget> {
final formKey = GlobalKey<FormState>();
late PromptBoxModel promptBoxModel;
Conversation conversation;
ConversationThreadModel(this.conversation);
@override
void initState(BuildContext context) {
conversation = Backend.getLoadedConversation();
promptBoxModel = createModel(context, () => PromptBoxModel());
}
@override
void dispose() {
promptBoxModel.dispose();
}
}
@@ -0,0 +1,184 @@
import 'package:app/components/conversation_thread/conversation.dart';
import 'package:app/components/util/backend.dart';
import 'package:provider/provider.dart';
import '/components/conversation_thread/chat_bubble_widget.dart';
import 'package:app/components/conversation_thread/conversation_thread_model.dart';
import '/components/prompt_box/prompt_box_widget.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:app/theme.dart';
import 'conversation_thread_model.dart';
export 'conversation_thread_model.dart';
class ConversationThreadWidget extends StatefulWidget {
final Conversation conversation;
const ConversationThreadWidget({super.key, required this.conversation});
@override
State<ConversationThreadWidget> createState() =>
_ConversationThreadWidgetState(conversation);
}
class _ConversationThreadWidgetState extends State<ConversationThreadWidget> {
late ConversationThreadModel _model;
Conversation conversation;
_ConversationThreadWidgetState(this.conversation);
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => ConversationThreadModel(conversation));
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: Add a scrollbar
return Container(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ListenableBuilder(
listenable: _model.conversation,
builder: (BuildContext context, Widget? child) {
return ListView.builder(
itemCount: Backend.getLoadedConversation().chats.length,
padding: const EdgeInsets.fromLTRB(0, 12, 0, 24,),
reverse: false,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return ChatBubbleWidget(c: Backend.getLoadedConversation().chats[index]);
},
);
},
),
),
Container(
width: double.infinity,
decoration: const BoxDecoration(
color: AppTheme.medium,
boxShadow: [
BoxShadow(
blurRadius: 3,
color: Color(0x33000000),
offset: Offset(
0,
-2,
),
)
],
),
// TODO
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
// Row(
// mainAxisSize: MainAxisSize.max,
// children: [
// Expanded(
// child: Padding(
// padding: const EdgeInsetsDirectional.fromSTEB(0, 12, 0, 0),
// child: SingleChildScrollView(
// scrollDirection: Axis.horizontal,
// child: Row(
// mainAxisSize: MainAxisSize.max,
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// FlutterFlowMediaDisplay(
// path: '',
// imageBuilder: (path) => ClipRRect(
// borderRadius: BorderRadius.circular(8),
// child: CachedNetworkImage(
// fadeInDuration: const Duration(milliseconds: 500),
// fadeOutDuration:
// const Duration(milliseconds: 500),
// imageUrl: path,
// width: 120,
// height: 100,
// fit: BoxFit.cover,
// ),
// ),
// // TODO
// videoPlayerBuilder: (path) =>
// FlutterFlowVideoPlayer(
// path: path,
// width: 300,
// autoPlay: false,
// looping: true,
// showControls: true,
// allowFullScreen: true,
// allowPlaybackSpeedMenu: false,
// ),
// ),
// Align(
// alignment: const AlignmentDirectional(-1, -1),
// // TODO: Make the delete button conditional upon media upload.
// child: FlutterFlowIconButton(
// borderColor:
// AppTheme.error,
// borderRadius: 20,
// borderWidth: 2,
// buttonSize: 40,
// fillColor: AppTheme.primaryBackground,
// icon: const Icon(
// Icons.delete_outline_rounded,
// color: AppTheme.error,
// size: 24,
// ),
// onPressed: () {
// print('IconButton pressed ...');
// },
// ),
// ),
// ]
// .divide(const SizedBox(width: 8))
// .addToStart(const SizedBox(width: 16))
// .addToEnd(const SizedBox(width: 16)),
// ),
// ),
// ),
// ),
// ],
// ),
Form(
key: _model.formKey,
autovalidateMode: AutovalidateMode.disabled,
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 8),
child: wrapWithModel(
model: _model.promptBoxModel,
updateCallback: () => setState(() {}),
child: const PromptBoxWidget(),
),
),
),
],
),
),
],
),
);
}
}
@@ -0,0 +1,125 @@
import 'package:app/components/conversation_thread/conversation.dart';
import '/components/conversation_details_overlay/conversation_details_overlay_widget.dart';
import '/components/conversation_thread/conversation_thread_widget.dart';
import '/components/model_item/model_item_widget.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:app/theme.dart';
import '../components/conversation_model.dart';
export '../components/conversation_model.dart';
class ConversationWidget extends StatefulWidget {
final Conversation conversation;
const ConversationWidget({super.key, required this.conversation});
@override
State<ConversationWidget> createState() => _ConversationWidgetState(conversation);
}
class _ConversationWidgetState extends State<ConversationWidget> {
late ConversationModel _model;
Conversation conversation;
_ConversationWidgetState(this.conversation);
final scaffoldKey = GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
_model = createModel(context, () => ConversationModel(conversation));
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _model.unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(_model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: Scaffold(
key: scaffoldKey,
backgroundColor: AppTheme.secondaryBackground,
appBar: AppBar(
backgroundColor: AppTheme.primaryBackground,
automaticallyImplyLeading: false,
// ---------- Back Button
leading: FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30,
borderWidth: 1,
buttonSize: 60,
icon: const Icon(
Icons.arrow_back_rounded,
color: AppTheme.lighterest,
size: 30,
),
onPressed: () async {
// TODO: Smooth out the animation to prevent the conversations list from loading half-way up the screen.
// Note: that only applies if the input was already selected.
SystemChannels.textInput.invokeMethod('TextInput.hide');
Navigator.pop(context);
},
),
title: wrapWithModel(
model: _model.modelItemModel,
updateCallback: () => setState(() {}),
child: ModelItemWidget(conversation: conversation,),
),
actions: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 8, 16, 8),
// ---------- Options Button
child: FlutterFlowIconButton(
icon: const Icon(
Icons.more_vert,
color: AppTheme.lighterest,
size: 24,
),
onPressed: () async {
await showModalBottomSheet(
isScrollControlled: true,
backgroundColor: Colors.transparent,
enableDrag: false,
context: context,
builder: (context) {
return GestureDetector(
onTap: () => _model.unfocusNode.canRequestFocus
? FocusScope.of(context)
.requestFocus(_model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: Padding(
padding: MediaQuery.viewInsetsOf(context),
child: const ConversationDetailsOverlayWidget(),
),
);
},
).then((value) => safeSetState(() {}));
},
),
),
],
centerTitle: false,
elevation: 0,
),
body: SafeArea(
top: true,
child: wrapWithModel(
model: _model.conversationThreadModel,
updateCallback: () => setState(() {}),
child: ConversationThreadWidget(conversation: conversation),
),
),
),
);
}
}
@@ -0,0 +1,16 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'conversations_list_widget.dart' show ConversationsListWidget;
import 'package:flutter/material.dart';
class ConversationsListModel extends FlutterFlowModel<ConversationsListWidget> {
final unfocusNode = FocusNode();
@override
void initState(BuildContext context) {}
@override
void dispose() {
unfocusNode.dispose();
}
}
@@ -0,0 +1,247 @@
import 'package:app/components/conversation_thread/conversation.dart';
import 'package:app/theme.dart';
import 'package:app/components/conversation_widget.dart';
import 'package:app/components/util/backend.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:app/components/options_dialog/options_dialog_widget.dart';
import '../components/conversations_list_model.dart';
export '../components/conversations_list_model.dart';
class ConversationsListWidget extends StatefulWidget {
const ConversationsListWidget({super.key});
@override
State<ConversationsListWidget> createState() =>
_ConversationsListWidgetState();
}
class _ConversationsListWidgetState extends State<ConversationsListWidget> {
late ConversationsListModel _model;
static List<ConversationWidget> conversations = [];
final scaffoldKey = GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
Backend().init();
if(conversations.isEmpty) {
List<Conversation> convoys = Backend.conversations;
for(Conversation c in convoys) {
conversations.add(ConversationWidget(conversation: c,));
}
}
_model = createModel(context, () => ConversationsListModel());
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Clean conversation list prior to building widgets, to prevent bloating UI with empty conversations.
// Additionally, delete conversations that have history disabled.
for(int i = 0; i < conversations.length; i++) {
if(
conversations[i].conversation.getChats().isEmpty ||
!conversations[i].conversation.history
) {
Backend.conversations.removeAt(i);
conversations.removeAt(i);
Backend.maxConversationID--; // maxConversationID will eventually be deprecated with better ID system.
i--;
}
}
return GestureDetector(
onTap: () => _model.unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(_model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: SafeArea(
top: true,
child: Stack(
children: [
Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Align(
alignment: const AlignmentDirectional(0, 0),
child: ListView.builder(
itemCount: conversations.length,
padding: EdgeInsets.zero,
reverse: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Align(
alignment: const AlignmentDirectional(0, 0),
child: InkWell(
// TODO
// onTap: () async {
// context.pushNamed('Conversation');
// },
child: Container(
decoration: const BoxDecoration(
//color: AppTheme.darkest,
border: Border(
top: BorderSide(width: 2.0, color: AppTheme.darkest),
),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width: 100,
height: 100,
decoration: const BoxDecoration(color: AppTheme.medium,),
child: const Align(
alignment: AlignmentDirectional(0, 0),
child: Icon(
Icons.settings_outlined, // TODO: Dynamically generate or allow users to color code/tag conversations.
color: AppTheme.secondaryText,
size: 48,
),
),
),
Expanded(
child: Align(
alignment: const AlignmentDirectional(-1, 0),
child: Container(
width: 100,
height: 100,
constraints: BoxConstraints(
minWidth: MediaQuery.sizeOf(context).width,
),
decoration: const BoxDecoration(
color: AppTheme.medium,
shape: BoxShape.rectangle,
),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Align(
alignment: const AlignmentDirectional(-1, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Text(
conversations[index].conversation.conversationLabel,
style: AppTheme.labelLarge,
),
],
),
),
Align(
alignment:
const AlignmentDirectional(-1, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Text(
conversations[index].conversation.conversationSubLabel,
style: AppTheme.labelSmall,
),
),
],
),
),
],
),
),
),
),
Container(
width: 100,
height: 100,
decoration: const BoxDecoration(
color: AppTheme.medium,
),
child: const Icon(
Icons.chevron_right_rounded,
color: AppTheme.secondaryText,
size: 48,
),
),
],
),
),
onTap: () => {
Backend.loadConversation(index),
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ConversationWidget(conversation: Backend.getLoadedConversation(),),
),
)
},
onLongPress: () => {
showModalBottomSheet(
isScrollControlled: true,
backgroundColor:
Colors.transparent,
enableDrag: false,
useSafeArea: true,
context: context,
builder: (context) {
return Padding(
padding:
MediaQuery.viewInsetsOf(
context),
child: const PopupWidget(),
);
},
).then((value) =>
safeSetState(() {})),
},
),
);
}
),
),
),
],
),
Positioned(
bottom: 20.0, // Adjust positioning as needed
right: 20.0, // Adjust positioning as needed
child: FloatingActionButton(
onPressed: () => {
Backend.loadConversation(Backend.createConversation()), // TODO: Dynamically get the next ID
conversations.add(ConversationWidget(conversation: Backend.getLoadedConversation())),
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ConversationWidget(conversation: Backend.loadedConversation,),
),
), // Handle the button press
},
backgroundColor: AppTheme.accent,
child: const Icon(
Icons.bubble_chart,
color: AppTheme.light,
),
),
),
],
),
),
);
}
}
@@ -0,0 +1,22 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'image_details_widget.dart' show ImageDetailsWidget;
import 'package:auto_size_text/auto_size_text.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class ImageDetailsModel extends FlutterFlowModel<ImageDetailsWidget> {
/// State fields for stateful widgets in this page.
final unfocusNode = FocusNode();
@override
void initState(BuildContext context) {}
@override
void dispose() {
unfocusNode.dispose();
}
}
@@ -0,0 +1,243 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
import 'image_details_model.dart';
export 'image_details_model.dart';
class ImageDetailsWidget extends StatefulWidget {
const ImageDetailsWidget({super.key});
@override
State<ImageDetailsWidget> createState() => _ImageDetailsWidgetState();
}
class _ImageDetailsWidgetState extends State<ImageDetailsWidget>
with TickerProviderStateMixin {
late ImageDetailsModel _model;
final scaffoldKey = GlobalKey<ScaffoldState>();
final animationsMap = <String, AnimationInfo>{};
@override
void initState() {
super.initState();
_model = createModel(context, () => ImageDetailsModel());
animationsMap.addAll({
'imageOnPageLoadAnimation': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
VisibilityEffect(duration: 1.ms),
FadeEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 300.0.ms,
begin: 0.0,
end: 1.0,
),
MoveEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 300.0.ms,
begin: const Offset(0.0, 30.0),
end: const Offset(0.0, 0.0),
),
ScaleEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 300.0.ms,
begin: const Offset(0.7, 0.7),
end: const Offset(1.0, 1.0),
),
],
),
'rowOnPageLoadAnimation': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
VisibilityEffect(duration: 1.ms),
FadeEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 300.0.ms,
begin: 0.0,
end: 1.0,
),
MoveEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 300.0.ms,
begin: const Offset(0.0, 30.0),
end: const Offset(0.0, 0.0),
),
TiltEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 300.0.ms,
begin: const Offset(-0.698, 0),
end: const Offset(0, 0),
),
],
),
});
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _model.unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(_model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: Scaffold(
key: scaffoldKey,
backgroundColor: AppTheme.secondaryBackground,
appBar: AppBar(
backgroundColor: AppTheme.secondaryBackground,
automaticallyImplyLeading: false,
leading: const FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30,
borderWidth: 1,
buttonSize: 60,
icon: Icon(
Icons.arrow_back_rounded,
color: AppTheme.primaryTextColor,
size: 30,
),
// TODO
// onPressed: () async {
// context.pop();
// },
),
actions: const [],
centerTitle: false,
elevation: 0,
),
body: SafeArea(
top: true,
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(12),
child: Hero(
tag: 'hero',
transitionOnUserGestures: true,
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CachedNetworkImage(
fadeInDuration: const Duration(milliseconds: 500),
fadeOutDuration: const Duration(milliseconds: 500),
imageUrl: 'https://picsum.photos/seed/150/600',
width: double.infinity,
fit: BoxFit.fitWidth,
memCacheWidth: 1200,
memCacheHeight: 1200,
),
),
).animateOnPageLoad(
animationsMap['imageOnPageLoadAnimation']!),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 12, 12, 32),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 4, 8, 16),
child: Container(
width: 36,
height: 36,
decoration: BoxDecoration(
color: AppTheme.accent1,
borderRadius: BorderRadius.circular(12),
shape: BoxShape.rectangle,
border: Border.all(
color: AppTheme.primary,
width: 2,
),
),
child: Padding(
padding: const EdgeInsets.all(2),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: CachedNetworkImage(
fadeInDuration: const Duration(milliseconds: 200),
fadeOutDuration: const Duration(milliseconds: 200),
imageUrl:
'https://images.unsplash.com/photo-1521572267360-ee0c2909d518?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w0NTYyMDF8MHwxfHNlYXJjaHwyMHx8cHJvZmlsZXxlbnwwfHx8fDE2OTU4MjQ5OTN8MA&ixlib=rb-4.0.3&q=80&w=1080',
width: 44,
height: 44,
fit: BoxFit.cover,
),
),
),
),
),
Flexible(
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 8),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const SelectionArea(
child: AutoSizeText(
'Thanks so much! We really do appreciate it!',
textAlign: TextAlign.start,
style: AppTheme.bodyMedium,
)),
const Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 4, 0, 0),
child: Text(
'Just Now',
style: AppTheme.labelSmall,
),
),
].divide(const SizedBox(width: 4)),
),
const Padding(
padding:
EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0),
child: SelectionArea(
child: AutoSizeText(
'Thanks so much! We really do appreciate it!',
textAlign: TextAlign.start,
style: AppTheme.labelLarge,
)),
),
],
),
),
),
],
).animateOnPageLoad(animationsMap['rowOnPageLoadAnimation']!),
),
],
),
),
),
);
}
}
@@ -0,0 +1,18 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'model_item_widget.dart' show ModelItemWidget;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class ModelItemModel extends FlutterFlowModel<ModelItemWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for iuser widget.
bool iuserHovered = false;
@override
void initState(BuildContext context) {}
@override
void dispose() {}
}
@@ -0,0 +1,115 @@
import 'package:app/components/conversation_thread/conversation.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
import 'model_item_model.dart';
export 'model_item_model.dart';
class ModelItemWidget extends StatefulWidget {
final Conversation conversation;
const ModelItemWidget({super.key, required this.conversation});
@override
State<ModelItemWidget> createState() => _ModelItemWidgetState(conversation);
}
class _ModelItemWidgetState extends State<ModelItemWidget> {
late ModelItemModel _model;
late Conversation conversation;
_ModelItemWidgetState(this.conversation);
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => ModelItemModel());
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MouseRegion(
opaque: false,
cursor: MouseCursor.defer ?? MouseCursor.defer,
onEnter: ((event) async {
setState(() => _model.iuserHovered = true);
}),
onExit: ((event) async {
setState(() => _model.iuserHovered = false);
}),
child: Container(
decoration: BoxDecoration(
color: AppTheme.primaryBackground,
borderRadius: BorderRadius.circular(0),
),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 8, 12, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: AppTheme.accent1,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppTheme.primary,
width: 2,
),
),
child: const Align(
alignment: AlignmentDirectional(0, 0),
child: Text(
'A',
textAlign: TextAlign.center,
style: AppTheme.bodyLarge,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 0, 8, 0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text( // Label
conversation.conversationLabel,
style: AppTheme.bodyMedium,
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0),
child: Text( // Sub-label
conversation.conversationSubLabel,
style: AppTheme.bodySmall,
),
),
],
),
),
),
],
),
),
),
);
}
}
@@ -0,0 +1,71 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
class NoChatsWidget extends StatefulWidget {
const NoChatsWidget({
super.key,
this.icon,
String? title,
String? body,
}) : title = title ?? 'No Comments',
body = body ?? 'There are no comments associated with this post.';
final Widget? icon;
final String title;
final String body;
@override
State<NoChatsWidget> createState() => _NoChatsWidgetState();
}
class _NoChatsWidgetState extends State<NoChatsWidget> {
@override
void setState(VoidCallback callback) {
super.setState(callback);
}
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Align(
alignment: const AlignmentDirectional(0, -1),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
widget.icon!,
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 16, 0, 0),
child: Text(
widget.title,
textAlign: TextAlign.center,
style: AppTheme.headlineSmall,
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16, 8, 16, 0),
child: Text(
widget.body,
textAlign: TextAlign.center,
style: AppTheme.labelMedium,
),
),
],
),
);
}
}
@@ -0,0 +1,20 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'options_dialog_widget.dart' show PopupWidget;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class OptionsDialogModel extends FlutterFlowModel<PopupWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for MouseRegion widget.
bool mouseRegionHovered1 = false;
// State field(s) for MouseRegion widget.
bool mouseRegionHovered2 = false;
@override
void initState(BuildContext context) {}
@override
void dispose() {}
}
@@ -0,0 +1,180 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
import '/components/popup/popup_model.dart';
export '/components/popup/popup_model.dart';
class PopupWidget extends StatefulWidget {
const PopupWidget({super.key});
@override
State<PopupWidget> createState() => _PopupWidgetState();
}
class _PopupWidgetState extends State<PopupWidget> {
late PopupModel _model;
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => PopupModel());
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Visibility(
visible: true,
child: Align(
alignment: const AlignmentDirectional(0, 0),
child: Container(
width: double.infinity,
constraints: const BoxConstraints(
maxWidth: 570,
maxHeight: 375,
),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 64,
color: Color(0xB2000000),
offset: Offset(
2,
2,
),
spreadRadius: 225,
)
],
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: const Color(0xFFE0E3E7),
),
),
alignment: const AlignmentDirectional(0, 0),
child: Align(
alignment: const AlignmentDirectional(0, 0),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
const Expanded(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 12, 0),
child: Text(
'Refine the components modal.',
style: AppTheme.headlineMedium,
),
),
),
FlutterFlowIconButton(
borderColor: const Color(0xFFF1F4F8),
borderRadius: 30,
borderWidth: 2,
buttonSize: 44,
icon: const Icon(
Icons.close_rounded,
color: Color(0xFF57636C),
size: 24,
),
onPressed: () async {
Navigator.pop(context);
},
),
],
),
const Divider(
height: 24,
thickness: 2,
color: Color(0xFFF1F4F8),
),
const Text(
'FlutterFlow is a visual development platform that allows you to easily create beautiful and responsive user interfaces for your mobile and web applications. With its drag-and-drop interface and pre-built components, you can quickly prototype and build your app without writing any code. \nAdditionally, FlutterFlow\'s real-time preview feature allows you to see your changes in real-time and make adjustments on the fly.',
style: AppTheme.labelMedium,
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 16, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FFButtonWidget(
onPressed: () async {
Navigator.pop(context);
},
text: 'Cancel',
options: FFButtonOptions(
height: 40,
padding:
const EdgeInsetsDirectional.fromSTEB(24, 0, 24, 0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: Colors.white,
textStyle: AppTheme.bodySmall,
elevation: 0,
borderSide: const BorderSide(
color: Color(0xFFF1F4F8),
width: 2,
),
borderRadius: BorderRadius.circular(8),
hoverColor: const Color(0xFFF1F4F8),
hoverTextColor: const Color(0xFF14181B),
),
),
FFButtonWidget(
onPressed: () {
print('Button pressed ...');
},
text: 'Create Task',
options: FFButtonOptions(
width: 130,
height: 40,
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: const Color(0xFF4B39EF),
textStyle: AppTheme.titleSmall,
elevation: 3,
borderSide: const BorderSide(
color: Colors.transparent,
width: 1,
),
borderRadius: BorderRadius.circular(8),
hoverColor: const Color(0xFF2B16ED),
hoverTextColor: Colors.white,
),
),
],
),
),
],
),
),
),
),
),
);
}
}
@@ -0,0 +1,13 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'popup_widget.dart' show PopupWidget;
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class PopupModel extends FlutterFlowModel<PopupWidget> {
@override
void initState(BuildContext context) {}
@override
void dispose() {}
}
@@ -0,0 +1,180 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
import 'popup_model.dart';
export 'popup_model.dart';
class PopupWidget extends StatefulWidget {
const PopupWidget({super.key});
@override
State<PopupWidget> createState() => _PopupWidgetState();
}
class _PopupWidgetState extends State<PopupWidget> {
late PopupModel _model;
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => PopupModel());
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Visibility(
visible: true,
child: Align(
alignment: const AlignmentDirectional(0, 0),
child: Container(
width: double.infinity,
constraints: const BoxConstraints(
maxWidth: 570,
maxHeight: 375,
),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 64,
color: Color(0xB2000000),
offset: Offset(
2,
2,
),
spreadRadius: 225,
)
],
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: const Color(0xFFE0E3E7),
),
),
alignment: const AlignmentDirectional(0, 0),
child: Align(
alignment: const AlignmentDirectional(0, 0),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
const Expanded(
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 12, 0),
child: Text(
'A popup',
style: AppTheme.headlineMedium,
),
),
),
FlutterFlowIconButton(
borderColor: const Color(0xFFF1F4F8),
borderRadius: 30,
borderWidth: 2,
buttonSize: 44,
icon: const Icon(
Icons.close_rounded,
color: Color(0xFF57636C),
size: 24,
),
onPressed: () async {
Navigator.pop(context);
},
),
],
),
const Divider(
height: 12,
thickness: 2,
color: Color(0xFFF1F4F8),
),
const Text(
'Test',
style: AppTheme.labelMedium,
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 16, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FFButtonWidget(
onPressed: () async {
Navigator.pop(context);
},
text: 'Cancel',
options: FFButtonOptions(
height: 40,
padding:
const EdgeInsetsDirectional.fromSTEB(24, 0, 24, 0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: Colors.white,
textStyle: AppTheme.bodySmall,
elevation: 0,
borderSide: const BorderSide(
color: Color(0xFFF1F4F8),
width: 2,
),
borderRadius: BorderRadius.circular(8),
hoverColor: const Color(0xFFF1F4F8),
hoverTextColor: const Color(0xFF14181B),
),
),
FFButtonWidget(
onPressed: () {
print('Button pressed ...');
},
text: 'Action',
options: FFButtonOptions(
width: 130,
height: 40,
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: const Color(0xFF4B39EF),
textStyle: AppTheme.titleSmall,
elevation: 3,
borderSide: const BorderSide(
color: Colors.transparent,
width: 1,
),
borderRadius: BorderRadius.circular(8),
hoverColor: const Color(0xFF2B16ED),
hoverTextColor: Colors.white,
),
),
],
),
),
],
),
),
),
),
),
);
}
}
@@ -0,0 +1,24 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'prompt_box_widget.dart' show PromptBoxWidget;
import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class PromptBoxModel extends FlutterFlowModel<PromptBoxWidget> {
/// State fields for stateful widgets in this component.
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode;
TextEditingController? textController;
String? Function(BuildContext, String?)? textControllerValidator;
@override
void initState(BuildContext context) {}
@override
void dispose() {
textFieldFocusNode?.dispose();
textController?.dispose();
}
}
@@ -0,0 +1,285 @@
import 'dart:io';
import 'package:app/components/util/backend.dart';
import 'package:camera/camera.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/services.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter/material.dart';
import 'package:app/theme.dart';
import 'package:image_picker/image_picker.dart';
import '../conversation_thread/chat.dart';
import 'prompt_box_model.dart';
export 'prompt_box_model.dart';
class PromptBoxWidget extends StatefulWidget {
const PromptBoxWidget({super.key});
@override
State<PromptBoxWidget> createState() => _PromptBoxWidgetState();
}
class _PromptBoxWidgetState extends State<PromptBoxWidget> {
late PromptBoxModel _model;
String entryText = "";
@override
void setState(VoidCallback callback) {
super.setState(callback);
_model.onUpdate();
}
@override
void initState() {
super.initState();
_model = createModel(context, () => PromptBoxModel());
_model.textController ??= TextEditingController();
_model.textFieldFocusNode ??= FocusNode();
}
@override
void dispose() {
_model.maybeDispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
const double buttonPadding = 4;
return SafeArea(
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: AppTheme.secondaryBackground,
borderRadius: BorderRadius.circular(10),
),
alignment: const AlignmentDirectional(0, 0),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
// TODO: Implement the context upload buttons
children: [
Expanded( // TODO: Video context upload
child: Padding(
padding: const EdgeInsets.all(buttonPadding),
child: IconButton(
icon: const Icon(
Icons.videocam_outlined,
color: AppTheme.accent2,
size: 30,
),
onPressed: () {
print('IconButton pressed ...');
},
),
),
),
Expanded( // TODO: Gallery context upload
child: Padding(
padding: const EdgeInsets.all(buttonPadding),
child: IconButton(
icon: const Icon(
Icons.photo_outlined,
color: AppTheme.accent2,
size: 30,
),
onPressed: () async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
// TODO: Allow for multiple pictures/photos to be selected.
// final images = await picker.pickMultiImage();
if (image != null) {
// TODO: Upload to server and add to conversation.chats
String i = Backend.convertToBase64(File(image.path)).toString();
Backend.loadedConversation.add(Chat.image(i, true, 1));
} else {
print('User canceled image selection');
}
},
),
),
),
Expanded( // TODO: File context upload
child: Padding(
padding: const EdgeInsets.all(buttonPadding),
child: IconButton(
icon: const Icon(
Icons.file_upload_outlined,
color: AppTheme.accent2,
size: 30,
),
onPressed: () async {
final picker = FilePicker.platform;
final result = await picker.pickFiles(allowMultiple: true); // Allow multiple files
if (result != null) {
for (final platformFile in result.files) {
// TODO: Upload file to server
final file = File(platformFile.path!);
}
} else {
print('User canceled file selection');
}
},
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(buttonPadding),
child: IconButton(
icon: const Icon(
Icons.camera_alt_outlined,
color: AppTheme.accent2,
size: 30,
),
onPressed: () async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.camera);
if (image != null) {
final i = Backend.convertToBase64(File(image.path));
// TODO: Add to widget rather than display in conversation thread.
Backend.loadedConversation.add(Chat.image(i.toString(), true, 1));
}
},
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(buttonPadding),
child: IconButton(
icon: Icon(
Backend.stt.speechToText.isNotListening ? Icons.mic_off_outlined : Icons.mic_none,
color: AppTheme.accent2,
size: 30,
),
onPressed: () {
// TODO: Audio input is still buggy, it appears to only enter the text field once the button is pressed again to stop.
if(Backend.stt.speechToText.isNotListening) {
print('STT engine starting ...');
Backend.stt.startListening();
updateText();
} else {
print('STT engine stopping');
Backend.stt.stopListening();
updateText();
}
},
),
),
),
],
),
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
flex: 7,
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(12, 0, 12, 0),
child: TextFormField(
keyboardAppearance: Brightness.dark,
controller: _model.textController,
focusNode: _model.textFieldFocusNode,
onChanged: (_) => EasyDebounce.debounce(
'_model.textController',
const Duration(milliseconds: 2000),
() => setState(() {}),
),
autofocus: true,
textCapitalization: TextCapitalization.none,
decoration: InputDecoration(
isDense: false,
counterStyle: AppTheme.bodyMedium,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.secondaryText,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Color(0x00000000),
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Color(0x00000000),
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: Color(0x00000000),
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
filled: true,
fillColor: AppTheme.alternate,
suffixIcon: GestureDetector(
onTap: () {
if(_model.textController.text != "") {
// TODO: Connect with multimedia
entryText = _model.textController.text;
Backend.respondWhenReady(entryText);
_model.textController?.clear(); // Clear the text field
SystemChannels.textInput.invokeMethod('TextInput.hide');
}
},
child: const Icon(
Icons.send,
color: AppTheme.accent,
size: 30,
),
),
),
style: AppTheme.displayMedium,
textAlign: TextAlign.start,
maxLines: 5,
minLines: 1,
textInputAction: TextInputAction.send, // "Send" on keyboard
onFieldSubmitted: (text) {
// Don't take any action unless there's an actual input.
if(_model.textController.text != "") {
entryText = _model.textController.text;
Backend.respondWhenReady(entryText); // TODO: Connect with multimedia
_model.textController?.clear(); // Clear the text field
}
},
),
),
),
],
),
],
),
),
);
}
void updateText() {
_model.textController.text = Backend.stt.text;
entryText = _model.textController.text;
print(entryText);
print(_model.textController.text);
Backend.stt.reset();
}
}
@@ -0,0 +1,16 @@
import '/components/popup/popup_widget.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'settings_widget.dart' show SettingsWidget;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class SettingsModel extends FlutterFlowModel<SettingsWidget> {
@override
void initState(BuildContext context) {}
@override
void dispose() {}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,20 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'setup_widget.dart' show SetupWidget;
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class SetupModel extends FlutterFlowModel<SetupWidget> {
/// State fields for stateful widgets in this page.
final unfocusNode = FocusNode();
@override
void initState(BuildContext context) {}
@override
void dispose() {
unfocusNode.dispose();
}
}
+303
View File
@@ -0,0 +1,303 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:app/theme.dart';
import 'setup_model.dart';
export 'setup_model.dart';
class SetupWidget extends StatefulWidget {
const SetupWidget({super.key});
@override
State<SetupWidget> createState() => _SetupWidgetState();
}
class _SetupWidgetState extends State<SetupWidget>
with TickerProviderStateMixin {
late SetupModel _model;
final scaffoldKey = GlobalKey<ScaffoldState>();
final animationsMap = <String, AnimationInfo>{};
@override
void initState() {
super.initState();
_model = createModel(context, () => SetupModel());
animationsMap.addAll({
'containerOnPageLoadAnimation1': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
VisibilityEffect(duration: 1.ms),
FadeEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 400.0.ms,
begin: 0.0,
end: 1.0,
),
ScaleEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 400.0.ms,
begin: const Offset(3.0, 3.0),
end: const Offset(1.0, 1.0),
),
],
),
'containerOnPageLoadAnimation2': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
VisibilityEffect(duration: 300.ms),
FadeEffect(
curve: Curves.easeInOut,
delay: 300.0.ms,
duration: 300.0.ms,
begin: 0.0,
end: 1.0,
),
ScaleEffect(
curve: Curves.bounceOut,
delay: 300.0.ms,
duration: 300.0.ms,
begin: const Offset(0.6, 0.6),
end: const Offset(1.0, 1.0),
),
],
),
'textOnPageLoadAnimation1': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
VisibilityEffect(duration: 350.ms),
FadeEffect(
curve: Curves.easeInOut,
delay: 350.0.ms,
duration: 400.0.ms,
begin: 0.0,
end: 1.0,
),
MoveEffect(
curve: Curves.easeInOut,
delay: 350.0.ms,
duration: 400.0.ms,
begin: const Offset(0.0, 30.0),
end: const Offset(0.0, 0.0),
),
],
),
'textOnPageLoadAnimation2': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
VisibilityEffect(duration: 400.ms),
FadeEffect(
curve: Curves.easeInOut,
delay: 400.0.ms,
duration: 400.0.ms,
begin: 0.0,
end: 1.0,
),
MoveEffect(
curve: Curves.easeInOut,
delay: 400.0.ms,
duration: 400.0.ms,
begin: const Offset(0.0, 30.0),
end: const Offset(0.0, 0.0),
),
],
),
'rowOnPageLoadAnimation': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
VisibilityEffect(duration: 300.ms),
FadeEffect(
curve: Curves.easeInOut,
delay: 300.0.ms,
duration: 600.0.ms,
begin: 0.0,
end: 1.0,
),
ScaleEffect(
curve: Curves.bounceOut,
delay: 300.0.ms,
duration: 600.0.ms,
begin: const Offset(0.6, 0.6),
end: const Offset(1.0, 1.0),
),
],
),
});
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _model.unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(_model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: Scaffold(
key: scaffoldKey,
backgroundColor: AppTheme.secondaryBackground,
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Container(
width: double.infinity,
height: 500,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
AppTheme.primary,
AppTheme.error,
AppTheme.tertiary
],
stops: [0, 0.5, 1],
begin: AlignmentDirectional(-1, -1),
end: AlignmentDirectional(1, 1),
),
),
child: Container(
width: 100,
height: 100,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [
Color(0x00FFFFFF),
AppTheme.secondaryBackground
],
stops: [0, 1],
begin: AlignmentDirectional(0, -1),
end: AlignmentDirectional(0, 1),
),
),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 120,
height: 120,
decoration: const BoxDecoration(
color: AppTheme.accent4,
shape: BoxShape.circle,
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Image.network(
'https://storage.googleapis.com/flutterflow-io-6f20.appspot.com/projects/f-f-templates-q1-23-fbcr63/assets/ax4fvwjz7awx/@4xff_badgeDesign_dark_small.png',
width: 100,
height: 100,
fit: BoxFit.cover,
),
),
).animateOnPageLoad(
animationsMap['containerOnPageLoadAnimation2']!),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 44, 0, 0),
child: const Text(
'Welcome!',
style: AppTheme.displaySmall,
).animateOnPageLoad(
animationsMap['textOnPageLoadAnimation1']!),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(44, 8, 44, 0),
child: const Text(
'Thanks for joining! Access or create your account below, and get started on your journey!',
textAlign: TextAlign.center,
style: AppTheme.labelMedium,
).animateOnPageLoad(
animationsMap['textOnPageLoadAnimation2']!),
),
],
),
),
).animateOnPageLoad(
animationsMap['containerOnPageLoadAnimation1']!),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16, 24, 16, 44),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Align(
alignment: const AlignmentDirectional(0, 0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 8, 16),
child: FFButtonWidget(
onPressed: () {
print('Button pressed ...');
},
text: 'Get Started',
options: FFButtonOptions(
width: 230,
height: 52,
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: AppTheme
.secondaryBackground,
textStyle: AppTheme.bodyLarge,
elevation: 0,
borderSide: const BorderSide(
color: AppTheme.alternate,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
),
),
),
),
Expanded(
child: Align(
alignment: const AlignmentDirectional(0, 0),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(8, 0, 0, 16),
child: FFButtonWidget(
onPressed: () {
print('Button pressed ...');
},
text: 'My Account',
options: FFButtonOptions(
width: 230,
height: 52,
padding: const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: AppTheme.primary,
textStyle: AppTheme.titleSmall,
elevation: 3,
borderSide: const BorderSide(
color: Colors.transparent,
width: 1,
),
borderRadius: BorderRadius.circular(12),
),
),
),
),
),
],
).animateOnPageLoad(animationsMap['rowOnPageLoadAnimation']!),
),
],
),
),
);
}
}
@@ -0,0 +1,40 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'support_form_widget.dart' show SupportFormWidget;
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
class SupportFormModel extends FlutterFlowModel<SupportFormWidget> {
/// State fields for stateful widgets in this page.
final unfocusNode = FocusNode();
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode1;
TextEditingController? textController1;
String? Function(BuildContext, String?)? textController1Validator;
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode2;
TextEditingController? textController2;
String? Function(BuildContext, String?)? textController2Validator;
// State field(s) for TextField widget.
FocusNode? textFieldFocusNode3;
TextEditingController? textController3;
String? Function(BuildContext, String?)? textController3Validator;
@override
void initState(BuildContext context) {}
@override
void dispose() {
unfocusNode.dispose();
textFieldFocusNode1?.dispose();
textController1?.dispose();
textFieldFocusNode2?.dispose();
textController2?.dispose();
textFieldFocusNode3?.dispose();
textController3?.dispose();
}
}
@@ -0,0 +1,496 @@
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import '../components/support_form_model.dart';
export '../components/support_form_model.dart';
import 'package:app/theme.dart';
class SupportFormWidget extends StatefulWidget {
const SupportFormWidget({super.key});
@override
State<SupportFormWidget> createState() => _SupportFormWidgetState();
}
class _SupportFormWidgetState extends State<SupportFormWidget>
with TickerProviderStateMixin {
late SupportFormModel _model;
final scaffoldKey = GlobalKey<ScaffoldState>();
final animationsMap = <String, AnimationInfo>{};
@override
void initState() {
super.initState();
_model = createModel(context, () => SupportFormModel());
_model.textController1 ??= TextEditingController();
_model.textFieldFocusNode1 ??= FocusNode();
_model.textController2 ??= TextEditingController();
_model.textFieldFocusNode2 ??= FocusNode();
_model.textController3 ??= TextEditingController();
_model.textFieldFocusNode3 ??= FocusNode();
animationsMap.addAll({
'containerOnPageLoadAnimation1': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
FadeEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 600.0.ms,
begin: 0.0,
end: 1.0,
),
MoveEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 600.0.ms,
begin: const Offset(0.0, 110.0),
end: const Offset(0.0, 0.0),
),
],
),
'containerOnPageLoadAnimation2': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
FadeEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 600.0.ms,
begin: 0.0,
end: 1.0,
),
MoveEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 600.0.ms,
begin: const Offset(0.0, 110.0),
end: const Offset(0.0, 0.0),
),
],
),
'containerOnPageLoadAnimation3': AnimationInfo(
trigger: AnimationTrigger.onPageLoad,
effectsBuilder: () => [
FadeEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 600.0.ms,
begin: 0.0,
end: 1.0,
),
MoveEffect(
curve: Curves.easeInOut,
delay: 0.0.ms,
duration: 600.0.ms,
begin: const Offset(0.0, 110.0),
end: const Offset(0.0, 0.0),
),
],
),
});
setupAnimations(
animationsMap.values.where((anim) =>
anim.trigger == AnimationTrigger.onActionTrigger ||
!anim.applyInitialState),
this,
);
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _model.unfocusNode.canRequestFocus
? FocusScope.of(context).requestFocus(_model.unfocusNode)
: FocusScope.of(context).unfocus(),
child: Scaffold(
key: scaffoldKey,
backgroundColor: AppTheme.secondaryBackground,
appBar: AppBar(
backgroundColor: AppTheme.secondaryBackground,
automaticallyImplyLeading: false,
leading: FlutterFlowIconButton(
borderColor: Colors.transparent,
borderRadius: 30,
borderWidth: 1,
buttonSize: 60,
icon: const Icon(
Icons.arrow_back_rounded,
color: AppTheme.primaryTextColor,
size: 30,
),
onPressed: () async {
//TODO: context.pop();
},
),
title: const Text(
'Submit Ticket',
style: AppTheme.titleLarge,
),
actions: const [],
centerTitle: false,
elevation: 0,
),
body: SafeArea(
top: true,
child: Align(
alignment: const AlignmentDirectional(0, 1),
child: Padding(
padding: const EdgeInsetsDirectional.fromSTEB(16, 12, 16, 0),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Welcome to support',
style: AppTheme.labelLarge,
),
const Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0),
child: Text(
'Submit a bug',
style: AppTheme.headlineMedium,
),
),
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0, 16, 0, 0),
child: Container(
width: 120,
constraints: const BoxConstraints(
maxWidth: 500,
),
decoration: BoxDecoration(
color: AppTheme
.secondaryBackground,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppTheme.alternate,
width: 2,
),
),
child: const Padding(
padding: EdgeInsetsDirectional.fromSTEB(
8, 16, 8, 16),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.email_outlined,
color:
AppTheme.primary,
size: 36,
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 12, 0, 0),
child: Text(
'Email Us',
textAlign: TextAlign.center,
style: AppTheme.bodyMedium,
),
),
],
),
),
).animateOnPageLoad(animationsMap[
'containerOnPageLoadAnimation1']!),
),
),
Expanded(
child: Padding(
padding:
const EdgeInsetsDirectional.fromSTEB(0, 16, 0, 0),
child: Container(
width: 120,
constraints: const BoxConstraints(
maxWidth: 500,
),
decoration: BoxDecoration(
color: AppTheme
.secondaryBackground,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppTheme.alternate,
width: 2,
),
),
child: const Padding(
padding: EdgeInsetsDirectional.fromSTEB(
8, 16, 8, 16),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.search_rounded,
color:
AppTheme.primary,
size: 36,
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(
0, 12, 0, 0),
child: Text(
'Search FAQs',
textAlign: TextAlign.center,
style: AppTheme.bodyMedium,
),
),
],
),
),
).animateOnPageLoad(animationsMap[
'containerOnPageLoadAnimation2']!),
),
),
].divide(const SizedBox(width: 12)),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 16, 0, 0),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
TextFormField(
controller: _model.textController1,
focusNode: _model.textFieldFocusNode1,
autofocus: true,
obscureText: false,
decoration: InputDecoration(
labelText: 'Channel Name',
labelStyle: AppTheme.labelMedium,
hintStyle: AppTheme.labelMedium,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.alternate,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.primary,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.error,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.error,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
contentPadding: const EdgeInsetsDirectional.fromSTEB(
16, 12, 16, 12),
),
style: AppTheme.bodyMedium,
cursorColor: AppTheme.primary,
validator: _model.textController1Validator
.asValidator(context),
),
TextFormField(
controller: _model.textController2,
focusNode: _model.textFieldFocusNode2,
autofocus: true,
obscureText: false,
decoration: InputDecoration(
labelText: 'Channel ID',
labelStyle: AppTheme.labelMedium,
hintStyle: AppTheme.labelMedium,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.alternate,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.primary,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.error,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.error,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
contentPadding: const EdgeInsetsDirectional.fromSTEB(
16, 12, 16, 12),
),
style: AppTheme.bodyMedium,
cursorColor: AppTheme.primary,
validator: _model.textController2Validator
.asValidator(context),
),
TextFormField(
controller: _model.textController3,
focusNode: _model.textFieldFocusNode3,
autofocus: true,
obscureText: false,
decoration: InputDecoration(
labelStyle: AppTheme.labelMedium,
hintText:
'Short Description of what is going on...',
hintStyle: AppTheme.labelMedium,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.alternate,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.primary,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
errorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.error,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: const BorderSide(
color: AppTheme.error,
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
contentPadding: const EdgeInsetsDirectional.fromSTEB(
16, 24, 16, 12),
),
style: AppTheme.bodyMedium,
maxLines: 16,
minLines: 6,
cursorColor: AppTheme.primary,
validator: _model.textController3Validator
.asValidator(context),
),
].divide(const SizedBox(height: 12)),
),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 16, 0, 0),
child: Container(
width: double.infinity,
constraints: const BoxConstraints(
maxWidth: 500,
),
decoration: BoxDecoration(
color:
AppTheme.secondaryBackground,
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppTheme.alternate,
width: 2,
),
),
child: const Padding(
padding: EdgeInsets.all(8),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Icon(
Icons.add_a_photo_rounded,
color: AppTheme.primary,
size: 32,
),
Padding(
padding:
EdgeInsetsDirectional.fromSTEB(16, 0, 0, 0),
child: Text(
'Upload Screenshot',
textAlign: TextAlign.center,
style: AppTheme.bodyMedium,
),
),
],
),
),
).animateOnPageLoad(
animationsMap['containerOnPageLoadAnimation3']!),
),
Padding(
padding: const EdgeInsetsDirectional.fromSTEB(0, 24, 0, 12),
child: FFButtonWidget(
onPressed: () {
print('Button pressed ...');
},
text: 'Submit Ticket',
icon: const Icon(
Icons.receipt_long,
size: 15,
),
options: FFButtonOptions(
width: double.infinity,
height: 48,
padding: const EdgeInsets.all(0),
iconPadding:
const EdgeInsetsDirectional.fromSTEB(0, 0, 0, 0),
color: AppTheme.primary,
textStyle: AppTheme.titleSmall,
elevation: 4,
borderSide: const BorderSide(
color: Colors.transparent,
width: 1,
),
borderRadius: BorderRadius.circular(60),
),
),
),
],
),
),
),
),
),
),
);
}
}
+253
View File
@@ -0,0 +1,253 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/widgets.dart';
import 'package:app/components/conversation_thread/conversation.dart';
import 'package:camera/camera.dart';
import 'package:http/http.dart' as http;
import 'package:app/components/conversation_thread/chat.dart';
import 'package:app/components/util/speech_to_text.dart';
import 'model.dart';
// Uses Singleton design pattern to ensure that any server references across the app are using the same instance.
class Backend {
// SERVER VARIABLES
static final Backend singleBackend = Backend._internal();
Backend._internal();
// TODO: One-time process to establish server connection is required for easy setup/maintenance.
static const url = "http://10.0.2.2:11434/api/"; // For emulated device in testing
//static final url = "http://192.168.1.68:11434/api"; // For local access to home server
static String endpoint = "";
static final Map<String, String> headers = {'Content-Type': 'application/json'};
static final bool UI_TESTING = true;
// AI VARIABLES
static final SpeechToText stt = SpeechToText();
static late bool _speechEnabled;
// PRIVACY-NECESSARY VARIABLES
// TODO: Reorder based on most recent usage.
static List<Conversation> conversations = [];
static List<Chat> loadedChats = [];
static late Conversation loadedConversation;
static late List<CameraDescription> cameras;
static late CameraController controller;
// RUNTIME & STATUS VARIABLES
static late int conversationID;
static late int maxConversationID;
static late Model model;
static String prompt = "";
static String response = "";
static bool initiated = false;
// TODO: Verify all different components of STT, TTS, LLM, etc have been initialized.
// TODO: Handshake w/ server to validate identity
factory Backend() {
return singleBackend;
}
void init() async {
// Prevent multiple initiations
if(!initiated) {
initiated = true;
// Speech-To-Text engine activation.
_speechEnabled = stt.isSpeechEnabled();
model = Model("llama3"); // Primarily used llama3, testing gemma2
maxConversationID = conversations.length;
cameras = await availableCameras();
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize(); // TODO: Add error catching on camera
}
// TODO: Dynamically get available models and models that can be pulled.
// TODO: Dynamically get the user's default model
// TODO: Dynamically obtain conversations.
// TODO: Obtain all user permissions at once.
}
// PRIMARY INTERFACES
@Deprecated("Use STT interface directly and use respondWhenReady().")
static Future<String> sttGetResponseWhenReady() async {
// TODO: In case on-device STT is unavailable, use server-side STT service.
if (!_speechEnabled) {
return "Unable to process Speech-To-Text on-device.";
}
prompt = stt.getTextWhenReady() as String;
conversations[conversationID].add(Chat(prompt, true, 0));
if(!UI_TESTING) {
httpSendRequest();
}
conversations[conversationID].add(Chat(response, false, 0));
return response;
}
static void respondWhenReady(String p) async {
prompt = p;
conversations[conversationID].add(Chat(prompt, true, 0));
if(!UI_TESTING) {
httpSendRequest();
}
}
static ImageProvider convertFromBase64(img) {
Uint8List imageBytes = base64Decode(img);
return Image.memory(imageBytes).image;
}
// Converts image to base64 encoded string for data transfer.
static String convertToBase64(f) {
List<int> imageBytes = f.readAsBytesSync();
String img = base64Encode(imageBytes);
// TODO: Add special handling for images included in prompts.
conversations[conversationID].add(Chat.image(img, true, 1));
return img;
}
// CONVERSATION MANAGEMENT
@Deprecated("")
static List<Conversation> getConversationsList() { return conversations; }
static Conversation getLoadedConversation() { return loadedConversation; }
// Load conversation should be called prior to any other server requests.
static void loadConversation(id) {
conversationID = id;
loadedConversation = conversations[id];
loadedChats = loadedConversation.chats;
}
// TODO: Better conversation ID management is needed. Preferably randomized IDs to not indicate the number of conversations.
static int createConversation() {
int id = conversations.length;
conversations.add(Conversation(id, "Conversation $id", "Another AI conversation"));
return id;
}
static void deleteConversation(id) {
loadedChats = conversations[conversationID].chats; // TODO: Temporarily saving the chats for "undo" popup.
conversations.removeAt(id);
}
@Deprecated('Just directly get loadedChats list. Unless multiple chats can be opened simultaneously?')
static List<Chat> getChatsByConversationID(id) { return conversations[id].chats; }
// SERVER UTILS
static List<Map<String, String>> convertMessages() {
// TODO: Integrate with getConversationByID()
List<Map<String, String>> messageList = [];
for (Chat c in loadedChats) {
messageList.add({
"role": c.role ? "user" : "assistant",
"content": c.content,
});
}
return messageList;
}
// Formats the prompt in JSON.
static String constructPrompt() {
// TODO: Allow for additional flags, ie. continuous conversation, images, etc.
// TODO: Allow for toggleable states between stream
// TODO: Allow for different models to be dynamically selected.
// TODO: Further adaption of API calls to allow for images to/from the AI model
// Example API call for image recognition
// curl http://localhost:11434/api/generate -d '{
// "model": "llava",
// "prompt":"What is in this picture?",
// "stream": false,
// "images": ["iVBORw0KGgoAAAANSUhEUgAAAG0AAABmCAYAAADBPx+VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAA3VSURBVHgB7Z27r0zdG8fX743i1bi1ikMoFMQloXRpKFFIqI7LH4BEQ+NWIkjQuSWCRIEoULk0gsK1kCBI0IhrQVT7tz/7zZo888yz1r7MnDl7z5xvsjkzs2fP3uu71nNfa7lkAsm7d++Sffv2JbNmzUqcc8m0adOSzZs3Z+/XES4ZckAWJEGWPiCxjsQNLWmQsWjRIpMseaxcuTKpG/7HP27I8P79e7dq1ars/yL4/v27S0ejqwv+cUOGEGGpKHR37tzJCEpHV9tnT58+dXXCJDdECBE2Ojrqjh071hpNECjx4cMHVycM1Uhbv359B2F79+51586daxN/+pyRkRFXKyRDAqxEp4yMlDDzXG1NPnnyJKkThoK0VFd1ELZu3TrzXKxKfW7dMBQ6bcuWLW2v0VlHjx41z717927ba22U9APcw7Nnz1oGEPeL3m3p2mTAYYnFmMOMXybPPXv2bNIPpFZr1NHn4HMw0KRBjg9NuRw95s8PEcz/6DZELQd/09C9QGq5RsmSRybqkwHGjh07OsJSsYYm3ijPpyHzoiacg35MLdDSIS/O1yM778jOTwYUkKNHWUzUWaOsylE00MyI0fcnOwIdjvtNdW/HZwNLGg+sR1kMepSNJXmIwxBZiG8tDTpEZzKg0GItNsosY8USkxDhD0Rinuiko2gfL/RbiD2LZAjU9zKQJj8RDR0vJBR1/Phx9+PHj9Z7REF4nTZkxzX4LCXHrV271qXkBAPGfP/atWvu/PnzHe4C97F48eIsRLZ9+3a3f/9+87dwP1JxaF7/3r17ba+5l4EcaVo0lj3SBq5kGTJSQmLWMjgYNei2GPT1MuMqGTDEFHzeQSP2wi/jGnkmPJ/nhccs44jvDAxpVcxnq0F6eT8h4ni/iIWpR5lPyA6ETkNXoSukvpJAD3AsXLiwpZs49+fPn5ke4j10TqYvegSfn0OnafC+Tv9ooA/JPkgQysqQNBzagXY55nO/oa1F7qvIPWkRL12WRpMWUvpVDYmxAPehxWSe8ZEXL20sadYIozfmNch4QJPAfeJgW3rNsnzphBKNJM2KKODo1rVOMRYik5ETy3ix4qWNI81qAAirizgMIc+yhTytx0JWZuNI03qsrgWlGtwjoS9XwgUhWGyhUaRZZQNNIEwCiXD16tXcAHUs79co0vSD8rrJCIW98pzvxpAWyyo3HYwqS0+H0BjStClcZJT5coMm6D2LOF8TolGJtK9fvyZpyiC5ePFi9nc/oJU4eiEP0jVoAnHa9wyJycITMP78+eMeP37sXrx44d6+fdt6f82aNdkx1pg9e3Zb5W+RSRE+n+VjksQWifvVaTKFhn5O8my63K8Qabdv33b379/PiAP//vuvW7BggZszZ072/+TJk91YgkafPn166zXB1rQHFvouAWHq9z3SEevSUerqCn2/dDCeta2jxYbr69evk4MHDyY7d+7MjhMnTiTPnz9Pfv/+nfQT2ggpO2dMF8cghuoM7Ygj5iWCqRlGFml0QC/ftGmTmzt3rmsaKDsgBSPh0/8yPeLLBihLkOKJc0jp8H8vUzcxIA1k6QJ/c78tWEyj5P3o4u9+jywNPdJi5rAH9x0KHcl4Hg570eQp3+vHXGyrmEeigzQsQsjavXt38ujRo44LQuDDhw+TW7duRS1HGgMxhNXHgflaNTOsHyKvHK5Ijo2jbFjJBQK9YwFd6RVMzfgRBmEfP37suBBm/p49e1qjEP2mwTViNRo0VJWH1deMXcNK08uUjVUu7s/zRaL+oLNxz1bpANco4npUgX4G2eFbpDFyQoQxojBCpEGSytmOH8qrH5Q9vuzD6ofQylkCUmh8DBAr+q8JCyVNtWQIidKQE9wNtLSQnS4jDSsxNHogzFuQBw4cyM61UKVsjfr3ooBkPSqqQHesUPWVtzi9/vQi1T+rJj7WiTz4Pt/l3LxUkr5P2VYZaZ4URpsE+st/dujQoaBBYokbrz/8TJNQYLSonrPS9kUaSkPeZyj1AWSj+d+VBoy1pIWVNed8P0Ll/ee5HdGRhrHhR5GGN0r4LGZBaj8oFDJitBTJzIZgFcmU0Y8ytWMZMzJOaXUSrUs5RxKnrxmbb5YXO9VGUhtpXldhEUogFr3IzIsvlpmdosVcGVGXFWp2oU9kLFL3dEkSz6NHEY1sjSRdIuDFWEhd8KxFqsRi1uM/nz9/zpxnwlESONdg6dKlbsaMGS4EHFHtjFIDHwKOo46l4TxSuxgDzi+rE2jg+BaFruOX4HXa0Nnf1lwAPufZeF8/r6zD97WK2qFnGjBxTw5qNGPxT+5T/r7/7RawFC3j4vTp09koCxkeHjqbHJqArmH5UrFKKksnxrK7FuRIs8STfBZv+luugXZ2pR/pP9Ois4z+TiMzUUkUjD0iEi1fzX8GmXyuxUBRcaUfykV0YZnlJGKQpOiGB76x5GeWkWWJc3mOrK6S7xdND+W5N6XyaRgtWJFe13GkaZnKOsYqGdOVVVbGupsyA/l7emTLHi7vwTdirNEt0qxnzAvBFcnQF16xh/TMpUuXHDowhlA9vQVraQhkudRdzOnK+04ZSP3DUhVSP61YsaLtd/ks7ZgtPcXqPqEafHkdqa84X6aCeL7YWlv6edGFHb+ZFICPlljHhg0bKuk0CSvVznWsotRu433alNdFrqG45ejoaPCaUkWERpLXjzFL2Rpllp7PJU2a/v7Ab8N05/9t27Z16KUqoFGsxnI9EosS2niSYg9SpU6B4JgTrvVW1flt1sT+0ADIJU2maXzcUTraGCRaL1Wp9rUMk16PMom8QhruxzvZIegJjFU7LLCePfS8uaQdPny4jTTL0dbee5mYokQsXTIWNY46kuMbnt8Kmec+LGWtOVIl9cT1rCB0V8WqkjAsRwta93TbwNYoGKsUSChN44lgBNCoHLHzquYKrU6qZ8lolCIN0Rh6cP0Q3U6I6IXILYOQI513hJaSKAorFpuHXJNfVlpRtmYBk1Su1obZr5dnKAO+L10Hrj3WZW+E3qh6IszE37F6EB+68mGpvKm4eb9bFrlzrok7fvr0Kfv727dvWRmdVTJHw0qiiCUSZ6wCK+7XL/AcsgNyL74DQQ730sv78Su7+t/A36MdY0sW5o40ahslXr58aZ5HtZB8GH64m9EmMZ7FpYw4T6QnrZfgenrhFxaSiSGXtPnz57e9TkNZLvTjeqhr734CNtrK41L40sUQckmj1lGKQ0rC37x544r8eNXRpnVE3ZZY7zXo8NomiO0ZUCj2uHz58rbXoZ6gc0uA+F6ZeKS/jhRDUq8MKrTho9fEkihMmhxtBI1DxKFY9XLpVcSkfoi8JGnToZO5sU5aiDQIW716ddt7ZLYtMQlhECdBGXZZMWldY5BHm5xgAroWj4C0hbYkSc/jBmggIrXJWlZM6pSETsEPGqZOndr2uuuR5rF169a2HoHPdurUKZM4CO1WTPqaDaAd+GFGKdIQkxAn9RuEWcTRyN2KSUgiSgF5aWzPTeA/lN5rZubMmR2bE4SIC4nJoltgAV/dVefZm72AtctUCJU2CMJ327hxY9t7EHbkyJFseq+EJSY16RPo3Dkq1kkr7+q0bNmyDuLQcZBEPYmHVdOBiJyIlrRDq41YPWfXOxUysi5fvtyaj+2BpcnsUV/oSoEMOk2CQGlr4ckhBwaetBhjCwH0ZHtJROPJkyc7UjcYLDjmrH7ADTEBXFfOYmB0k9oYBOjJ8b4aOYSe7QkKcYhFlq3QYLQhSidNmtS2RATwy8YOM3EQJsUjKiaWZ+vZToUQgzhkHXudb/PW5YMHD9yZM2faPsMwoc7RciYJXbGuBqJ1UIGKKLv915jsvgtJxCZDubdXr165mzdvtr1Hz5LONA8jrUwKPqsmVesKa49S3Q4WxmRPUEYdTjgiUcfUwLx589ySJUva3oMkP6IYddq6HMS4o55xBJBUeRjzfa4Zdeg56QZ43LhxoyPo7Lf1kNt7oO8wWAbNwaYjIv5lhyS7kRf96dvm5Jah8vfvX3flyhX35cuX6HfzFHOToS1H4BenCaHvO8pr8iDuwoUL7tevX+b5ZdbBair0xkFIlFDlW4ZknEClsp/TzXyAKVOmmHWFVSbDNw1l1+4f90U6IY/q4V27dpnE9bJ+v87QEydjqx/UamVVPRG+mwkNTYN+9tjkwzEx+atCm/X9WvWtDtAb68Wy9LXa1UmvCDDIpPkyOQ5ZwSzJ4jMrvFcr0rSjOUh+GcT4LSg5ugkW1Io0/SCDQBojh0hPlaJdah+tkVYrnTZowP8iq1F1TgMBBauufyB33x1v+NWFYmT5KmppgHC+NkAgbmRkpD3yn9QIseXymoTQFGQmIOKTxiZIWpvAatenVqRVXf2nTrAWMsPnKrMZHz6bJq5jvce6QK8J1cQNgKxlJapMPdZSR64/UivS9NztpkVEdKcrs5alhhWP9NeqlfWopzhZScI6QxseegZRGeg5a8C3Re1Mfl1ScP36ddcUaMuv24iOJtz7sbUjTS4qBvKmstYJoUauiuD3k5qhyr7QdUHMeCgLa1Ear9NquemdXgmum4fvJ6w1lqsuDhNrg1qSpleJK7K3TF0Q2jSd94uSZ60kK1e3qyVpQK6PVWXp2/FC3mp6jBhKKOiY2h3gtUV64TWM6wDETRPLDfSakXmH3w8g9Jlug8ZtTt4kVF0kLUYYmCCtD/DrQ5YhMGbA9L3ucdjh0y8kOHW5gU/VEEmJTcL4Pz/f7mgoAbYkAAAAAElFTkSuQmCC"]
// }'
Map<String, dynamic> data;
if(loadedConversation.conversationContext) {
loadedChats = [...loadedChats, Chat(prompt, true, 0)];
endpoint = "chat";
List<Map<String, String>> messageList = convertMessages();
// Last prompt was text
if(loadedChats.last.chatType == 0) {
data = {
"model": model.name,
"messages": messageList,
"stream": loadedConversation.stream,
};
// Last prompt was image
} else { //if (loadedChats.last.chatType == 1) {
// TODO: Do some wizardry to pipe the output of llava as additional context for the user's actual prompt or something.
data = {
"model": "llava",
"prompt": "What is in this picture?",
"stream": loadedConversation.stream,
"images" : [loadedChats.last.content],
};
}
}
else {
endpoint = "generate";
data = {
"model": model.name,
"prompt": prompt,
"stream": loadedConversation.stream,
};
}
// Encode the JSON payload
return json.encode(data);
}
// Send the HTTP request to the server.
static void httpSendRequest() async {
// TODO: Add AES256 encryption to the prompt/messages thread.
// TODO: Add SHA256 checksum to be sent and verified to prevent/notify in case of data loss.
String json = constructPrompt();
// Send the HTTP POST request
final serverResponse = await http.post(
Uri.parse('$url$endpoint'),
headers: headers,
body: json,
);
if (serverResponse.statusCode == 200) {
Map<String, dynamic> re = jsonDecode(serverResponse.body);
if(conversations[conversationID].conversationContext) {
response = re["message"]["content"];
// TODO: Modify in case of different response types.
loadedChats = [...loadedChats, Chat(response, false, 0)];
} else {
response = re["response"];
}
}
conversations[conversationID].add(Chat(response, false, 0));
prompt = "";
response = "";
}
}
@@ -0,0 +1,5 @@
class Model {
late String name;
Model(this.name);
}

Some files were not shown because too many files have changed in this diff Show More