From b4f3eae96b005233c412424f49b702191996f4b2 Mon Sep 17 00:00:00 2001 From: xbss <2055761346@qq.com> Date: Mon, 19 Feb 2024 19:03:26 +0800 Subject: [PATCH] first commit --- .gitignore | 43 ++ .metadata | 33 + README.md | 9 + analysis_options.yaml | 28 + android/.gitignore | 13 + android/app/build.gradle | 67 ++ android/app/src/debug/AndroidManifest.xml | 7 + android/app/src/main/AndroidManifest.xml | 38 ++ .../com/xbss/c_clipboard/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 939 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 671 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 1273 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1895 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 2837 bytes .../app/src/main/res/values-night/styles.xml | 18 + android/app/src/main/res/values/styles.xml | 18 + android/app/src/profile/AndroidManifest.xml | 7 + android/build.gradle | 30 + android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 + android/settings.gradle | 29 + assets/image/computer.png | Bin 0 -> 244 bytes assets/image/icon.png | Bin 0 -> 2837 bytes assets/image/phone.png | Bin 0 -> 283 bytes assets/image/spot.png | Bin 0 -> 299 bytes assets/svg/computer.svg | 1 + assets/svg/phone.svg | 1 + assets/svg/spot.svg | 1 + ios/.gitignore | 34 + ios/Flutter/AppFrameworkInfo.plist | 26 + ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Runner.xcodeproj/project.pbxproj | 614 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 38317 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 561 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 883 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1208 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 744 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1141 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1481 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 883 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1421 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 1753 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 0 -> 1023 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 0 -> 1522 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 0 -> 1140 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 0 -> 1702 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 1753 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 2104 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 0 -> 1345 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 0 -> 1936 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1416 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 2018 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 2097 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + ios/Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ ios/Runner/Base.lproj/Main.storyboard | 26 + ios/Runner/Info.plist | 49 ++ ios/Runner/Runner-Bridging-Header.h | 1 + ios/RunnerTests/RunnerTests.swift | 12 + lib/CodeInputContainer.dart | 265 ++++++++ lib/DeviceInfoContainer.dart | 131 ++++ lib/example.dart | 125 ++++ .../json/base/json_convert_content.dart | 240 +++++++ lib/generated/json/base/json_field.dart | 32 + .../json/clipboard_message_entity.g.dart | 30 + .../json/close_message_entity.g.dart | 28 + .../json/heart_package_message_entity.g.dart | 31 + ...pair_device_response_message_entity.g.dart | 33 + .../pair_code_response_message_entity.g.dart | 32 + ...evice_infos_response_message_entity.g.dart | 37 ++ .../remove_pair_request_message_entity.g.dart | 32 + ...remove_pair_response_message_entity.g.dart | 33 + ...erver_ready_response_message_entity.g.dart | 32 + .../json/work_error_message_entity.g.dart | 31 + lib/main.dart | 459 +++++++++++++ lib/message/Codec.dart | 167 +++++ lib/message/DeviceChangeResponseMessage.dart | 35 + lib/message/DeviceInfo.dart | 27 + lib/message/Message.dart | 4 + lib/message/PairCreateMessage.dart | 28 + .../PairDeviceInfosResponseMessage2.dart | 29 + lib/message/PairRequestMessage.dart | 60 ++ lib/message/clipboard_message_entity.dart | 28 + lib/message/close_message_entity.dart | 28 + lib/message/heart_package_message_entity.dart | 28 + ...o_pair_device_response_message_entity.dart | 28 + .../pair_code_response_message_entity.dart | 28 + ..._device_infos_response_message_entity.dart | 29 + .../remove_pair_request_message_entity.dart | 29 + .../remove_pair_response_message_entity.dart | 28 + .../server_ready_response_message_entity.dart | 28 + lib/message/test.dart | 17 + lib/message/work_error_message_entity.dart | 27 + lib/parent.dart | 69 ++ lib/test.dart | 67 ++ pubspec.lock | 418 ++++++++++++ pubspec.yaml | 120 ++++ test/widget_test.dart | 30 + 114 files changed, 4412 insertions(+) create mode 100644 .gitignore create mode 100644 .metadata create mode 100644 README.md create mode 100644 analysis_options.yaml create mode 100644 android/.gitignore create mode 100644 android/app/build.gradle create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/kotlin/com/xbss/c_clipboard/MainActivity.kt create mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 android/app/src/main/res/drawable/launch_background.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/values-night/styles.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/profile/AndroidManifest.xml create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/settings.gradle create mode 100644 assets/image/computer.png create mode 100644 assets/image/icon.png create mode 100644 assets/image/phone.png create mode 100644 assets/image/spot.png create mode 100644 assets/svg/computer.svg create mode 100644 assets/svg/phone.svg create mode 100644 assets/svg/spot.svg create mode 100644 ios/.gitignore create mode 100644 ios/Flutter/AppFrameworkInfo.plist create mode 100644 ios/Flutter/Debug.xcconfig create mode 100644 ios/Flutter/Release.xcconfig create mode 100644 ios/Runner.xcodeproj/project.pbxproj create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner/AppDelegate.swift create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 ios/Runner/Base.lproj/Main.storyboard create mode 100644 ios/Runner/Info.plist create mode 100644 ios/Runner/Runner-Bridging-Header.h create mode 100644 ios/RunnerTests/RunnerTests.swift create mode 100644 lib/CodeInputContainer.dart create mode 100644 lib/DeviceInfoContainer.dart create mode 100644 lib/example.dart create mode 100644 lib/generated/json/base/json_convert_content.dart create mode 100644 lib/generated/json/base/json_field.dart create mode 100644 lib/generated/json/clipboard_message_entity.g.dart create mode 100644 lib/generated/json/close_message_entity.g.dart create mode 100644 lib/generated/json/heart_package_message_entity.g.dart create mode 100644 lib/generated/json/no_pair_device_response_message_entity.g.dart create mode 100644 lib/generated/json/pair_code_response_message_entity.g.dart create mode 100644 lib/generated/json/pair_device_infos_response_message_entity.g.dart create mode 100644 lib/generated/json/remove_pair_request_message_entity.g.dart create mode 100644 lib/generated/json/remove_pair_response_message_entity.g.dart create mode 100644 lib/generated/json/server_ready_response_message_entity.g.dart create mode 100644 lib/generated/json/work_error_message_entity.g.dart create mode 100644 lib/main.dart create mode 100644 lib/message/Codec.dart create mode 100644 lib/message/DeviceChangeResponseMessage.dart create mode 100644 lib/message/DeviceInfo.dart create mode 100644 lib/message/Message.dart create mode 100644 lib/message/PairCreateMessage.dart create mode 100644 lib/message/PairDeviceInfosResponseMessage2.dart create mode 100644 lib/message/PairRequestMessage.dart create mode 100644 lib/message/clipboard_message_entity.dart create mode 100644 lib/message/close_message_entity.dart create mode 100644 lib/message/heart_package_message_entity.dart create mode 100644 lib/message/no_pair_device_response_message_entity.dart create mode 100644 lib/message/pair_code_response_message_entity.dart create mode 100644 lib/message/pair_device_infos_response_message_entity.dart create mode 100644 lib/message/remove_pair_request_message_entity.dart create mode 100644 lib/message/remove_pair_response_message_entity.dart create mode 100644 lib/message/server_ready_response_message_entity.dart create mode 100644 lib/message/test.dart create mode 100644 lib/message/work_error_message_entity.dart create mode 100644 lib/parent.dart create mode 100644 lib/test.dart create mode 100644 pubspec.lock create mode 100644 pubspec.yaml create mode 100644 test/widget_test.dart diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..29a3a50 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..31967fd --- /dev/null +++ b/.metadata @@ -0,0 +1,33 @@ +# 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: "46787ee49c1fd80ab603f0702733edab54653aef" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 46787ee49c1fd80ab603f0702733edab54653aef + base_revision: 46787ee49c1fd80ab603f0702733edab54653aef + - platform: android + create_revision: 46787ee49c1fd80ab603f0702733edab54653aef + base_revision: 46787ee49c1fd80ab603f0702733edab54653aef + - platform: ios + create_revision: 46787ee49c1fd80ab603f0702733edab54653aef + base_revision: 46787ee49c1fd80ab603f0702733edab54653aef + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md new file mode 100644 index 0000000..f284cb5 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# c_clipboard + +A Sync App + +在我的手机上基本一放后台就被杀。 +目前是每次打开放在前台都会检测是否被杀,若被杀重新连接,若被杀前已经配对,则尝试重新配对(用上一次的配对码)。 +所以推荐电脑创建配对码让手机加。 +每次打开前台都会读取剪切板并发送。 +如果想要从电脑同步到手机,请先配对好保持前台状态,电脑复制完在退出前台,不然你配对好划出去再电脑复制,此时有可能已经被杀了。 \ No newline at end of file diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..0d29021 --- /dev/null +++ b/analysis_options.yaml @@ -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 diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..ccee4e0 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "com.xbss.c_clipboard" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.xbss.c_clipboard" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies {} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7cfd244 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/xbss/c_clipboard/MainActivity.kt b/android/app/src/main/kotlin/com/xbss/c_clipboard/MainActivity.kt new file mode 100644 index 0000000..8e8725f --- /dev/null +++ b/android/app/src/main/kotlin/com/xbss/c_clipboard/MainActivity.kt @@ -0,0 +1,6 @@ +package com.xbss.c_clipboard + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..1d643ce192485c96abefa519a18ff7dda989537f GIT binary patch literal 939 zcmV;c162HpP)Px&Wl2OqRCr$PTwQY7Fc98#I6z7-KxRs2dWynH(mX;Bk#LB@BgsiZPm!6>nQ(#9 zyf=7T(HI;fd66aA^02&0+Mmy#KK&pGp`qXTY&l2(uZXCZg^&>4Z<5X8W%PN~P*?|U zvFKYjJ#pAc^H$pg@8J-)ms+U`!Dp7ZsP=-So)Cc&-fS7D5_th0|1H{x{*rP6@A8G@@w*;1?X_Jp^|yYUNh_xp;d~T zVSdhIHOd*CnPPp5({gm=0Ybc6k3MO2pr{vi0Kq@a&WkiRKjN*M*zpedHUY$^Y*#}7 zV(=1x1R%RERjeHygOvEWrR2A@X&0a|k@lNjIBVGsg7ToYRBUz%oQC;uDaB)10OEvS zSN^`wnkS0Jw$QnXhXdu2qyRt47O`F#6nudj3iXoNwO4?GuEaxuv$d<=dQl~Q0m}Ar zO4e^d^RzUs_PPjhu9~IzdZC*p2tWdmnO4FerppOH0+6LD7pe<`gh9d}Hw1)1Zumu^ zLD?}Ew^Zy}r|@TT%n_O>0LlkpmuB_are#CXq5#we4H5?BzS8cW*4%1dX%Lb+*-_sw zJ5s}WjG~KiK{i<~0JTAbnq&y)TNoq^;y6-XE(~e|gZ8Ia-M+T&z^9u0jLdKOc=y2H6D9s>6zi;%5fb;9R#m(2%NJXMHl0OY_ePcYJ&zf$q>%BFi050 zaij%HjhIft7B}*v=wg26L2gXRTCd0bcgKAMpaQM}5JNNpsEq)LNHc3OKk^#JN)#d; zCN)1+1t6J8yD>=^Bn%P;xgk&&gVc$wGGEyuP!LCKxGr~_A;=#(7Sygsp_*iHXdE;DyAn3)9W_M`d?N^MwG21qVE6z N002ovPDHLkV1nQFsipt` literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d573a6a80aaad62b9ef3316d3fa7da9dba71e99b GIT binary patch literal 671 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 JT4~}I|2L@{Uh4n= literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..21aaf028a73b4e96528f73591d68454c7744469b GIT binary patch literal 2837 zcmdUx`#aR@7Qnyr?TbP7eCZ@A42fjQc4 z@YZY$spza*zGanAYrRfwQ94_6C7l~P6Gcd@Sxd~7hAb{fU$U8nE}=eNuLJv_xcNJ{ zOZY&WFFK5ix{QIEl!m#xgKtuwzM`ob-*ccqb<&*ub_T1$rnv6F8ynXyN1EAW`s9VY zL1Ph!$=BkgH5-eE=dQKy$Eoq1*H_0UfA5cJG1V-k0^kMJ#)ai&KVE^v*Civ$0=5sK z>LQpdX^u|yJbTGTzC}kO%E)w7T)B+94(L@>x~_4B_F(P(Uo}AV%Ik!w@IgQy9&(~$ z5d|jG04`0JIX4~=TGf@Xrs!f_P^*XeN?kj zq=-ejx{s`n*RQorMr@wNgfP!$VLmO+mA^P+5Saj?dktFKU9UNe%nq*hJ;0b;Ay-Sa zJS>$QC0JYvunk*jSjJS-SX1k>t>^if3lD!DUCQJON`8F(O$lCPy9+w%4=q z6(5JEy1vXGnYx#Igyt1An(OiMYiz=b&t>w!0?C!4? z^X!#Hp?wdJj}&~i{dx0;0`N+jMBCzh>*F?_XX89iyTrF$b1weWVzb)^P?%yr@l#_qTd#H6PCZ&k9DJ{e z%@$9WknhTIddSs0Wjw_jl_!?#(b-^Q<))z<-gg?cT)4++Xz2Fd{L2@KPcvyRwB_zV z90_}kY-_-v3OjsgU&&Pi`)_3}wCkgGiPhs*nlyBD3!JT}*=9>#p~U0z<10J+Ll^to z-pZXm=zqgV?YgB>u2r(SsP-q+vj5iUl2YP?R$Zs$0MURMwO8Vt(0_&-FrbTcJ*Y53 z<#7Y7_A9S(Be`O*0Pi+KtFP1mN!Sk_f3UPrBFoD4?`TVd%!W<*Q9M3NsO6F$>nXaa zHg*94pk4c$HfCf1=)l0dY_21OP|nwPwZ1}A0QrB0H@G_f=K&f73b)B6t32m+6B_p+ zQDBrfH=Mz4Kj)Vf)BH1tCPX(+`EEf$<9aVAJvJefvdIuZqpSogDIL?t9L&U`vJkG-qdH-QTo^-<_bmuL6av8+w zQDB7>c+ll1Bh5!$tv&An3@JB{X+{4*QvJ3}jV7&M&lJ4nW7!%f^=p=vVDz-J%7Y>= z^>rv`552qW2RO{SuEh2vt!zi@VU%9s$aB(mOwzlwbo~SjLYbNG&L&|g!05n7G&b2x z{UA{LJp|ipQgtcb8sIfrMmvn)HliE}9l>a<`c*)0*C|s7Rz3)*X4T64sk#*OYwwMy zm(O7Y3c+0kf`h)TV~jwHTkUV*DArhlyYsda5M1J00StTkL2=u-vy}#_$drOCxl&We zd(%{-&id$uybI#K78_k8AozBSjKf!@$2)^%97cEl@v2z{>b3j>(Xuqrgie>6!^(dh z@Wh!yJo`-jN#;f#Kj3H~ONzUFXUrXa+keWWZFKsjybLM5OW(wW*Mb!yl?iQzx|ew# zNA_oM8BRii^-Vx;Ngwrm#4vK-=kypd-SU26X6TjIBt`I=uj>D}~}{=SWw0m{+l9?x;Zd9%9pwzzquh}4}D(rgzXxyijZI# zQyV&A8UckSph^57Rjhe0_Y+KmIo&Vx5F$-x4SN`*N`t*`0;#P;ZFQ8{hOz&`$l>fj z>a8+I;x74w)oXm!P7>c0*H;@J73|j7n+iJ>qp?-V8~}om6j>er&pP+t?})iEWln@M zoGgwKa|?0FfK_;AXhok=Z)4ET#hAoq%b4?w@Gxi>Dt^%vk88~?s!Ro5uscxnz+XWN zoVNckV~%CRQ`!P?l=!ukrw2fiM3IXAp5D-KPpJ7DppwLI$!n9Ak6OSq%Td#+zc&IbtQiT(@_m1c!D0Sfhv%>7R==aX81O#+e`#Q+9tamw1>Wh4LObxb60PI>5IG za~t}s*;N5>4?jzs`P5%zn=B_F2Dp{rxg*-|a?+4VvWu9dZrDG^*|)@z>wMX1iHXZ*r3*qJqnw~pb*Ty=H--BmD4GHbmEtUlaJ)a(@c6LM?hyJ63 z-rvNq(K0;rHwzEN-l^%ev7R$qX8lu2DEjrkfI%&mHgWll? + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..e83fb5d --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,30 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..598d13f --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..7cd7128 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,29 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } + + plugins { + id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.3.0" apply false +} + +include ":app" diff --git a/assets/image/computer.png b/assets/image/computer.png new file mode 100644 index 0000000000000000000000000000000000000000..f374c32802193e665d19c452106b0aa4d2ef96c8 GIT binary patch literal 244 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 literal 0 HcmV?d00001 diff --git a/assets/image/spot.png b/assets/image/spot.png new file mode 100644 index 0000000000000000000000000000000000000000..7da85525edbc7b9a0569f5a745e41cb6be0cd4e6 GIT binary patch literal 299 zcmV+`0o4A9P)Px#LQ@3;7qybuiD@L@ybL%VoMAEMWVmoy z*!OndhXi=6wXKx$!f+xQ`o6y+PYD58Yn7Dp@s154G{%^z^d2Jc-ghy^CHj1b=!j$i z5hQuW%`)JRQx+#7gbE=Xj4}6;Jd0llXbom3D5_T_5gR?vGuQrv^gxx#-up4e*rt%D zR7t;SH0KYKh9ufoCRBlG9(A=V^9c=Mc^O%m9ijjL002ovPDHLkV1hzudTjsz literal 0 HcmV?d00001 diff --git a/assets/svg/computer.svg b/assets/svg/computer.svg new file mode 100644 index 0000000..f480571 --- /dev/null +++ b/assets/svg/computer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svg/phone.svg b/assets/svg/phone.svg new file mode 100644 index 0000000..34a49b1 --- /dev/null +++ b/assets/svg/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/svg/spot.svg b/assets/svg/spot.svg new file mode 100644 index 0000000..06c081d --- /dev/null +++ b/assets/svg/spot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -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 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..7c56964 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..27b7c5b --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,614 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; +/* 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 = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807E294A63A400263BE5 /* Frameworks */, + 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 = 1430; + 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 */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.xbss.c_clipboard; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.xbss.c_clipboard.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.xbss.c_clipboard.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.xbss.c_clipboard.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; + 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; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + 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; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.xbss.c_clipboard; + 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.xbss.c_clipboard; + 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 */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..87131a0 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -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" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd8802852c663c48fbf10ece94cc19d2a08c1bb GIT binary patch literal 38317 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 L|0z7}{OkV!o+Z>^ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..752ffe313e3922203f6cb01b85a43183ce20a275 GIT binary patch literal 561 zcmV-10?z%3P)$U?P*VS~dv@3NEtC52sRscTFv-rv!Dj3o&d9{Xjx5P$>KFF^*Z1#V zX61zPq)*@a|L0mVQ@7FO2Z7x(V`v2T7qi>jGD z&_H3B0#;=cJJ#$ud!XEJF!5jKwlDp8WaSnneaFu;vjYEreD#qS16hqc?O9~C zOmP}W3BYL}BRdy6i>{+3F8Tl8KYs=$mn%dY$Sf)^!jm~`6E69`kFJ~mMxZaz2L5?+ z{ptHGRZ(2>xBzZ1bMkVq$Z4abv45Z5zWn>}(p9nyWEPbJd3h_c*ze2xR(+YC9#58m ze;!?Z0`xK`KFuT<2=p>1(95=j4EX!RWve-D{23IdH?G7ozwe%omjt{QgdN|g%Zsi-npq<-g#4iOg0doSzJ+; zC$7`&hmuj)2pQay>0jZ>14Mn)b%5g^F~Vt-v$8w7OBv!ACnt`KP4qr=26ZqAc7 zb?d)(&t4HS=l`$o&%do{&H4N2>O+DKJ$(QQffIdV0dN{dIEBDu@W#Bms80NFM*x1 zI-GWqV>1{<^Sh4;|fv0#F?I``V$6oF18e+)*u?k;VT!x~f1| zS0Mou2Y%nwzu@<^!-s+8oEWnB-xqhDv&id-gV<~aZodEIwDA@V1K zKo9^nkM1&nFuM4oE2n?oIlY|2Bcq!URC>__Fn<2FsjmWA1ON?x5z+FQeCGfF002ov JPDHLkV1m~OnN0uy literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ba65ae25db80619b7382b6e719306eb85e39ee7 GIT binary patch literal 1208 zcmV;p1V{UcP)V?>wvhv*BlEzV3M z*ab~C9D8HJaB~_0)E5}C!~`TBn#fE*g_vc)oKUHSUJrWy9%5tZwQ}t}*U9BR$&Pw&GSQjJ+n8@d*(*&4=FusX+{D05Pe=LKVnf#u*p&LmCkI97W*>9c3p!lmsz~y3q(=*xYEE>e#hBb{($g)qLeSu zBowT-u3H25-^Z{^r()Q+z2-<{KkR=oINj)SgvTCF;A48Dqako*O`km zt*6hWG7jLM|NGHHVb&j#(m1YQ)9!kg(Xsa@3j9vdiAC_keV&Neh2sa^Pxz66cDj(+ zv*3i)?#w%K)tRb&_&|Gn$IG@!X)6*8SCu9y_6^yhaS$b{OBI+W$_?9Vc5=5{+Lvl8 z5)7eiiHMzhI?xvOjsLaC(R@n*U0A#)8HZ?FaV^Z)SHRZv!l3q&wfe&1oypk1@FVOu z!qmk4A_2Cd3YaUl(6*vaIE0cH4Co>|!P_mry_smrWhxOA?Ed*I&)%AeuFG+IvNJ)jR2zyuhogZIUWaGobd8sYvf$k4X}XAtD&k$j{-q z>VRE633~*1KHK4GgzWBR>Auc%E-B@j4oZlzg z4`$zIQwQu@N&6Fv5?442NL`{3nsjRJnJ38Wl7Tr4T9;7 zIc`q}Y^RrMpC$^R1o@`}qQ3^o4q1PLYcGgxpmJAifP)fLJ-_pW6f;18g;<4*d?JFpIrH~0vT^eKx_WRA ztGbl~U(xa-9~<5D{(pJ@i7ZQ*MC8OdeezluS=jioS}GtR#l*!Y`E6rw>W`f>=CC`& zhI5D2t>Dd^z2)EgXD_hn`TzUp`|q3jD*wHI{tm09oF19QEXpP}e_z}=1LCu)n0Yg@ za|)sx#Kb2m0j7C`q`(F!>f16X>LV=r`RzF{==XxnP&RS;_u*yY_l-ThSS@Ab;O6>$ zY45IYtDEydeEx>r7n#KrFf8S8jBR3fjLl|bV3fe-yMG^FUHLLKB^JcyNtrYY7#$qw zYH-Hs-`5W>F#P@f8J9c|+{LQz-Lq?W^x(G?=-PNfnh615f?EwtWFLvP6b9G~Jv^AC zRCUO<85s4ffH}(`{#c@HG7$p zYB)ufQX3FuDX@J6%BRaoH5?eVg&=6kp2U6Ba4E*KBsqX7Ks1%)x+C=pIm!NQ%isBnLCXu zq`HI6)Gq+U|9#`w0idOzE(0UYECtqow?6lT2O&!`a`AIAFtaiWO}qVuLVFm$ZJpEr a;{X5wV)TaGay!5P0000KE~GC+;gkK|4 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 Xt64_;1^*{|FIvdO0S0Zf_e=i^lSkUf literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b02e86f79a10dfac7c83b8555767f956116f725 GIT binary patch literal 883 zcmV-(1C0EMP)RWve-D{23IdH?G7ozwe%omjt{QgdN|g%Zsi-npq<-g#4iOg0doSzJ+; zC$7`&hmuj)2pQay>0jZ>14Mn)b%5g^F~Vt-v$8w7OBv!ACnt`KP4qr=26ZqAc7 zb?d)(&t4HS=l`$o&%do{&H4N2>O+DKJ$(QQffIdV0dN{dIEBDu@W#Bms80NFM*x1 zI-GWqV>1{<^Sh4;|fv0#F?I``V$6oF18e+)*u?k;VT!x~f1| zS0Mou2Y%nwzu@<^!-s+8oEWnB-xqhDv&id-gV<~aZodEIwDA@V1K zKo9^nkM1&nFuM4oE2n?oIlY|2Bcq!URC>__Fn<2FsjmWA1ON?x5z+FQeCGfF002ov JPDHLkV1m~OnN0uy literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5f42e70a2df1e05213f6c05e861bc46f8c61c8cd GIT binary patch literal 1421 zcmV;81#7TdD!k3nrAb^k~;wiUKDZu>*)jK&zfeUHZOCb=`o_wHSs?*pfo zckkZ!`Qg30_j1Y8ObUb|!QW^X{I7C^D}|R1k%)Iz!u?+*!u=yg*G&zx(G{?GynL}Q z_&p(9r92%();NT~F^Ay4wHywfNQ6KA$*4N2VW>c8ajkYC&xE6SpZ=R~1797S*>kORY+twjPU4#D}`-Qqk)R zn`us8U$f2Ac;Vk%oYi*d`0J@q;4ON!RcBj)X1?Z0b4Bf8j*$IY1vQoNFKta*jf{57 zlBgTuD!20!7r=Qq=!D>rQj{%B`=MbDRDhE zlh8jjXN9}`yU@BXB_pFb4VM%J!oc=9nY{b3{ia-u__X|DpAV)Imv@bjA$b~CQfhNF z`rpKqo90*87Be3bT@Y!nv}djMdNdOV@=7-Mq0liHgT11Z_wj+~ACP}vE`hh=IQmW> zu{-a=fO&i~t=RwhIk^5+V9J$PjfCHihdRE@bnH=I@GP{vQ|XsEHv+?FA~N>DfcdIJ zXuk&2xG2m-4nvyT=t^xzAqfPyBKUC-{Ws zO&ha||Iq2{orJk`#;1e22sF9)CX#+ol#GlFuE%C3^oXM;X1=!4Qc-(CdY4Ih6E{vM z3jFUoITr_#kVMa+)DY_T^I=yh=d75!UQ5=0+BF*NSHt*Odt{_ z5D8U*(t~pIf$GO-#*~w~b8}H#m|NAdOsWDMM>~(%Ji;K&m~xgvff}u+m8=URVFHmb zfk>zd+?bz>iG*CG8B>l(#QR#8Nmby=w>@LhMl+_~ur7>*2}HsKB4GlNFo8&zKqOQJ zI(@xOFc;4B6|bCu@#N3*C;1jF%ECaq1v-dE9~|chnbo2kEUXJ7VFHoR7Pu^G)b%(b z=Jn-3t)VI~9_kp5la67UG4+OZVI)i-5+)D{6NrQfM8X6jp*I$gn4ya zKIgI)h=d75!UQ6rDsVkEGfPDAJDM@Gf)n%p9t%~0(h_!sx{O`Eur7>*2}HsKB4GlN zFo8&zKqO2c5+)FdqCio$+K<)K@WS4K=#OdzEr)}hiE#h8TAu$SiUO07kx9GYpXCVW zCJ)vIR9zo1y#o2JLs6i#e(6d$_?klqTud)Z$H;){H84GItundzBUX?13AMay)8n@^ zt=SG?+nWeToPuB7xvV=Z|MY>azO56kp#`&WcD9&YR4h8HluwttaBBM6H$?D% z09}8-fIm|Pw@-J^6=AA!*uiKS4W)#(dL|2*JXZbuH6IH}Y9wQ}W)o>X*v bN-5VrIiPEe`svPy00000NkvXXu0mjfmno}q literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ecc64b297c460cbff7da27326367a1a47c42055 GIT binary patch literal 1753 zcmaKtdpH|*7ssPb$>LHGEh5upZfynWY;6<`noc7som<_B%VO#lY2y+`Q=K4I>Qa@& zbeS5p(A0tzYv_!)HWV8vr53kD>ei-Mr+eS-kN0`rJlnMXV&+j695?boi6^7Ds*M;2)cT~lwAtgPp?QNV ztFC-{fn^da-cA|yqfw1kijE7$Z0=icrASE`Tn&VSO}rKPAkL<%h?#RTo-vl;V0pp5 zdU-LwZVh``O&j=l@VJd=$W=F26eetE_&w^9-oI2hwdx~kWlff(WTpOgmxqfP| z-;pXDU$hmFE~O66bAnU4(St^8ct2UUAfSBP z$|tQj^P}9Y+-uRTQYRULStJ2)y>Dyblg2ItBb&H63e#j-Ukkt@{P4UZeR^25I`i2S zz9+xCx`)A#Ly=eBSg4<_-vo{Ud)qxjE}Q+l&R$3@n0u`g^BWh_;flVbF3z9UZ1RJ( zQ1%MEnv`D`x_1(14T1ndX?eA`iyx}4m_#hiQyF-5ex)yd|CF@-Cy3WAS2__?2)g*= zcE*Q03X<}B-60&FV%8pYs!yC1#eDeM=;|iApw=IU(m=f4UnYwqfEkS)Lw}4r?pNOV zRg?`b#f-d4Q0W>%K9&1s=KAyd4^7l?23fT68y_^ou-diW>+J{jbQb!}-#aRsnczLm z-Ug0>6Pc5Co|Gx6hg#PYhs~&OJ!4mDJzx7*bvCwPc5n}7P;u}{U11l^s1-*W*wN9L zdn$799};Z1c;2d8HeJ%HAD)KxMJ&M#u2_a+li)-^RcM%+4io+kw)=ZjA~<5&{T0`k zj+u1bCx|amsChr`MhMFxbWa!ix47R+1-ML3CAQTHUO#>;-{A6f-g4>c)Bp7Q zFFrhLx|u`h%2vlo$c?!J0S62bR!zJZPzb@ql!$YqTGz5h?*Zg9*wVX%+2#EyN+uQUdk)gDSb zqT5u6az@p?_;|aA8cj}Hy6t092Ev%=+y29+po0N~*qTexDS@Dm35?wuJ3c?d`IY*D zOE6;~^oRc^@U6OZsXZy}d=gxSMfq&7SHp(pV7n66^w4=_sn@kk9Tm$Yi?XQq-%ZBb z5ithR@Gqr5Ew`@PP|jf$Url_Sn6KTs*%(+-BuBeF0tvB81)cFnlD>(J&1x2n*pf4ephHgqVC%J*N}XHt0>+ Z*{gyOnPtw>9ClY00C&b6%X1E;{{?_CT?GID literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..ff2415ee91ccf03ac2cd1a433c14bfe85542c588 GIT binary patch literal 1023 zcmV*U_=8+#`Gxqsmnwe3O%EYviNSw>Ttw_wR8CN4fL zm>8>?xdvVI9RMAOI`;Y`Tq|n`T@ug0@BRv7Qr2V z-#&fzW9#I_)Up#9P|YL2u8lrfnswrcE%5q-rS8OgX{c zbH7P5?f;u^TPK$QV{#!rRTv)O3aOq%i63(H7>=r42fw2{SGjXYx6jl3#|v6{m!y6V@t?OXpnzw?g6J2#X?O4W@Reg7H$ zU-&vFKN?vKm}GmIB~?9`gr)gN@(2t79dZqs&m^hxf*8ku)$$5!2-I%7{hxv139ty( zBUT>}{6M#t-7fkAvm{}SR4sl{0izHjxWu9lAjKn~XeByU$OP}m)kw5QfThN45GL0m zS_2v;E$V=8Yg*zNIe8QR+&=vSpSnTsk-txF{31pjSsnp~5Iax$^aU(x=AdGgi5xR1 z0AGIWn_mH}XqO@jlI0P0r-V3QV=&^+<7=mY%?+|MC^-PwFxBI9N}TiS#Jcss*n-z9 z`zc-ae&zuaYVr`LT8KN@|!x z2^dXUgAGup)KWDw1X6s|Fbf+17S%@yO%73~9w}Thjf%~94DhKxT98m5Wi)9aga6+? zJz(VI6QG7!IKV$b3aHbJFENRvhB=gg(WEulz^F$C8^GxiU?nGyE(UDuz4`a<=~vo1 zi9CSek-u-BTwxZLQQ#|F`T$+-`_@Srz?SYzy10x)fZ>rZGc!}TLaKX!oh6JO-@k94 zXg#Y-Ho%OLCpTVxo)8<0PZMY%0Ep%at)2p`49OaYA{Q{rXo8wTzd*?xS)8oQ{&U}g tC2aaGK0rg=80kKT$oSzKFo~n*RRDY#F9ma|V3+^^002ovPDHLkV1l?Y)209b literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..050551ea425967d94357b51f36fd42a12c8c9267 GIT binary patch literal 1522 zcmai!c{tPw7{?uxXG}|C+~?#Plu0W&GMS%iP;!pe8PQnE405a~8GdvuGvit`u9mhC zQo|+G=f)L~ z9l1RNp_tGxT?rNX#YC}juYHH}#XKXsF`?)^+tSGG`Zwz?J5gtUa z*8s0dwfeMYgda^xE?yUKQ6UwehKu1sOYM~jCJj7O@B#4iXwnIG+H0xvyVAj==;AXb zPMHqJi=~9L!_OK0g}<&_UhA@h_WoF*?FH;_c_|7K?0@Na=3g(qdKib(!e<5H1h+s? zJ;w8zh!0Qn?ewxCq2eKLe55iK5v&>gQAbDOIRv^RYR^%$9$U|+fWdQObuT1ao(NLd z80v$*p*(21`H>kgljI=IYsa_ z@mG5;2ZTv@2aaEhH#WC&ecIl8bmQuMK-Tmo>eB%BJkD=bAhx^Zs+`bHWM`8~?P&iL5LRMpz2 zo9O|XfH=N)#l4LrU#z=dUZYL3cDe`!*(SUVWPN&O>EV7{G~AB0=HagI+inZcFaT|; zk=9}U!TN~Ot=962^a1qm#K1}CzsGfo8Nh7kC1kz3lYwNak_pnZD%th|!FBV+g!7vF z-g%A9$=;MzuDTvJ!Q=KQ`Z4*CE$^Ufb$k!KxoG}9URBHdHua*7jnGu*l?%fO<#BRg zmRHKAwwF=wy%OIpf>Q04G{+iX<_>6BO^{h4sMoluvYg}}BoqG!L%=X{tz3putbAva zzp5Mzf*JiXCW=n0ss~WW1RCKp7Mdo}ngXgNeMLBp=BZPZefIr)6uQqQ>$AOR8jV@j zIR38sCI9N0f*}A^{O?FZ;ELXk7+yG~d@Hnlu_8WpNL2yxo--VBW6~N9*2P1LLby=G zB`oyVH@MJ)8|;uSSmwLM{?ED?_1WIV)j!3yBW#3G7_!S@w1?2&t?OZ)=HkJP_9N|?uwsMM6aD#k`RIY^T4AQEvi+A!Mk$b2AiX4;BpWA>n zhMCwi%;jq&2OX!N1S0&9cIJWH^fC+M>VaHSx)av+@=Ya$=asRzKAKd`w2k)mki*An zda4i3G;HW@=_0!uU9;auTV!cKu*R1COq5b0iNGI|Z~@IY{@ns!bcH#u~_KWP}*0+(`l lKhv^6PSr#zQ+6|VRlQ_ymNY8)hwS}w0Xu6)t194p;y;Bk#=Zam literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..9c3e8a9c25efda77c9eafa9796f5f251ee0ed255 GIT binary patch literal 1140 zcmV-)1dIELP)K6s6VnGmDY%ma?%S4(@L$)sdKw~`dzZPwlnW`&skpgfpgD2FTdya^?vvKp4(1C zNQi3WxZ(P&J^OS^ts6;#Or(8n&4Ic*l|9v0%1~!}my~m}(MV-@m?e9W!FHh>#3hI8 zR0&C`ahbc8=`z-D^Pbv}MSpAYN;N+lNknSXmM<{cN*+Q{&(#iM=MOKuUE@8UyOQ=a zwMyXw8%adQuRC~>_$3fg0jJ}1&{_3BW6qeRUz%GCl_NmtETgsfjQ8x8?Na!_reBd- zOZHrnAd+J-sxp}uhsz-FvfrM6lqvT*tDd4z?dW`_nY%jSA83R_Z^$`uBR0#34mhih z`Rxaa2kIFmQk{}M3YWk>NYiij$4s0+5-1Mp#oATrEZIffrqWWluYG^&87*>@>6cTT z_WYTV?XY6jFzJA=EBYnYL&1icd(?YZ3u#P@H`q$9fP-qj;}L;eaJ8(F^{}u#0Xs=5 zW1@j32w@`Gz&+FuS!W*8V}cRw2<*Y50@VR@B3J?JQ;xj zu73I;%@xI9iTtYw776KKRV?FT1;X4f)`nnb;r@6jc2XQ5f_?-aBayGYXP~}AHe5UM zrsnePD_SI^1-)jy9=8kjk}cv~6o=ZBY6f3c#bxc?)OEAyCc90PNXUJYna}R~rMqE4 zsuyEREU=TxgKgeLuBaNa3y%;Kk#a#1DHjxxLV?|n7V?z=r_C^wr^zq;yP!U>ij2=W zzEx*gU53+Um`;0sMy$D530Jv*Rb;Qz@f^18`*GR~Lv?sQ#5xwM$e`2lmN{_R#DNm7 zazPO(6kX=dx!M%VW})M{A6+{`y?1@V=?fdIA~h-LGlp5R4+|X!Nxp2zi2PTh}5?Q46cN=RA=r%`W7_Ca#KcKxry8Lqz4oolseE4FLR8RNLx>9*#t zeI@ksRT4c9LHCuc{_$>D$UDmIcc&jFEO++HazI^7QIYNp_rGNSrbl|w_+!>q*}Up zcWoMzmoAi-SS*xqL~>qQSH>8}x#ym{=bn4| zn_7dka`o|V+N!$iONU0mZd^q+xo9I&lR8=Xv@5H<>aDR4BPOg^$bWD&VLjmJ1ADM5 z%iyC^#081j=|7TBOyT$_|#}myD1KqwMBb8-ngo)qQ}m&zlRo_OG%N>?-61lDY zGbg+a+aWZ~g{YU*RB{!2wqY96I5Tgr%rC1xS{?{}o`VSGIuDn)&1Bd`_niaLPSD!Z zdm%mY~h*QC@_=Jc9eI46dRGSd$N1) z+54^B9_!1uHMQ8q$g;49t6$S;zQT_fmAF0OTo3#ajQ_&7o(I^o3M>(4Wle34ywr`F zVr|o)2OhS5L-yatbA$J5J8Yqef>y56E+|DAu!#SM-hlfI(v34{?Q%M{@M#`DL)APC z$+uWtP!qwL*Vo4)_U;=~gxNJDUfUOt34dq!uhiavcg`~_dd%a zeK_{gpzlBX{}}&0;9tUQLtU+Qkv1fK?|v^YqTNJhTkkeu1)iM?N+mp7U${pOUfp94 z5D8ZYuD&Gd;q^>dQ=Dr2YFxB(h*S>M=-Vy6GB{hjwzzybNUO|53^UDKY2j64n%aA6 zic@$;Zt=X3=TnQmx3Qh8f1dqT)P!o4R~xc?7~!%gX@$TuRYUq@IjPT`%VkupriCfJ zt{CgLzhc+;6Z4T&cN*KTL$OBV=j+8f{R49eL))(zjVco*c?Xsq823!U>zd~cXGplv z*If6If#!v+2~U{OrZoyGg*LayF6O+(1Pi+Fo+>fMR@-(Xu2>kux3INRN58yv*j9OQ l+!9GCE%-6Rjvi?Fim@KYcMM4K6L0<>0Eyt?RE;O6`~fiF9HsyO literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ecc64b297c460cbff7da27326367a1a47c42055 GIT binary patch literal 1753 zcmaKtdpH|*7ssPb$>LHGEh5upZfynWY;6<`noc7som<_B%VO#lY2y+`Q=K4I>Qa@& zbeS5p(A0tzYv_!)HWV8vr53kD>ei-Mr+eS-kN0`rJlnMXV&+j695?boi6^7Ds*M;2)cT~lwAtgPp?QNV ztFC-{fn^da-cA|yqfw1kijE7$Z0=icrASE`Tn&VSO}rKPAkL<%h?#RTo-vl;V0pp5 zdU-LwZVh``O&j=l@VJd=$W=F26eetE_&w^9-oI2hwdx~kWlff(WTpOgmxqfP| z-;pXDU$hmFE~O66bAnU4(St^8ct2UUAfSBP z$|tQj^P}9Y+-uRTQYRULStJ2)y>Dyblg2ItBb&H63e#j-Ukkt@{P4UZeR^25I`i2S zz9+xCx`)A#Ly=eBSg4<_-vo{Ud)qxjE}Q+l&R$3@n0u`g^BWh_;flVbF3z9UZ1RJ( zQ1%MEnv`D`x_1(14T1ndX?eA`iyx}4m_#hiQyF-5ex)yd|CF@-Cy3WAS2__?2)g*= zcE*Q03X<}B-60&FV%8pYs!yC1#eDeM=;|iApw=IU(m=f4UnYwqfEkS)Lw}4r?pNOV zRg?`b#f-d4Q0W>%K9&1s=KAyd4^7l?23fT68y_^ou-diW>+J{jbQb!}-#aRsnczLm z-Ug0>6Pc5Co|Gx6hg#PYhs~&OJ!4mDJzx7*bvCwPc5n}7P;u}{U11l^s1-*W*wN9L zdn$799};Z1c;2d8HeJ%HAD)KxMJ&M#u2_a+li)-^RcM%+4io+kw)=ZjA~<5&{T0`k zj+u1bCx|amsChr`MhMFxbWa!ix47R+1-ML3CAQTHUO#>;-{A6f-g4>c)Bp7Q zFFrhLx|u`h%2vlo$c?!J0S62bR!zJZPzb@ql!$YqTGz5h?*Zg9*wVX%+2#EyN+uQUdk)gDSb zqT5u6az@p?_;|aA8cj}Hy6t092Ev%=+y29+po0N~*qTexDS@Dm35?wuJ3c?d`IY*D zOE6;~^oRc^@U6OZsXZy}d=gxSMfq&7SHp(pV7n66^w4=_sn@kk9Tm$Yi?XQq-%ZBb z5ithR@Gqr5Ew`@PP|jf$Url_Sn6KTs*%(+-BuBeF0tvB81)cFnlD>(J&1x2n*pf4ephHgqVC%J*N}XHt0>+ Z*{gyOnPtw>9ClY00C&b6%X1E;{{?_CT?GID literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a3e5603ec2c20fdad70991613ade577ed8093206 GIT binary patch literal 2104 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 Dj(K`n literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d8cf9d105f7e883eeddab352d3d589a4bbc534e5 GIT binary patch literal 1936 zcmaJ?X*3&X8x>Kpm#U=|M5{=(V>*=29uWkswMA`3Cn#bnv3!aYwbYW5sil}A+6X$f zF{8vzl%|U%waiE;k%}cuTFVI0(V0KrneR-0ywCgNp7%cQz4x5w$#QYBla@FsAtWRu zZI48_9p3q$kC^CTU9w$h6A}V>+9Ry4{1?DwT1Lo+C=c;=x~AR0&_Z$Rjwq?vWyPX2 zrwcymgwjaWY%%xM(ft|9nFv(2^*y3|gF^_c?rG$Id{R=rJv(j9#FMggpHPpz=t_EX zA0lkJz02F}N)YTJpZB$!_7HlE=ltHpBBYxBc+?Z&h-ff8(B|?BF|Aro z-ZmELbCy8L_u#D7clH0~P=70dz7du28YW^8OYXd+`>=5ReZx@EN&68?aC>Jy^Mz*Q zCMF^k#W-W%HG7Q5QXd;>Dvq5PVPN=8W9vYjCpGZ z!c=s+=prLX!%yF~QbGD%TXY>C3>dhs2?=sZQ%PrGkCnX}9nSw3XUvREL z37>Yh>T!&~DZn6BPw8ABD#7?6jwt<31;i###L`s@Dki|IxA5gOZ&3s<*B!yC?{0Kl z`{0XeY>Msnm=4{;VxkpB$G*bou%cAGGY6f>F%>i?Hq9n}ywwF_Z(8KEbL zkfy822t-2!Gd3CiL_3aYoXY*}Z`5~V)XRZ~$t)!)+f~>^@X6!LZ@+Kl_3uia&b+a_ z(UKy5Z_=XGnZ?m{MDBnqgS6@8vpTPJG|=jqEd84uWni4@#hv4_0vQ}*!AD_!-iTs_ zuSl$XV@E5wuc>v%Ovf@le*9Yk6~Q22uCXX&PLg6wpWjDt4{A7Ss`B7>{&7Rbnyt4D z1w=O!L=g-xsjtp_UC7HTTAyQO;%V~QAFgNn3$KWY!d_$U`;dUS}MF#t?BM?U)zO4>K=iG$b^=3Z;!)?>GO zL5tlo=*4lyQ3o0pUhC4`rZrlC#ItER4q%JKuG{SDy)a+B7LW;KHbEs7#B!6u=Y1tO z6&o@V&zH0c0Al8@D)2UyYznG$^@Wf1mxkdwFrLlj9xbCZP~%I-_KloHHVKg;jWkR` zKd4)Kr3E@bvu~4r)#}f8zb?r(^|K8ChBRhZPJ4E=6#TG)i2#_oy98}M{{53TG?qPEEaQY`-0)4v&W z)=xMtA1$jaC(F6}+2$|wKBRE2QyN1tSuSui zH~3gMWoXRVR^$r#ZSJ}TQX@M$Jz2;k{U0Q`;z)7VF>_JqTV3W2j?w22=Q<}IuNJix z5#j%x`j<2h-b)r;cr0UvdD7it(EW|PJa)9=OuJTu_ zY6FmOv>>CvFG%}m5X<&30`-ZiV@_@4`>XIP;ptmk|6Cw{#2vO7@QJ>*9g4v`?}|3g zI4{9TEdH1ptTqL6ny3hbdBscAcud#Gke8Is2ciTgWz%w&(3LA|=^QrnT3ptdqLxS+y=q6*|p z#lS%9kc*Uv@#3;y)MPjhj~Y%Fy0u!yU3{1UM$xOq!cU}_=hu{qAS}aHt~Bh!9J0Fl z)LbrGEdNGSNG(Q*7()2GRt}sv{0GkmT6L5EB1W1P-Pqav^jZM0P9gHUJYWCe@w!l( z9WT+r!@-^Bza$<3Yj|{N;kj3Xf%U4Y&jwNySU;s6|44fj&>kE7AjGbC{f^4zOE~U2 y&z`uzT}pj3EFo}b>N04OaUnHL{ya+BCxD*CYG!SmdjH|36|%Q+LNvewQvU?d?t#nz literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..1faf557d6791678ca38d026ba2b1c22f8d2e62d0 GIT binary patch literal 1416 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 Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -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. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..9a2275c --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + CClipboard + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + c_clipboard + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -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. + } + +} diff --git a/lib/CodeInputContainer.dart b/lib/CodeInputContainer.dart new file mode 100644 index 0000000..88358d8 --- /dev/null +++ b/lib/CodeInputContainer.dart @@ -0,0 +1,265 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +GlobalKey<_CodeInputContainerState> globalKey = GlobalKey(); +/// 验证码输入框 +class CodeInputContainer extends StatefulWidget { + final int count; + // final String phone; + final Function(String code) onResult; + /// 重新发起获取验证码 + /// [return] 是否发起"获取验证码"操作成功 + final Future Function() onRequest; + + const CodeInputContainer({ + super.key, + required this.count, + // required this.phone, + required this.onResult, + required this.onRequest, + }); + + @override + State createState() => _CodeInputContainerState(); +} + +class _CodeInputContainerState extends State with WidgetsBindingObserver { + late final ValueNotifier code = ValueNotifier(''); + late FocusNode inputFocus = FocusNode(); + + bool canRequestPairCode = true; + // Timer? timer; + final int seconds = 60; + late final ValueNotifier timeCount = ValueNotifier(seconds); + DateTime? pausedTime; + + void setPairSuccess(){ + setState(() { + canRequestPairCode = false; + }); + } + void setPairCode(rcode){ + setState(() { + print("进来设置配对码"); + canRequestPairCode = false; + code.value = rcode; + }); + } + String getPairCode(){ + return code.value; + } + void removeSelf(){ + setState(() { + canRequestPairCode = true; + code.value = ''; + }); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + WidgetsBinding.instance.addPostFrameCallback((_) { + inputFocus.requestFocus(); + // startTimer(); + }); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + /// 适配页面切换、熄屏时倒计时混乱问题 + if (state == AppLifecycleState.resumed) { + if (pausedTime != null) { + int seconds = DateTime.now().difference(pausedTime!).inSeconds; + pausedTime = null; + timeCount.value = max(0, timeCount.value - seconds); + // startTimer(); + } + } else if (state == AppLifecycleState.paused) { + // timer?.cancel(); + pausedTime = DateTime.now(); + } + } + + @override + void dispose() { + super.dispose(); + WidgetsBinding.instance.removeObserver(this); + // timer?.cancel(); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Transform.translate( + offset: const Offset(40.0,0.0), + child: const Text( + '配对码', + style: TextStyle( + color: Colors.black, + fontSize: 24, + fontWeight: FontWeight.w600, + ), + ), + ), + // const Text( + // '输入配对码', + // style: TextStyle( + // color: Colors.black, + // fontSize: 24, + // fontWeight: FontWeight.w600, + // ), + // ), + // const SizedBox(height: 8), + // Text( + // '验证码已发送至 ${handlePhone(widget.phone)}', + // style: const TextStyle(color: Colors.grey, fontSize: 13), + // ), + const SizedBox(height: 20), + buildCodeInput(), + GestureDetector( + onTap: () { + /// 点击时弹出输入键盘 + SystemChannels.textInput.invokeMethod('TextInput.show'); + inputFocus.requestFocus(); + }, + child: buildCodeView(), + ), + const SizedBox(height: 15), + // if (!restart) + // ValueListenableBuilder( + // valueListenable: timeCount, + // builder: (context, value, child) { + // return Text( + // '$value 秒后可重新获取', + // style: const TextStyle(color: Colors.grey, fontSize: 13), + // ); + // }, + // ), + // GestureDetector( + // onTap: () async { + // if(canRequestPairCode){ + // requestPairCode(); + // } + // // if (await widget.onRestart.call()) { + // // setState(() { + // // canRequestPairCode = false; + // // }); + // // requestPairCode(); + // // // startTimer(); + // // } + // }, + // child: const Text( + // '没有配对码?点击创建.', + // style: TextStyle(color: Colors.red, fontSize: 13), + // ), + // ), + Row( + mainAxisAlignment: MainAxisAlignment.center, // 水平居中 + children: [ + GestureDetector( + onTap: () async { + if(canRequestPairCode){ + widget.onRequest.call(); + // requestPairCode(); + } + }, + child: buildPairButton(), + ), + ], + ), + ], + ); + } + + Widget buildPairButton(){ + if(canRequestPairCode){ + return const Text( + '没有配对码?点击创建.', + style: TextStyle(color: Colors.red, fontSize: 15), + ); + }else{ + return const Text( + '配对成功.', + style: TextStyle(color: Colors.green, fontSize: 15), + ); + } + } + + + Widget buildCodeInput() { + return SizedBox( + height: 0, + width: 0, + child: TextField( + enabled: canRequestPairCode, + controller: TextEditingController(text: code.value), + focusNode: inputFocus, + maxLength: widget.count, + keyboardType: TextInputType.number, + // 禁止长按复制 + enableInteractiveSelection: false, + decoration: const InputDecoration( + counterText: '', + border: OutlineInputBorder(borderSide: BorderSide.none), + ), + inputFormatters: [ + // 只允许输入数字 + FilteringTextInputFormatter(RegExp("^[0-9]*\$"), allow: true) + ], + onChanged: (v) async { + code.value = v; + if (v.length == widget.count) widget.onResult.call(v); + }, + ), + ); + } + + Widget buildCodeView() { + return ValueListenableBuilder( + valueListenable: code, + builder: (context, value, child) { + return GridView.count( + padding: EdgeInsets.zero, + // padding: const EdgeInsets.only(left: 25.0,right: 25.0), + crossAxisCount: widget.count, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + crossAxisSpacing: 8, + childAspectRatio: 0.95, + children: List.generate(widget.count, (int i) => i).map((index) { + return Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: Colors.grey.shade200, + border: ((index < widget.count && index == value.length) || + (inputFocus.hasFocus && value.isEmpty && index == 0)) + ? Border.all(width: 1, color: Colors.red) + : null, + borderRadius: BorderRadius.circular(8), + ), + child: (value.length > index) + ? Text( + value[index], + style: const TextStyle( + color: Colors.black, + fontSize: 24, + fontWeight: FontWeight.w500, + ), + ) + : null, + ); + }).toList(), + ); + }, + ); + } +} + diff --git a/lib/DeviceInfoContainer.dart b/lib/DeviceInfoContainer.dart new file mode 100644 index 0000000..9b677a7 --- /dev/null +++ b/lib/DeviceInfoContainer.dart @@ -0,0 +1,131 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:c_clipboard/example.dart'; +import 'package:c_clipboard/main.dart'; +import 'package:c_clipboard/message/DeviceInfo.dart'; + +class DeviceInfoContainer extends StatefulWidget{ + final bool self; + final DeviceInfo deviceInfo; + final Function(String addr) remove; + const DeviceInfoContainer({super.key,required this.self,required this.deviceInfo,required this.remove}); + @override + State createState()=>_DeviceInfoContainerState(); +} +class _DeviceInfoContainerState extends State with SingleTickerProviderStateMixin{ + bool showButton = false; + + late final AnimationController _controller = AnimationController( + duration: const Duration(milliseconds: 100), vsync: this, + ); + late final Animation _offsetAnimation = Tween( + begin: Offset.zero, + end: const Offset(-0.1, 0), + ).animate(CurvedAnimation( + parent: _controller, + curve: Curves.linear, + )); + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + void toggleButtonVisibility() { + setState(() { + var status = _controller.status; + if(status==AnimationStatus.dismissed){ + _controller.forward(from: 0); + }else if(status==AnimationStatus.completed){ + _controller.reverse(); + } + showButton = !showButton; + }); + } + void rowComplete() { + var status = _controller.status; + if(status==AnimationStatus.completed){ + setState(() { + _controller.reverse(); + showButton = !showButton; + }); + } + } + + + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + rowComplete(); + }, + child:SlideTransition( + position: _offsetAnimation, + child: Row( + children: [ + const SizedBox(width: 50), + if (widget.deviceInfo.deviceType == "Phone") + SvgPicture.asset('assets/svg/phone.svg', width: 40, height: 40,) + else + SvgPicture.asset('assets/svg/computer.svg', width: 40, height: 40,), + const SizedBox(width: 25,), + if (widget.self) + SizedBox( + width: 110, + child: Text( + widget.deviceInfo.deviceName, + style: const TextStyle(color: Colors.blue,), + ), + ) + else + SizedBox(width: 110, child: Text(widget.deviceInfo.deviceName),), + const SizedBox(width: 20), + GestureDetector( + onTap: () { + toggleButtonVisibility(); + }, + child:Align( + alignment: Alignment.center, + child: SvgPicture.asset('assets/svg/spot.svg', width: 20, height: 20,), + ), + ), + AnimatedOpacity( + duration: Duration(milliseconds: 200), + opacity: showButton ? 1 : 0, // 控制按钮的显示或隐藏 + child: Visibility( + visible: showButton, // 控制按钮的显示或隐藏 + child: Transform.translate( + offset: const Offset(-5.0, 0.0), + child: SizedBox( + width: 35, + height: 35, + child: TextButton( + style: ButtonStyle( + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), // 设置圆角大小 + ), + ), + backgroundColor: MaterialStateProperty.all(Colors.red), // 设置红色背景 + foregroundColor: MaterialStateProperty.all(Colors.white), // 设置白色字体 + padding: MaterialStateProperty.all(EdgeInsets.zero), // 移除内边距 + ), + onPressed:(){ + showToast("info", "请求移除${widget.deviceInfo.deviceName}"); + widget.remove.call(widget.deviceInfo.socketAddr); + }, + child: const Text("解除") + ), + ), + ) + ), + ), + ], + ), + )); + } +} + + diff --git a/lib/example.dart b/lib/example.dart new file mode 100644 index 0000000..cdd6f62 --- /dev/null +++ b/lib/example.dart @@ -0,0 +1,125 @@ +import 'package:flutter/material.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + // This is the theme of your application. + // + // TRY THIS: Try running your application with "flutter run". You'll see + // the application has a purple toolbar. Then, without quitting the app, + // try changing the seedColor in the colorScheme below to Colors.green + // and then invoke "hot reload" (save your changes or press the "hot + // reload" button in a Flutter-supported IDE, or press "r" if you used + // the command line to start the app). + // + // Notice that the counter didn't reset back to zero; the application + // state is not lost during the reload. To reset the state, use hot + // restart instead. + // + // This works for code too, not just values: Most code changes can be + // tested with just a hot reload. + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + // This widget is the home page of your application. It is stateful, meaning + // that it has a State object (defined below) that contains fields that affect + // how it looks. + + // This class is the configuration for the state. It holds the values (in this + // case the title) provided by the parent (in this case the App widget) and + // used by the build method of the State. Fields in a Widget subclass are + // always marked "final". + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { + setState(() { + // This call to setState tells the Flutter framework that something has + // changed in this State, which causes it to rerun the build method below + // so that the display can reflect the updated values. If we changed + // _counter without calling setState(), then the build method would not be + // called again, and so nothing would appear to happen. + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + appBar: AppBar( + // TRY THIS: Try changing the color here to a specific color (to + // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar + // change color while the other colors stay the same. + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), + ), + body: Center( + // Center is a layout widget. It takes a single child and positions it + // in the middle of the parent. + child: Column( + // Column is also a layout widget. It takes a list of children and + // arranges them vertically. By default, it sizes itself to fit its + // children horizontally, and tries to be as tall as its parent. + // + // Column has various properties to control how it sizes itself and + // how it positions its children. Here we use mainAxisAlignment to + // center the children vertically; the main axis here is the vertical + // axis because Columns are vertical (the cross axis would be + // horizontal). + // + // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" + // action in the IDE, or press "p" in the console), to see the + // wireframe for each widget. + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + '你 受不了了have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} diff --git a/lib/generated/json/base/json_convert_content.dart b/lib/generated/json/base/json_convert_content.dart new file mode 100644 index 0000000..c7a497b --- /dev/null +++ b/lib/generated/json/base/json_convert_content.dart @@ -0,0 +1,240 @@ +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: camel_case_types +// ignore_for_file: prefer_single_quotes + +// This file is automatically generated. DO NOT EDIT, all your changes would be lost. +import 'package:flutter/material.dart' show debugPrint; +import 'package:c_clipboard/message/clipboard_message_entity.dart'; +import 'package:c_clipboard/message/close_message_entity.dart'; +import 'package:c_clipboard/message/heart_package_message_entity.dart'; +import 'package:c_clipboard/message/no_pair_device_response_message_entity.dart'; +import 'package:c_clipboard/message/pair_code_response_message_entity.dart'; +import 'package:c_clipboard/message/pair_device_infos_response_message_entity.dart'; +import 'package:c_clipboard/message/remove_pair_request_message_entity.dart'; +import 'package:c_clipboard/message/remove_pair_response_message_entity.dart'; +import 'package:c_clipboard/message/server_ready_response_message_entity.dart'; +import 'package:c_clipboard/message/work_error_message_entity.dart'; + +JsonConvert jsonConvert = JsonConvert(); + +typedef JsonConvertFunction = T Function(Map json); +typedef EnumConvertFunction = T Function(String value); +typedef ConvertExceptionHandler = void Function(Object error, StackTrace stackTrace); +extension MapSafeExt on Map { + T? getOrNull(K? key) { + if (!containsKey(key) || key == null) { + return null; + } else { + return this[key] as T?; + } + } +} + +class JsonConvert { + static ConvertExceptionHandler? onError; + JsonConvertClassCollection convertFuncMap = JsonConvertClassCollection(); + + /// When you are in the development, to generate a new model class, hot-reload doesn't find new generation model class, you can build on MaterialApp method called jsonConvert. ReassembleConvertFuncMap (); This method only works in a development environment + /// https://flutter.cn/docs/development/tools/hot-reload + /// class MyApp extends StatelessWidget { + /// const MyApp({Key? key}) + /// : super(key: key); + /// + /// @override + /// Widget build(BuildContext context) { + /// jsonConvert.reassembleConvertFuncMap(); + /// return MaterialApp(); + /// } + /// } + void reassembleConvertFuncMap() { + bool isReleaseMode = const bool.fromEnvironment('dart.vm.product'); + if (!isReleaseMode) { + convertFuncMap = JsonConvertClassCollection(); + } + } + + T? convert(dynamic value, {EnumConvertFunction? enumConvert}) { + if (value == null) { + return null; + } + if (value is T) { + return value; + } + try { + return _asT(value, enumConvert: enumConvert); + } catch (e, stackTrace) { + debugPrint('asT<$T> $e $stackTrace'); + if (onError != null) { + onError!(e, stackTrace); + } + return null; + } + } + + List? convertList(List? value, + {EnumConvertFunction? enumConvert}) { + if (value == null) { + return null; + } + try { + return value.map((dynamic e) => _asT(e, enumConvert: enumConvert)) + .toList(); + } catch (e, stackTrace) { + debugPrint('asT<$T> $e $stackTrace'); + if (onError != null) { + onError!(e, stackTrace); + } + return []; + } + } + + List? convertListNotNull(dynamic value, + {EnumConvertFunction? enumConvert}) { + if (value == null) { + return null; + } + try { + return (value as List).map((dynamic e) => + _asT(e, enumConvert: enumConvert)!).toList(); + } catch (e, stackTrace) { + debugPrint('asT<$T> $e $stackTrace'); + if (onError != null) { + onError!(e, stackTrace); + } + return []; + } + } + + T? _asT(dynamic value, + {EnumConvertFunction? enumConvert}) { + final String type = T.toString(); + final String valueS = value.toString(); + if (enumConvert != null) { + return enumConvert(valueS) as T; + } else if (type == "String") { + return valueS as T; + } else if (type == "int") { + final int? intValue = int.tryParse(valueS); + if (intValue == null) { + return double.tryParse(valueS)?.toInt() as T?; + } else { + return intValue as T; + } + } else if (type == "double") { + return double.parse(valueS) as T; + } else if (type == "DateTime") { + return DateTime.parse(valueS) as T; + } else if (type == "bool") { + if (valueS == '0' || valueS == '1') { + return (valueS == '1') as T; + } + return (valueS == 'true') as T; + } else if (type == "Map" || type.startsWith("Map<")) { + return value as T; + } else { + if (convertFuncMap.containsKey(type)) { + if (value == null) { + return null; + } + return convertFuncMap[type]!(value as Map) as T; + } else { + throw UnimplementedError( + '$type unimplemented,you can try running the app again'); + } + } + } + + //list is returned by type + static M? _getListChildType(List> data) { + if ([] is M) { + return data.map((Map e) => + ClipboardMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map((Map e) => + CloseMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map((Map e) => + HeartPackageMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map(( + Map e) => + NoPairDeviceResponseMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map((Map e) => + PairCodeResponseMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map(( + Map e) => + PairDeviceInfosResponseMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map(( + Map e) => RemovePairRequestMessage.fromJson(e)) + .toList() as M; + } + if ([] is M) { + return data.map(( + Map e) => + RemovePairResponseMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map(( + Map e) => + ServerReadyResponseMessage.fromJson(e)).toList() as M; + } + if ([] is M) { + return data.map((Map e) => + WorkErrorMessage.fromJson(e)).toList() as M; + } + + debugPrint("$M not found"); + + return null; + } + + static M? fromJsonAsT(dynamic json) { + if (json is M) { + return json; + } + if (json is List) { + return _getListChildType( + json.map((dynamic e) => e as Map).toList()); + } else { + return jsonConvert.convert(json); + } + } +} + +class JsonConvertClassCollection { + Map convertFuncMap = { + (ClipboardMessage).toString(): ClipboardMessage.fromJson, + (CloseMessage).toString(): CloseMessage.fromJson, + (HeartPackageMessage).toString(): HeartPackageMessage.fromJson, + (NoPairDeviceResponseMessage) + .toString(): NoPairDeviceResponseMessage.fromJson, + (PairCodeResponseMessage).toString(): PairCodeResponseMessage + .fromJson, + (PairDeviceInfosResponseMessage) + .toString(): PairDeviceInfosResponseMessage.fromJson, + (RemovePairRequestMessage).toString(): RemovePairRequestMessage + .fromJson, + (RemovePairResponseMessage) + .toString(): RemovePairResponseMessage.fromJson, + (ServerReadyResponseMessage) + .toString(): ServerReadyResponseMessage.fromJson, + (WorkErrorMessage).toString(): WorkErrorMessage.fromJson, + }; + + bool containsKey(String type) { + return convertFuncMap.containsKey(type); + } + + JsonConvertFunction? operator [](String key) { + return convertFuncMap[key]; + } +} \ No newline at end of file diff --git a/lib/generated/json/base/json_field.dart b/lib/generated/json/base/json_field.dart new file mode 100644 index 0000000..8c967d4 --- /dev/null +++ b/lib/generated/json/base/json_field.dart @@ -0,0 +1,32 @@ +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: camel_case_types +// ignore_for_file: prefer_single_quotes + +// This file is automatically generated. DO NOT EDIT, all your changes would be lost. + +import 'package:meta/meta_meta.dart'; + +@Target({TargetKind.classType}) +class JsonSerializable { + const JsonSerializable(); +} + +@Target({TargetKind.field}) +class JSONField { + //Specify the parse field name + final String? name; + + //Whether to participate in toJson + final bool? serialize; + + //Whether to participate in fromMap + final bool? deserialize; + + //Whether to participate in copyWith + final bool? copyWith; + + //Enumeration or not + final bool? isEnum; + + const JSONField({this.name, this.serialize, this.deserialize, this.isEnum, this.copyWith}); +} diff --git a/lib/generated/json/clipboard_message_entity.g.dart b/lib/generated/json/clipboard_message_entity.g.dart new file mode 100644 index 0000000..d51ffc6 --- /dev/null +++ b/lib/generated/json/clipboard_message_entity.g.dart @@ -0,0 +1,30 @@ +import 'package:c_clipboard/generated/json/base/json_convert_content.dart'; +import 'package:c_clipboard/message/clipboard_message_entity.dart'; + + +ClipboardMessage $ClipboardMessageEntityFromJson( + Map json) { + final ClipboardMessage clipboardMessageEntity = ClipboardMessage(); + final String? clipboardMessage = jsonConvert.convert( + json['ClipboardMessage']); + if (clipboardMessage != null) { + clipboardMessageEntity.clipboardMessage = clipboardMessage; + } + return clipboardMessageEntity; +} + +Map $ClipboardMessageEntityToJson( + ClipboardMessage entity) { + final Map data = {}; + data['ClipboardMessage'] = entity.clipboardMessage; + return data; +} + +extension ClipboardMessageEntityExtension on ClipboardMessage { + ClipboardMessage copyWith({ + String? clipboardMessage, + }) { + return ClipboardMessage() + ..clipboardMessage = clipboardMessage ?? this.clipboardMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/close_message_entity.g.dart b/lib/generated/json/close_message_entity.g.dart new file mode 100644 index 0000000..019ddd1 --- /dev/null +++ b/lib/generated/json/close_message_entity.g.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/message/close_message_entity.dart'; + +CloseMessage $CloseMessageEntityFromJson(Map json) { + final CloseMessage closeMessageEntity = CloseMessage(); + final List? closeMessage = (json['CloseMessage'] as List?) + ?.map( + (e) => e) + .toList(); + if (closeMessage != null) { + closeMessageEntity.closeMessage = closeMessage; + } + return closeMessageEntity; +} + +Map $CloseMessageEntityToJson(CloseMessage entity) { + final Map data = {}; + data['CloseMessage'] = entity.closeMessage; + return data; +} + +extension CloseMessageEntityExtension on CloseMessage { + CloseMessage copyWith({ + List? closeMessage, + }) { + return CloseMessage() + ..closeMessage = closeMessage ?? this.closeMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/heart_package_message_entity.g.dart b/lib/generated/json/heart_package_message_entity.g.dart new file mode 100644 index 0000000..072c506 --- /dev/null +++ b/lib/generated/json/heart_package_message_entity.g.dart @@ -0,0 +1,31 @@ +import 'package:c_clipboard/message/heart_package_message_entity.dart'; + + +HeartPackageMessage $HeartPackageMessageEntityFromJson( + Map json) { + final HeartPackageMessage heartPackageMessageEntity = HeartPackageMessage(); + final List< + dynamic>? heartPackageMessage = (json['HeartPackageMessage'] as List< + dynamic>?)?.map( + (e) => e).toList(); + if (heartPackageMessage != null) { + heartPackageMessageEntity.heartPackageMessage = heartPackageMessage; + } + return heartPackageMessageEntity; +} + +Map $HeartPackageMessageEntityToJson( + HeartPackageMessage entity) { + final Map data = {}; + data['HeartPackageMessage'] = entity.heartPackageMessage; + return data; +} + +extension HeartPackageMessageEntityExtension on HeartPackageMessage { + HeartPackageMessage copyWith({ + List? heartPackageMessage, + }) { + return HeartPackageMessage() + ..heartPackageMessage = heartPackageMessage ?? this.heartPackageMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/no_pair_device_response_message_entity.g.dart b/lib/generated/json/no_pair_device_response_message_entity.g.dart new file mode 100644 index 0000000..27b9845 --- /dev/null +++ b/lib/generated/json/no_pair_device_response_message_entity.g.dart @@ -0,0 +1,33 @@ +import 'package:c_clipboard/message/no_pair_device_response_message_entity.dart'; + + +NoPairDeviceResponseMessage $NoPairDeviceResponseMessageEntityFromJson( + Map json) { + final NoPairDeviceResponseMessage noPairDeviceResponseMessageEntity = NoPairDeviceResponseMessage(); + final List< + dynamic>? noPairDeviceResponseMessage = (json['NoPairDeviceResponseMessage'] as List< + dynamic>?)?.map( + (e) => e).toList(); + if (noPairDeviceResponseMessage != null) { + noPairDeviceResponseMessageEntity.noPairDeviceResponseMessage = + noPairDeviceResponseMessage; + } + return noPairDeviceResponseMessageEntity; +} + +Map $NoPairDeviceResponseMessageEntityToJson( + NoPairDeviceResponseMessage entity) { + final Map data = {}; + data['NoPairDeviceResponseMessage'] = entity.noPairDeviceResponseMessage; + return data; +} + +extension NoPairDeviceResponseMessageEntityExtension on NoPairDeviceResponseMessage { + NoPairDeviceResponseMessage copyWith({ + List? noPairDeviceResponseMessage, + }) { + return NoPairDeviceResponseMessage() + ..noPairDeviceResponseMessage = noPairDeviceResponseMessage ?? + this.noPairDeviceResponseMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/pair_code_response_message_entity.g.dart b/lib/generated/json/pair_code_response_message_entity.g.dart new file mode 100644 index 0000000..abf4643 --- /dev/null +++ b/lib/generated/json/pair_code_response_message_entity.g.dart @@ -0,0 +1,32 @@ +import 'package:c_clipboard/generated/json/base/json_convert_content.dart'; +import 'package:c_clipboard/message/pair_code_response_message_entity.dart'; + + +PairCodeResponseMessage $PairCodeResponseMessageEntityFromJson( + Map json) { + final PairCodeResponseMessage pairCodeResponseMessageEntity = PairCodeResponseMessage(); + final String? pairCodeResponseMessage = jsonConvert.convert( + json['PairCodeResponseMessage']); + if (pairCodeResponseMessage != null) { + pairCodeResponseMessageEntity.pairCodeResponseMessage = + pairCodeResponseMessage; + } + return pairCodeResponseMessageEntity; +} + +Map $PairCodeResponseMessageEntityToJson( + PairCodeResponseMessage entity) { + final Map data = {}; + data['PairCodeResponseMessage'] = entity.pairCodeResponseMessage; + return data; +} + +extension PairCodeResponseMessageEntityExtension on PairCodeResponseMessage { + PairCodeResponseMessage copyWith({ + String? pairCodeResponseMessage, + }) { + return PairCodeResponseMessage() + ..pairCodeResponseMessage = pairCodeResponseMessage ?? + this.pairCodeResponseMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/pair_device_infos_response_message_entity.g.dart b/lib/generated/json/pair_device_infos_response_message_entity.g.dart new file mode 100644 index 0000000..c489be6 --- /dev/null +++ b/lib/generated/json/pair_device_infos_response_message_entity.g.dart @@ -0,0 +1,37 @@ +import 'package:c_clipboard/generated/json/base/json_convert_content.dart'; +import 'package:c_clipboard/message/pair_device_infos_response_message_entity.dart'; +import 'package:c_clipboard/message/DeviceInfo.dart'; + + + +PairDeviceInfosResponseMessage $PairDeviceInfosResponseMessageEntityFromJson( + Map json) { + final PairDeviceInfosResponseMessage pairDeviceInfosResponseMessageEntity = PairDeviceInfosResponseMessage(); + final List< + DeviceInfo>? pairDeviceInfosResponseMessage = (json['PairDeviceInfosResponseMessage'] as List< + dynamic>?)?.map( + (e) => jsonConvert.convert(e) as DeviceInfo).toList(); + if (pairDeviceInfosResponseMessage != null) { + pairDeviceInfosResponseMessageEntity.pairDeviceInfosResponseMessage = + pairDeviceInfosResponseMessage; + } + return pairDeviceInfosResponseMessageEntity; +} + +Map $PairDeviceInfosResponseMessageEntityToJson( + PairDeviceInfosResponseMessage entity) { + final Map data = {}; + data['PairDeviceInfosResponseMessage'] = + entity.pairDeviceInfosResponseMessage.map((v) => v.toJson()).toList(); + return data; +} + +extension PairDeviceInfosResponseMessageEntityExtension on PairDeviceInfosResponseMessage { + PairDeviceInfosResponseMessage copyWith({ + List? pairDeviceInfosResponseMessage, + }) { + return PairDeviceInfosResponseMessage() + ..pairDeviceInfosResponseMessage = pairDeviceInfosResponseMessage ?? + this.pairDeviceInfosResponseMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/remove_pair_request_message_entity.g.dart b/lib/generated/json/remove_pair_request_message_entity.g.dart new file mode 100644 index 0000000..76b8ee2 --- /dev/null +++ b/lib/generated/json/remove_pair_request_message_entity.g.dart @@ -0,0 +1,32 @@ +import 'package:c_clipboard/generated/json/base/json_convert_content.dart'; +import 'package:c_clipboard/message/remove_pair_request_message_entity.dart'; + + +RemovePairRequestMessage $RemovePairRequestMessageEntityFromJson( + Map json) { + final RemovePairRequestMessage removePairRequestMessageEntity = RemovePairRequestMessage(); + final String? removePairRequestMessage = jsonConvert.convert( + json['RemovePairRequestMessage']); + if (removePairRequestMessage != null) { + removePairRequestMessageEntity.removePairRequestMessage = + removePairRequestMessage; + } + return removePairRequestMessageEntity; +} + +Map $RemovePairRequestMessageEntityToJson( + RemovePairRequestMessage entity) { + final Map data = {}; + data['RemovePairRequestMessage'] = entity.removePairRequestMessage; + return data; +} + +extension RemovePairRequestMessageEntityExtension on RemovePairRequestMessage { + RemovePairRequestMessage copyWith({ + String? removePairRequestMessage, + }) { + return RemovePairRequestMessage() + ..removePairRequestMessage = removePairRequestMessage ?? + this.removePairRequestMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/remove_pair_response_message_entity.g.dart b/lib/generated/json/remove_pair_response_message_entity.g.dart new file mode 100644 index 0000000..d8d352d --- /dev/null +++ b/lib/generated/json/remove_pair_response_message_entity.g.dart @@ -0,0 +1,33 @@ +import 'package:c_clipboard/message/remove_pair_response_message_entity.dart'; + + +RemovePairResponseMessage $RemovePairResponseMessageEntityFromJson( + Map json) { + final RemovePairResponseMessage removePairResponseMessageEntity = RemovePairResponseMessage(); + final List< + dynamic>? removePairResponseMessage = (json['RemovePairResponseMessage'] as List< + dynamic>?)?.map( + (e) => e).toList(); + if (removePairResponseMessage != null) { + removePairResponseMessageEntity.removePairResponseMessage = + removePairResponseMessage; + } + return removePairResponseMessageEntity; +} + +Map $RemovePairResponseMessageEntityToJson( + RemovePairResponseMessage entity) { + final Map data = {}; + data['RemovePairResponseMessage'] = entity.removePairResponseMessage; + return data; +} + +extension RemovePairResponseMessageEntityExtension on RemovePairResponseMessage { + RemovePairResponseMessage copyWith({ + List? removePairResponseMessage, + }) { + return RemovePairResponseMessage() + ..removePairResponseMessage = removePairResponseMessage ?? + this.removePairResponseMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/server_ready_response_message_entity.g.dart b/lib/generated/json/server_ready_response_message_entity.g.dart new file mode 100644 index 0000000..750365e --- /dev/null +++ b/lib/generated/json/server_ready_response_message_entity.g.dart @@ -0,0 +1,32 @@ +import 'package:c_clipboard/generated/json/base/json_convert_content.dart'; +import 'package:c_clipboard/message/server_ready_response_message_entity.dart'; + + +ServerReadyResponseMessage $ServerReadyResponseMessageEntityFromJson( + Map json) { + final ServerReadyResponseMessage serverReadyResponseMessageEntity = ServerReadyResponseMessage(); + final String? serverReadyResponseMessage = jsonConvert.convert( + json['ServerReadyResponseMessage']); + if (serverReadyResponseMessage != null) { + serverReadyResponseMessageEntity.serverReadyResponseMessage = + serverReadyResponseMessage; + } + return serverReadyResponseMessageEntity; +} + +Map $ServerReadyResponseMessageEntityToJson( + ServerReadyResponseMessage entity) { + final Map data = {}; + data['ServerReadyResponseMessage'] = entity.serverReadyResponseMessage; + return data; +} + +extension ServerReadyResponseMessageEntityExtension on ServerReadyResponseMessage { + ServerReadyResponseMessage copyWith({ + String? serverReadyResponseMessage, + }) { + return ServerReadyResponseMessage() + ..serverReadyResponseMessage = serverReadyResponseMessage ?? + this.serverReadyResponseMessage; + } +} \ No newline at end of file diff --git a/lib/generated/json/work_error_message_entity.g.dart b/lib/generated/json/work_error_message_entity.g.dart new file mode 100644 index 0000000..2fccc2a --- /dev/null +++ b/lib/generated/json/work_error_message_entity.g.dart @@ -0,0 +1,31 @@ +import 'package:c_clipboard/generated/json/base/json_convert_content.dart'; +import 'package:c_clipboard/message/work_error_message_entity.dart'; + + +WorkErrorMessage $WorkErrorMessageEntityFromJson( + Map json) { + final WorkErrorMessage workErrorMessageEntity = WorkErrorMessage(); + final List? workErrorMessage = (json['WorkErrorMessage'] as List< + dynamic>?)?.map( + (e) => e).toList(); + if (workErrorMessage != null) { + workErrorMessageEntity.workErrorMessage = workErrorMessage; + } + return workErrorMessageEntity; +} + +Map $WorkErrorMessageEntityToJson( + WorkErrorMessage entity) { + final Map data = {}; + data['WorkErrorMessage'] = entity.workErrorMessage; + return data; +} + +extension WorkErrorMessageEntityExtension on WorkErrorMessage { + WorkErrorMessage copyWith({ + List? workErrorMessage, + }) { + return WorkErrorMessage() + ..workErrorMessage = workErrorMessage ?? this.workErrorMessage; + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..d2fe6ac --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,459 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:io' show Platform; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + + +import 'package:c_clipboard/DeviceInfoContainer.dart'; +import 'package:c_clipboard/message/Codec.dart'; +import 'package:c_clipboard/message/DeviceInfo.dart'; +import 'package:c_clipboard/message/Message.dart'; +import 'package:c_clipboard/message/PairCreateMessage.dart'; +import 'package:c_clipboard/message/PairRequestMessage.dart'; + +import 'CodeInputContainer.dart'; +import 'message/DeviceChangeResponseMessage.dart'; +import 'message/PairDeviceInfosResponseMessage2.dart'; +import 'message/clipboard_message_entity.dart'; +import 'message/close_message_entity.dart'; +import 'message/heart_package_message_entity.dart'; +import 'message/no_pair_device_response_message_entity.dart'; +import 'message/pair_code_response_message_entity.dart'; +import 'message/remove_pair_request_message_entity.dart'; +import 'message/remove_pair_response_message_entity.dart'; +import 'message/server_ready_response_message_entity.dart'; +import 'message/work_error_message_entity.dart'; + +void showToast(type,msg){ + var color = Colors.black; + switch(type){ + case "success": + color = Colors.greenAccent; + case "error": + color = Colors.red; + case "info": + color = Colors.grey; + } + Fluttertoast.showToast( + msg: msg, + toastLength: Toast.LENGTH_SHORT, + timeInSecForIosWeb: 1, + backgroundColor: color, + textColor: Colors.white, + fontSize: 16.0 + ); +} +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + static DeviceInfo? deviceInfo; + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'c_clipboard', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.white), + useMaterial3: true, + ), + home: const MyHomePage(), + ); + } +} +class MyHomePage extends StatefulWidget{ + const MyHomePage({super.key}); + + @override + State createState() { + return _MyHomeState(); + } + +} +class _MyHomeState extends State with WidgetsBindingObserver { + + Socket? _socket; + late final ValueNotifier info = ValueNotifier(false); + List devices = []; + bool isConnect = false; + String oldCode = ""; + List log = []; + + void _connectToServer() async { + // final String host = _hostController.text; + const String host = "101.132.113.152"; + // final int port = int.tryParse(_portController.text) ?? 0; + const int port = 8888; + // //addLog("------------------------------------------------------------"); + // PairRequestMessage p =PairRequestMessage(message: "test",deviceInfo: DeviceInfo(socketAddr: "127.0.0.1:8080", deviceName: "xbss", deviceType: "DeskTop")); + // var encode = jsonEncode(p.toJson()); + // List content = utf8.encode(encode); + // // var content = encode.codeUnits; + // //addLog(encode); + // List buffer = [content.length]; + // //addLog("长度是${content.length}"); + // buffer.addAll(content); + // //addLog(buffer.toString()); + // // 将 List 转换为 Uint8List,因为 Socket.write() 需要 Uint8List + // Uint8List uint8Buffer = Uint8List.fromList(buffer); + // //addLog("------------------------------------------------------------"); + try { + setState(() { + //addLog("清除配对设施"); + devices.clear(); + }); + _socket = await Socket.connect(host, port); + isConnect = true; + // //addLog(_socket?.address); + // //addLog(_socket?.address.address); + // //addLog(_socket?.address.host); + // _socket?.write(buffer); + // _socket!.add(buffer); + // _socket?.flush(); + + // _socket?.listen( + // responseHandler, + // onError: (error) { + // //addLog('Error: $error'); + // }, + // onDone: () { + // //addLog('Disconnected from server'); + // }, + // ); + List oldbuffer = []; + _socket?.listen((List data) { + //addLog("收到了数据"); + isConnect = true; + oldbuffer.addAll(data); + var result = Codec.decodeData(oldbuffer); + oldbuffer.clear(); + oldbuffer.addAll(result.remainingData); + var msg = result.msg; + if(msg!=null){ + //addLog("解析出了数据"); + switch(msg.runtimeType){ + case HeartPackageMessage: + + // //addLog(msg.toString()); + case PairRequestMessage: + //addLog(msg.toString()); + case PairCreateMessage: + //addLog(msg.toString()); + case PairDeviceInfosResponseMessage: + var infos = (msg as PairDeviceInfosResponseMessage).deviceInfos; + infos.removeWhere((device) => device.socketAddr == MyApp.deviceInfo!.socketAddr); + // infos.remove(MyApp.deviceInfo!); + setState(() { + devices.addAll(infos); + showToast("success", "配对成功"); + if(oldCode==""){//手动输入的配对码配对成功了,记下此时的配对码当做老的。 + globalKey.currentState?.setPairSuccess(); + oldCode = globalKey.currentState!.getPairCode(); + }else{//老配对码不是空,说明是自动输入的。 + globalKey.currentState?.setPairCode(oldCode); + } + readClipboard(); + }); + readClipboard(); + //addLog(msg.toString()); + case PairCodeResponseMessage: + var message = msg as PairCodeResponseMessage; + setState(() { + showToast("success", "创建配对码成功."); + globalKey.currentState?.setPairCode(message.pairCodeResponseMessage); + oldCode = message.pairCodeResponseMessage; + }); + //addLog(msg.toString()); + case ClipboardMessage: + var message = msg as ClipboardMessage; + //addLog("收到剪切板消息"); + Clipboard.setData(ClipboardData(text:message.clipboardMessage)); + showToast("info", "收到剪切板消息."); + case ServerReadyResponseMessage: + var addr = (msg as ServerReadyResponseMessage).serverReadyResponseMessage; + //addLog(addr); + setState(() { + MyApp.deviceInfo?.socketAddr = addr; + showToast("success", "获取设备信息成功."); + }); + if(oldCode!=""){ + sendMessage(PairRequestMessage(code: oldCode, deviceInfo:MyApp.deviceInfo!)); + } + case NoPairDeviceResponseMessage: + setState(() { + showToast("error", "没有配对的设备!"); + }); + oldCode = ""; + //addLog(msg.toString()); + case RemovePairRequestMessage: + //addLog(msg.toString()); + case RemovePairResponseMessage: + oldCode = ""; + setState(() { + globalKey.currentState?.removeSelf(); + showToast("error", "您已被取消配对!"); + devices.clear(); + }); + //addLog(msg.toString()); + case WorkErrorMessage: + showToast("error", "服务器错误!"); + //addLog(msg.toString()); + case DeviceChangeResponseMessage: + var message = msg as DeviceChangeResponseMessage; + //addLog(message); + if(message.dir){ + setState(() { + devices.add(message.deviceInfo); + showToast("info", "已添加设备${message.deviceInfo.deviceName}."); + }); + }else{ + setState(() { + devices.removeWhere((device) => device.socketAddr == message.deviceInfo.socketAddr); + // devices.remove(message.deviceInfo); + showToast("info", "已移除设备${message.deviceInfo.deviceName}."); + }); + } + case CloseMessage: + //addLog(msg.toString()); + } + } + // setState(() { + // _response = utf8.decode(data); + // }); + }, + onError: (error) { + isConnect = false; + //addLog('Error: $error'); + }, + onDone: () { + isConnect = false; + //addLog('Disconnected from server'); + }, + ); + } catch (e) { + isConnect = false; + //addLog('Error: $e'); + } + } + + void checkConnect(){ + if(!isConnect){ + setState(() { + globalKey.currentState?.removeSelf(); + }); + // devices.clear(); + _connectToServer(); + // if(oldCode!=""){ + // sendMessage(PairRequestMessage(code: oldCode, deviceInfo:MyApp.deviceInfo!)); + // } + // readClipboard(); + }else{ + readClipboard(); + } + } + + @override + void didChangeDependencies() async { + super.didChangeDependencies(); + //addLog("------------------获取设备信息-------------------------"); + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + var name = ""; + if (Platform.isIOS) { + //addLog("This is an iOS device"); + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + name = iosInfo.utsname.machine; + //addLog('Running on ${iosInfo.utsname.machine}'); + // 在这里编写iOS特定的代码 + } else if (Platform.isAndroid) { + //addLog("This is an Android device"); + // 在这里编写Android特定的代码 + var androidInfo = await deviceInfo.androidInfo; + //addLog('Running on ${androidInfo.host}'); + //addLog('Running on ${androidInfo.device}'); + name = androidInfo.device; + } + MyApp.deviceInfo = DeviceInfo(socketAddr: "", deviceName: name, deviceType: "Phone"); + //addLog("------------------连接服务器-------------------------"); + _connectToServer(); + Timer.periodic(const Duration(seconds: 30), (timer) { + isConnect = false; + sendMessage(HeartPackageMessage()); + }); + } + + @override + void initState(){ + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + + @override + void dispose() { + super.dispose(); + WidgetsBinding.instance.removeObserver(this); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + switch (state) { + case AppLifecycleState.inactive: // 处于这种状态的应用程序应该假设它们可能在任何时候暂停。 + break; + case AppLifecycleState.resumed: //从后台切换前台,界面可见 + //addLog("到前台了"); + checkConnect(); + break; + case AppLifecycleState.paused: // 界面不可见,后台 + //addLog("应用处于不可见状态 后台======"); + break; + case AppLifecycleState.detached: // APP结束时调用 + sendMessage(CloseMessage()); + break; + case AppLifecycleState.hidden: + // TODO: Handle this case. + } + } + + void readClipboard() async { + var text = await Clipboard.getData(Clipboard.kTextPlain); + if(text==null){ + //addLog("读取到null"); + }else{ + var content = text.text; + //addLog("读取到${content}"); + if(content!=null){ + var clipboardMessage = ClipboardMessage(); + clipboardMessage.clipboardMessage = content; + sendMessage(clipboardMessage); + } + } + } + + + void sendMessage(Message msg) { + if (_socket == null) return; + var bytes = Codec.encode(msg); + _socket!.add(bytes); + + // PairRequestMessage p =PairRequestMessage(message: "test",deviceInfo: DeviceInfo(socketAddr: "127.0.0.1:8080", deviceName: "xbss", deviceType: "DeskTop")); + // var encode = jsonEncode(p.toJson()); + // List content = utf8.encode(encode); + // // var content = encode.codeUnits; + // //addLog(encode); + // //addLog("长度是${content.length}"); + // List buffer = [content.length]; + // buffer.addAll(content); + // //addLog("内容是$buffer"); + // // _socket!.write(buffer); + // _socket!.add(buffer); + // // final String message = "nmihao"; + // // _socket!.write(message); + // setState(() { + // _response = ''; + // }); + } + + + void requestPairCode(){ + if (_socket == null) return; + sendMessage(PairCreateMessage(deviceInfo:DeviceInfo(socketAddr: "106.111.212.177:31959", deviceName: "xbss", deviceType: "Phone"))); + } + void _remove_pair(addr){ + //addLog("请求解除${addr}"); + var removePairRequestMessage = RemovePairRequestMessage(); + removePairRequestMessage.removePairRequestMessage = addr; + sendMessage(removePairRequestMessage); + } + void addinfo(){ + setState(() { + devices.add(DeviceInfo(socketAddr: "127.01.0.1", deviceName: "dev5eName", deviceType: "Computer")); + }); + } + void addLog(msg){ + // setState(() { + // log.add(msg); + // }); + } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + // backgroundColor: Theme.of(context).colorScheme.inversePrimary, + backgroundColor: Colors.white, + title: const Text("CClipboard", + style: TextStyle(fontWeight: FontWeight.bold),), + ), + body: Center( + child: Container( + padding: const EdgeInsets.all(25.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // TextButton(onPressed:addinfo , child: Text("child")), + CodeInputContainer( + key: globalKey, + count: 6, + // phone: '18888888888', + onRequest: () async { + sendMessage(PairCreateMessage(deviceInfo: MyApp.deviceInfo!)); + // Function() cancel = MsgUtil.loading(); + // await Future.delayed(const Duration(seconds: 1)); + // cancel.call(); + // MsgUtil.toast('验证码发送成功'); + return true; + }, + onResult: (code) { + //addLog("请求配对"); + oldCode = "";//手动请求配对后把老配对码清空。 + sendMessage(PairRequestMessage(code: code, deviceInfo: MyApp.deviceInfo!)); + // _sendMessage(PairRequestMessage(message: message, deviceInfo: deviceInfo)) + } + ), + const SizedBox(height: 30), + // if(info.value) + if(MyApp.deviceInfo!=null) + DeviceInfoContainer(self: true, deviceInfo: MyApp.deviceInfo!,remove: (addr){ + _remove_pair(addr); + },), + // DeviceInfoContainer(self: true, name: MyApp.deviceInfo!.deviceName, type: MyApp.deviceInfo!.deviceType), + const SizedBox(height: 20,), + Expanded( + child: ListView.builder( + itemCount: devices.length, + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 8), + DeviceInfoContainer(self: false, deviceInfo: devices[index],remove: (addr){ + _remove_pair(addr); + },), + ] + ); + }, + ), + ), + // Expanded( + // child: ListView.builder( + // itemCount: log.length, + // itemBuilder: (context, index) { + // return Text(log[index]); + // }, + // ), + // ) + ], + ), + ) + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} \ No newline at end of file diff --git a/lib/message/Codec.dart b/lib/message/Codec.dart new file mode 100644 index 0000000..cb6f943 --- /dev/null +++ b/lib/message/Codec.dart @@ -0,0 +1,167 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:c_clipboard/message/Message.dart'; +import 'package:c_clipboard/message/heart_package_message_entity.dart'; +import 'package:c_clipboard/message/pair_code_response_message_entity.dart'; +import 'package:c_clipboard/message/remove_pair_request_message_entity.dart'; +import 'package:c_clipboard/message/remove_pair_response_message_entity.dart'; +import 'package:c_clipboard/message/server_ready_response_message_entity.dart'; +import 'package:c_clipboard/message/work_error_message_entity.dart'; + +import 'DeviceChangeResponseMessage.dart'; +import 'PairCreateMessage.dart'; +import 'PairDeviceInfosResponseMessage2.dart'; +import 'PairRequestMessage.dart'; +import 'clipboard_message_entity.dart'; +import 'close_message_entity.dart'; +import 'no_pair_device_response_message_entity.dart'; + +class Codec{ + final messageTypeMap = { + 0: "HeartPackageMessage", + 1: "PairRequestMessage", + 2: "PairCreateMessage", + 3: "PairDeviceInfosResponseMessage", + 4: "PairCodeResponseMessage", + 5: "ClipboardMessage", + 6: "ServerReadyResponseMessage", + 7: "NoPairDeviceResponseMessage", + 8: "RemovePairRequestMessage", + 9: "RemovePairResponseMessage", + 10: "WorkErrorMessage", + 11: "DeviceChangeResponseMessage", + 12: "CloseMessage", + }; + // 反序列化函数 + static Message fromJsonAsMessage(int typeId, Map json) { + switch (typeId) { + case 0: + return HeartPackageMessage.fromJson(json) as Message; + case 1: + return PairRequestMessage.fromJson(json) as Message; + case 2: + return PairCreateMessage.fromJson(json) as Message; + case 3: + return PairDeviceInfosResponseMessage.fromJson(json) as Message; + case 4: + return PairCodeResponseMessage.fromJson(json) as Message; + case 5: + return ClipboardMessage.fromJson(json) as Message; + case 6: + return ServerReadyResponseMessage.fromJson(json) as Message; + case 7: + return NoPairDeviceResponseMessage.fromJson(json) as Message; + case 8: + return RemovePairRequestMessage.fromJson(json) as Message; + case 9: + return RemovePairResponseMessage.fromJson(json) as Message; + case 10: + return WorkErrorMessage.fromJson(json) as Message; + case 11: + return DeviceChangeResponseMessage.fromJson(json) as Message; + case 12: + return CloseMessage.fromJson(json) as Message; + default: + throw ArgumentError('Unsupported typeId: $typeId'); + } + } + static List encode(Message msg){ + var json = jsonEncode(msg.toJson()); + int typeId = msg.getTypeId(); + List content = utf8.encode(json); + final bytes = Uint8List(content.length + 1 + 4); + final buffer = ByteData.view(bytes.buffer); + + int offset = 0; + + buffer.setUint8(offset, typeId); + offset += 1; + + buffer.setInt32(offset, content.length); + offset += 4; + + for (int i = 0; i < content.length; i++) { + buffer.setUint8(offset + i, content[i]); + } + return bytes; + } + static bool checkEntireMessage(List data){ + var encodedData = Uint8List.fromList(data); + if (encodedData.length < 5) { + // Not enough data to decode header + return false; // Return null to indicate insufficient data + } + ByteData byteData = encodedData.buffer.asByteData(); + int typeId = byteData.getUint8(0); + int contentLength = byteData.getInt32(1); + if (encodedData.length < 5 + contentLength) { + // Not enough data to decode content + return false; // Return null to indicate insufficient data + } + + return true; + } + static DecodeResult decodeData(List data) { + var encodedData = Uint8List.fromList(data); + if (encodedData.length < 5) { + // Not enough data to decode header + return DecodeResult(null,data); + } + ByteData byteData = encodedData.buffer.asByteData(); + + // Decode type id + int typeId = byteData.getUint8(0); + print("消息类型id是${typeId}"); + // Decode content length + int contentLength = byteData.getInt32(1); + if (encodedData.length < 5 + contentLength) { + return DecodeResult(null,data); + } + // Decode content + Uint8List content = Uint8List.sublistView(encodedData, 5, 5 + contentLength); + // Convert remaining data to List + List remainingData = []; + if (encodedData.length > 5 + contentLength) { + remainingData = encodedData.sublist(5 + contentLength).toList(); + } + + Map json = decodeJsonFromUint8List(content); + //反序列化过程 + Message msg = fromJsonAsMessage(typeId, json); + return DecodeResult(msg, remainingData); + } + + static Map decodeJsonFromUint8List(Uint8List data) { + // Step 1: Convert Uint8List to String + String jsonString = utf8.decode(data); + print("反序列化过程的json字符串是${jsonString}"); + // Step 2: Parse string to JSON + Map json = jsonDecode(jsonString); + print("反序列化过程的json是${json}"); + return json; + } + // static Uint8List encodeData(int typeId, List content) { + // final bytes = Uint8List(content.length + 1 + 4); + // final buffer = ByteData.view(bytes.buffer); + // + // int offset = 0; + // + // buffer.setUint8(offset, typeId); + // offset += 1; + // + // buffer.setInt32(offset, content.length); + // offset += 4; + // + // for (int i = 0; i < content.length; i++) { + // buffer.setUint8(offset + i, content[i]); + // } + // + // return bytes; + // } +} +class DecodeResult{ + Message? msg; + List remainingData = []; + DecodeResult(this.msg, this.remainingData); +} \ No newline at end of file diff --git a/lib/message/DeviceChangeResponseMessage.dart b/lib/message/DeviceChangeResponseMessage.dart new file mode 100644 index 0000000..402a56b --- /dev/null +++ b/lib/message/DeviceChangeResponseMessage.dart @@ -0,0 +1,35 @@ +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; + +import 'DeviceInfo.dart'; +import 'Message.dart'; + +class DeviceChangeResponseMessage implements Message{ + bool dir; + DeviceInfo deviceInfo; + + DeviceChangeResponseMessage({ + required this.dir, + required this.deviceInfo, + }); + + factory DeviceChangeResponseMessage.fromJson(Map json) { + return DeviceChangeResponseMessage( + dir: json['DeviceChangeResponseMessage'][0] as bool, + deviceInfo: DeviceInfo.fromJson(json['DeviceChangeResponseMessage'][1] as Map), + ); + } + + @override + Map toJson() { + return { + 'DeviceChangeResponseMessage': [dir, deviceInfo.toJson()] + }; + } + + @override + int getTypeId() { + return 11; + } +} \ No newline at end of file diff --git a/lib/message/DeviceInfo.dart b/lib/message/DeviceInfo.dart new file mode 100644 index 0000000..943f29e --- /dev/null +++ b/lib/message/DeviceInfo.dart @@ -0,0 +1,27 @@ +class DeviceInfo { + String socketAddr; + String deviceName; + String deviceType; + + DeviceInfo({ + required this.socketAddr, + required this.deviceName, + required this.deviceType, + }); + + factory DeviceInfo.fromJson(Map json) { + return DeviceInfo( + socketAddr: json['socket_addr'] as String, + deviceName: json['device_name'] as String, + deviceType: json['device_type'] as String, + ); + } + + Map toJson() { + return { + 'socket_addr': socketAddr, + 'device_name': deviceName, + 'device_type': deviceType, + }; + } +} \ No newline at end of file diff --git a/lib/message/Message.dart b/lib/message/Message.dart new file mode 100644 index 0000000..b32672c --- /dev/null +++ b/lib/message/Message.dart @@ -0,0 +1,4 @@ +abstract class Message{ + int getTypeId(); + Map toJson(); +} \ No newline at end of file diff --git a/lib/message/PairCreateMessage.dart b/lib/message/PairCreateMessage.dart new file mode 100644 index 0000000..c16a23c --- /dev/null +++ b/lib/message/PairCreateMessage.dart @@ -0,0 +1,28 @@ +import 'DeviceInfo.dart'; +import 'Message.dart'; + +class PairCreateMessage implements Message{ + DeviceInfo deviceInfo; + + PairCreateMessage({ + required this.deviceInfo, + }); + + factory PairCreateMessage.fromJson(Map json) { + return PairCreateMessage( + deviceInfo: DeviceInfo.fromJson(json['PairCreateMessage'] as Map), + ); + } + + @override + Map toJson() { + return { + 'PairCreateMessage': deviceInfo.toJson(), + }; + } + + @override + int getTypeId() { + return 2; + } +} \ No newline at end of file diff --git a/lib/message/PairDeviceInfosResponseMessage2.dart b/lib/message/PairDeviceInfosResponseMessage2.dart new file mode 100644 index 0000000..4aa9b33 --- /dev/null +++ b/lib/message/PairDeviceInfosResponseMessage2.dart @@ -0,0 +1,29 @@ +import 'DeviceInfo.dart'; +import 'Message.dart'; +//反序列化过程的json是{"PairDeviceInfosResponseMessage":[{"socket_addr":"180.127.102.56:25430","device_name":"Xiaobaishushu","device_type":"DeskTop"},{"socket_addr":"180.127.102.56:23050","device_name":"emulator64_x86_64_arm64","device_type":"Phone"}]} +//反序列化过程的json是{PairDeviceInfosResponseMessage: [{socket_addr: 180.127.102.56:25430, device_name: Xiaobaishushu, device_type: DeskTop}, {socket_addr: 180.127.102.56:23226, device_name: emulator64_x86_64_arm64, device_type: Phone}]} +class PairDeviceInfosResponseMessage implements Message { + List deviceInfos; + + PairDeviceInfosResponseMessage({ + required this.deviceInfos, + }); + + factory PairDeviceInfosResponseMessage.fromJson(Map json) { + return PairDeviceInfosResponseMessage( + deviceInfos: List.from(json['PairDeviceInfosResponseMessage'].map((deviceJson) => DeviceInfo.fromJson(deviceJson as Map))), + ); + } + + @override + Map toJson() { + return { + 'PairDeviceInfosResponseMessage2': deviceInfos.map((deviceInfo) => deviceInfo.toJson()).toList() + }; + } + + @override + int getTypeId() { + return 1; + } +} \ No newline at end of file diff --git a/lib/message/PairRequestMessage.dart b/lib/message/PairRequestMessage.dart new file mode 100644 index 0000000..986991a --- /dev/null +++ b/lib/message/PairRequestMessage.dart @@ -0,0 +1,60 @@ +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; + +import 'DeviceInfo.dart'; +// class DeviceInfoM { +// String socketAddr; +// String deviceName; +// String deviceType; +// +// DeviceInfoM({ +// required this.socketAddr, +// required this.deviceName, +// required this.deviceType, +// }); +// +// factory DeviceInfoM.fromJson(Map json) { +// return DeviceInfoM( +// socketAddr: json['socket_addr'] as String, +// deviceName: json['device_name'] as String, +// deviceType: json['device_type'] as String, +// ); +// } +// +// Map toJson() { +// return { +// 'socket_addr': socketAddr, +// 'device_name': deviceName, +// 'device_type': deviceType, +// }; +// } +// } +class PairRequestMessage implements Message{ + String code; + DeviceInfo deviceInfo; + + PairRequestMessage({ + required this.code, + required this.deviceInfo, + }); + + factory PairRequestMessage.fromJson(Map json) { + return PairRequestMessage( + code: json['PairRequestMessage'][0] as String, + deviceInfo: DeviceInfo.fromJson(json['PairRequestMessage'][1] as Map), + ); + } + + @override + Map toJson() { + return { + 'PairRequestMessage': [code, deviceInfo.toJson()] + }; + } + + @override + int getTypeId() { + return 1; + } +} \ No newline at end of file diff --git a/lib/message/clipboard_message_entity.dart b/lib/message/clipboard_message_entity.dart new file mode 100644 index 0000000..7b20fdd --- /dev/null +++ b/lib/message/clipboard_message_entity.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/clipboard_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/clipboard_message_entity.g.dart'; + +@JsonSerializable() +class ClipboardMessage implements Message{ + @JSONField(name: "ClipboardMessage") + late String clipboardMessage = ''; + + ClipboardMessage(); + + factory ClipboardMessage.fromJson(Map json) => $ClipboardMessageEntityFromJson(json); + + Map toJson() => $ClipboardMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 5; + } +} \ No newline at end of file diff --git a/lib/message/close_message_entity.dart b/lib/message/close_message_entity.dart new file mode 100644 index 0000000..5bd598d --- /dev/null +++ b/lib/message/close_message_entity.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/close_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/close_message_entity.g.dart'; + +@JsonSerializable() +class CloseMessage implements Message{ + @JSONField(name: "CloseMessage") + List closeMessage = []; + + CloseMessage(); + + factory CloseMessage.fromJson(Map json) => $CloseMessageEntityFromJson(json); + + Map toJson() => $CloseMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 12; + } +} \ No newline at end of file diff --git a/lib/message/heart_package_message_entity.dart b/lib/message/heart_package_message_entity.dart new file mode 100644 index 0000000..fc41f77 --- /dev/null +++ b/lib/message/heart_package_message_entity.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/heart_package_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/heart_package_message_entity.g.dart'; + +@JsonSerializable() +class HeartPackageMessage implements Message{ + @JSONField(name: "HeartPackageMessage") + List heartPackageMessage = []; + + HeartPackageMessage(); + + factory HeartPackageMessage.fromJson(Map json) => $HeartPackageMessageEntityFromJson(json); + + Map toJson() => $HeartPackageMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 0; + } +} \ No newline at end of file diff --git a/lib/message/no_pair_device_response_message_entity.dart b/lib/message/no_pair_device_response_message_entity.dart new file mode 100644 index 0000000..ddba5ed --- /dev/null +++ b/lib/message/no_pair_device_response_message_entity.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/no_pair_device_response_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/no_pair_device_response_message_entity.g.dart'; + +@JsonSerializable() +class NoPairDeviceResponseMessage implements Message { + @JSONField(name: "NoPairDeviceResponseMessage") + List noPairDeviceResponseMessage = []; + + NoPairDeviceResponseMessage(); + + factory NoPairDeviceResponseMessage.fromJson(Map json) => $NoPairDeviceResponseMessageEntityFromJson(json); + + Map toJson() => $NoPairDeviceResponseMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 7; + } +} \ No newline at end of file diff --git a/lib/message/pair_code_response_message_entity.dart b/lib/message/pair_code_response_message_entity.dart new file mode 100644 index 0000000..91f5070 --- /dev/null +++ b/lib/message/pair_code_response_message_entity.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/pair_code_response_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/pair_code_response_message_entity.g.dart'; + +@JsonSerializable() +class PairCodeResponseMessage implements Message{ + @JSONField(name: "PairCodeResponseMessage") + late String pairCodeResponseMessage = ''; + + PairCodeResponseMessage(); + + factory PairCodeResponseMessage.fromJson(Map json) => $PairCodeResponseMessageEntityFromJson(json); + + Map toJson() => $PairCodeResponseMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 4; + } +} \ No newline at end of file diff --git a/lib/message/pair_device_infos_response_message_entity.dart b/lib/message/pair_device_infos_response_message_entity.dart new file mode 100644 index 0000000..a85de6f --- /dev/null +++ b/lib/message/pair_device_infos_response_message_entity.dart @@ -0,0 +1,29 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/pair_device_infos_response_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/DeviceInfo.dart'; +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/pair_device_infos_response_message_entity.g.dart'; + +@JsonSerializable() +class PairDeviceInfosResponseMessage implements Message { + @JSONField(name: "PairDeviceInfosResponseMessage") + List pairDeviceInfosResponseMessage = []; + + PairDeviceInfosResponseMessage(); + + factory PairDeviceInfosResponseMessage.fromJson(Map json) => $PairDeviceInfosResponseMessageEntityFromJson(json); + + Map toJson() => $PairDeviceInfosResponseMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 3; + } +} \ No newline at end of file diff --git a/lib/message/remove_pair_request_message_entity.dart b/lib/message/remove_pair_request_message_entity.dart new file mode 100644 index 0000000..2013454 --- /dev/null +++ b/lib/message/remove_pair_request_message_entity.dart @@ -0,0 +1,29 @@ + +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/remove_pair_request_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/remove_pair_request_message_entity.g.dart'; + +@JsonSerializable() +class RemovePairRequestMessage implements Message{ + @JSONField(name: "RemovePairRequestMessage") + late String removePairRequestMessage = ''; + + RemovePairRequestMessage(); + + factory RemovePairRequestMessage.fromJson(Map json) => $RemovePairRequestMessageEntityFromJson(json); + + Map toJson() => $RemovePairRequestMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 8; + } +} \ No newline at end of file diff --git a/lib/message/remove_pair_response_message_entity.dart b/lib/message/remove_pair_response_message_entity.dart new file mode 100644 index 0000000..2f3ae54 --- /dev/null +++ b/lib/message/remove_pair_response_message_entity.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/remove_pair_response_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/remove_pair_response_message_entity.g.dart'; + +@JsonSerializable() +class RemovePairResponseMessage implements Message { + @JSONField(name: "RemovePairResponseMessage") + late List removePairResponseMessage = []; + + RemovePairResponseMessage(); + + factory RemovePairResponseMessage.fromJson(Map json) => $RemovePairResponseMessageEntityFromJson(json); + + Map toJson() => $RemovePairResponseMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 9; + } +} \ No newline at end of file diff --git a/lib/message/server_ready_response_message_entity.dart b/lib/message/server_ready_response_message_entity.dart new file mode 100644 index 0000000..9ef20fa --- /dev/null +++ b/lib/message/server_ready_response_message_entity.dart @@ -0,0 +1,28 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/server_ready_response_message_entity.g.dart'; +import 'dart:convert'; + +import 'package:c_clipboard/message/Message.dart'; +export 'package:c_clipboard/generated/json/server_ready_response_message_entity.g.dart'; + +@JsonSerializable() +class ServerReadyResponseMessage implements Message{ + @JSONField(name: "ServerReadyResponseMessage") + late String serverReadyResponseMessage = ''; + + ServerReadyResponseMessage(); + + factory ServerReadyResponseMessage.fromJson(Map json) => $ServerReadyResponseMessageEntityFromJson(json); + + Map toJson() => $ServerReadyResponseMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 6; + } +} \ No newline at end of file diff --git a/lib/message/test.dart b/lib/message/test.dart new file mode 100644 index 0000000..dac23f8 --- /dev/null +++ b/lib/message/test.dart @@ -0,0 +1,17 @@ +// import 'package:test/test.dart'; +import 'work_error_message_entity.dart'; + +// 定义一个简单的函数,用于测试 +int add(int a, int b) { + return a + b; +} + +// 使用test函数来定义测试 +void main() { + // test('adds 1 + 2 to equal 3', () { + // // 断言add函数返回的结果是否为3 + // print(WorkErrorMessageEntity().toJson()); + // }); + + print(WorkErrorMessage().toJson()); +} \ No newline at end of file diff --git a/lib/message/work_error_message_entity.dart b/lib/message/work_error_message_entity.dart new file mode 100644 index 0000000..1c67206 --- /dev/null +++ b/lib/message/work_error_message_entity.dart @@ -0,0 +1,27 @@ +import 'package:c_clipboard/generated/json/base/json_field.dart'; +import 'package:c_clipboard/generated/json/work_error_message_entity.g.dart'; +import 'dart:convert'; + +import 'Message.dart'; + +@JsonSerializable() +class WorkErrorMessage implements Message{ + @JSONField(name: "WorkErrorMessage") + List workErrorMessage = []; + + WorkErrorMessage(); + + factory WorkErrorMessage.fromJson(Map json) => $WorkErrorMessageEntityFromJson(json); + + Map toJson() => $WorkErrorMessageEntityToJson(this); + + @override + String toString() { + return jsonEncode(this); + } + + @override + int getTypeId() { + return 0; + } +} \ No newline at end of file diff --git a/lib/parent.dart b/lib/parent.dart new file mode 100644 index 0000000..68f32a8 --- /dev/null +++ b/lib/parent.dart @@ -0,0 +1,69 @@ + +import 'package:c_clipboard/test.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class FatherOutContainer extends StatefulWidget { + const FatherOutContainer({super.key}); + + @override + State createState() => _FatherOutContainerState(); +} + +class _FatherOutContainerState extends State { + @override + void initState() { + // TODO: implement initState + super.initState(); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + } + + // 这里是父组件方法 + void fatherFunction(String param) { + print("这里是父组件方法 params:${param}"); + } + + @override + Widget build(BuildContext context) { + return Container( + width: 375, + height: 600, + color: Colors.amber, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox( + width: 20, + height: 100, + ), + SubChild( + key: globalKey, + onPressedCallback: (param) { + fatherFunction(param); + }, + ), + SizedBox( + width: 20, + height: 40, + ), + TextButton( + child: Text("点击调用子组件方法"), + onPressed: () { + String arg = "来自父组件的参数"; + globalKey.currentState?.subFunction(arg); + }, + ), + Expanded(child: Container()), + ], + ), + ); + } +} + + diff --git a/lib/test.dart b/lib/test.dart new file mode 100644 index 0000000..bafa17e --- /dev/null +++ b/lib/test.dart @@ -0,0 +1,67 @@ + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +GlobalKey<_SubChildState> globalKey = GlobalKey(); + +// 子组件Widget +class SubChild extends StatefulWidget { + const SubChild({ + super.key, + required this.onPressedCallback, + }); + + final Function(String param) onPressedCallback; + + @override + State createState() => _SubChildState(); +} + +class _SubChildState extends State { + @override + void initState() { + // TODO: implement initState + super.initState(); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + } + + // 这里是子组件方法 + void subFunction(String arg) { + print("这里是子组件方法 arg:${arg}"); + } + + @override + Widget build(BuildContext context) { + return Container( + width: 300, + height: 300, + color: Colors.greenAccent, + child: Container( + width: 200, + height: 50, + child: TextButton( + child: Text("点击调用父组件方法", style: TextStyle( + color: Colors.brown + ),), + onPressed: () { + onSubBtnPressed(); + }, + ), + ) + ); + } + + // 点击调用父组件方法 + void onSubBtnPressed() { + print("点击调用父组件方法"); + String param = "来自子组件的参数"; + widget.onPressedCallback(param); + } +} + + diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..0904a67 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,418 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.4.10" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.4.1" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.3" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.6" + device_info_plus: + dependency: "direct main" + description: + name: device_info_plus + sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" + url: "https://pub.flutter-io.cn" + source: hosted + version: "9.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.0.0" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.0.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.13.1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.3" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.9" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "8.2.2" + image: + dependency: transitive + description: + name: image + sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e" + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.1.7" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.8.1" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.10.0" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.0.2" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.8" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.7.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.2" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.6.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.10+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.10+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.10+1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.2.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.2" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.7.0-0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..22f8995 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,120 @@ +name: c_clipboard +description: "A Sync App" +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=3.2.3 <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + # flutter_verification_box: ^1.0.4 + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + device_info_plus: ^9.1.2 + flutter_svg: ^2.0.9 + fluttertoast: 8.2.2 + + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 + flutter_launcher_icons: "^0.13.1" + + +flutter_launcher_icons: + # android: "launcher_icon" + ios: true + image_path: "assets/image/icon.png" +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # 目录批量指定并不递归,只有在该目录下的文件才可以被包括,如果下面还有子目录的话,需要单独声明子目录下的文件。 + assets: + - assets/image/ + - assets/svg/ + - assets/image/phone.png + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages +# flutter_launcher_icons: +# android: "launcher_icon" +# ios: true +# image_path: "assets/image/icon.png" +# min_sdk_android: 21 # android min sdk min:16, default 21 +# web: +# generate: true +# image_path: "path/to/image.png" +# background_color: "#hexcode" +# theme_color: "#hexcode" +# windows: +# generate: true +# image_path: "path/to/image.png" +# icon_size: 48 # min:48, max:256, default: 48 +# macos: +# generate: true +# image_path: "path/to/image.png" diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..730566a --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:c_clipboard/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +}