init
45
.gitignore
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.build/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
.swiftpm/
|
||||
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-dependencies
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
/coverage/
|
||||
|
||||
# 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
.metadata
Normal 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: "582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
base_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
- platform: android
|
||||
create_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
base_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
- platform: ios
|
||||
create_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
base_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
- platform: linux
|
||||
create_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
base_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
- platform: macos
|
||||
create_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
base_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
- platform: web
|
||||
create_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
base_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
- platform: windows
|
||||
create_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
base_revision: 582a0e7c5581dc0ca5f7bfd8662bb8db6f59d536
|
||||
|
||||
# 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'
|
||||
17
README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# mesh_drop_flutter
|
||||
|
||||
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:
|
||||
|
||||
- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter)
|
||||
- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources)
|
||||
|
||||
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.
|
||||
28
analysis_options.yaml
Normal 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
|
||||
14
android/.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
gradle-wrapper.jar
|
||||
/.gradle
|
||||
/captures/
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
.cxx/
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/to/reference-keystore
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
44
android/app/build.gradle.kts
Normal file
@@ -0,0 +1,44 @@
|
||||
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")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.mesh_drop_flutter"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.example.mesh_drop_flutter"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = flutter.minSdkVersion
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
7
android/app/src/debug/AndroidManifest.xml
Normal file
@@ -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>
|
||||
45
android/app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:label="mesh_drop_flutter"
|
||||
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.mesh_drop_flutter
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity : FlutterActivity()
|
||||
12
android/app/src/main/res/drawable-v21/launch_background.xml
Normal file
@@ -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>
|
||||
12
android/app/src/main/res/drawable/launch_background.xml
Normal file
@@ -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>
|
||||
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 544 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 442 B |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
18
android/app/src/main/res/values-night/styles.xml
Normal file
@@ -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>
|
||||
18
android/app/src/main/res/values/styles.xml
Normal file
@@ -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>
|
||||
7
android/app/src/profile/AndroidManifest.xml
Normal file
@@ -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>
|
||||
24
android/build.gradle.kts
Normal file
@@ -0,0 +1,24 @@
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
val newBuildDir: Directory =
|
||||
rootProject.layout.buildDirectory
|
||||
.dir("../../build")
|
||||
.get()
|
||||
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||
|
||||
subprojects {
|
||||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(":app")
|
||||
}
|
||||
|
||||
tasks.register<Delete>("clean") {
|
||||
delete(rootProject.layout.buildDirectory)
|
||||
}
|
||||
2
android/gradle.properties
Normal file
@@ -0,0 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
5
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -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-8.14-all.zip
|
||||
26
android/settings.gradle.kts
Normal file
@@ -0,0 +1,26 @@
|
||||
pluginManagement {
|
||||
val flutterSdkPath =
|
||||
run {
|
||||
val properties = java.util.Properties()
|
||||
file("local.properties").inputStream().use { properties.load(it) }
|
||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||
flutterSdkPath
|
||||
}
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
id("com.android.application") version "8.11.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
3
flutter_rust_bridge.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
rust_input: crate::api
|
||||
rust_root: rust/
|
||||
dart_output: lib/backend
|
||||
34
ios/.gitignore
vendored
Normal 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
|
||||
24
ios/Flutter/AppFrameworkInfo.plist
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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>
|
||||
</dict>
|
||||
</plist>
|
||||
1
ios/Flutter/Debug.xcconfig
Normal file
@@ -0,0 +1 @@
|
||||
#include "Generated.xcconfig"
|
||||
1
ios/Flutter/Release.xcconfig
Normal file
@@ -0,0 +1 @@
|
||||
#include "Generated.xcconfig"
|
||||
620
ios/Runner.xcodeproj/project.pbxproj
Normal file
@@ -0,0 +1,620 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.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 */
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
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 */,
|
||||
);
|
||||
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 */,
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
);
|
||||
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 = (
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
);
|
||||
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";
|
||||
};
|
||||
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";
|
||||
};
|
||||
/* 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 */,
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift 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 = 13.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)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.meshDropFlutter;
|
||||
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;
|
||||
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.meshDropFlutter.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;
|
||||
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.meshDropFlutter.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;
|
||||
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.meshDropFlutter.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 = 13.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 = 13.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)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.meshDropFlutter;
|
||||
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)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.meshDropFlutter;
|
||||
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 */;
|
||||
}
|
||||
7
ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -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>
|
||||
101
ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
Normal file
@@ -0,0 +1,101 @@
|
||||
<?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"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
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"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
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>
|
||||
7
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.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>
|
||||
16
ios/Runner/AppDelegate.swift
Normal file
@@ -0,0 +1,16 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||
}
|
||||
}
|
||||
122
ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 295 B |
|
After Width: | Height: | Size: 406 B |
|
After Width: | Height: | Size: 450 B |
|
After Width: | Height: | Size: 282 B |
|
After Width: | Height: | Size: 462 B |
|
After Width: | Height: | Size: 704 B |
|
After Width: | Height: | Size: 406 B |
|
After Width: | Height: | Size: 586 B |
|
After Width: | Height: | Size: 862 B |
|
After Width: | Height: | Size: 862 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 762 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
23
ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
vendored
Normal file
@@ -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"
|
||||
}
|
||||
}
|
||||
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
vendored
Normal file
|
After Width: | Height: | Size: 68 B |
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 68 B |
BIN
ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 68 B |
5
ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
vendored
Normal file
@@ -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.
|
||||
37
ios/Runner/Base.lproj/LaunchScreen.storyboard
Normal file
@@ -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>
|
||||
26
ios/Runner/Base.lproj/Main.storyboard
Normal file
@@ -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>
|
||||
70
ios/Runner/Info.plist
Normal file
@@ -0,0 +1,70 @@
|
||||
<?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>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Mesh Drop Flutter</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>mesh_drop_flutter</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>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneClassName</key>
|
||||
<string>UIWindowScene</string>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>flutter</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
<key>UISceneStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<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>
|
||||
1
ios/Runner/Runner-Bridging-Header.h
Normal file
@@ -0,0 +1 @@
|
||||
#import "GeneratedPluginRegistrant.h"
|
||||
6
ios/Runner/SceneDelegate.swift
Normal file
@@ -0,0 +1,6 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
class SceneDelegate: FlutterSceneDelegate {
|
||||
|
||||
}
|
||||
12
ios/RunnerTests/RunnerTests.swift
Normal file
@@ -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.
|
||||
}
|
||||
|
||||
}
|
||||
61
lib/app/app.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../backend/event.dart';
|
||||
import 'features/peers/controller/peers_controller.dart';
|
||||
import 'features/transfer/controller/transfers_controller.dart';
|
||||
import 'navigation/home_shell.dart';
|
||||
import 'sync/backend_event_sync.dart';
|
||||
import 'theme/app_theme.dart';
|
||||
import 'theme/theme_mode_controller.dart';
|
||||
|
||||
class MeshDropApp extends ConsumerWidget {
|
||||
const MeshDropApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final themeMode = ref.watch(themeModeControllerProvider);
|
||||
|
||||
ref.listen<AsyncValue<AppEvent>>(backendEventSyncProvider, (
|
||||
previous,
|
||||
next,
|
||||
) {
|
||||
next.whenData((event) {
|
||||
switch (event) {
|
||||
case AppEvent_PeerConnectOrUpdated(:final peer):
|
||||
ref.read(peersControllerProvider.notifier).upsertPeer(peer);
|
||||
case AppEvent_PeerDisconnected(:final id):
|
||||
ref.read(peersControllerProvider.notifier).removePeer(id);
|
||||
case AppEvent_TransferAdded(:final transfer):
|
||||
ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.upsertTransfer(transfer);
|
||||
case AppEvent_TransferStatusChanged(:final transfer):
|
||||
ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.upsertTransfer(transfer);
|
||||
case AppEvent_TransferRemoved(:final id):
|
||||
ref.read(transfersControllerProvider.notifier).removeTransfer(id);
|
||||
case AppEvent_TransferClear():
|
||||
ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.clearTransfersLocal();
|
||||
case AppEvent_TransferProgressChanged(:final id, :final progress):
|
||||
final currentBytes = progress < 0 ? 0.0 : progress;
|
||||
ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.updateProgress(id, currentBytes);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return MaterialApp(
|
||||
title: 'Mesh Drop',
|
||||
debugShowCheckedModeBanner: false,
|
||||
themeMode: themeMode,
|
||||
theme: AppTheme.lightTheme,
|
||||
darkTheme: AppTheme.darkTheme,
|
||||
home: const HomeShell(),
|
||||
);
|
||||
}
|
||||
}
|
||||
246
lib/app/features/modals/send_files_modal.dart
Normal file
@@ -0,0 +1,246 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:desktop_drop/desktop_drop.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../backend/api/commands.dart' as commands;
|
||||
import '../../../backend/discovery/model.dart';
|
||||
|
||||
class SendFilesModal extends StatefulWidget {
|
||||
const SendFilesModal({
|
||||
super.key,
|
||||
required this.peer,
|
||||
required this.targetIp,
|
||||
this.initialPaths = const [],
|
||||
});
|
||||
|
||||
final Peer peer;
|
||||
final String targetIp;
|
||||
final List<String> initialPaths;
|
||||
|
||||
@override
|
||||
State<SendFilesModal> createState() => _SendFilesModalState();
|
||||
}
|
||||
|
||||
class _SendFilesModalState extends State<SendFilesModal> {
|
||||
late final List<String> _paths = [...widget.initialPaths];
|
||||
bool _dragging = false;
|
||||
|
||||
Future<void> _submit() async {
|
||||
if (_paths.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final pending = List<String>.from(_paths);
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
for (final path in pending) {
|
||||
final entityType = FileSystemEntity.typeSync(path);
|
||||
if (entityType == FileSystemEntityType.directory) {
|
||||
commands.sendFolder(
|
||||
target: widget.peer,
|
||||
targetIp: widget.targetIp,
|
||||
folderPath: path,
|
||||
);
|
||||
} else {
|
||||
commands.sendFile(
|
||||
target: widget.peer,
|
||||
targetIp: widget.targetIp,
|
||||
filePath: path,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _pickFiles() async {
|
||||
final result = await FilePicker.platform.pickFiles(allowMultiple: true);
|
||||
if (result == null || !mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
final selected = result.paths.whereType<String>().where(
|
||||
(p) => p.isNotEmpty,
|
||||
);
|
||||
setState(() {
|
||||
for (final path in selected) {
|
||||
if (!_paths.contains(path)) {
|
||||
_paths.add(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _pickFolder() async {
|
||||
final folder = await FilePicker.platform.getDirectoryPath();
|
||||
if (folder == null || folder.isEmpty || !mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
if (!_paths.contains(folder)) {
|
||||
_paths.add(folder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool get _enableDragDrop =>
|
||||
Platform.isLinux || Platform.isWindows || Platform.isMacOS;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return AlertDialog(
|
||||
title: Text('发送文件给 ${widget.peer.name}'),
|
||||
content: SizedBox(
|
||||
width: 640,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (_enableDragDrop)
|
||||
DropTarget(
|
||||
onDragEntered: (_) => setState(() => _dragging = true),
|
||||
onDragExited: (_) => setState(() => _dragging = false),
|
||||
onDragDone: (details) {
|
||||
setState(() {
|
||||
_dragging = false;
|
||||
_paths.addAll(
|
||||
details.files
|
||||
.map((f) => f.path)
|
||||
.where((p) => p.isNotEmpty)
|
||||
.where((p) => !_paths.contains(p)),
|
||||
);
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: _dragging
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outlineVariant,
|
||||
width: _dragging ? 2 : 1,
|
||||
),
|
||||
color: theme.colorScheme.surfaceContainerHighest.withValues(
|
||||
alpha: 0.35,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
_dragging
|
||||
? Icons.file_download_done_rounded
|
||||
: Icons.file_upload_rounded,
|
||||
size: 36,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(_dragging ? '松手即可添加文件' : '将文件或文件夹拖到这里'),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: theme.colorScheme.outlineVariant),
|
||||
color: theme.colorScheme.surfaceContainerHighest.withValues(
|
||||
alpha: 0.35,
|
||||
),
|
||||
),
|
||||
child: const Column(
|
||||
children: [
|
||||
Icon(Icons.file_upload_rounded, size: 36),
|
||||
SizedBox(height: 8),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: _pickFiles,
|
||||
icon: const Icon(Icons.attach_file_rounded),
|
||||
label: const Text('选择文件'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: _pickFolder,
|
||||
icon: const Icon(Icons.folder_open_rounded),
|
||||
label: const Text('选择文件夹'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxHeight: 260),
|
||||
child: _paths.isEmpty
|
||||
? const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 24),
|
||||
child: Text('暂无待发送文件'),
|
||||
),
|
||||
)
|
||||
: ListView.separated(
|
||||
shrinkWrap: true,
|
||||
itemCount: _paths.length,
|
||||
separatorBuilder: (_, _) => const Divider(height: 1),
|
||||
itemBuilder: (context, index) {
|
||||
final path = _paths[index];
|
||||
final isDirectory =
|
||||
FileSystemEntity.typeSync(path) ==
|
||||
FileSystemEntityType.directory;
|
||||
return ListTile(
|
||||
dense: true,
|
||||
leading: Icon(
|
||||
isDirectory
|
||||
? Icons.folder_copy_rounded
|
||||
: Icons.insert_drive_file_rounded,
|
||||
),
|
||||
title: Text(
|
||||
path.split(Platform.pathSeparator).last,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
subtitle: Text(
|
||||
path,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.delete_outline_rounded),
|
||||
onPressed: () =>
|
||||
setState(() => _paths.removeAt(index)),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
FilledButton.icon(
|
||||
onPressed: _paths.isEmpty ? null : _submit,
|
||||
icon: const Icon(Icons.send_rounded),
|
||||
label: Text('发送 (${_paths.length})'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
65
lib/app/features/modals/send_text_modal.dart
Normal file
@@ -0,0 +1,65 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../backend/api/commands.dart' as commands;
|
||||
import '../../../backend/discovery/model.dart';
|
||||
|
||||
class SendTextModal extends StatefulWidget {
|
||||
const SendTextModal({super.key, required this.peer, required this.targetIp});
|
||||
|
||||
final Peer peer;
|
||||
final String targetIp;
|
||||
|
||||
@override
|
||||
State<SendTextModal> createState() => _SendTextModalState();
|
||||
}
|
||||
|
||||
class _SendTextModalState extends State<SendTextModal> {
|
||||
final _controller = TextEditingController();
|
||||
|
||||
Future<void> _submit() async {
|
||||
final text = _controller.text.trim();
|
||||
if (text.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
commands.sendText(
|
||||
target: widget.peer,
|
||||
targetIp: widget.targetIp,
|
||||
text: text,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('发送文本给 ${widget.peer.name}'),
|
||||
content: SizedBox(
|
||||
width: 540,
|
||||
child: TextField(
|
||||
controller: _controller,
|
||||
maxLines: 8,
|
||||
minLines: 4,
|
||||
decoration: const InputDecoration(
|
||||
hintText: '输入你想发送的文本内容',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
FilledButton.icon(
|
||||
onPressed: _submit,
|
||||
icon: const Icon(Icons.send_rounded),
|
||||
label: const Text('发送'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
50
lib/app/features/peers/controller/peers_controller.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import '../../../../backend/api/commands.dart' as commands;
|
||||
import '../../../../backend/discovery/model.dart';
|
||||
|
||||
part 'peers_controller.g.dart';
|
||||
|
||||
@riverpod
|
||||
class PeersController extends _$PeersController {
|
||||
@override
|
||||
Future<List<Peer>> build() async {
|
||||
return commands.getPeers();
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(commands.getPeers);
|
||||
}
|
||||
|
||||
void upsertPeer(Peer peer) {
|
||||
final current = state.asData?.value ?? const <Peer>[];
|
||||
final index = current.indexWhere((item) => item.id == peer.id);
|
||||
|
||||
if (index < 0) {
|
||||
state = AsyncData([...current, peer]);
|
||||
return;
|
||||
}
|
||||
|
||||
final old = current[index];
|
||||
if (old == peer) {
|
||||
return;
|
||||
}
|
||||
|
||||
final next = [...current];
|
||||
next[index] = peer;
|
||||
state = AsyncData(next);
|
||||
}
|
||||
|
||||
void removePeer(String id) {
|
||||
final current = state.asData?.value;
|
||||
if (current == null || current.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final next = current.where((item) => item.id != id).toList(growable: false);
|
||||
if (next.length != current.length) {
|
||||
state = AsyncData(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
54
lib/app/features/peers/controller/peers_controller.g.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'peers_controller.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(PeersController)
|
||||
final peersControllerProvider = PeersControllerProvider._();
|
||||
|
||||
final class PeersControllerProvider
|
||||
extends $AsyncNotifierProvider<PeersController, List<Peer>> {
|
||||
PeersControllerProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'peersControllerProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$peersControllerHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
PeersController create() => PeersController();
|
||||
}
|
||||
|
||||
String _$peersControllerHash() => r'd6d108b39274dd5de380523373f115d2e4c10e0e';
|
||||
|
||||
abstract class _$PeersController extends $AsyncNotifier<List<Peer>> {
|
||||
FutureOr<List<Peer>> build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<AsyncValue<List<Peer>>, List<Peer>>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<AsyncValue<List<Peer>>, List<Peer>>,
|
||||
AsyncValue<List<Peer>>,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
73
lib/app/features/peers/pages/peers_page.dart
Normal file
@@ -0,0 +1,73 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../controller/peers_controller.dart';
|
||||
import '../widgets/peer_card.dart';
|
||||
import '../../../shared/widgets/empty_state.dart';
|
||||
|
||||
class PeersPage extends ConsumerWidget {
|
||||
const PeersPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final peersAsync = ref.watch(peersControllerProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Peers Discovery'),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '刷新',
|
||||
onPressed: () =>
|
||||
ref.read(peersControllerProvider.notifier).refresh(),
|
||||
icon: const Icon(Icons.refresh_rounded),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: peersAsync.when(
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => AppEmptyState(
|
||||
icon: Icons.cloud_off_rounded,
|
||||
title: '发现失败',
|
||||
message: error.toString(),
|
||||
action: FilledButton.icon(
|
||||
onPressed: () =>
|
||||
ref.read(peersControllerProvider.notifier).refresh(),
|
||||
icon: const Icon(Icons.refresh_rounded),
|
||||
label: const Text('重试'),
|
||||
),
|
||||
),
|
||||
data: (peers) {
|
||||
if (peers.isEmpty) {
|
||||
return AppEmptyState(
|
||||
icon: Icons.wifi_tethering,
|
||||
title: '扫描中',
|
||||
message: '请确认局域网连接和防火墙配置。',
|
||||
);
|
||||
}
|
||||
|
||||
final width = MediaQuery.sizeOf(context).width;
|
||||
final columns = width >= 1320
|
||||
? 4
|
||||
: width >= 1100
|
||||
? 3
|
||||
: width >= 720
|
||||
? 2
|
||||
: 1;
|
||||
|
||||
return GridView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: columns,
|
||||
mainAxisSpacing: 12,
|
||||
crossAxisSpacing: 12,
|
||||
childAspectRatio: 1.36,
|
||||
),
|
||||
itemCount: peers.length,
|
||||
itemBuilder: (context, index) => PeerCard(peer: peers[index]),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
266
lib/app/features/peers/widgets/peer_card.dart
Normal file
@@ -0,0 +1,266 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:desktop_drop/desktop_drop.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../backend/api/commands.dart' as commands;
|
||||
import '../../../../backend/discovery/model.dart';
|
||||
import '../../modals/send_files_modal.dart';
|
||||
import '../../modals/send_text_modal.dart';
|
||||
|
||||
class PeerCard extends StatefulWidget {
|
||||
const PeerCard({super.key, required this.peer});
|
||||
|
||||
final Peer peer;
|
||||
|
||||
@override
|
||||
State<PeerCard> createState() => _PeerCardState();
|
||||
}
|
||||
|
||||
class _PeerCardState extends State<PeerCard> {
|
||||
bool _dragging = false;
|
||||
|
||||
String? get _targetIp {
|
||||
if (widget.peer.routes.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return widget.peer.routes.values.first.ip;
|
||||
}
|
||||
|
||||
Future<void> _openTextModal() async {
|
||||
final targetIp = _targetIp;
|
||||
if (targetIp == null || !mounted) {
|
||||
return;
|
||||
}
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => SendTextModal(peer: widget.peer, targetIp: targetIp),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _openFilesModal(List<String> files) async {
|
||||
final targetIp = _targetIp;
|
||||
if (targetIp == null || !mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => SendFilesModal(
|
||||
peer: widget.peer,
|
||||
targetIp: targetIp,
|
||||
initialPaths: files,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool get _enableDragDrop =>
|
||||
Platform.isLinux || Platform.isWindows || Platform.isMacOS;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final targetIp = _targetIp;
|
||||
|
||||
final card = Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
side: BorderSide(
|
||||
color: _dragging
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outlineVariant,
|
||||
width: _dragging ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundColor: theme.colorScheme.primaryContainer,
|
||||
child: Icon(
|
||||
_iconForOs(widget.peer.os),
|
||||
color: theme.colorScheme.onPrimaryContainer,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.peer.name,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
targetIp ?? '无路由',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
Chip(
|
||||
avatar: const Icon(Icons.shield_rounded, size: 16),
|
||||
label: Text(widget.peer.enableTls ? 'TLS on' : 'TLS off'),
|
||||
),
|
||||
if (widget.peer.trustMismatch)
|
||||
const Chip(
|
||||
avatar: Icon(Icons.warning_amber_rounded, size: 16),
|
||||
label: Text('Trust Mismatch'),
|
||||
),
|
||||
FutureBuilder<bool>(
|
||||
future: commands.isTrusted(peerId: widget.peer.id),
|
||||
builder: (context, snapshot) {
|
||||
final trusted = snapshot.data ?? false;
|
||||
return Chip(
|
||||
avatar: Icon(
|
||||
trusted
|
||||
? Icons.verified_user_rounded
|
||||
: Icons.gpp_maybe_rounded,
|
||||
size: 16,
|
||||
),
|
||||
label: Text(trusted ? 'Trusted' : 'Untrusted'),
|
||||
);
|
||||
},
|
||||
),
|
||||
Chip(
|
||||
avatar: const Icon(Icons.hub_rounded, size: 16),
|
||||
label: Text('${widget.peer.routes.length} routes'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
if (_enableDragDrop && _dragging)
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: theme.colorScheme.primaryContainer.withValues(
|
||||
alpha: 0.55,
|
||||
),
|
||||
),
|
||||
child: const Center(child: Text('释放后发送文件')),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: FilledButton.tonalIcon(
|
||||
onPressed: targetIp == null ? null : _openTextModal,
|
||||
icon: const Icon(Icons.chat_bubble_rounded),
|
||||
label: const Text('文本'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: FilledButton.icon(
|
||||
onPressed: targetIp == null
|
||||
? null
|
||||
: () => _openFilesModal(const []),
|
||||
icon: const Icon(Icons.upload_file_rounded),
|
||||
label: const Text('文件/文件夹'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
FutureBuilder<bool>(
|
||||
future: commands.isTrusted(peerId: widget.peer.id),
|
||||
builder: (context, snapshot) {
|
||||
final trusted = snapshot.data ?? false;
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () async {
|
||||
if (trusted) {
|
||||
await commands.untrustPeer(peerId: widget.peer.id);
|
||||
} else {
|
||||
await commands.trustPeer(peerId: widget.peer.id);
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
icon: Icon(
|
||||
trusted
|
||||
? Icons.verified_user_rounded
|
||||
: Icons.gpp_maybe_rounded,
|
||||
),
|
||||
label: Text(trusted ? '取消信任' : '设为信任设备'),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (targetIp == null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Text(
|
||||
'该设备暂无可用传输路由',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
if (!_enableDragDrop) {
|
||||
return card;
|
||||
}
|
||||
|
||||
return DropTarget(
|
||||
onDragEntered: (_) => setState(() => _dragging = true),
|
||||
onDragExited: (_) => setState(() => _dragging = false),
|
||||
onDragDone: (details) {
|
||||
final files = details.files
|
||||
.map((f) => f.path)
|
||||
.where((e) => e.isNotEmpty)
|
||||
.toList();
|
||||
setState(() => _dragging = false);
|
||||
if (files.isNotEmpty) {
|
||||
_openFilesModal(files);
|
||||
}
|
||||
},
|
||||
child: card,
|
||||
);
|
||||
}
|
||||
|
||||
IconData _iconForOs(String os) {
|
||||
final normalized = os.toLowerCase();
|
||||
if (normalized.contains('windows')) {
|
||||
return Icons.laptop_windows_rounded;
|
||||
}
|
||||
if (normalized.contains('mac') || normalized.contains('darwin')) {
|
||||
return Icons.laptop_mac_rounded;
|
||||
}
|
||||
if (normalized.contains('linux')) {
|
||||
return Icons.computer_rounded;
|
||||
}
|
||||
if (normalized.contains('android')) {
|
||||
return Icons.phone_android_rounded;
|
||||
}
|
||||
if (normalized.contains('ios') || normalized.contains('iphone')) {
|
||||
return Icons.phone_iphone_rounded;
|
||||
}
|
||||
return Platform.isAndroid
|
||||
? Icons.devices_rounded
|
||||
: Icons.device_hub_rounded;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import '../../../../backend/api/commands.dart' as commands;
|
||||
|
||||
part 'settings_controller.g.dart';
|
||||
|
||||
class SettingsState {
|
||||
const SettingsState({
|
||||
required this.hostname,
|
||||
required this.savePath,
|
||||
required this.autoAccept,
|
||||
required this.saveHistory,
|
||||
required this.enableTls,
|
||||
});
|
||||
|
||||
final String hostname;
|
||||
final String savePath;
|
||||
final bool autoAccept;
|
||||
final bool saveHistory;
|
||||
final bool enableTls;
|
||||
|
||||
SettingsState copyWith({
|
||||
String? hostname,
|
||||
String? savePath,
|
||||
bool? autoAccept,
|
||||
bool? saveHistory,
|
||||
bool? enableTls,
|
||||
}) {
|
||||
return SettingsState(
|
||||
hostname: hostname ?? this.hostname,
|
||||
savePath: savePath ?? this.savePath,
|
||||
autoAccept: autoAccept ?? this.autoAccept,
|
||||
saveHistory: saveHistory ?? this.saveHistory,
|
||||
enableTls: enableTls ?? this.enableTls,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class SettingsController extends _$SettingsController {
|
||||
@override
|
||||
Future<SettingsState> build() async {
|
||||
final values = await Future.wait([
|
||||
commands.getHostname(),
|
||||
commands.getSavePath(),
|
||||
commands.getAutoAccept(),
|
||||
commands.getSaveHistory(),
|
||||
commands.getEnableTls(),
|
||||
]);
|
||||
|
||||
return SettingsState(
|
||||
hostname: values[0] as String,
|
||||
savePath: values[1] as String,
|
||||
autoAccept: values[2] as bool,
|
||||
saveHistory: values[3] as bool,
|
||||
enableTls: values[4] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateHostname(String value) async {
|
||||
await commands.setHostname(hostname: value);
|
||||
final current = state.value;
|
||||
if (current != null) {
|
||||
state = AsyncData(current.copyWith(hostname: value));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateSavePath(String value) async {
|
||||
await commands.setSavePath(savePath: value);
|
||||
final current = state.value;
|
||||
if (current != null) {
|
||||
state = AsyncData(current.copyWith(savePath: value));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateAutoAccept(bool value) async {
|
||||
await commands.setAutoAccept(autoAccept: value);
|
||||
final current = state.value;
|
||||
if (current != null) {
|
||||
state = AsyncData(current.copyWith(autoAccept: value));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateSaveHistory(bool value) async {
|
||||
await commands.setSaveHistory(saveHistory: value);
|
||||
final current = state.value;
|
||||
if (current != null) {
|
||||
state = AsyncData(current.copyWith(saveHistory: value));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateEnableTls(bool value) async {
|
||||
await commands.setEnableTls(enableTls: value);
|
||||
final current = state.value;
|
||||
if (current != null) {
|
||||
state = AsyncData(current.copyWith(enableTls: value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'settings_controller.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(SettingsController)
|
||||
final settingsControllerProvider = SettingsControllerProvider._();
|
||||
|
||||
final class SettingsControllerProvider
|
||||
extends $AsyncNotifierProvider<SettingsController, SettingsState> {
|
||||
SettingsControllerProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'settingsControllerProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$settingsControllerHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
SettingsController create() => SettingsController();
|
||||
}
|
||||
|
||||
String _$settingsControllerHash() =>
|
||||
r'9a56637cd6a41c05c9c35b78430ff9fd9f9affe6';
|
||||
|
||||
abstract class _$SettingsController extends $AsyncNotifier<SettingsState> {
|
||||
FutureOr<SettingsState> build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<AsyncValue<SettingsState>, SettingsState>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<AsyncValue<SettingsState>, SettingsState>,
|
||||
AsyncValue<SettingsState>,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
161
lib/app/features/settings/pages/settings_page.dart
Normal file
@@ -0,0 +1,161 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../theme/theme_mode_controller.dart';
|
||||
import '../controller/settings_controller.dart';
|
||||
|
||||
class SettingsPage extends ConsumerWidget {
|
||||
const SettingsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final settingsAsync = ref.watch(settingsControllerProvider);
|
||||
final themeMode = ref.watch(themeModeControllerProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Settings')),
|
||||
body: settingsAsync.when(
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => Center(child: Text(error.toString())),
|
||||
data: (settings) {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.brightness_6_rounded),
|
||||
title: const Text('主题模式'),
|
||||
subtitle: Text(themeMode.name),
|
||||
trailing: SegmentedButton<ThemeMode>(
|
||||
segments: const [
|
||||
ButtonSegment(
|
||||
value: ThemeMode.light,
|
||||
icon: Icon(Icons.light_mode_rounded),
|
||||
label: Text('Light'),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: ThemeMode.dark,
|
||||
icon: Icon(Icons.dark_mode_rounded),
|
||||
label: Text('Dark'),
|
||||
),
|
||||
ButtonSegment(
|
||||
value: ThemeMode.system,
|
||||
icon: Icon(Icons.settings_suggest_rounded),
|
||||
label: Text('System'),
|
||||
),
|
||||
],
|
||||
selected: {themeMode},
|
||||
onSelectionChanged: (selection) => ref
|
||||
.read(themeModeControllerProvider.notifier)
|
||||
.setThemeMode(selection.first),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Icons.badge_rounded),
|
||||
title: const Text('Hostname'),
|
||||
subtitle: Text(settings.hostname),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.edit_rounded),
|
||||
onPressed: () => _editText(
|
||||
context: context,
|
||||
title: 'Hostname',
|
||||
initial: settings.hostname,
|
||||
onSubmit: (value) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateHostname(value),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.folder_rounded),
|
||||
title: const Text('默认保存路径'),
|
||||
subtitle: Text(settings.savePath),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.edit_rounded),
|
||||
onPressed: () => _editText(
|
||||
context: context,
|
||||
title: '保存路径',
|
||||
initial: settings.savePath,
|
||||
onSubmit: (value) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateSavePath(value),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
SwitchListTile.adaptive(
|
||||
secondary: const Icon(Icons.auto_mode_rounded),
|
||||
title: const Text('自动接收'),
|
||||
value: settings.autoAccept,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateAutoAccept(v),
|
||||
),
|
||||
SwitchListTile.adaptive(
|
||||
secondary: const Icon(Icons.history_rounded),
|
||||
title: const Text('保存历史记录'),
|
||||
value: settings.saveHistory,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateSaveHistory(v),
|
||||
),
|
||||
SwitchListTile.adaptive(
|
||||
secondary: const Icon(Icons.shield_rounded),
|
||||
title: const Text('启用 TLS'),
|
||||
value: settings.enableTls,
|
||||
onChanged: (v) => ref
|
||||
.read(settingsControllerProvider.notifier)
|
||||
.updateEnableTls(v),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _editText({
|
||||
required BuildContext context,
|
||||
required String title,
|
||||
required String initial,
|
||||
required Future<void> Function(String value) onSubmit,
|
||||
}) async {
|
||||
final controller = TextEditingController(text: initial);
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
return AlertDialog(
|
||||
title: Text(title),
|
||||
content: TextField(controller: controller),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
child: const Text('保存'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (confirmed == true) {
|
||||
await onSubmit(controller.text.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
127
lib/app/features/transfer/controller/transfers_controller.dart
Normal file
@@ -0,0 +1,127 @@
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import '../../../../backend/api/commands.dart' as commands;
|
||||
import '../../../../backend/transfer/model.dart';
|
||||
|
||||
part 'transfers_controller.g.dart';
|
||||
|
||||
@riverpod
|
||||
class TransfersController extends _$TransfersController {
|
||||
@override
|
||||
Future<List<Transfer>> build() async {
|
||||
return commands.getTransfers();
|
||||
}
|
||||
|
||||
Future<void> refresh() async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(commands.getTransfers);
|
||||
}
|
||||
|
||||
void updateProgress(String id, double currentBytes) {
|
||||
final current = state.asData?.value;
|
||||
if (current == null || current.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final normalized = currentBytes < 0 ? 0.0 : currentBytes;
|
||||
var changed = false;
|
||||
|
||||
final next = current
|
||||
.map((item) {
|
||||
if (item.id != id) {
|
||||
return item;
|
||||
}
|
||||
|
||||
if ((item.progress - normalized).abs() < 0.001) {
|
||||
return item;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
return Transfer(
|
||||
id: item.id,
|
||||
createTime: item.createTime,
|
||||
sender: item.sender,
|
||||
senderIp: item.senderIp,
|
||||
fileName: item.fileName,
|
||||
fileSize: item.fileSize,
|
||||
savePath: item.savePath,
|
||||
status: item.status,
|
||||
type: item.type,
|
||||
contentType: item.contentType,
|
||||
text: item.text,
|
||||
errorMsg: item.errorMsg,
|
||||
token: item.token,
|
||||
progress: normalized,
|
||||
lastReadTime: item.lastReadTime,
|
||||
speed: item.speed,
|
||||
);
|
||||
})
|
||||
.toList(growable: false);
|
||||
|
||||
if (changed) {
|
||||
state = AsyncData(next);
|
||||
}
|
||||
}
|
||||
|
||||
void upsertTransfer(Transfer transfer) {
|
||||
final current = state.asData?.value ?? const <Transfer>[];
|
||||
final index = current.indexWhere((item) => item.id == transfer.id);
|
||||
|
||||
if (index < 0) {
|
||||
state = AsyncData([...current, transfer]);
|
||||
return;
|
||||
}
|
||||
|
||||
final old = current[index];
|
||||
if (old == transfer) {
|
||||
return;
|
||||
}
|
||||
|
||||
final next = [...current];
|
||||
next[index] = transfer;
|
||||
state = AsyncData(next);
|
||||
}
|
||||
|
||||
void removeTransfer(String id) {
|
||||
final current = state.asData?.value;
|
||||
if (current == null || current.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final next = current.where((item) => item.id != id).toList(growable: false);
|
||||
if (next.length != current.length) {
|
||||
state = AsyncData(next);
|
||||
}
|
||||
}
|
||||
|
||||
void clearTransfersLocal() {
|
||||
state = const AsyncData(<Transfer>[]);
|
||||
}
|
||||
|
||||
Future<void> cancel(String id) async {
|
||||
await commands.cancelTransfer(id: id);
|
||||
}
|
||||
|
||||
Future<void> accept(String id, String path) async {
|
||||
await commands.resolvePendingRequest(id: id, accept: true, path: path);
|
||||
}
|
||||
|
||||
Future<void> reject(String id) async {
|
||||
await commands.resolvePendingRequest(id: id, accept: false, path: '');
|
||||
}
|
||||
|
||||
Future<void> delete(String id) async {
|
||||
await commands.deleteTransfer(id: id);
|
||||
}
|
||||
|
||||
Future<void> clearCompleted() async {
|
||||
final current = state.asData?.value ?? const <Transfer>[];
|
||||
final hasCompleted = current.any(
|
||||
(item) => item.status is TransferStatus_Completed,
|
||||
);
|
||||
if (!hasCompleted) {
|
||||
return;
|
||||
}
|
||||
await commands.clearTransfers();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'transfers_controller.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(TransfersController)
|
||||
final transfersControllerProvider = TransfersControllerProvider._();
|
||||
|
||||
final class TransfersControllerProvider
|
||||
extends $AsyncNotifierProvider<TransfersController, List<Transfer>> {
|
||||
TransfersControllerProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'transfersControllerProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$transfersControllerHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
TransfersController create() => TransfersController();
|
||||
}
|
||||
|
||||
String _$transfersControllerHash() =>
|
||||
r'4bb376e37746360ad323d2428d4fcfc4b1e37aa7';
|
||||
|
||||
abstract class _$TransfersController extends $AsyncNotifier<List<Transfer>> {
|
||||
FutureOr<List<Transfer>> build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<AsyncValue<List<Transfer>>, List<Transfer>>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<AsyncValue<List<Transfer>>, List<Transfer>>,
|
||||
AsyncValue<List<Transfer>>,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
98
lib/app/features/transfer/pages/transfer_page.dart
Normal file
@@ -0,0 +1,98 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../../backend/transfer/model.dart';
|
||||
import '../../../shared/widgets/empty_state.dart';
|
||||
import '../../settings/controller/settings_controller.dart';
|
||||
import '../controller/transfers_controller.dart';
|
||||
import '../widgets/transfer_item.dart';
|
||||
|
||||
class TransferPage extends ConsumerWidget {
|
||||
const TransferPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final transfersAsync = ref.watch(transfersControllerProvider);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Transfer Queue'),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: '清理已完成',
|
||||
onPressed: () =>
|
||||
ref.read(transfersControllerProvider.notifier).clearCompleted(),
|
||||
icon: const Icon(Icons.cleaning_services_rounded),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: '刷新',
|
||||
onPressed: () =>
|
||||
ref.read(transfersControllerProvider.notifier).refresh(),
|
||||
icon: const Icon(Icons.refresh_rounded),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: transfersAsync.when(
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => AppEmptyState(
|
||||
icon: Icons.warning_amber_rounded,
|
||||
title: '加载失败',
|
||||
message: error.toString(),
|
||||
),
|
||||
data: (transfers) {
|
||||
if (transfers.isEmpty) {
|
||||
return const AppEmptyState(
|
||||
icon: Icons.inbox_rounded,
|
||||
title: '暂无传输记录',
|
||||
message: '发起或接收一次文件后,会在这里看到记录。',
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.separated(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemBuilder: (context, index) {
|
||||
final item = transfers[index];
|
||||
final isSender = item.type == TransferType.send;
|
||||
final isReceiver = item.type == TransferType.receive;
|
||||
|
||||
final canCancel =
|
||||
(isSender &&
|
||||
(item.status is TransferStatus_Pending ||
|
||||
item.status is TransferStatus_Active)) ||
|
||||
(isReceiver && item.status is TransferStatus_Active);
|
||||
|
||||
return TransferItem(
|
||||
transfer: item,
|
||||
onCancel: canCancel
|
||||
? () => ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.cancel(item.id)
|
||||
: null,
|
||||
onAccept: isReceiver && item.status is TransferStatus_Pending
|
||||
? () async {
|
||||
final settings = await ref.read(
|
||||
settingsControllerProvider.future,
|
||||
);
|
||||
await ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.accept(item.id, settings.savePath);
|
||||
}
|
||||
: null,
|
||||
onReject: isReceiver && item.status is TransferStatus_Pending
|
||||
? () => ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.reject(item.id)
|
||||
: null,
|
||||
onDelete: () => ref
|
||||
.read(transfersControllerProvider.notifier)
|
||||
.delete(item.id),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, _) => const SizedBox(height: 12),
|
||||
itemCount: transfers.length,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
282
lib/app/features/transfer/widgets/transfer_item.dart
Normal file
@@ -0,0 +1,282 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../../../backend/transfer/model.dart';
|
||||
|
||||
class TransferItem extends StatelessWidget {
|
||||
const TransferItem({
|
||||
super.key,
|
||||
required this.transfer,
|
||||
this.onAccept,
|
||||
this.onReject,
|
||||
this.onCancel,
|
||||
this.onDelete,
|
||||
});
|
||||
|
||||
final Transfer transfer;
|
||||
final VoidCallback? onAccept;
|
||||
final VoidCallback? onReject;
|
||||
final VoidCallback? onCancel;
|
||||
final VoidCallback? onDelete;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundColor: theme.colorScheme.secondaryContainer,
|
||||
child: Icon(
|
||||
_iconForContentType(transfer.contentType),
|
||||
color: theme.colorScheme.onSecondaryContainer,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
transfer.fileName.isNotEmpty
|
||||
? transfer.fileName
|
||||
: '文本消息',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
Text(
|
||||
'${transfer.sender.name} · ${transfer.type.name}',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_StatusChip(status: transfer.status),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
LinearProgressIndicator(
|
||||
value: _progressOrNull(transfer),
|
||||
color: _progressColor(theme, transfer.status),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'进度 ${_progressPercent(transfer).toStringAsFixed(0)}% 大小 ${_formatSize(transfer.fileSize)} 速度 ${_formatSpeed(transfer.speed)}',
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
Wrap(spacing: 8, children: _buildActions(context)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildActions(BuildContext context) {
|
||||
final actions = <Widget>[];
|
||||
|
||||
if (transfer.status is TransferStatus_Pending) {
|
||||
if (onReject != null) {
|
||||
actions.add(
|
||||
OutlinedButton.icon(
|
||||
onPressed: onReject,
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
label: const Text('拒绝'),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (onAccept != null) {
|
||||
actions.add(
|
||||
FilledButton.icon(
|
||||
onPressed: onAccept,
|
||||
icon: const Icon(Icons.check_rounded),
|
||||
label: const Text('接收'),
|
||||
),
|
||||
);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
if ((transfer.status is TransferStatus_Active ||
|
||||
transfer.status is TransferStatus_Accepted) &&
|
||||
onCancel != null) {
|
||||
actions.add(
|
||||
OutlinedButton.icon(
|
||||
onPressed: onCancel,
|
||||
icon: const Icon(Icons.stop_circle_outlined),
|
||||
label: const Text('取消'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final canPreviewText =
|
||||
transfer.type == TransferType.receive &&
|
||||
transfer.contentType == ContentType.text &&
|
||||
transfer.status is TransferStatus_Completed;
|
||||
|
||||
if (canPreviewText) {
|
||||
actions.add(
|
||||
IconButton(
|
||||
tooltip: '复制文本',
|
||||
onPressed: () async {
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
await Clipboard.setData(ClipboardData(text: transfer.text));
|
||||
messenger.showSnackBar(const SnackBar(content: Text('文本已复制')));
|
||||
},
|
||||
icon: const Icon(Icons.copy_rounded),
|
||||
),
|
||||
);
|
||||
|
||||
actions.add(
|
||||
IconButton(
|
||||
tooltip: '查看文本',
|
||||
onPressed: () {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => AlertDialog(
|
||||
title: const Text('接收文本内容'),
|
||||
content: SizedBox(
|
||||
width: 560,
|
||||
child: SingleChildScrollView(
|
||||
child: SelectableText(transfer.text),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('关闭'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.visibility_rounded),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ((transfer.status is TransferStatus_Completed ||
|
||||
transfer.status is TransferStatus_Error ||
|
||||
transfer.status is TransferStatus_Canceled) &&
|
||||
onDelete != null) {
|
||||
actions.add(
|
||||
IconButton(
|
||||
tooltip: '删除记录',
|
||||
onPressed: onDelete,
|
||||
icon: const Icon(Icons.delete_outline_rounded),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
IconData _iconForContentType(ContentType contentType) {
|
||||
return switch (contentType) {
|
||||
ContentType.file => Icons.insert_drive_file_rounded,
|
||||
ContentType.folder => Icons.folder_zip_rounded,
|
||||
ContentType.text => Icons.text_snippet_rounded,
|
||||
};
|
||||
}
|
||||
|
||||
double? _progressOrNull(Transfer transfer) {
|
||||
if (transfer.status is TransferStatus_Pending) {
|
||||
return null;
|
||||
}
|
||||
return _progressFraction(transfer);
|
||||
}
|
||||
|
||||
Color _progressColor(ThemeData theme, TransferStatus status) {
|
||||
return switch (status) {
|
||||
TransferStatus_Completed() => theme.colorScheme.primary,
|
||||
TransferStatus_Active() ||
|
||||
TransferStatus_Accepted() => theme.colorScheme.tertiary,
|
||||
TransferStatus_Rejected() ||
|
||||
TransferStatus_Error() => theme.colorScheme.error,
|
||||
TransferStatus_Canceled() => theme.colorScheme.outline,
|
||||
TransferStatus_Pending() => theme.colorScheme.secondary,
|
||||
};
|
||||
}
|
||||
|
||||
String _formatSpeed(double? bytesPerSec) {
|
||||
if (bytesPerSec == null || bytesPerSec <= 0) {
|
||||
return '--';
|
||||
}
|
||||
return '${_formatSize(bytesPerSec)}/s';
|
||||
}
|
||||
|
||||
String _formatSize(double bytes) {
|
||||
if (bytes <= 0) {
|
||||
return '0 B';
|
||||
}
|
||||
|
||||
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
var size = bytes;
|
||||
var i = 0;
|
||||
while (size >= 1024 && i < units.length - 1) {
|
||||
size /= 1024;
|
||||
i++;
|
||||
}
|
||||
|
||||
final fixed = size >= 100 ? 0 : (size >= 10 ? 1 : 2);
|
||||
return '${size.toStringAsFixed(fixed)} ${units[i]}';
|
||||
}
|
||||
|
||||
double _progressedBytes(Transfer transfer) {
|
||||
final current = transfer.progress;
|
||||
if (current <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (transfer.fileSize <= 0) {
|
||||
return current;
|
||||
}
|
||||
return current.clamp(0, transfer.fileSize).toDouble();
|
||||
}
|
||||
|
||||
double _progressFraction(Transfer transfer) {
|
||||
if (transfer.fileSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return (_progressedBytes(transfer) / transfer.fileSize)
|
||||
.clamp(0, 1)
|
||||
.toDouble();
|
||||
}
|
||||
|
||||
double _progressPercent(Transfer transfer) {
|
||||
return _progressFraction(transfer) * 100;
|
||||
}
|
||||
}
|
||||
|
||||
class _StatusChip extends StatelessWidget {
|
||||
const _StatusChip({required this.status});
|
||||
|
||||
final TransferStatus status;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final label = switch (status) {
|
||||
TransferStatus_Pending() => 'Pending',
|
||||
TransferStatus_Accepted() => 'Accepted',
|
||||
TransferStatus_Rejected() => 'Rejected',
|
||||
TransferStatus_Completed() => 'Completed',
|
||||
TransferStatus_Error() => 'Error',
|
||||
TransferStatus_Canceled() => 'Canceled',
|
||||
TransferStatus_Active() => 'Active',
|
||||
};
|
||||
|
||||
return Chip(label: Text(label));
|
||||
}
|
||||
}
|
||||
83
lib/app/navigation/home_shell.dart
Normal file
@@ -0,0 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../features/peers/pages/peers_page.dart';
|
||||
import '../features/settings/pages/settings_page.dart';
|
||||
import '../features/transfer/pages/transfer_page.dart';
|
||||
|
||||
enum AppTab { peers, transfer, settings }
|
||||
|
||||
class HomeShell extends StatefulWidget {
|
||||
const HomeShell({super.key});
|
||||
|
||||
@override
|
||||
State<HomeShell> createState() => _HomeShellState();
|
||||
}
|
||||
|
||||
class _HomeShellState extends State<HomeShell> {
|
||||
AppTab _current = AppTab.peers;
|
||||
|
||||
void _onSelect(int index) {
|
||||
setState(() {
|
||||
_current = AppTab.values[index];
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isWide = MediaQuery.sizeOf(context).width >= 920;
|
||||
final pages = const [PeersPage(), TransferPage(), SettingsPage()];
|
||||
|
||||
if (isWide) {
|
||||
return Scaffold(
|
||||
body: Row(
|
||||
children: [
|
||||
NavigationRail(
|
||||
selectedIndex: _current.index,
|
||||
onDestinationSelected: _onSelect,
|
||||
labelType: NavigationRailLabelType.all,
|
||||
minWidth: 84,
|
||||
destinations: const [
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.radar_rounded),
|
||||
label: Text('Peers'),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.sync_alt_rounded),
|
||||
label: Text('Transfer'),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.tune_rounded),
|
||||
label: Text('Settings'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const VerticalDivider(width: 1),
|
||||
Expanded(child: pages[_current.index]),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
body: pages[_current.index],
|
||||
bottomNavigationBar: NavigationBar(
|
||||
selectedIndex: _current.index,
|
||||
onDestinationSelected: _onSelect,
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.radar_rounded),
|
||||
label: 'Peers',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.sync_alt_rounded),
|
||||
label: 'Transfer',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.tune_rounded),
|
||||
label: 'Settings',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
43
lib/app/shared/widgets/empty_state.dart
Normal file
@@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppEmptyState extends StatelessWidget {
|
||||
const AppEmptyState({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.title,
|
||||
required this.message,
|
||||
this.action,
|
||||
});
|
||||
|
||||
final IconData icon;
|
||||
final String title;
|
||||
final String message;
|
||||
final Widget? action;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(icon, size: 52, color: theme.colorScheme.primary),
|
||||
const SizedBox(height: 14),
|
||||
Text(title, style: theme.textTheme.titleLarge),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
message,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
if (action != null) ...[const SizedBox(height: 16), action!],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
11
lib/app/sync/backend_event_sync.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
import '../../backend/api/commands.dart' as commands;
|
||||
import '../../backend/event.dart';
|
||||
|
||||
part 'backend_event_sync.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
Stream<AppEvent> backendEventSync(Ref ref) {
|
||||
return commands.createEventStream();
|
||||
}
|
||||
44
lib/app/sync/backend_event_sync.g.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'backend_event_sync.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(backendEventSync)
|
||||
final backendEventSyncProvider = BackendEventSyncProvider._();
|
||||
|
||||
final class BackendEventSyncProvider
|
||||
extends
|
||||
$FunctionalProvider<AsyncValue<AppEvent>, AppEvent, Stream<AppEvent>>
|
||||
with $FutureModifier<AppEvent>, $StreamProvider<AppEvent> {
|
||||
BackendEventSyncProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'backendEventSyncProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$backendEventSyncHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<AppEvent> $createElement($ProviderPointer pointer) =>
|
||||
$StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<AppEvent> create(Ref ref) {
|
||||
return backendEventSync(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$backendEventSyncHash() => r'98ada20a035b92e209fca4c366faf7f41f412160';
|
||||
47
lib/app/theme/app_theme.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final class AppTheme {
|
||||
const AppTheme._();
|
||||
|
||||
static ThemeData get lightTheme {
|
||||
const seed = Color(0xFF4F46E5);
|
||||
final colorScheme = ColorScheme.fromSeed(
|
||||
seedColor: seed,
|
||||
brightness: Brightness.light,
|
||||
);
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
colorScheme: colorScheme,
|
||||
scaffoldBackgroundColor: const Color(0xFFF7F8FC),
|
||||
cardTheme: CardThemeData(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
),
|
||||
chipTheme: ChipThemeData(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(999)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static ThemeData get darkTheme {
|
||||
const seed = Color(0xFF8B8BFF);
|
||||
final colorScheme = ColorScheme.fromSeed(
|
||||
seedColor: seed,
|
||||
brightness: Brightness.dark,
|
||||
);
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
colorScheme: colorScheme,
|
||||
scaffoldBackgroundColor: const Color(0xFF0B1020),
|
||||
cardTheme: CardThemeData(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
),
|
||||
chipTheme: ChipThemeData(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(999)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
21
lib/app/theme/theme_mode_controller.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'theme_mode_controller.g.dart';
|
||||
|
||||
@riverpod
|
||||
class ThemeModeController extends _$ThemeModeController {
|
||||
@override
|
||||
ThemeMode build() => ThemeMode.system;
|
||||
|
||||
void setThemeMode(ThemeMode mode) {
|
||||
state = mode;
|
||||
}
|
||||
|
||||
void toggle() {
|
||||
state = switch (state) {
|
||||
ThemeMode.dark => ThemeMode.light,
|
||||
ThemeMode.light || ThemeMode.system => ThemeMode.dark,
|
||||
};
|
||||
}
|
||||
}
|
||||
63
lib/app/theme/theme_mode_controller.g.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'theme_mode_controller.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
|
||||
@ProviderFor(ThemeModeController)
|
||||
final themeModeControllerProvider = ThemeModeControllerProvider._();
|
||||
|
||||
final class ThemeModeControllerProvider
|
||||
extends $NotifierProvider<ThemeModeController, ThemeMode> {
|
||||
ThemeModeControllerProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'themeModeControllerProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$themeModeControllerHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
ThemeModeController create() => ThemeModeController();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(ThemeMode value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<ThemeMode>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$themeModeControllerHash() =>
|
||||
r'96d7617273bf6319cb57844c94190c8514dc0b36';
|
||||
|
||||
abstract class _$ThemeModeController extends $Notifier<ThemeMode> {
|
||||
ThemeMode build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final ref = this.ref as $Ref<ThemeMode, ThemeMode>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<ThemeMode, ThemeMode>,
|
||||
ThemeMode,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleCreate(ref, build);
|
||||
}
|
||||
}
|
||||
107
lib/backend/api/commands.dart
Normal file
@@ -0,0 +1,107 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../discovery/model.dart';
|
||||
import '../event.dart';
|
||||
import '../frb_generated.dart';
|
||||
import '../transfer/model.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
Stream<AppEvent> createEventStream() =>
|
||||
RustLib.instance.api.crateApiCommandsCreateEventStream();
|
||||
|
||||
Future<String> getSavePath() =>
|
||||
RustLib.instance.api.crateApiCommandsGetSavePath();
|
||||
|
||||
Future<void> setSavePath({required String savePath}) =>
|
||||
RustLib.instance.api.crateApiCommandsSetSavePath(savePath: savePath);
|
||||
|
||||
Future<void> setHostname({required String hostname}) =>
|
||||
RustLib.instance.api.crateApiCommandsSetHostname(hostname: hostname);
|
||||
|
||||
Future<String> getHostname() =>
|
||||
RustLib.instance.api.crateApiCommandsGetHostname();
|
||||
|
||||
Future<bool> getAutoAccept() =>
|
||||
RustLib.instance.api.crateApiCommandsGetAutoAccept();
|
||||
|
||||
Future<void> setAutoAccept({required bool autoAccept}) =>
|
||||
RustLib.instance.api.crateApiCommandsSetAutoAccept(autoAccept: autoAccept);
|
||||
|
||||
Future<bool> getSaveHistory() =>
|
||||
RustLib.instance.api.crateApiCommandsGetSaveHistory();
|
||||
|
||||
Future<void> setSaveHistory({required bool saveHistory}) => RustLib.instance.api
|
||||
.crateApiCommandsSetSaveHistory(saveHistory: saveHistory);
|
||||
|
||||
Future<bool> getEnableTls() =>
|
||||
RustLib.instance.api.crateApiCommandsGetEnableTls();
|
||||
|
||||
Future<void> setEnableTls({required bool enableTls}) =>
|
||||
RustLib.instance.api.crateApiCommandsSetEnableTls(enableTls: enableTls);
|
||||
|
||||
Future<List<Peer>> getPeers() =>
|
||||
RustLib.instance.api.crateApiCommandsGetPeers();
|
||||
|
||||
Future<void> sendFile({
|
||||
required Peer target,
|
||||
required String targetIp,
|
||||
required String filePath,
|
||||
}) => RustLib.instance.api.crateApiCommandsSendFile(
|
||||
target: target,
|
||||
targetIp: targetIp,
|
||||
filePath: filePath,
|
||||
);
|
||||
|
||||
Future<void> sendText({
|
||||
required Peer target,
|
||||
required String targetIp,
|
||||
required String text,
|
||||
}) => RustLib.instance.api.crateApiCommandsSendText(
|
||||
target: target,
|
||||
targetIp: targetIp,
|
||||
text: text,
|
||||
);
|
||||
|
||||
Future<void> sendFolder({
|
||||
required Peer target,
|
||||
required String targetIp,
|
||||
required String folderPath,
|
||||
}) => RustLib.instance.api.crateApiCommandsSendFolder(
|
||||
target: target,
|
||||
targetIp: targetIp,
|
||||
folderPath: folderPath,
|
||||
);
|
||||
|
||||
Future<List<Transfer>> getTransfers() =>
|
||||
RustLib.instance.api.crateApiCommandsGetTransfers();
|
||||
|
||||
Future<void> resolvePendingRequest({
|
||||
required String id,
|
||||
required bool accept,
|
||||
required String path,
|
||||
}) => RustLib.instance.api.crateApiCommandsResolvePendingRequest(
|
||||
id: id,
|
||||
accept: accept,
|
||||
path: path,
|
||||
);
|
||||
|
||||
Future<void> cancelTransfer({required String id}) =>
|
||||
RustLib.instance.api.crateApiCommandsCancelTransfer(id: id);
|
||||
|
||||
Future<void> deleteTransfer({required String id}) =>
|
||||
RustLib.instance.api.crateApiCommandsDeleteTransfer(id: id);
|
||||
|
||||
Future<void> clearTransfers() =>
|
||||
RustLib.instance.api.crateApiCommandsClearTransfers();
|
||||
|
||||
Future<bool> isTrusted({required String peerId}) =>
|
||||
RustLib.instance.api.crateApiCommandsIsTrusted(peerId: peerId);
|
||||
|
||||
Future<void> trustPeer({required String peerId}) =>
|
||||
RustLib.instance.api.crateApiCommandsTrustPeer(peerId: peerId);
|
||||
|
||||
Future<void> untrustPeer({required String peerId}) =>
|
||||
RustLib.instance.api.crateApiCommandsUntrustPeer(peerId: peerId);
|
||||
72
lib/backend/discovery/model.dart
Normal file
@@ -0,0 +1,72 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
|
||||
class Peer {
|
||||
final String id;
|
||||
final String name;
|
||||
final Map<String, RouteState> routes;
|
||||
final int port;
|
||||
final String os;
|
||||
final String publicKey;
|
||||
final bool trustMismatch;
|
||||
final bool enableTls;
|
||||
|
||||
const Peer({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.routes,
|
||||
required this.port,
|
||||
required this.os,
|
||||
required this.publicKey,
|
||||
required this.trustMismatch,
|
||||
required this.enableTls,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
id.hashCode ^
|
||||
name.hashCode ^
|
||||
routes.hashCode ^
|
||||
port.hashCode ^
|
||||
os.hashCode ^
|
||||
publicKey.hashCode ^
|
||||
trustMismatch.hashCode ^
|
||||
enableTls.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Peer &&
|
||||
runtimeType == other.runtimeType &&
|
||||
id == other.id &&
|
||||
name == other.name &&
|
||||
routes == other.routes &&
|
||||
port == other.port &&
|
||||
os == other.os &&
|
||||
publicKey == other.publicKey &&
|
||||
trustMismatch == other.trustMismatch &&
|
||||
enableTls == other.enableTls;
|
||||
}
|
||||
|
||||
class RouteState {
|
||||
final String ip;
|
||||
final double lastSeen;
|
||||
|
||||
const RouteState({required this.ip, required this.lastSeen});
|
||||
|
||||
@override
|
||||
int get hashCode => ip.hashCode ^ lastSeen.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is RouteState &&
|
||||
runtimeType == other.runtimeType &&
|
||||
ip == other.ip &&
|
||||
lastSeen == other.lastSeen;
|
||||
}
|
||||
34
lib/backend/event.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import 'discovery/model.dart';
|
||||
import 'frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||
import 'transfer/model.dart';
|
||||
part 'event.freezed.dart';
|
||||
|
||||
@freezed
|
||||
sealed class AppEvent with _$AppEvent {
|
||||
const AppEvent._();
|
||||
|
||||
const factory AppEvent.transferStatusChanged({required Transfer transfer}) =
|
||||
AppEvent_TransferStatusChanged;
|
||||
const factory AppEvent.transferProgressChanged({
|
||||
required String id,
|
||||
required double progress,
|
||||
required double total,
|
||||
required double speed,
|
||||
}) = AppEvent_TransferProgressChanged;
|
||||
const factory AppEvent.peerConnectOrUpdated({required Peer peer}) =
|
||||
AppEvent_PeerConnectOrUpdated;
|
||||
const factory AppEvent.peerDisconnected({required String id}) =
|
||||
AppEvent_PeerDisconnected;
|
||||
const factory AppEvent.transferAdded({required Transfer transfer}) =
|
||||
AppEvent_TransferAdded;
|
||||
const factory AppEvent.transferRemoved({required String id}) =
|
||||
AppEvent_TransferRemoved;
|
||||
const factory AppEvent.transferClear() = AppEvent_TransferClear;
|
||||
}
|
||||
638
lib/backend/event.freezed.dart
Normal file
@@ -0,0 +1,638 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'event.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$AppEvent {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class $AppEventCopyWith<$Res> {
|
||||
$AppEventCopyWith(AppEvent _, $Res Function(AppEvent) __);
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [AppEvent].
|
||||
extension AppEventPatterns on AppEvent {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( AppEvent_TransferStatusChanged value)? transferStatusChanged,TResult Function( AppEvent_TransferProgressChanged value)? transferProgressChanged,TResult Function( AppEvent_PeerConnectOrUpdated value)? peerConnectOrUpdated,TResult Function( AppEvent_PeerDisconnected value)? peerDisconnected,TResult Function( AppEvent_TransferAdded value)? transferAdded,TResult Function( AppEvent_TransferRemoved value)? transferRemoved,TResult Function( AppEvent_TransferClear value)? transferClear,required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case AppEvent_TransferStatusChanged() when transferStatusChanged != null:
|
||||
return transferStatusChanged(_that);case AppEvent_TransferProgressChanged() when transferProgressChanged != null:
|
||||
return transferProgressChanged(_that);case AppEvent_PeerConnectOrUpdated() when peerConnectOrUpdated != null:
|
||||
return peerConnectOrUpdated(_that);case AppEvent_PeerDisconnected() when peerDisconnected != null:
|
||||
return peerDisconnected(_that);case AppEvent_TransferAdded() when transferAdded != null:
|
||||
return transferAdded(_that);case AppEvent_TransferRemoved() when transferRemoved != null:
|
||||
return transferRemoved(_that);case AppEvent_TransferClear() when transferClear != null:
|
||||
return transferClear(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( AppEvent_TransferStatusChanged value) transferStatusChanged,required TResult Function( AppEvent_TransferProgressChanged value) transferProgressChanged,required TResult Function( AppEvent_PeerConnectOrUpdated value) peerConnectOrUpdated,required TResult Function( AppEvent_PeerDisconnected value) peerDisconnected,required TResult Function( AppEvent_TransferAdded value) transferAdded,required TResult Function( AppEvent_TransferRemoved value) transferRemoved,required TResult Function( AppEvent_TransferClear value) transferClear,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case AppEvent_TransferStatusChanged():
|
||||
return transferStatusChanged(_that);case AppEvent_TransferProgressChanged():
|
||||
return transferProgressChanged(_that);case AppEvent_PeerConnectOrUpdated():
|
||||
return peerConnectOrUpdated(_that);case AppEvent_PeerDisconnected():
|
||||
return peerDisconnected(_that);case AppEvent_TransferAdded():
|
||||
return transferAdded(_that);case AppEvent_TransferRemoved():
|
||||
return transferRemoved(_that);case AppEvent_TransferClear():
|
||||
return transferClear(_that);}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( AppEvent_TransferStatusChanged value)? transferStatusChanged,TResult? Function( AppEvent_TransferProgressChanged value)? transferProgressChanged,TResult? Function( AppEvent_PeerConnectOrUpdated value)? peerConnectOrUpdated,TResult? Function( AppEvent_PeerDisconnected value)? peerDisconnected,TResult? Function( AppEvent_TransferAdded value)? transferAdded,TResult? Function( AppEvent_TransferRemoved value)? transferRemoved,TResult? Function( AppEvent_TransferClear value)? transferClear,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case AppEvent_TransferStatusChanged() when transferStatusChanged != null:
|
||||
return transferStatusChanged(_that);case AppEvent_TransferProgressChanged() when transferProgressChanged != null:
|
||||
return transferProgressChanged(_that);case AppEvent_PeerConnectOrUpdated() when peerConnectOrUpdated != null:
|
||||
return peerConnectOrUpdated(_that);case AppEvent_PeerDisconnected() when peerDisconnected != null:
|
||||
return peerDisconnected(_that);case AppEvent_TransferAdded() when transferAdded != null:
|
||||
return transferAdded(_that);case AppEvent_TransferRemoved() when transferRemoved != null:
|
||||
return transferRemoved(_that);case AppEvent_TransferClear() when transferClear != null:
|
||||
return transferClear(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function( Transfer transfer)? transferStatusChanged,TResult Function( String id, double progress, double total, double speed)? transferProgressChanged,TResult Function( Peer peer)? peerConnectOrUpdated,TResult Function( String id)? peerDisconnected,TResult Function( Transfer transfer)? transferAdded,TResult Function( String id)? transferRemoved,TResult Function()? transferClear,required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case AppEvent_TransferStatusChanged() when transferStatusChanged != null:
|
||||
return transferStatusChanged(_that.transfer);case AppEvent_TransferProgressChanged() when transferProgressChanged != null:
|
||||
return transferProgressChanged(_that.id,_that.progress,_that.total,_that.speed);case AppEvent_PeerConnectOrUpdated() when peerConnectOrUpdated != null:
|
||||
return peerConnectOrUpdated(_that.peer);case AppEvent_PeerDisconnected() when peerDisconnected != null:
|
||||
return peerDisconnected(_that.id);case AppEvent_TransferAdded() when transferAdded != null:
|
||||
return transferAdded(_that.transfer);case AppEvent_TransferRemoved() when transferRemoved != null:
|
||||
return transferRemoved(_that.id);case AppEvent_TransferClear() when transferClear != null:
|
||||
return transferClear();case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function( Transfer transfer) transferStatusChanged,required TResult Function( String id, double progress, double total, double speed) transferProgressChanged,required TResult Function( Peer peer) peerConnectOrUpdated,required TResult Function( String id) peerDisconnected,required TResult Function( Transfer transfer) transferAdded,required TResult Function( String id) transferRemoved,required TResult Function() transferClear,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case AppEvent_TransferStatusChanged():
|
||||
return transferStatusChanged(_that.transfer);case AppEvent_TransferProgressChanged():
|
||||
return transferProgressChanged(_that.id,_that.progress,_that.total,_that.speed);case AppEvent_PeerConnectOrUpdated():
|
||||
return peerConnectOrUpdated(_that.peer);case AppEvent_PeerDisconnected():
|
||||
return peerDisconnected(_that.id);case AppEvent_TransferAdded():
|
||||
return transferAdded(_that.transfer);case AppEvent_TransferRemoved():
|
||||
return transferRemoved(_that.id);case AppEvent_TransferClear():
|
||||
return transferClear();}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function( Transfer transfer)? transferStatusChanged,TResult? Function( String id, double progress, double total, double speed)? transferProgressChanged,TResult? Function( Peer peer)? peerConnectOrUpdated,TResult? Function( String id)? peerDisconnected,TResult? Function( Transfer transfer)? transferAdded,TResult? Function( String id)? transferRemoved,TResult? Function()? transferClear,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case AppEvent_TransferStatusChanged() when transferStatusChanged != null:
|
||||
return transferStatusChanged(_that.transfer);case AppEvent_TransferProgressChanged() when transferProgressChanged != null:
|
||||
return transferProgressChanged(_that.id,_that.progress,_that.total,_that.speed);case AppEvent_PeerConnectOrUpdated() when peerConnectOrUpdated != null:
|
||||
return peerConnectOrUpdated(_that.peer);case AppEvent_PeerDisconnected() when peerDisconnected != null:
|
||||
return peerDisconnected(_that.id);case AppEvent_TransferAdded() when transferAdded != null:
|
||||
return transferAdded(_that.transfer);case AppEvent_TransferRemoved() when transferRemoved != null:
|
||||
return transferRemoved(_that.id);case AppEvent_TransferClear() when transferClear != null:
|
||||
return transferClear();case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class AppEvent_TransferStatusChanged extends AppEvent {
|
||||
const AppEvent_TransferStatusChanged({required this.transfer}): super._();
|
||||
|
||||
|
||||
final Transfer transfer;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AppEvent_TransferStatusChangedCopyWith<AppEvent_TransferStatusChanged> get copyWith => _$AppEvent_TransferStatusChangedCopyWithImpl<AppEvent_TransferStatusChanged>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent_TransferStatusChanged&&(identical(other.transfer, transfer) || other.transfer == transfer));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,transfer);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent.transferStatusChanged(transfer: $transfer)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AppEvent_TransferStatusChangedCopyWith<$Res> implements $AppEventCopyWith<$Res> {
|
||||
factory $AppEvent_TransferStatusChangedCopyWith(AppEvent_TransferStatusChanged value, $Res Function(AppEvent_TransferStatusChanged) _then) = _$AppEvent_TransferStatusChangedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
Transfer transfer
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AppEvent_TransferStatusChangedCopyWithImpl<$Res>
|
||||
implements $AppEvent_TransferStatusChangedCopyWith<$Res> {
|
||||
_$AppEvent_TransferStatusChangedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AppEvent_TransferStatusChanged _self;
|
||||
final $Res Function(AppEvent_TransferStatusChanged) _then;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? transfer = null,}) {
|
||||
return _then(AppEvent_TransferStatusChanged(
|
||||
transfer: null == transfer ? _self.transfer : transfer // ignore: cast_nullable_to_non_nullable
|
||||
as Transfer,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class AppEvent_TransferProgressChanged extends AppEvent {
|
||||
const AppEvent_TransferProgressChanged({required this.id, required this.progress, required this.total, required this.speed}): super._();
|
||||
|
||||
|
||||
final String id;
|
||||
final double progress;
|
||||
final double total;
|
||||
final double speed;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AppEvent_TransferProgressChangedCopyWith<AppEvent_TransferProgressChanged> get copyWith => _$AppEvent_TransferProgressChangedCopyWithImpl<AppEvent_TransferProgressChanged>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent_TransferProgressChanged&&(identical(other.id, id) || other.id == id)&&(identical(other.progress, progress) || other.progress == progress)&&(identical(other.total, total) || other.total == total)&&(identical(other.speed, speed) || other.speed == speed));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,progress,total,speed);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent.transferProgressChanged(id: $id, progress: $progress, total: $total, speed: $speed)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AppEvent_TransferProgressChangedCopyWith<$Res> implements $AppEventCopyWith<$Res> {
|
||||
factory $AppEvent_TransferProgressChangedCopyWith(AppEvent_TransferProgressChanged value, $Res Function(AppEvent_TransferProgressChanged) _then) = _$AppEvent_TransferProgressChangedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, double progress, double total, double speed
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AppEvent_TransferProgressChangedCopyWithImpl<$Res>
|
||||
implements $AppEvent_TransferProgressChangedCopyWith<$Res> {
|
||||
_$AppEvent_TransferProgressChangedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AppEvent_TransferProgressChanged _self;
|
||||
final $Res Function(AppEvent_TransferProgressChanged) _then;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? id = null,Object? progress = null,Object? total = null,Object? speed = null,}) {
|
||||
return _then(AppEvent_TransferProgressChanged(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,progress: null == progress ? _self.progress : progress // ignore: cast_nullable_to_non_nullable
|
||||
as double,total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable
|
||||
as double,speed: null == speed ? _self.speed : speed // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class AppEvent_PeerConnectOrUpdated extends AppEvent {
|
||||
const AppEvent_PeerConnectOrUpdated({required this.peer}): super._();
|
||||
|
||||
|
||||
final Peer peer;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AppEvent_PeerConnectOrUpdatedCopyWith<AppEvent_PeerConnectOrUpdated> get copyWith => _$AppEvent_PeerConnectOrUpdatedCopyWithImpl<AppEvent_PeerConnectOrUpdated>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent_PeerConnectOrUpdated&&(identical(other.peer, peer) || other.peer == peer));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,peer);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent.peerConnectOrUpdated(peer: $peer)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AppEvent_PeerConnectOrUpdatedCopyWith<$Res> implements $AppEventCopyWith<$Res> {
|
||||
factory $AppEvent_PeerConnectOrUpdatedCopyWith(AppEvent_PeerConnectOrUpdated value, $Res Function(AppEvent_PeerConnectOrUpdated) _then) = _$AppEvent_PeerConnectOrUpdatedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
Peer peer
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AppEvent_PeerConnectOrUpdatedCopyWithImpl<$Res>
|
||||
implements $AppEvent_PeerConnectOrUpdatedCopyWith<$Res> {
|
||||
_$AppEvent_PeerConnectOrUpdatedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AppEvent_PeerConnectOrUpdated _self;
|
||||
final $Res Function(AppEvent_PeerConnectOrUpdated) _then;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? peer = null,}) {
|
||||
return _then(AppEvent_PeerConnectOrUpdated(
|
||||
peer: null == peer ? _self.peer : peer // ignore: cast_nullable_to_non_nullable
|
||||
as Peer,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class AppEvent_PeerDisconnected extends AppEvent {
|
||||
const AppEvent_PeerDisconnected({required this.id}): super._();
|
||||
|
||||
|
||||
final String id;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AppEvent_PeerDisconnectedCopyWith<AppEvent_PeerDisconnected> get copyWith => _$AppEvent_PeerDisconnectedCopyWithImpl<AppEvent_PeerDisconnected>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent_PeerDisconnected&&(identical(other.id, id) || other.id == id));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent.peerDisconnected(id: $id)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AppEvent_PeerDisconnectedCopyWith<$Res> implements $AppEventCopyWith<$Res> {
|
||||
factory $AppEvent_PeerDisconnectedCopyWith(AppEvent_PeerDisconnected value, $Res Function(AppEvent_PeerDisconnected) _then) = _$AppEvent_PeerDisconnectedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AppEvent_PeerDisconnectedCopyWithImpl<$Res>
|
||||
implements $AppEvent_PeerDisconnectedCopyWith<$Res> {
|
||||
_$AppEvent_PeerDisconnectedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AppEvent_PeerDisconnected _self;
|
||||
final $Res Function(AppEvent_PeerDisconnected) _then;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? id = null,}) {
|
||||
return _then(AppEvent_PeerDisconnected(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class AppEvent_TransferAdded extends AppEvent {
|
||||
const AppEvent_TransferAdded({required this.transfer}): super._();
|
||||
|
||||
|
||||
final Transfer transfer;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AppEvent_TransferAddedCopyWith<AppEvent_TransferAdded> get copyWith => _$AppEvent_TransferAddedCopyWithImpl<AppEvent_TransferAdded>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent_TransferAdded&&(identical(other.transfer, transfer) || other.transfer == transfer));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,transfer);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent.transferAdded(transfer: $transfer)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AppEvent_TransferAddedCopyWith<$Res> implements $AppEventCopyWith<$Res> {
|
||||
factory $AppEvent_TransferAddedCopyWith(AppEvent_TransferAdded value, $Res Function(AppEvent_TransferAdded) _then) = _$AppEvent_TransferAddedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
Transfer transfer
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AppEvent_TransferAddedCopyWithImpl<$Res>
|
||||
implements $AppEvent_TransferAddedCopyWith<$Res> {
|
||||
_$AppEvent_TransferAddedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AppEvent_TransferAdded _self;
|
||||
final $Res Function(AppEvent_TransferAdded) _then;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? transfer = null,}) {
|
||||
return _then(AppEvent_TransferAdded(
|
||||
transfer: null == transfer ? _self.transfer : transfer // ignore: cast_nullable_to_non_nullable
|
||||
as Transfer,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class AppEvent_TransferRemoved extends AppEvent {
|
||||
const AppEvent_TransferRemoved({required this.id}): super._();
|
||||
|
||||
|
||||
final String id;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AppEvent_TransferRemovedCopyWith<AppEvent_TransferRemoved> get copyWith => _$AppEvent_TransferRemovedCopyWithImpl<AppEvent_TransferRemoved>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent_TransferRemoved&&(identical(other.id, id) || other.id == id));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent.transferRemoved(id: $id)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AppEvent_TransferRemovedCopyWith<$Res> implements $AppEventCopyWith<$Res> {
|
||||
factory $AppEvent_TransferRemovedCopyWith(AppEvent_TransferRemoved value, $Res Function(AppEvent_TransferRemoved) _then) = _$AppEvent_TransferRemovedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AppEvent_TransferRemovedCopyWithImpl<$Res>
|
||||
implements $AppEvent_TransferRemovedCopyWith<$Res> {
|
||||
_$AppEvent_TransferRemovedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AppEvent_TransferRemoved _self;
|
||||
final $Res Function(AppEvent_TransferRemoved) _then;
|
||||
|
||||
/// Create a copy of AppEvent
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? id = null,}) {
|
||||
return _then(AppEvent_TransferRemoved(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class AppEvent_TransferClear extends AppEvent {
|
||||
const AppEvent_TransferClear(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppEvent_TransferClear);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppEvent.transferClear()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// dart format on
|
||||
1645
lib/backend/frb_generated.dart
Normal file
303
lib/backend/frb_generated.io.dart
Normal file
@@ -0,0 +1,303 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field
|
||||
|
||||
import 'api/commands.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi' as ffi;
|
||||
import 'discovery/model.dart';
|
||||
import 'event.dart';
|
||||
import 'frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_io.dart';
|
||||
import 'transfer/model.dart';
|
||||
|
||||
abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
RustLibApiImplPlatform({
|
||||
required super.handler,
|
||||
required super.wire,
|
||||
required super.generalizedFrbRustBinding,
|
||||
required super.portManager,
|
||||
});
|
||||
|
||||
@protected
|
||||
AnyhowException dco_decode_AnyhowException(dynamic raw);
|
||||
|
||||
@protected
|
||||
Map<String, RouteState> dco_decode_Map_String_route_state_None(dynamic raw);
|
||||
|
||||
@protected
|
||||
RustStreamSink<AppEvent> dco_decode_StreamSink_app_event_Sse(dynamic raw);
|
||||
|
||||
@protected
|
||||
String dco_decode_String(dynamic raw);
|
||||
|
||||
@protected
|
||||
AppEvent dco_decode_app_event(dynamic raw);
|
||||
|
||||
@protected
|
||||
bool dco_decode_bool(dynamic raw);
|
||||
|
||||
@protected
|
||||
Peer dco_decode_box_autoadd_peer(dynamic raw);
|
||||
|
||||
@protected
|
||||
Transfer dco_decode_box_autoadd_transfer(dynamic raw);
|
||||
|
||||
@protected
|
||||
CanceledBy dco_decode_canceled_by(dynamic raw);
|
||||
|
||||
@protected
|
||||
ContentType dco_decode_content_type(dynamic raw);
|
||||
|
||||
@protected
|
||||
double dco_decode_f_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
int dco_decode_i_32(dynamic raw);
|
||||
|
||||
@protected
|
||||
PlatformInt64 dco_decode_i_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<Peer> dco_decode_list_peer(dynamic raw);
|
||||
|
||||
@protected
|
||||
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<(String, RouteState)> dco_decode_list_record_string_route_state(
|
||||
dynamic raw,
|
||||
);
|
||||
|
||||
@protected
|
||||
List<Transfer> dco_decode_list_transfer(dynamic raw);
|
||||
|
||||
@protected
|
||||
Peer dco_decode_peer(dynamic raw);
|
||||
|
||||
@protected
|
||||
(String, RouteState) dco_decode_record_string_route_state(dynamic raw);
|
||||
|
||||
@protected
|
||||
RouteState dco_decode_route_state(dynamic raw);
|
||||
|
||||
@protected
|
||||
Transfer dco_decode_transfer(dynamic raw);
|
||||
|
||||
@protected
|
||||
TransferStatus dco_decode_transfer_status(dynamic raw);
|
||||
|
||||
@protected
|
||||
TransferType dco_decode_transfer_type(dynamic raw);
|
||||
|
||||
@protected
|
||||
int dco_decode_u_16(dynamic raw);
|
||||
|
||||
@protected
|
||||
int dco_decode_u_8(dynamic raw);
|
||||
|
||||
@protected
|
||||
void dco_decode_unit(dynamic raw);
|
||||
|
||||
@protected
|
||||
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Map<String, RouteState> sse_decode_Map_String_route_state_None(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
RustStreamSink<AppEvent> sse_decode_StreamSink_app_event_Sse(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
String sse_decode_String(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
AppEvent sse_decode_app_event(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
bool sse_decode_bool(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Peer sse_decode_box_autoadd_peer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Transfer sse_decode_box_autoadd_transfer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
CanceledBy sse_decode_canceled_by(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
ContentType sse_decode_content_type(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
double sse_decode_f_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int sse_decode_i_32(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
PlatformInt64 sse_decode_i_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
List<Peer> sse_decode_list_peer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
List<(String, RouteState)> sse_decode_list_record_string_route_state(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
List<Transfer> sse_decode_list_transfer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Peer sse_decode_peer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
(String, RouteState) sse_decode_record_string_route_state(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
RouteState sse_decode_route_state(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Transfer sse_decode_transfer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
TransferStatus sse_decode_transfer_status(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
TransferType sse_decode_transfer_type(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int sse_decode_u_16(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int sse_decode_u_8(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
void sse_decode_unit(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_AnyhowException(
|
||||
AnyhowException self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_Map_String_route_state_None(
|
||||
Map<String, RouteState> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_StreamSink_app_event_Sse(
|
||||
RustStreamSink<AppEvent> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_String(String self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_app_event(AppEvent self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bool(bool self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_peer(Peer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_transfer(Transfer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_canceled_by(CanceledBy self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_content_type(ContentType self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_f_64(double self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_i_32(int self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_peer(List<Peer> self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_prim_u_8_strict(
|
||||
Uint8List self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_record_string_route_state(
|
||||
List<(String, RouteState)> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_transfer(List<Transfer> self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_peer(Peer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_record_string_route_state(
|
||||
(String, RouteState) self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_route_state(RouteState self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_transfer(Transfer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_transfer_status(
|
||||
TransferStatus self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_transfer_type(TransferType self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_u_16(int self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_u_8(int self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_unit(void self, SseSerializer serializer);
|
||||
}
|
||||
|
||||
// Section: wire_class
|
||||
|
||||
class RustLibWire implements BaseWire {
|
||||
factory RustLibWire.fromExternalLibrary(ExternalLibrary lib) =>
|
||||
RustLibWire(lib.ffiDynamicLibrary);
|
||||
|
||||
/// Holds the symbol lookup function.
|
||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||
_lookup;
|
||||
|
||||
/// The symbols are looked up in [dynamicLibrary].
|
||||
RustLibWire(ffi.DynamicLibrary dynamicLibrary)
|
||||
: _lookup = dynamicLibrary.lookup;
|
||||
}
|
||||
303
lib/backend/frb_generated.web.dart
Normal file
@@ -0,0 +1,303 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field
|
||||
|
||||
// Static analysis wrongly picks the IO variant, thus ignore this
|
||||
// ignore_for_file: argument_type_not_assignable
|
||||
|
||||
import 'api/commands.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'discovery/model.dart';
|
||||
import 'event.dart';
|
||||
import 'frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated_web.dart';
|
||||
import 'transfer/model.dart';
|
||||
|
||||
abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
|
||||
RustLibApiImplPlatform({
|
||||
required super.handler,
|
||||
required super.wire,
|
||||
required super.generalizedFrbRustBinding,
|
||||
required super.portManager,
|
||||
});
|
||||
|
||||
@protected
|
||||
AnyhowException dco_decode_AnyhowException(dynamic raw);
|
||||
|
||||
@protected
|
||||
Map<String, RouteState> dco_decode_Map_String_route_state_None(dynamic raw);
|
||||
|
||||
@protected
|
||||
RustStreamSink<AppEvent> dco_decode_StreamSink_app_event_Sse(dynamic raw);
|
||||
|
||||
@protected
|
||||
String dco_decode_String(dynamic raw);
|
||||
|
||||
@protected
|
||||
AppEvent dco_decode_app_event(dynamic raw);
|
||||
|
||||
@protected
|
||||
bool dco_decode_bool(dynamic raw);
|
||||
|
||||
@protected
|
||||
Peer dco_decode_box_autoadd_peer(dynamic raw);
|
||||
|
||||
@protected
|
||||
Transfer dco_decode_box_autoadd_transfer(dynamic raw);
|
||||
|
||||
@protected
|
||||
CanceledBy dco_decode_canceled_by(dynamic raw);
|
||||
|
||||
@protected
|
||||
ContentType dco_decode_content_type(dynamic raw);
|
||||
|
||||
@protected
|
||||
double dco_decode_f_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
int dco_decode_i_32(dynamic raw);
|
||||
|
||||
@protected
|
||||
PlatformInt64 dco_decode_i_64(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<Peer> dco_decode_list_peer(dynamic raw);
|
||||
|
||||
@protected
|
||||
Uint8List dco_decode_list_prim_u_8_strict(dynamic raw);
|
||||
|
||||
@protected
|
||||
List<(String, RouteState)> dco_decode_list_record_string_route_state(
|
||||
dynamic raw,
|
||||
);
|
||||
|
||||
@protected
|
||||
List<Transfer> dco_decode_list_transfer(dynamic raw);
|
||||
|
||||
@protected
|
||||
Peer dco_decode_peer(dynamic raw);
|
||||
|
||||
@protected
|
||||
(String, RouteState) dco_decode_record_string_route_state(dynamic raw);
|
||||
|
||||
@protected
|
||||
RouteState dco_decode_route_state(dynamic raw);
|
||||
|
||||
@protected
|
||||
Transfer dco_decode_transfer(dynamic raw);
|
||||
|
||||
@protected
|
||||
TransferStatus dco_decode_transfer_status(dynamic raw);
|
||||
|
||||
@protected
|
||||
TransferType dco_decode_transfer_type(dynamic raw);
|
||||
|
||||
@protected
|
||||
int dco_decode_u_16(dynamic raw);
|
||||
|
||||
@protected
|
||||
int dco_decode_u_8(dynamic raw);
|
||||
|
||||
@protected
|
||||
void dco_decode_unit(dynamic raw);
|
||||
|
||||
@protected
|
||||
AnyhowException sse_decode_AnyhowException(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Map<String, RouteState> sse_decode_Map_String_route_state_None(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
RustStreamSink<AppEvent> sse_decode_StreamSink_app_event_Sse(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
String sse_decode_String(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
AppEvent sse_decode_app_event(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
bool sse_decode_bool(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Peer sse_decode_box_autoadd_peer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Transfer sse_decode_box_autoadd_transfer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
CanceledBy sse_decode_canceled_by(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
ContentType sse_decode_content_type(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
double sse_decode_f_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int sse_decode_i_32(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
PlatformInt64 sse_decode_i_64(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
List<Peer> sse_decode_list_peer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
List<(String, RouteState)> sse_decode_list_record_string_route_state(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
List<Transfer> sse_decode_list_transfer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Peer sse_decode_peer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
(String, RouteState) sse_decode_record_string_route_state(
|
||||
SseDeserializer deserializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
RouteState sse_decode_route_state(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
Transfer sse_decode_transfer(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
TransferStatus sse_decode_transfer_status(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
TransferType sse_decode_transfer_type(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int sse_decode_u_16(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
int sse_decode_u_8(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
void sse_decode_unit(SseDeserializer deserializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_AnyhowException(
|
||||
AnyhowException self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_Map_String_route_state_None(
|
||||
Map<String, RouteState> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_StreamSink_app_event_Sse(
|
||||
RustStreamSink<AppEvent> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_String(String self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_app_event(AppEvent self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_bool(bool self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_peer(Peer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_box_autoadd_transfer(Transfer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_canceled_by(CanceledBy self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_content_type(ContentType self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_f_64(double self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_i_32(int self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_i_64(PlatformInt64 self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_peer(List<Peer> self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_prim_u_8_strict(
|
||||
Uint8List self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_record_string_route_state(
|
||||
List<(String, RouteState)> self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_list_transfer(List<Transfer> self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_peer(Peer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_record_string_route_state(
|
||||
(String, RouteState) self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_route_state(RouteState self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_transfer(Transfer self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_transfer_status(
|
||||
TransferStatus self,
|
||||
SseSerializer serializer,
|
||||
);
|
||||
|
||||
@protected
|
||||
void sse_encode_transfer_type(TransferType self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_u_16(int self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_u_8(int self, SseSerializer serializer);
|
||||
|
||||
@protected
|
||||
void sse_encode_unit(void self, SseSerializer serializer);
|
||||
}
|
||||
|
||||
// Section: wire_class
|
||||
|
||||
class RustLibWire implements BaseWire {
|
||||
RustLibWire.fromExternalLibrary(ExternalLibrary lib);
|
||||
}
|
||||
|
||||
@JS('wasm_bindgen')
|
||||
external RustLibWasmModule get wasmModule;
|
||||
|
||||
@JS()
|
||||
@anonymous
|
||||
extension type RustLibWasmModule._(JSObject _) implements JSObject {}
|
||||
109
lib/backend/transfer/model.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
// This file is automatically generated, so please do not edit it.
|
||||
// @generated by `flutter_rust_bridge`@ 2.11.1.
|
||||
|
||||
// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import
|
||||
|
||||
import '../discovery/model.dart';
|
||||
import '../frb_generated.dart';
|
||||
import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart' hide protected;
|
||||
part 'model.freezed.dart';
|
||||
|
||||
enum CanceledBy { sender, receiver }
|
||||
|
||||
enum ContentType { file, text, folder }
|
||||
|
||||
class Transfer {
|
||||
final String id;
|
||||
final double createTime;
|
||||
final Peer sender;
|
||||
final String senderIp;
|
||||
final String fileName;
|
||||
final double fileSize;
|
||||
final String savePath;
|
||||
final TransferStatus status;
|
||||
final TransferType type;
|
||||
final ContentType contentType;
|
||||
final String text;
|
||||
final String errorMsg;
|
||||
final String token;
|
||||
final double progress;
|
||||
final PlatformInt64 lastReadTime;
|
||||
final double speed;
|
||||
|
||||
const Transfer({
|
||||
required this.id,
|
||||
required this.createTime,
|
||||
required this.sender,
|
||||
required this.senderIp,
|
||||
required this.fileName,
|
||||
required this.fileSize,
|
||||
required this.savePath,
|
||||
required this.status,
|
||||
required this.type,
|
||||
required this.contentType,
|
||||
required this.text,
|
||||
required this.errorMsg,
|
||||
required this.token,
|
||||
required this.progress,
|
||||
required this.lastReadTime,
|
||||
required this.speed,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
id.hashCode ^
|
||||
createTime.hashCode ^
|
||||
sender.hashCode ^
|
||||
senderIp.hashCode ^
|
||||
fileName.hashCode ^
|
||||
fileSize.hashCode ^
|
||||
savePath.hashCode ^
|
||||
status.hashCode ^
|
||||
type.hashCode ^
|
||||
contentType.hashCode ^
|
||||
text.hashCode ^
|
||||
errorMsg.hashCode ^
|
||||
token.hashCode ^
|
||||
progress.hashCode ^
|
||||
lastReadTime.hashCode ^
|
||||
speed.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Transfer &&
|
||||
runtimeType == other.runtimeType &&
|
||||
id == other.id &&
|
||||
createTime == other.createTime &&
|
||||
sender == other.sender &&
|
||||
senderIp == other.senderIp &&
|
||||
fileName == other.fileName &&
|
||||
fileSize == other.fileSize &&
|
||||
savePath == other.savePath &&
|
||||
status == other.status &&
|
||||
type == other.type &&
|
||||
contentType == other.contentType &&
|
||||
text == other.text &&
|
||||
errorMsg == other.errorMsg &&
|
||||
token == other.token &&
|
||||
progress == other.progress &&
|
||||
lastReadTime == other.lastReadTime &&
|
||||
speed == other.speed;
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class TransferStatus with _$TransferStatus {
|
||||
const TransferStatus._();
|
||||
|
||||
const factory TransferStatus.pending() = TransferStatus_Pending;
|
||||
const factory TransferStatus.accepted() = TransferStatus_Accepted;
|
||||
const factory TransferStatus.rejected() = TransferStatus_Rejected;
|
||||
const factory TransferStatus.completed() = TransferStatus_Completed;
|
||||
const factory TransferStatus.error() = TransferStatus_Error;
|
||||
const factory TransferStatus.canceled(CanceledBy field0) =
|
||||
TransferStatus_Canceled;
|
||||
const factory TransferStatus.active() = TransferStatus_Active;
|
||||
}
|
||||
|
||||
enum TransferType { send, receive }
|
||||
462
lib/backend/transfer/model.freezed.dart
Normal file
@@ -0,0 +1,462 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$TransferStatus {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class $TransferStatusCopyWith<$Res> {
|
||||
$TransferStatusCopyWith(TransferStatus _, $Res Function(TransferStatus) __);
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [TransferStatus].
|
||||
extension TransferStatusPatterns on TransferStatus {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( TransferStatus_Pending value)? pending,TResult Function( TransferStatus_Accepted value)? accepted,TResult Function( TransferStatus_Rejected value)? rejected,TResult Function( TransferStatus_Completed value)? completed,TResult Function( TransferStatus_Error value)? error,TResult Function( TransferStatus_Canceled value)? canceled,TResult Function( TransferStatus_Active value)? active,required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case TransferStatus_Pending() when pending != null:
|
||||
return pending(_that);case TransferStatus_Accepted() when accepted != null:
|
||||
return accepted(_that);case TransferStatus_Rejected() when rejected != null:
|
||||
return rejected(_that);case TransferStatus_Completed() when completed != null:
|
||||
return completed(_that);case TransferStatus_Error() when error != null:
|
||||
return error(_that);case TransferStatus_Canceled() when canceled != null:
|
||||
return canceled(_that);case TransferStatus_Active() when active != null:
|
||||
return active(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( TransferStatus_Pending value) pending,required TResult Function( TransferStatus_Accepted value) accepted,required TResult Function( TransferStatus_Rejected value) rejected,required TResult Function( TransferStatus_Completed value) completed,required TResult Function( TransferStatus_Error value) error,required TResult Function( TransferStatus_Canceled value) canceled,required TResult Function( TransferStatus_Active value) active,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case TransferStatus_Pending():
|
||||
return pending(_that);case TransferStatus_Accepted():
|
||||
return accepted(_that);case TransferStatus_Rejected():
|
||||
return rejected(_that);case TransferStatus_Completed():
|
||||
return completed(_that);case TransferStatus_Error():
|
||||
return error(_that);case TransferStatus_Canceled():
|
||||
return canceled(_that);case TransferStatus_Active():
|
||||
return active(_that);}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( TransferStatus_Pending value)? pending,TResult? Function( TransferStatus_Accepted value)? accepted,TResult? Function( TransferStatus_Rejected value)? rejected,TResult? Function( TransferStatus_Completed value)? completed,TResult? Function( TransferStatus_Error value)? error,TResult? Function( TransferStatus_Canceled value)? canceled,TResult? Function( TransferStatus_Active value)? active,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case TransferStatus_Pending() when pending != null:
|
||||
return pending(_that);case TransferStatus_Accepted() when accepted != null:
|
||||
return accepted(_that);case TransferStatus_Rejected() when rejected != null:
|
||||
return rejected(_that);case TransferStatus_Completed() when completed != null:
|
||||
return completed(_that);case TransferStatus_Error() when error != null:
|
||||
return error(_that);case TransferStatus_Canceled() when canceled != null:
|
||||
return canceled(_that);case TransferStatus_Active() when active != null:
|
||||
return active(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? pending,TResult Function()? accepted,TResult Function()? rejected,TResult Function()? completed,TResult Function()? error,TResult Function( CanceledBy field0)? canceled,TResult Function()? active,required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case TransferStatus_Pending() when pending != null:
|
||||
return pending();case TransferStatus_Accepted() when accepted != null:
|
||||
return accepted();case TransferStatus_Rejected() when rejected != null:
|
||||
return rejected();case TransferStatus_Completed() when completed != null:
|
||||
return completed();case TransferStatus_Error() when error != null:
|
||||
return error();case TransferStatus_Canceled() when canceled != null:
|
||||
return canceled(_that.field0);case TransferStatus_Active() when active != null:
|
||||
return active();case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() pending,required TResult Function() accepted,required TResult Function() rejected,required TResult Function() completed,required TResult Function() error,required TResult Function( CanceledBy field0) canceled,required TResult Function() active,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case TransferStatus_Pending():
|
||||
return pending();case TransferStatus_Accepted():
|
||||
return accepted();case TransferStatus_Rejected():
|
||||
return rejected();case TransferStatus_Completed():
|
||||
return completed();case TransferStatus_Error():
|
||||
return error();case TransferStatus_Canceled():
|
||||
return canceled(_that.field0);case TransferStatus_Active():
|
||||
return active();}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? pending,TResult? Function()? accepted,TResult? Function()? rejected,TResult? Function()? completed,TResult? Function()? error,TResult? Function( CanceledBy field0)? canceled,TResult? Function()? active,}) {final _that = this;
|
||||
switch (_that) {
|
||||
case TransferStatus_Pending() when pending != null:
|
||||
return pending();case TransferStatus_Accepted() when accepted != null:
|
||||
return accepted();case TransferStatus_Rejected() when rejected != null:
|
||||
return rejected();case TransferStatus_Completed() when completed != null:
|
||||
return completed();case TransferStatus_Error() when error != null:
|
||||
return error();case TransferStatus_Canceled() when canceled != null:
|
||||
return canceled(_that.field0);case TransferStatus_Active() when active != null:
|
||||
return active();case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class TransferStatus_Pending extends TransferStatus {
|
||||
const TransferStatus_Pending(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus_Pending);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus.pending()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class TransferStatus_Accepted extends TransferStatus {
|
||||
const TransferStatus_Accepted(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus_Accepted);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus.accepted()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class TransferStatus_Rejected extends TransferStatus {
|
||||
const TransferStatus_Rejected(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus_Rejected);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus.rejected()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class TransferStatus_Completed extends TransferStatus {
|
||||
const TransferStatus_Completed(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus_Completed);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus.completed()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class TransferStatus_Error extends TransferStatus {
|
||||
const TransferStatus_Error(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus_Error);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus.error()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class TransferStatus_Canceled extends TransferStatus {
|
||||
const TransferStatus_Canceled(this.field0): super._();
|
||||
|
||||
|
||||
final CanceledBy field0;
|
||||
|
||||
/// Create a copy of TransferStatus
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$TransferStatus_CanceledCopyWith<TransferStatus_Canceled> get copyWith => _$TransferStatus_CanceledCopyWithImpl<TransferStatus_Canceled>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus_Canceled&&(identical(other.field0, field0) || other.field0 == field0));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,field0);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus.canceled(field0: $field0)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $TransferStatus_CanceledCopyWith<$Res> implements $TransferStatusCopyWith<$Res> {
|
||||
factory $TransferStatus_CanceledCopyWith(TransferStatus_Canceled value, $Res Function(TransferStatus_Canceled) _then) = _$TransferStatus_CanceledCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
CanceledBy field0
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$TransferStatus_CanceledCopyWithImpl<$Res>
|
||||
implements $TransferStatus_CanceledCopyWith<$Res> {
|
||||
_$TransferStatus_CanceledCopyWithImpl(this._self, this._then);
|
||||
|
||||
final TransferStatus_Canceled _self;
|
||||
final $Res Function(TransferStatus_Canceled) _then;
|
||||
|
||||
/// Create a copy of TransferStatus
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') $Res call({Object? field0 = null,}) {
|
||||
return _then(TransferStatus_Canceled(
|
||||
null == field0 ? _self.field0 : field0 // ignore: cast_nullable_to_non_nullable
|
||||
as CanceledBy,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class TransferStatus_Active extends TransferStatus {
|
||||
const TransferStatus_Active(): super._();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is TransferStatus_Active);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransferStatus.active()';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// dart format on
|
||||
11
lib/main.dart
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'app/app.dart';
|
||||
import 'backend/frb_generated.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await RustLib.init();
|
||||
runApp(const ProviderScope(child: MeshDropApp()));
|
||||
}
|
||||
1
linux/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
flutter/ephemeral
|
||||
128
linux/CMakeLists.txt
Normal file
@@ -0,0 +1,128 @@
|
||||
# Project-level configuration.
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(runner LANGUAGES CXX)
|
||||
|
||||
# The name of the executable created for the application. Change this to change
|
||||
# the on-disk name of your application.
|
||||
set(BINARY_NAME "mesh_drop_flutter")
|
||||
# The unique GTK application identifier for this application. See:
|
||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||
set(APPLICATION_ID "com.example.mesh_drop_flutter")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
cmake_policy(SET CMP0063 NEW)
|
||||
|
||||
# Load bundled libraries from the lib/ directory relative to the binary.
|
||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
|
||||
|
||||
# Root filesystem for cross-building.
|
||||
if(FLUTTER_TARGET_PLATFORM_SYSROOT)
|
||||
set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
|
||||
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
endif()
|
||||
|
||||
# Define build configuration options.
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE "Debug" CACHE
|
||||
STRING "Flutter build mode" FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Profile" "Release")
|
||||
endif()
|
||||
|
||||
# Compilation settings that should be applied to most targets.
|
||||
#
|
||||
# Be cautious about adding new options here, as plugins use this function by
|
||||
# default. In most cases, you should add new options to specific targets instead
|
||||
# of modifying this function.
|
||||
function(APPLY_STANDARD_SETTINGS TARGET)
|
||||
target_compile_features(${TARGET} PUBLIC cxx_std_14)
|
||||
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
|
||||
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||
endfunction()
|
||||
|
||||
# Flutter library and tool build rules.
|
||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
|
||||
# Application build; see runner/CMakeLists.txt.
|
||||
add_subdirectory("runner")
|
||||
|
||||
# Run the Flutter tool portions of the build. This must not be removed.
|
||||
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||
|
||||
# Only the install-generated bundle's copy of the executable will launch
|
||||
# correctly, since the resources must in the right relative locations. To avoid
|
||||
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||
# the default top-level location.
|
||||
set_target_properties(${BINARY_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||
)
|
||||
|
||||
|
||||
# Generated plugin build rules, which manage building the plugins and adding
|
||||
# them to the application.
|
||||
include(flutter/generated_plugins.cmake)
|
||||
|
||||
|
||||
# === Installation ===
|
||||
# By default, "installing" just makes a relocatable bundle in the build
|
||||
# directory.
|
||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||
endif()
|
||||
|
||||
# Start with a clean build bundle directory every time.
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||
" COMPONENT Runtime)
|
||||
|
||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||
install(FILES "${bundled_library}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endforeach(bundled_library)
|
||||
|
||||
# Copy the native assets provided by the build.dart from all packages.
|
||||
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
|
||||
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
||||
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
|
||||
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||
# from a previous install.
|
||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||
install(CODE "
|
||||
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||
" COMPONENT Runtime)
|
||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||
|
||||
# Install the AOT library on non-Debug builds only.
|
||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||
COMPONENT Runtime)
|
||||
endif()
|
||||
88
linux/flutter/CMakeLists.txt
Normal file
@@ -0,0 +1,88 @@
|
||||
# This file controls Flutter-level build steps. It should not be edited.
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
|
||||
|
||||
# Configuration provided via flutter tool.
|
||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
|
||||
|
||||
# TODO: Move the rest of this into files in ephemeral. See
|
||||
# https://github.com/flutter/flutter/issues/57146.
|
||||
|
||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
|
||||
# which isn't available in 3.10.
|
||||
function(list_prepend LIST_NAME PREFIX)
|
||||
set(NEW_LIST "")
|
||||
foreach(element ${${LIST_NAME}})
|
||||
list(APPEND NEW_LIST "${PREFIX}${element}")
|
||||
endforeach(element)
|
||||
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# === Flutter Library ===
|
||||
# System-level dependencies.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
|
||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
|
||||
|
||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
|
||||
|
||||
# Published to parent scope for install step.
|
||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
|
||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
|
||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
|
||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
|
||||
|
||||
list(APPEND FLUTTER_LIBRARY_HEADERS
|
||||
"fl_basic_message_channel.h"
|
||||
"fl_binary_codec.h"
|
||||
"fl_binary_messenger.h"
|
||||
"fl_dart_project.h"
|
||||
"fl_engine.h"
|
||||
"fl_json_message_codec.h"
|
||||
"fl_json_method_codec.h"
|
||||
"fl_message_codec.h"
|
||||
"fl_method_call.h"
|
||||
"fl_method_channel.h"
|
||||
"fl_method_codec.h"
|
||||
"fl_method_response.h"
|
||||
"fl_plugin_registrar.h"
|
||||
"fl_plugin_registry.h"
|
||||
"fl_standard_message_codec.h"
|
||||
"fl_standard_method_codec.h"
|
||||
"fl_string_codec.h"
|
||||
"fl_value.h"
|
||||
"fl_view.h"
|
||||
"flutter_linux.h"
|
||||
)
|
||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
|
||||
add_library(flutter INTERFACE)
|
||||
target_include_directories(flutter INTERFACE
|
||||
"${EPHEMERAL_DIR}"
|
||||
)
|
||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
|
||||
target_link_libraries(flutter INTERFACE
|
||||
PkgConfig::GTK
|
||||
PkgConfig::GLIB
|
||||
PkgConfig::GIO
|
||||
)
|
||||
add_dependencies(flutter flutter_assemble)
|
||||
|
||||
# === Flutter tool backend ===
|
||||
# _phony_ is a non-existent file to force this command to run every time,
|
||||
# since currently there's no way to get a full input/output list from the
|
||||
# flutter tool.
|
||||
add_custom_command(
|
||||
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/_phony_
|
||||
COMMAND ${CMAKE_COMMAND} -E env
|
||||
${FLUTTER_TOOL_ENVIRONMENT}
|
||||
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
|
||||
${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(flutter_assemble DEPENDS
|
||||
"${FLUTTER_LIBRARY}"
|
||||
${FLUTTER_LIBRARY_HEADERS}
|
||||
)
|
||||
15
linux/flutter/generated_plugin_registrant.cc
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) desktop_drop_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin");
|
||||
desktop_drop_plugin_register_with_registrar(desktop_drop_registrar);
|
||||
}
|
||||
15
linux/flutter/generated_plugin_registrant.h
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// clang-format off
|
||||
|
||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||
#define GENERATED_PLUGIN_REGISTRANT_
|
||||
|
||||
#include <flutter_linux/flutter_linux.h>
|
||||
|
||||
// Registers Flutter plugins.
|
||||
void fl_register_plugins(FlPluginRegistry* registry);
|
||||
|
||||
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||