diff --git a/.gitignore b/.gitignore
index f8d19d4..d5aa5f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,7 +19,7 @@ migrate_working_dir/
# 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/
+.vscode/
# Flutter/Dart/Pub related
**/doc/api/
@@ -42,4 +42,4 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
-/android/key.properties
\ No newline at end of file
+/android/key.properties
diff --git a/.metadata b/.metadata
index 0b30307..acfc1cf 100644
--- a/.metadata
+++ b/.metadata
@@ -1,11 +1,11 @@
# 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.
+# This file should be version controlled and should not be manually edited.
version:
- revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
- channel: stable
+ revision: "6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e"
+ channel: "stable"
project_type: app
@@ -13,11 +13,26 @@ project_type: app
migration:
platforms:
- platform: root
- create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
- base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
+ create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ - platform: android
+ create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ - platform: ios
+ create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ - platform: linux
+ create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ - platform: macos
+ create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ - platform: web
+ create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
- platform: windows
- create_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
- base_revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf
+ create_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
+ base_revision: 6c4930c4ac86fb286f30e31d0ec8bffbcbb9953e
# User provided section
diff --git a/README.md b/README.md
index 5016559..da8eaf2 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
# ReCon
-A Resonite Contacts App for Android
+A Resonite Contacts App
[Get it here](https://github.com/Nutcake/ReCon/releases/latest)
@@ -10,10 +10,10 @@ A Resonite Contacts App for Android
This is a standard Flutter application, refer to the [Flutter docs](https://docs.flutter.dev/get-started/install) on how to build it.
-Currently only Android is supported.
+Currently only Android is fully supported.
-In theory this app should also build fine for desktop, though not every feature will be functional.
-For example, voice-messages and notifications are currently not supported on desktop builds.
+The app works on other platforms, though not every feature will be functional.
+For example, notifications are currently not supported on non-android builds.
## Screenshots
diff --git a/android/app/build.gradle b/android/app/build.gradle
index e2844ec..5ddc060 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -50,7 +50,7 @@ android {
defaultConfig {
applicationId "me.voidspace.recon"
- minSdkVersion 21
+ minSdkVersion 24
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
diff --git a/android/app/src/main/kotlin/me/voidspace/recon/MainActivity.kt b/android/app/src/main/kotlin/me/voidspace/recon/MainActivity.kt
new file mode 100644
index 0000000..7d54812
--- /dev/null
+++ b/android/app/src/main/kotlin/me/voidspace/recon/MainActivity.kt
@@ -0,0 +1,6 @@
+package me.voidspace.recon
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
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..9625e10
--- /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
+ 11.0
+
+
diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig
new file mode 100644
index 0000000..ec97fc6
--- /dev/null
+++ b/ios/Flutter/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "Generated.xcconfig"
diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig
new file mode 100644
index 0000000..c4855bf
--- /dev/null
+++ b/ios/Flutter/Release.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "Generated.xcconfig"
diff --git a/ios/Podfile b/ios/Podfile
new file mode 100644
index 0000000..9a3af86
--- /dev/null
+++ b/ios/Podfile
@@ -0,0 +1,47 @@
+# Uncomment this line to define a global platform for your project
+platform :ios, '13.0'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+ target 'RunnerTests' do
+ inherit! :search_paths
+ end
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_ios_build_settings(target)
+ target.build_configurations.each do |config|
+ config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
+ end
+ end
+end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
new file mode 100644
index 0000000..5924ee2
--- /dev/null
+++ b/ios/Podfile.lock
@@ -0,0 +1,180 @@
+PODS:
+ - audio_session (0.0.1):
+ - Flutter
+ - background_downloader (0.0.1):
+ - Flutter
+ - camera_avfoundation (0.0.1):
+ - Flutter
+ - DKImagePickerController/Core (4.3.4):
+ - DKImagePickerController/ImageDataManager
+ - DKImagePickerController/Resource
+ - DKImagePickerController/ImageDataManager (4.3.4)
+ - DKImagePickerController/PhotoGallery (4.3.4):
+ - DKImagePickerController/Core
+ - DKPhotoGallery
+ - DKImagePickerController/Resource (4.3.4)
+ - DKPhotoGallery (0.0.17):
+ - DKPhotoGallery/Core (= 0.0.17)
+ - DKPhotoGallery/Model (= 0.0.17)
+ - DKPhotoGallery/Preview (= 0.0.17)
+ - DKPhotoGallery/Resource (= 0.0.17)
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Core (0.0.17):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Preview
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Model (0.0.17):
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Preview (0.0.17):
+ - DKPhotoGallery/Model
+ - DKPhotoGallery/Resource
+ - SDWebImage
+ - SwiftyGif
+ - DKPhotoGallery/Resource (0.0.17):
+ - SDWebImage
+ - SwiftyGif
+ - ffmpeg-kit-ios-audio (6.0)
+ - ffmpeg_kit_flutter_audio (6.0.3):
+ - ffmpeg_kit_flutter_audio/audio (= 6.0.3)
+ - Flutter
+ - ffmpeg_kit_flutter_audio/audio (6.0.3):
+ - ffmpeg-kit-ios-audio (= 6.0)
+ - Flutter
+ - file_picker (0.0.1):
+ - DKImagePickerController/PhotoGallery
+ - Flutter
+ - Flutter (1.0.0)
+ - flutter_local_notifications (0.0.1):
+ - Flutter
+ - flutter_secure_storage (6.0.0):
+ - Flutter
+ - FMDB (2.7.5):
+ - FMDB/standard (= 2.7.5)
+ - FMDB/standard (2.7.5)
+ - image_picker_ios (0.0.1):
+ - Flutter
+ - just_audio (0.0.1):
+ - Flutter
+ - package_info_plus (0.4.5):
+ - Flutter
+ - path_provider_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - permission_handler_apple (9.1.1):
+ - Flutter
+ - record_darwin (1.0.0):
+ - Flutter
+ - FlutterMacOS
+ - SDWebImage (5.13.2):
+ - SDWebImage/Core (= 5.13.2)
+ - SDWebImage/Core (5.13.2)
+ - share_plus (0.0.1):
+ - Flutter
+ - sqflite (0.0.3):
+ - Flutter
+ - FMDB (>= 2.7.5)
+ - SwiftyGif (5.4.4)
+ - url_launcher_ios (0.0.1):
+ - Flutter
+ - workmanager (0.0.1):
+ - Flutter
+
+DEPENDENCIES:
+ - audio_session (from `.symlinks/plugins/audio_session/ios`)
+ - background_downloader (from `.symlinks/plugins/background_downloader/ios`)
+ - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
+ - ffmpeg_kit_flutter_audio (from `.symlinks/plugins/ffmpeg_kit_flutter_audio/ios`)
+ - file_picker (from `.symlinks/plugins/file_picker/ios`)
+ - Flutter (from `Flutter`)
+ - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
+ - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
+ - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
+ - just_audio (from `.symlinks/plugins/just_audio/ios`)
+ - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
+ - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
+ - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
+ - record_darwin (from `.symlinks/plugins/record_darwin/ios`)
+ - share_plus (from `.symlinks/plugins/share_plus/ios`)
+ - sqflite (from `.symlinks/plugins/sqflite/ios`)
+ - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+ - workmanager (from `.symlinks/plugins/workmanager/ios`)
+
+SPEC REPOS:
+ trunk:
+ - DKImagePickerController
+ - DKPhotoGallery
+ - ffmpeg-kit-ios-audio
+ - FMDB
+ - SDWebImage
+ - SwiftyGif
+
+EXTERNAL SOURCES:
+ audio_session:
+ :path: ".symlinks/plugins/audio_session/ios"
+ background_downloader:
+ :path: ".symlinks/plugins/background_downloader/ios"
+ camera_avfoundation:
+ :path: ".symlinks/plugins/camera_avfoundation/ios"
+ ffmpeg_kit_flutter_audio:
+ :path: ".symlinks/plugins/ffmpeg_kit_flutter_audio/ios"
+ file_picker:
+ :path: ".symlinks/plugins/file_picker/ios"
+ Flutter:
+ :path: Flutter
+ flutter_local_notifications:
+ :path: ".symlinks/plugins/flutter_local_notifications/ios"
+ flutter_secure_storage:
+ :path: ".symlinks/plugins/flutter_secure_storage/ios"
+ image_picker_ios:
+ :path: ".symlinks/plugins/image_picker_ios/ios"
+ just_audio:
+ :path: ".symlinks/plugins/just_audio/ios"
+ package_info_plus:
+ :path: ".symlinks/plugins/package_info_plus/ios"
+ path_provider_foundation:
+ :path: ".symlinks/plugins/path_provider_foundation/darwin"
+ permission_handler_apple:
+ :path: ".symlinks/plugins/permission_handler_apple/ios"
+ record_darwin:
+ :path: ".symlinks/plugins/record_darwin/ios"
+ share_plus:
+ :path: ".symlinks/plugins/share_plus/ios"
+ sqflite:
+ :path: ".symlinks/plugins/sqflite/ios"
+ url_launcher_ios:
+ :path: ".symlinks/plugins/url_launcher_ios/ios"
+ workmanager:
+ :path: ".symlinks/plugins/workmanager/ios"
+
+SPEC CHECKSUMS:
+ audio_session: 4f3e461722055d21515cf3261b64c973c062f345
+ background_downloader: 6f55e5548875be2ad4bb91b542558b5be22f339a
+ camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb
+ DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
+ DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
+ ffmpeg-kit-ios-audio: 9fa9953fc197280a69e59c603c7fa7690df7190c
+ ffmpeg_kit_flutter_audio: 9b107d9902e16804c90637cd7f42106a5447a9e6
+ file_picker: 15fd9539e4eb735dc54bae8c0534a7a9511a03de
+ Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
+ flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
+ flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
+ FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
+ image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
+ just_audio: baa7252489dbcf47a4c7cc9ca663e9661c99aafa
+ package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
+ path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
+ permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
+ record_darwin: 1f6619f2abac4d1ca91d3eeab038c980d76f1517
+ SDWebImage: 72f86271a6f3139cc7e4a89220946489d4b9a866
+ share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
+ sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
+ SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
+ url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86
+ workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
+
+PODFILE CHECKSUM: 0a7d5b7d0e53420cb0284f7b2f171f93843b94d2
+
+COCOAPODS: 1.12.1
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..88f7ac5
--- /dev/null
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,744 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 3EACF4502AF94B2E0009EB00 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3BAB80CE2FD566CD74754C6 /* Pods_Runner.framework */; };
+ 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 */; };
+ A04538A4FD002863EA8D7E2E /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B83C597EDF1CEFE95FFFB1B /* Pods_RunnerTests.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 97C146E61CF9000F007C117D /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 97C146ED1CF9000F007C117D;
+ remoteInfo = Runner;
+ };
+/* End PBXContainerItemProxy 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 = ""; };
+ 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; };
+ 35345364120A3EBED9C200D8 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; };
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 3EACF44C2AF946870009EB00 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
+ 3EACF44D2AF94B1B0009EB00 /* sqflite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = sqflite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6357E70700B420135CF38106 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; };
+ 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 = ""; };
+ 8B83C597EDF1CEFE95FFFB1B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 947052A3147FEB296CDB1CF8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; };
+ 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 /* ReCon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReCon.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 = ""; };
+ 98689629DBCBD9B9079D4BCB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
+ 9B70C4D26DEBAB78C4541963 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ ACF34F80AF1EDFE1E02822A3 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ C3BAB80CE2FD566CD74754C6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 2597599605DD2CD4DB799735 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ A04538A4FD002863EA8D7E2E /* Pods_RunnerTests.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3EACF4502AF94B2E0009EB00 /* Pods_Runner.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 331C8082294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXGroup;
+ children = (
+ 331C807B294A618700263BE5 /* RunnerTests.swift */,
+ );
+ path = RunnerTests;
+ sourceTree = "";
+ };
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ 331C8082294A63A400263BE5 /* RunnerTests */,
+ EB365C9671FE77D43024480F /* Pods */,
+ F90E3A4B697A7FB1786B0BCF /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* ReCon.app */,
+ 331C8081294A63A400263BE5 /* RunnerTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 3EACF44C2AF946870009EB00 /* Runner.entitlements */,
+ 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 = "";
+ };
+ EB365C9671FE77D43024480F /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 98689629DBCBD9B9079D4BCB /* Pods-Runner.debug.xcconfig */,
+ ACF34F80AF1EDFE1E02822A3 /* Pods-Runner.release.xcconfig */,
+ 9B70C4D26DEBAB78C4541963 /* Pods-Runner.profile.xcconfig */,
+ 35345364120A3EBED9C200D8 /* Pods-RunnerTests.debug.xcconfig */,
+ 6357E70700B420135CF38106 /* Pods-RunnerTests.release.xcconfig */,
+ 947052A3147FEB296CDB1CF8 /* Pods-RunnerTests.profile.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+ F90E3A4B697A7FB1786B0BCF /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 3EACF44D2AF94B1B0009EB00 /* sqflite.framework */,
+ C3BAB80CE2FD566CD74754C6 /* Pods_Runner.framework */,
+ 8B83C597EDF1CEFE95FFFB1B /* Pods_RunnerTests.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 331C8080294A63A400263BE5 /* RunnerTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
+ buildPhases = (
+ 19ED0D0FE3A6C2191496F46B /* [CP] Check Pods Manifest.lock */,
+ 331C807D294A63A400263BE5 /* Sources */,
+ 331C807F294A63A400263BE5 /* Resources */,
+ 2597599605DD2CD4DB799735 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 331C8086294A63A400263BE5 /* PBXTargetDependency */,
+ );
+ name = RunnerTests;
+ productName = RunnerTests;
+ productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 197307D9FE00A90F03801302 /* [CP] Check Pods Manifest.lock */,
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ BDF85620D00D0FE7A8BAEF7B /* [CP] Embed Pods Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 97C146EE1CF9000F007C117D /* ReCon.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 */
+ 197307D9FE00A90F03801302 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 19ED0D0FE3A6C2191496F46B /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 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";
+ };
+ BDF85620D00D0FE7A8BAEF7B /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* 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 = "Apple Development: grwdragon@gmail.com (GDFAMRH4F8)";
+ "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;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = "iphonesimulator 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;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = P9AV4LPNLL;
+ ENABLE_BITCODE = NO;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 11.0;
+ MARKETING_VERSION = 0.10.3;
+ PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon;
+ PRODUCT_NAME = ReCon;
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Profile;
+ };
+ 331C8088294A63A400263BE5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 35345364120A3EBED9C200D8 /* 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 = me.voidspace.recon.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 = 6357E70700B420135CF38106 /* 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 = me.voidspace.recon.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 = 947052A3147FEB296CDB1CF8 /* 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 = me.voidspace.recon.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 = "Apple Development: grwdragon@gmail.com (GDFAMRH4F8)";
+ "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;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ 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 = "Apple Development: grwdragon@gmail.com (GDFAMRH4F8)";
+ "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;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = "iphonesimulator 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;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = P9AV4LPNLL;
+ ENABLE_BITCODE = NO;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 11.0;
+ MARKETING_VERSION = 0.10.3;
+ PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon;
+ PRODUCT_NAME = ReCon;
+ 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;
+ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = P9AV4LPNLL;
+ ENABLE_BITCODE = NO;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 11.0;
+ MARKETING_VERSION = 0.10.3;
+ PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon;
+ PRODUCT_NAME = ReCon;
+ 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..30e0c22
--- /dev/null
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..21a3cc1
--- /dev/null
+++ b/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
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..9e18cb0
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,104 @@
+{
+ "images": [
+ {
+ "filename": "Icon_40x40@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "40x40"
+ },
+ {
+ "filename": "Icon_58x58@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "58x58"
+ },
+ {
+ "filename": "Icon_60x60@3x.png",
+ "idiom": "universal",
+ "scale": "3x",
+ "size": "60x60"
+ },
+ {
+ "filename": "Icon_76x76@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "76x76"
+ },
+ {
+ "filename": "Icon_80x80@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "80x80"
+ },
+ {
+ "filename": "Icon_87x87@3x.png",
+ "idiom": "universal",
+ "scale": "3x",
+ "size": "87x87"
+ },
+ {
+ "filename": "Icon_114x114@3x.png",
+ "idiom": "universal",
+ "scale": "3x",
+ "size": "114x114"
+ },
+ {
+ "filename": "Icon_120x120@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "120x120"
+ },
+ {
+ "filename": "Icon_120x120@3x.png",
+ "idiom": "universal",
+ "scale": "3x",
+ "size": "120x120"
+ },
+ {
+ "filename": "Icon_128x128@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "128x128"
+ },
+ {
+ "filename": "Icon_136x136@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "136x136"
+ },
+ {
+ "filename": "Icon_152x152@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "152x152"
+ },
+ {
+ "filename": "Icon_167x167@2x.png",
+ "idiom": "universal",
+ "scale": "2x",
+ "size": "167x167"
+ },
+ {
+ "filename": "Icon_180x180@3x.png",
+ "idiom": "universal",
+ "scale": "3x",
+ "size": "180x180"
+ },
+ {
+ "filename": "Icon_192x192@3x.png",
+ "idiom": "universal",
+ "scale": "3x",
+ "size": "192x192"
+ },
+ {
+ "filename": "Icon-App-iTunes.png",
+ "idiom": "ios-marketing",
+ "scale": "1x",
+ "size": "1024x1024"
+ }
+ ],
+ "info": {
+ "author": "me.voidspace",
+ "version": 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png
new file mode 100644
index 0000000..c09f06b
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_114×114@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_114×114@3x.png
new file mode 100644
index 0000000..1fcb422
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_114×114@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_120×120@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_120×120@2x.png
new file mode 100644
index 0000000..59b2189
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_120×120@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_120×120@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_120×120@3x.png
new file mode 100644
index 0000000..59b2189
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_120×120@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_128×128@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_128×128@2x.png
new file mode 100644
index 0000000..cbe3994
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_128×128@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_136×136@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_136×136@2x.png
new file mode 100644
index 0000000..f2d74f8
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_136×136@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_152×152@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_152×152@2x.png
new file mode 100644
index 0000000..053e852
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_152×152@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_167x167@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_167x167@2x.png
new file mode 100644
index 0000000..84b14a1
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_167x167@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_180×180@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_180×180@3x.png
new file mode 100644
index 0000000..1561fe1
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_180×180@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_192×192@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_192×192@3x.png
new file mode 100644
index 0000000..241d86c
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_192×192@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_40×40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_40×40@2x.png
new file mode 100644
index 0000000..11be4c9
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_40×40@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_58×58@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_58×58@2x.png
new file mode 100644
index 0000000..cbf20ab
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_58×58@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_60×60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_60×60@3x.png
new file mode 100644
index 0000000..e92b902
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_60×60@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_76×76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_76×76@2x.png
new file mode 100644
index 0000000..4df26dd
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_76×76@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_80×80@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_80×80@2x.png
new file mode 100644
index 0000000..bb479ce
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_80×80@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_87×87@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_87×87@3x.png
new file mode 100644
index 0000000..e44a290
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon_87×87@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
new file mode 100644
index 0000000..0bedcf2
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
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 0000000..9da19ea
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
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 0000000..9da19ea
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
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..7b71a45
--- /dev/null
+++ b/ios/Runner/Info.plist
@@ -0,0 +1,55 @@
+
+
+
+
+ CADisableMinimumFrameDurationOnPhone
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ ReCon
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ReCon
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UIBackgroundModes
+
+ fetch
+ processing
+ remote-notification
+
+ UILaunchStoryboardName
+ LaunchScreen.storyboard
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
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/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements
new file mode 100644
index 0000000..39f5fef
--- /dev/null
+++ b/ios/Runner/Runner.entitlements
@@ -0,0 +1,10 @@
+
+
+
+
+ keychain-access-groups
+
+ $(AppIdentifierPrefix)me.voidspace.recon
+
+
+
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/clients/audio_cache_client.dart b/lib/clients/audio_cache_client.dart
index 3954444..619b0ab 100644
--- a/lib/clients/audio_cache_client.dart
+++ b/lib/clients/audio_cache_client.dart
@@ -1,24 +1,39 @@
import 'dart:io';
-import 'package:recon/auxiliary.dart';
-import 'package:recon/clients/api_client.dart';
+import 'package:ffmpeg_kit_flutter_audio/ffmpeg_kit.dart';
import 'package:http/http.dart' as http;
-import 'package:recon/models/message.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
+import 'package:recon/auxiliary.dart';
+import 'package:recon/clients/api_client.dart';
+import 'package:recon/models/message.dart';
class AudioCacheClient {
final Future _directoryFuture = getTemporaryDirectory();
+ final bool _isDarwin = Platform.isMacOS || Platform.isIOS;
Future cachedNetworkAudioFile(AudioClipContent clip) async {
final directory = await _directoryFuture;
- final file = File("${directory.path}/${basename(clip.assetUri)}");
+ final fileName = basenameWithoutExtension(clip.assetUri);
+ final file = File("${directory.path}/$fileName.ogg");
if (!await file.exists()) {
await file.create(recursive: true);
final response = await http.get(Uri.parse(Aux.resdbToHttp(clip.assetUri)));
ApiClient.checkResponseCode(response);
await file.writeAsBytes(response.bodyBytes);
}
+ if (_isDarwin) {
+ final wavFile = File("${directory.path}/$fileName.wav");
+ final wavFileExists = await wavFile.exists();
+ if (wavFileExists && await wavFile.length() == 0) {
+ await wavFile.delete();
+ }
+ if (!wavFileExists) {
+ await wavFile.create(recursive: true);
+ await FFmpegKit.executeAsync("-y -acodec libvorbis -i ${file.path} -acodec pcm_s16le ${wavFile.path}");
+ }
+ return wavFile;
+ }
return file;
}
-}
\ No newline at end of file
+}
diff --git a/lib/clients/notification_client.dart b/lib/clients/notification_client.dart
index 831fac9..812cdde 100644
--- a/lib/clients/notification_client.dart
+++ b/lib/clients/notification_client.dart
@@ -1,10 +1,10 @@
import 'dart:convert';
+import 'package:collection/collection.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart' as fln;
import 'package:recon/auxiliary.dart';
import 'package:recon/models/message.dart';
import 'package:recon/models/session.dart';
-import 'package:flutter_local_notifications/flutter_local_notifications.dart' as fln;
-import 'package:collection/collection.dart';
class NotificationChannel {
final String id;
@@ -22,11 +22,12 @@ class NotificationClient {
);
final fln.FlutterLocalNotificationsPlugin _notifier = fln.FlutterLocalNotificationsPlugin()
- ..initialize(
- const fln.InitializationSettings(
- android: fln.AndroidInitializationSettings("ic_notification"),
- )
- );
+ ..initialize(const fln.InitializationSettings(
+ android: fln.AndroidInitializationSettings("ic_notification"),
+ iOS: fln.DarwinInitializationSettings(),
+ macOS: fln.DarwinInitializationSettings(),
+ linux: fln.LinuxInitializationSettings(defaultActionName: "Open ReCon"),
+ ));
Future showUnreadMessagesNotification(Iterable messages) async {
if (messages.isEmpty) return;
@@ -39,56 +40,57 @@ class NotificationClient {
uname.hashCode,
null,
null,
- fln.NotificationDetails(android: fln.AndroidNotificationDetails(
- _messageChannel.id,
- _messageChannel.name,
- channelDescription: _messageChannel.description,
- importance: fln.Importance.high,
- priority: fln.Priority.max,
- actions: [], //TODO: Make clicking message notification open chat of specified user.
- styleInformation: fln.MessagingStyleInformation(
- fln.Person(
- name: uname,
- bot: false,
+ fln.NotificationDetails(
+ android: fln.AndroidNotificationDetails(
+ _messageChannel.id,
+ _messageChannel.name,
+ channelDescription: _messageChannel.description,
+ importance: fln.Importance.high,
+ priority: fln.Priority.max,
+ actions: [], //TODO: Make clicking message notification open chat of specified user.
+ styleInformation: fln.MessagingStyleInformation(
+ fln.Person(
+ name: uname,
+ bot: false,
+ ),
+ groupConversation: false,
+ messages: entry.value.map((message) {
+ String content;
+ switch (message.type) {
+ case MessageType.unknown:
+ content = "Unknown Message Type";
+ break;
+ case MessageType.text:
+ content = message.content;
+ break;
+ case MessageType.sound:
+ content = "Audio Message";
+ break;
+ case MessageType.sessionInvite:
+ try {
+ final session = Session.fromMap(jsonDecode(message.content));
+ content = "Session Invite to ${session.name}";
+ } catch (e) {
+ content = "Session Invite";
+ }
+ break;
+ case MessageType.object:
+ content = "Asset";
+ break;
+ }
+ return fln.Message(
+ content,
+ message.sendTime.toLocal(),
+ fln.Person(
+ name: uname,
+ bot: false,
+ ),
+ );
+ }).toList(),
),
- groupConversation: false,
- messages: entry.value.map((message) {
- String content;
- switch (message.type) {
- case MessageType.unknown:
- content = "Unknown Message Type";
- break;
- case MessageType.text:
- content = message.content;
- break;
- case MessageType.sound:
- content = "Audio Message";
- break;
- case MessageType.sessionInvite:
- try {
- final session = Session.fromMap(jsonDecode(message.content));
- content = "Session Invite to ${session.name}";
- } catch (e) {
- content = "Session Invite";
- }
- break;
- case MessageType.object:
- content = "Asset";
- break;
- }
- return fln.Message(
- content,
- message.sendTime.toLocal(),
- fln.Person(
- name: uname,
- bot: false,
- ),
- );
- }).toList(),
),
),
- ),
);
}
}
-}
\ No newline at end of file
+}
diff --git a/lib/main.dart b/lib/main.dart
index c940b2e..8de17ae 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,10 +1,12 @@
import 'dart:developer';
+import 'dart:isolate';
+import 'dart:ui';
+import 'package:background_downloader/background_downloader.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
-import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:flutter_phoenix/flutter_phoenix.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:intl/intl.dart';
@@ -28,10 +30,6 @@ import 'models/authentication_data.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
- await FlutterDownloader.initialize(
- debug: kDebugMode,
- );
-
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
systemStatusBarContrastEnforced: true,
@@ -57,7 +55,9 @@ void main() async {
AuthenticationData cachedAuth = AuthenticationData.unauthenticated();
try {
cachedAuth = await ApiClient.tryCachedLogin();
- } catch (_) {}
+ } catch (_) {
+ // Ignore
+ }
runApp(ReCon(settingsClient: settingsClient, cachedAuthentication: cachedAuth));
}
@@ -73,7 +73,8 @@ class ReCon extends StatefulWidget {
}
class _ReConState extends State {
- final Typography _typography = Typography.material2021(platform: TargetPlatform.android);
+ final Typography _typography = Typography.material2021(platform: defaultTargetPlatform);
+ final ReceivePort _port = ReceivePort();
late AuthenticationData _authData = widget.cachedAuthentication;
bool _checkedForUpdate = false;
@@ -124,6 +125,30 @@ class _ReConState extends State {
});
}
+ @override
+ void initState() {
+ super.initState();
+
+ IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
+ _port.listen((dynamic data) {
+ // Not useful yet? idk...
+ // String id = data[0];
+ // DownloadTaskStatus status = data[1];
+ // int progress = data[2];
+ });
+
+ FileDownloader().updates.listen(downloadCallback);
+ }
+
+ @override
+ void dispose() {
+ IsolateNameServer.removePortNameMapping('downloader_send_port');
+ super.dispose();
+ }
+
+ @pragma('vm:entry-point')
+ static void downloadCallback(TaskUpdate event) {}
+
@override
Widget build(BuildContext context) {
return Phoenix(
diff --git a/lib/widgets/homepage.dart b/lib/widgets/homepage.dart
index 1397037..2cbece2 100644
--- a/lib/widgets/homepage.dart
+++ b/lib/widgets/homepage.dart
@@ -1,3 +1,4 @@
+import 'package:flutter/material.dart';
import 'package:recon/widgets/friends/friends_list.dart';
import 'package:recon/widgets/friends/friends_list_app_bar.dart';
import 'package:recon/widgets/inventory/inventory_browser.dart';
@@ -6,7 +7,6 @@ import 'package:recon/widgets/sessions/session_list.dart';
import 'package:recon/widgets/sessions/session_list_app_bar.dart';
import 'package:recon/widgets/settings_app_bar.dart';
import 'package:recon/widgets/settings_page.dart';
-import 'package:flutter/material.dart';
class Home extends StatefulWidget {
const Home({super.key});
@@ -80,4 +80,4 @@ class _HomeState extends State {
),
);
}
-}
\ No newline at end of file
+}
diff --git a/lib/widgets/inventory/inventory_browser_app_bar.dart b/lib/widgets/inventory/inventory_browser_app_bar.dart
index 040b545..f2ec14e 100644
--- a/lib/widgets/inventory/inventory_browser_app_bar.dart
+++ b/lib/widgets/inventory/inventory_browser_app_bar.dart
@@ -1,11 +1,13 @@
+import 'dart:io';
import 'dart:isolate';
import 'dart:ui';
+import 'package:background_downloader/background_downloader.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:intl/intl.dart';
import 'package:path/path.dart';
+import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
import 'package:recon/auxiliary.dart';
import 'package:recon/clients/inventory_client.dart';
@@ -19,32 +21,15 @@ class InventoryBrowserAppBar extends StatefulWidget {
}
class _InventoryBrowserAppBarState extends State {
- final ReceivePort _port = ReceivePort();
-
- @override
- void initState() {
- super.initState();
-
- IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port');
- _port.listen((dynamic data) {
- // Not useful yet? idk...
- // String id = data[0];
- // DownloadTaskStatus status = data[1];
- // int progress = data[2];
- });
-
- FlutterDownloader.registerCallback(downloadCallback);
- }
-
- @override
- void dispose() {
- IsolateNameServer.removePortNameMapping('downloader_send_port');
- super.dispose();
- }
+ final Future _tempDirectoryFuture = getTemporaryDirectory();
@pragma('vm:entry-point')
- static void downloadCallback(String id, int status, int progress) {
+ static void downloadCallback(TaskUpdate event) {
+ final id = event.task.taskId;
+ final status = event is TaskStatusUpdate ? event.status : null;
+ final progress = event is TaskProgressUpdate ? event.progress : null;
final SendPort? send = IsolateNameServer.lookupPortByName('downloader_send_port');
+
send?.send([id, status, progress]);
}
@@ -247,16 +232,51 @@ class _InventoryBrowserAppBarState extends State {
}
return;
}
+
for (var record in selectedRecords) {
final uri = selectedUris == thumbUris ? record.thumbnailUri : record.assetUri;
- await FlutterDownloader.enqueue(
- url: Aux.resdbToHttp(uri),
- savedDir: directory,
- showNotification: true,
- openFileFromNotification: false,
- fileName:
- "${record.id.split("-")[1]}-${record.formattedName.toString()}${extension(uri)}",
- );
+ final filename =
+ "${record.id.split("-")[1]}-${record.formattedName.toString()}${extension(uri)}";
+ try {
+ final downloadTask = DownloadTask(
+ url: Aux.resdbToHttp(uri),
+ allowPause: true,
+ baseDirectory: BaseDirectory.temporary,
+ filename: filename,
+ updates: Updates.statusAndProgress,
+ );
+ final downloadStatus = await FileDownloader().download(downloadTask);
+ if (downloadStatus.status == TaskStatus.complete) {
+ final tempDirectory = await _tempDirectoryFuture;
+ final file = File(
+ "${tempDirectory.path}/${record.id.split("-")[1]}-${record.formattedName.toString()}${extension(uri)}");
+ if (await file.exists()) {
+ final newFile = File("$directory/$filename");
+ await file.copy(newFile.absolute.path);
+ await file.delete();
+ }
+ if (context.mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text("Downloaded ${record.formattedName.toString()}"),
+ ),
+ );
+ } else {
+ throw downloadStatus.exception ?? "Unknown Error";
+ }
+ }
+ } catch (e, s) {
+ FlutterError.reportError(FlutterErrorDetails(exception: e, stack: s));
+ if (context.mounted) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(
+ content: Text(
+ "Failed to download '${record.formattedName.toString()}':\n$e",
+ ),
+ ),
+ );
+ }
+ }
}
iClient.clearSelectedRecords();
},
diff --git a/lib/widgets/login_screen.dart b/lib/widgets/login_screen.dart
index f974807..449340f 100644
--- a/lib/widgets/login_screen.dart
+++ b/lib/widgets/login_screen.dart
@@ -1,9 +1,11 @@
-import 'package:recon/clients/api_client.dart';
-import 'package:recon/models/authentication_data.dart';
+import 'dart:io';
+
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:recon/client_holder.dart';
+import 'package:recon/clients/api_client.dart';
+import 'package:recon/models/authentication_data.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({this.onLoginSuccessful, this.cachedUsername, super.key});
@@ -125,9 +127,21 @@ class _LoginScreenState extends State {
TextButton(
onPressed: () async {
Navigator.of(context).pop();
- final requestResult = await notificationManager
- .resolvePlatformSpecificImplementation()
- ?.requestPermission();
+ final requestResult = switch (Platform.operatingSystem) {
+ "android" => await notificationManager
+ .resolvePlatformSpecificImplementation()
+ ?.requestNotificationsPermission(),
+ "fuschia" => null, // "fuschia" is not supported by flutter_local_notifications
+ "ios" => await notificationManager
+ .resolvePlatformSpecificImplementation()
+ ?.requestPermissions(alert: true, badge: true, sound: true),
+ "linux" => null, // don't want to deal with this right now
+ "macos" => await notificationManager
+ .resolvePlatformSpecificImplementation()
+ ?.requestPermissions(alert: true, badge: true, sound: true),
+ "windows" => null, // also don't want to deal with this right now
+ _ => null,
+ };
await settingsClient.changeSettings(settingsClient.currentSettings
.copyWith(notificationsDenied: requestResult == null ? false : !requestResult));
},
diff --git a/lib/widgets/messages/message_audio_player.dart b/lib/widgets/messages/message_audio_player.dart
index e5f6573..f8e67f7 100644
--- a/lib/widgets/messages/message_audio_player.dart
+++ b/lib/widgets/messages/message_audio_player.dart
@@ -1,13 +1,12 @@
import 'dart:convert';
-import 'dart:io' show Platform;
+import 'package:flutter/material.dart';
+import 'package:just_audio/just_audio.dart';
+import 'package:provider/provider.dart';
import 'package:recon/auxiliary.dart';
import 'package:recon/clients/audio_cache_client.dart';
import 'package:recon/models/message.dart';
import 'package:recon/widgets/messages/message_state_indicator.dart';
-import 'package:flutter/material.dart';
-import 'package:just_audio/just_audio.dart';
-import 'package:provider/provider.dart';
class MessageAudioPlayer extends StatefulWidget {
const MessageAudioPlayer({required this.message, this.foregroundColor, super.key});
@@ -97,10 +96,6 @@ class _MessageAudioPlayerState extends State with WidgetsBin
@override
Widget build(BuildContext context) {
- if (!Platform.isAndroid) {
- return _createErrorWidget("Sorry, audio-messages are not\n supported on this platform.");
- }
-
return IntrinsicWidth(
child: StreamBuilder(
stream: _audioPlayer.playerStateStream,
@@ -122,8 +117,11 @@ class _MessageAudioPlayerState extends State with WidgetsBin
future: _audioFileFuture,
builder: (context, fileSnapshot) {
if (fileSnapshot.hasError) {
+ FlutterError.reportError(
+ FlutterErrorDetails(exception: fileSnapshot.error!, stack: fileSnapshot.stackTrace));
return const IconButton(
icon: Icon(Icons.warning),
+ tooltip: "Failed to load audio-message.",
onPressed: null,
);
}
diff --git a/lib/widgets/messages/message_input_bar.dart b/lib/widgets/messages/message_input_bar.dart
index d0c793c..ebe1a35 100644
--- a/lib/widgets/messages/message_input_bar.dart
+++ b/lib/widgets/messages/message_input_bar.dart
@@ -2,27 +2,23 @@ import 'dart:convert';
import 'dart:io';
import 'package:collection/collection.dart';
+import 'package:file_picker/file_picker.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:provider/provider.dart';
import 'package:recon/apis/record_api.dart';
import 'package:recon/auxiliary.dart';
import 'package:recon/client_holder.dart';
import 'package:recon/clients/api_client.dart';
import 'package:recon/clients/messaging_client.dart';
-import 'package:recon/models/users/friend.dart';
import 'package:recon/models/message.dart';
+import 'package:recon/models/users/friend.dart';
import 'package:recon/widgets/messages/message_attachment_list.dart';
-import 'package:file_picker/file_picker.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:image_picker/image_picker.dart';
-import 'package:path_provider/path_provider.dart';
-import 'package:permission_handler/permission_handler.dart';
-import 'package:provider/provider.dart';
import 'package:record/record.dart';
-import 'package:uuid/uuid.dart';
-
class MessageInputBar extends StatefulWidget {
- const MessageInputBar({this.disabled=false, required this.recipient, this.onMessageSent, super.key});
+ const MessageInputBar({this.disabled = false, required this.recipient, this.onMessageSent, super.key});
final bool disabled;
final Friend recipient;
@@ -35,7 +31,7 @@ class MessageInputBar extends StatefulWidget {
class _MessageInputBarState extends State {
final TextEditingController _messageTextController = TextEditingController();
final List<(FileType, File)> _loadedFiles = [];
- final Record _recorder = Record();
+ final AudioRecorder _recorder = AudioRecorder();
final ImagePicker _imagePicker = ImagePicker();
DateTime? _recordingStartTime;
@@ -84,8 +80,7 @@ class _MessageInputBarState extends State {
type: MessageType.object,
content: jsonEncode(record.toMap()),
sendTime: DateTime.now().toUtc(),
- state: MessageState.local
- );
+ state: MessageState.local);
mClient.sendMessage(message);
}
@@ -133,12 +128,12 @@ class _MessageInputBarState extends State {
if (!_isRecording) return;
final width = MediaQuery.of(context).size.width;
- if (event.localPosition.dx < width - width/4) {
+ if (event.localPosition.dx < width - width / 4) {
if (!_recordingCancelled) {
HapticFeedback.vibrate();
setState(() {
- _recordingCancelled = true;
- });
+ _recordingCancelled = true;
+ });
}
} else {
if (_recordingCancelled) {
@@ -193,16 +188,11 @@ class _MessageInputBarState extends State {
});
final apiClient = cHolder.apiClient;
await sendVoiceMessage(
- apiClient,
- mClient,
- file,
- cHolder.settingsClient.currentSettings.machineId.valueOrDefault,
- (progress) {
- setState(() {
- _sendProgress = progress;
- });
- }
- );
+ apiClient, mClient, file, cHolder.settingsClient.currentSettings.machineId.valueOrDefault, (progress) {
+ setState(() {
+ _sendProgress = progress;
+ });
+ });
setState(() {
_isSending = false;
_sendProgress = null;
@@ -213,104 +203,102 @@ class _MessageInputBarState extends State {
child: Container(
decoration: BoxDecoration(
border: const Border(top: BorderSide(width: 1, color: Colors.black)),
- color: Theme
- .of(context)
- .colorScheme
- .surfaceVariant,
+ color: Theme.of(context).colorScheme.surfaceVariant,
),
padding: const EdgeInsets.symmetric(horizontal: 4),
child: SafeArea(
top: false,
child: Column(
children: [
- if (_isSending && _sendProgress != null)
- LinearProgressIndicator(value: _sendProgress),
+ if (_isSending && _sendProgress != null) LinearProgressIndicator(value: _sendProgress),
Container(
decoration: BoxDecoration(
- color: Theme
- .of(context)
- .colorScheme
- .surfaceVariant,
+ color: Theme.of(context).colorScheme.surfaceVariant,
),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
switchInCurve: Curves.easeOut,
switchOutCurve: Curves.easeOut,
- transitionBuilder: (Widget child, animation) =>
- SizeTransition(sizeFactor: animation, child: child,),
- child: switch ((_attachmentPickerOpen, _loadedFiles)) {
- (true, []) =>
- Row(
- key: const ValueKey("attachment-picker"),
- children: [
- TextButton.icon(
- onPressed: _isSending ? null : () async {
- final result = await FilePicker.platform.pickFiles(
- type: FileType.image, allowMultiple: true);
- if (result != null) {
- setState(() {
- _loadedFiles.addAll(
- result.files.map((e) =>
- e.path != null ? (FileType.image, File(e.path!)) : null)
- .whereNotNull());
- });
- }
- },
- icon: const Icon(Icons.image),
- label: const Text("Gallery"),
- ),
- TextButton.icon(
- onPressed: _isSending ? null : () async {
- final picture = await _imagePicker.pickImage(source: ImageSource.camera);
- if (picture == null) {
- if (context.mounted) {
- ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Failed to get image path")));
- }
- return;
- }
- final file = File(picture.path);
- if (await file.exists()) {
- setState(() {
- _loadedFiles.add((FileType.image, file));
- });
- } else {
- if (context.mounted) {
- ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Failed to load image file")));
- }
- }
-
- },
- icon: const Icon(Icons.camera),
- label: const Text("Camera"),
- ),
- TextButton.icon(
- onPressed: _isSending ? null : () async {
- final result = await FilePicker.platform.pickFiles(
- type: FileType.any, allowMultiple: true);
- if (result != null) {
- setState(() {
- _loadedFiles.addAll(
- result.files.map((e) =>
- e.path != null ? (FileType.any, File(e.path!)) : null)
- .whereNotNull());
- });
- }
- },
- icon: const Icon(Icons.file_present_rounded),
- label: const Text("Document"),
- ),
- ],
- ),
- (false, []) => null,
- (_, _) =>
- MessageAttachmentList(
- disabled: _isSending,
- initialFiles: _loadedFiles,
- onChange: (List<(FileType, File)> loadedFiles) => setState(() {
- _loadedFiles.clear();
- _loadedFiles.addAll(loadedFiles);
- }),
+ transitionBuilder: (Widget child, animation) => SizeTransition(
+ sizeFactor: animation,
+ child: child,
),
+ child: switch ((_attachmentPickerOpen, _loadedFiles)) {
+ (true, []) => Row(
+ key: const ValueKey("attachment-picker"),
+ children: [
+ TextButton.icon(
+ onPressed: _isSending
+ ? null
+ : () async {
+ final result =
+ await FilePicker.platform.pickFiles(type: FileType.image, allowMultiple: true);
+ if (result != null) {
+ setState(() {
+ _loadedFiles.addAll(result.files
+ .map((e) => e.path != null ? (FileType.image, File(e.path!)) : null)
+ .whereNotNull());
+ });
+ }
+ },
+ icon: const Icon(Icons.image),
+ label: const Text("Gallery"),
+ ),
+ TextButton.icon(
+ onPressed: _isSending
+ ? null
+ : () async {
+ final picture = await _imagePicker.pickImage(source: ImageSource.camera);
+ if (picture == null) {
+ if (context.mounted) {
+ ScaffoldMessenger.of(context)
+ .showSnackBar(const SnackBar(content: Text("Failed to get image path")));
+ }
+ return;
+ }
+ final file = File(picture.path);
+ if (await file.exists()) {
+ setState(() {
+ _loadedFiles.add((FileType.image, file));
+ });
+ } else {
+ if (context.mounted) {
+ ScaffoldMessenger.of(context)
+ .showSnackBar(const SnackBar(content: Text("Failed to load image file")));
+ }
+ }
+ },
+ icon: const Icon(Icons.camera),
+ label: const Text("Camera"),
+ ),
+ TextButton.icon(
+ onPressed: _isSending
+ ? null
+ : () async {
+ final result =
+ await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: true);
+ if (result != null) {
+ setState(() {
+ _loadedFiles.addAll(result.files
+ .map((e) => e.path != null ? (FileType.any, File(e.path!)) : null)
+ .whereNotNull());
+ });
+ }
+ },
+ icon: const Icon(Icons.file_present_rounded),
+ label: const Text("Document"),
+ ),
+ ],
+ ),
+ (false, []) => null,
+ (_, _) => MessageAttachmentList(
+ disabled: _isSending,
+ initialFiles: _loadedFiles,
+ onChange: (List<(FileType, File)> loadedFiles) => setState(() {
+ _loadedFiles.clear();
+ _loadedFiles.addAll(loadedFiles);
+ }),
+ ),
},
),
),
@@ -318,67 +306,77 @@ class _MessageInputBarState extends State {
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
- transitionBuilder: (Widget child, Animation animation) =>
- FadeTransition(
- opacity: animation,
- child: RotationTransition(
- turns: Tween(begin: 0.6, end: 1).animate(animation),
- child: child,
+ transitionBuilder: (Widget child, Animation animation) => FadeTransition(
+ opacity: animation,
+ child: RotationTransition(
+ turns: Tween(begin: 0.6, end: 1).animate(animation),
+ child: child,
+ ),
+ ),
+ child: switch ((_attachmentPickerOpen, _isRecording)) {
+ (_, true) => IconButton(
+ onPressed: () {},
+ icon: Icon(
+ Icons.delete,
+ color: _recordingCancelled ? Theme.of(context).colorScheme.error : null,
+ ),
+ ),
+ (false, _) => IconButton(
+ key: const ValueKey("add-attachment-icon"),
+ onPressed: _isSending
+ ? null
+ : () {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text("Sorry, this feature is not yet available")));
+ return;
+ // setState(() {
+ // _attachmentPickerOpen = true;
+ // });
+ },
+ icon: const Icon(
+ Icons.attach_file,
+ ),
+ ),
+ (true, _) => IconButton(
+ key: const ValueKey("remove-attachment-icon"),
+ onPressed: _isSending
+ ? null
+ : () async {
+ if (_loadedFiles.isNotEmpty) {
+ await showDialog(
+ context: context,
+ builder: (context) => AlertDialog(
+ title: const Text("Remove all attachments"),
+ content: const Text("This will remove all attachments, are you sure?"),
+ actions: [
+ TextButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ child: const Text("No"),
+ ),
+ TextButton(
+ onPressed: () {
+ setState(() {
+ _loadedFiles.clear();
+ _attachmentPickerOpen = false;
+ });
+ Navigator.of(context).pop();
+ },
+ child: const Text("Yes"),
+ )
+ ],
+ ));
+ } else {
+ setState(() {
+ _attachmentPickerOpen = false;
+ });
+ }
+ },
+ icon: const Icon(
+ Icons.close,
),
),
- child: switch((_attachmentPickerOpen, _isRecording)) {
- (_, true) => IconButton(
- onPressed: () {
-
- },
- icon: Icon(Icons.delete, color: _recordingCancelled ? Theme.of(context).colorScheme.error : null,),
- ),
- (false, _) => IconButton(
- key: const ValueKey("add-attachment-icon"),
- onPressed: _isSending ? null : () {
- ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Sorry, this feature is not yet available")));
- return;
- setState(() {
- _attachmentPickerOpen = true;
- });
- },
- icon: const Icon(Icons.attach_file,),
- ),
- (true, _) => IconButton(
- key: const ValueKey("remove-attachment-icon"),
- onPressed: _isSending ? null : () async {
- if (_loadedFiles.isNotEmpty) {
- await showDialog(context: context, builder: (context) =>
- AlertDialog(
- title: const Text("Remove all attachments"),
- content: const Text("This will remove all attachments, are you sure?"),
- actions: [
- TextButton(
- onPressed: () {
- Navigator.of(context).pop();
- },
- child: const Text("No"),
- ),
- TextButton(
- onPressed: () {
- setState(() {
- _loadedFiles.clear();
- _attachmentPickerOpen = false;
- });
- Navigator.of(context).pop();
- },
- child: const Text("Yes"),
- )
- ],
- ));
- } else {
- setState(() {
- _attachmentPickerOpen = false;
- });
- }
- },
- icon: const Icon(Icons.close,),
- ),
},
),
Expanded(
@@ -404,61 +402,74 @@ class _MessageInputBarState extends State {
},
style: Theme.of(context).textTheme.bodyLarge,
decoration: InputDecoration(
- isDense: true,
- hintText: _isRecording ? "" : "Message ${widget.recipient
- .username}...",
- hintMaxLines: 1,
- contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
- fillColor: Colors.black26,
- filled: true,
- border: OutlineInputBorder(
- borderSide: BorderSide.none,
- borderRadius: BorderRadius.circular(24),
- )
- ),
+ isDense: true,
+ hintText: _isRecording ? "" : "Message ${widget.recipient.username}...",
+ hintMaxLines: 1,
+ contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
+ fillColor: Colors.black26,
+ filled: true,
+ border: OutlineInputBorder(
+ borderSide: BorderSide.none,
+ borderRadius: BorderRadius.circular(24),
+ )),
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
- transitionBuilder: (Widget child, Animation animation) =>
- FadeTransition(
- opacity: animation,
- child: SlideTransition(
- position: Tween(
- begin: const Offset(0, .2),
- end: const Offset(0, 0),
- ).animate(animation),
- child: child,
- ),
- ),
- child: _isRecording ? Padding(
- padding: const EdgeInsets.symmetric(vertical: 12.0),
- child: _recordingCancelled ? Row(
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- const SizedBox(width: 8,),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 8.0),
- child: Icon(Icons.cancel, color: Colors.red, size: 16,),
- ),
- Text("Cancel Recording", style: Theme.of(context).textTheme.titleMedium),
- ],
- ) : Row(
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- const SizedBox(width: 8,),
- const Padding(
- padding: EdgeInsets.symmetric(horizontal: 8.0),
- child: Icon(Icons.circle, color: Colors.red, size: 16,),
- ),
- StreamBuilder(
- stream: _recordingDurationStream(),
- builder: (context, snapshot) {
- return Text("Recording: ${snapshot.data?.format()}", style: Theme.of(context).textTheme.titleMedium);
- }
- ),
- ],
+ transitionBuilder: (Widget child, Animation animation) => FadeTransition(
+ opacity: animation,
+ child: SlideTransition(
+ position: Tween(
+ begin: const Offset(0, .2),
+ end: const Offset(0, 0),
+ ).animate(animation),
+ child: child,
),
- ) : const SizedBox.shrink(),
+ ),
+ child: _isRecording
+ ? Padding(
+ padding: const EdgeInsets.symmetric(vertical: 12.0),
+ child: _recordingCancelled
+ ? Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ const SizedBox(
+ width: 8,
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 8.0),
+ child: Icon(
+ Icons.cancel,
+ color: Colors.red,
+ size: 16,
+ ),
+ ),
+ Text("Cancel Recording", style: Theme.of(context).textTheme.titleMedium),
+ ],
+ )
+ : Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ const SizedBox(
+ width: 8,
+ ),
+ const Padding(
+ padding: EdgeInsets.symmetric(horizontal: 8.0),
+ child: Icon(
+ Icons.circle,
+ color: Colors.red,
+ size: 16,
+ ),
+ ),
+ StreamBuilder(
+ stream: _recordingDurationStream(),
+ builder: (context, snapshot) {
+ return Text("Recording: ${snapshot.data?.format()}",
+ style: Theme.of(context).textTheme.titleMedium);
+ }),
+ ],
+ ),
+ )
+ : const SizedBox.shrink(),
),
],
),
@@ -466,105 +477,128 @@ class _MessageInputBarState extends State {
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
- transitionBuilder: (Widget child, Animation animation) =>
- FadeTransition(opacity: animation, child: RotationTransition(
- turns: Tween(begin: 0.5, end: 1).animate(animation), child: child,),),
- child: _currentText.isNotEmpty || _loadedFiles.isNotEmpty ? IconButton(
- key: const ValueKey("send-button"),
- splashRadius: 24,
- padding: EdgeInsets.zero,
- onPressed: _isSending ? null : () async {
- final cHolder = ClientHolder.of(context);
- final sMsgnr = ScaffoldMessenger.of(context);
- final settings = cHolder.settingsClient.currentSettings;
- final toSend = List<(FileType, File)>.from(_loadedFiles);
- setState(() {
- _isSending = true;
- _sendProgress = 0;
- _attachmentPickerOpen = false;
- _loadedFiles.clear();
- });
- try {
- for (int i = 0; i < toSend.length; i++) {
- final totalProgress = i / toSend.length;
- final file = toSend[i];
- if (file.$1 == FileType.image) {
- await sendImageMessage(
- cHolder.apiClient, mClient, file.$2, settings.machineId.valueOrDefault,
- (progress) =>
- setState(() {
- _sendProgress = totalProgress + progress * 1 / toSend.length;
- }),
- );
- } else {
- await sendRawFileMessage(
- cHolder.apiClient, mClient, file.$2, settings.machineId.valueOrDefault, (progress) =>
- setState(() =>
- _sendProgress = totalProgress + progress * 1 / toSend.length));
- }
- }
- setState(() {
- _sendProgress = null;
- });
-
- if (_currentText.isNotEmpty) {
- await sendTextMessage(cHolder.apiClient, mClient, _messageTextController.text);
- }
- _messageTextController.clear();
- _currentText = "";
- _loadedFiles.clear();
- _attachmentPickerOpen = false;
- } catch (e, s) {
- FlutterError.reportError(FlutterErrorDetails(exception: e, stack: s));
- sMsgnr.showSnackBar(SnackBar(content: Text("Failed to send a message: $e")));
- }
- setState(() {
- _isSending = false;
- _sendProgress = null;
- });
- widget.onMessageSent?.call();
- },
- icon: const Icon(Icons.send),
- ) : GestureDetector(
- onTapUp: (_) {
- _recordingCancelled = true;
- },
- onTapDown: widget.disabled ? null : (_) async {
- ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Sorry, this feature is not yet available")));
- return;
- HapticFeedback.vibrate();
- final hadToAsk = await Permission.microphone.isDenied;
- final hasPermission = !await _recorder.hasPermission();
- if (hasPermission) {
- if (context.mounted) {
- ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
- content: Text("No permission to record audio."),
- ));
- }
- return;
- }
- if (hadToAsk) {
- // We had to ask for permissions so the user removed their finger from the record button.
- return;
- }
-
- final dir = await getTemporaryDirectory();
- await _recorder.start(
- path: "${dir.path}/A-${const Uuid().v4()}.wav",
- encoder: AudioEncoder.wav,
- samplingRate: 44100
- );
- setState(() {
- _isRecording = true;
- });
- },
- child: IconButton(
- icon: const Icon(Icons.mic_outlined),
- onPressed: _isSending ? null : () {
- // Empty onPressed for that sweet sweet ripple effect
- },
+ transitionBuilder: (Widget child, Animation animation) => FadeTransition(
+ opacity: animation,
+ child: RotationTransition(
+ turns: Tween(begin: 0.5, end: 1).animate(animation),
+ child: child,
),
),
+ child: _currentText.isNotEmpty || _loadedFiles.isNotEmpty
+ ? IconButton(
+ key: const ValueKey("send-button"),
+ splashRadius: 24,
+ padding: EdgeInsets.zero,
+ onPressed: _isSending
+ ? null
+ : () async {
+ final cHolder = ClientHolder.of(context);
+ final sMsgnr = ScaffoldMessenger.of(context);
+ final settings = cHolder.settingsClient.currentSettings;
+ final toSend = List<(FileType, File)>.from(_loadedFiles);
+ setState(() {
+ _isSending = true;
+ _sendProgress = 0;
+ _attachmentPickerOpen = false;
+ _loadedFiles.clear();
+ });
+ try {
+ for (int i = 0; i < toSend.length; i++) {
+ final totalProgress = i / toSend.length;
+ final file = toSend[i];
+ if (file.$1 == FileType.image) {
+ await sendImageMessage(
+ cHolder.apiClient,
+ mClient,
+ file.$2,
+ settings.machineId.valueOrDefault,
+ (progress) => setState(() {
+ _sendProgress = totalProgress + progress * 1 / toSend.length;
+ }),
+ );
+ } else {
+ await sendRawFileMessage(
+ cHolder.apiClient,
+ mClient,
+ file.$2,
+ settings.machineId.valueOrDefault,
+ (progress) => setState(
+ () => _sendProgress = totalProgress + progress * 1 / toSend.length));
+ }
+ }
+ setState(() {
+ _sendProgress = null;
+ });
+
+ if (_currentText.isNotEmpty) {
+ await sendTextMessage(cHolder.apiClient, mClient, _messageTextController.text);
+ }
+ _messageTextController.clear();
+ _currentText = "";
+ _loadedFiles.clear();
+ _attachmentPickerOpen = false;
+ } catch (e, s) {
+ FlutterError.reportError(FlutterErrorDetails(exception: e, stack: s));
+ sMsgnr.showSnackBar(SnackBar(content: Text("Failed to send a message: $e")));
+ }
+ setState(() {
+ _isSending = false;
+ _sendProgress = null;
+ });
+ widget.onMessageSent?.call();
+ },
+ icon: const Icon(Icons.send),
+ )
+ : GestureDetector(
+ onTapUp: (_) {
+ _recordingCancelled = true;
+ },
+ onTapDown: widget.disabled
+ ? null
+ : (_) async {
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text("Sorry, this feature is not yet available")));
+ return;
+ // HapticFeedback.vibrate();
+ // final hadToAsk =
+ // await Permission.microphone.isDenied;
+ // final hasPermission =
+ // !await _recorder.hasPermission();
+ // if (hasPermission) {
+ // if (context.mounted) {
+ // ScaffoldMessenger.of(context)
+ // .showSnackBar(const SnackBar(
+ // content: Text(
+ // "No permission to record audio."),
+ // ));
+ // }
+ // return;
+ // }
+ // if (hadToAsk) {
+ // // We had to ask for permissions so the user removed their finger from the record button.
+ // return;
+ // }
+
+ // final dir = await getTemporaryDirectory();
+ // await _recorder.start(
+ // path: "${dir.path}/A-${const Uuid().v4()}.wav",
+ // const RecordConfig(
+ // numChannels: 1,
+ // sampleRate: 44100,
+ // encoder: AudioEncoder.wav));
+ // setState(() {
+ // _isRecording = true;
+ // });
+ },
+ child: IconButton(
+ icon: const Icon(Icons.mic_outlined),
+ onPressed: _isSending
+ ? null
+ : () {
+ // Empty onPressed for that sweet sweet ripple effect
+ },
+ ),
+ ),
),
],
),
@@ -574,4 +608,4 @@ class _MessageInputBarState extends State {
),
);
}
-}
\ No newline at end of file
+}
diff --git a/lib/widgets/messages/messages_list.dart b/lib/widgets/messages/messages_list.dart
index ef3590e..a3311c8 100644
--- a/lib/widgets/messages/messages_list.dart
+++ b/lib/widgets/messages/messages_list.dart
@@ -1,4 +1,5 @@
-import 'package:collection/collection.dart';
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
import 'package:recon/clients/audio_cache_client.dart';
import 'package:recon/clients/messaging_client.dart';
import 'package:recon/models/users/friend.dart';
@@ -6,8 +7,6 @@ import 'package:recon/widgets/default_error_widget.dart';
import 'package:recon/widgets/friends/friend_online_status_indicator.dart';
import 'package:recon/widgets/messages/message_input_bar.dart';
import 'package:recon/widgets/messages/messages_session_header.dart';
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
import 'message_bubble.dart';
diff --git a/lib/widgets/messages/messages_session_header.dart b/lib/widgets/messages/messages_session_header.dart
index ee3d5f6..9c4d96f 100644
--- a/lib/widgets/messages/messages_session_header.dart
+++ b/lib/widgets/messages/messages_session_header.dart
@@ -1,10 +1,9 @@
-import 'package:cached_network_image/cached_network_image.dart';
+import 'package:flutter/material.dart';
import 'package:recon/auxiliary.dart';
import 'package:recon/models/session.dart';
import 'package:recon/widgets/formatted_text.dart';
import 'package:recon/widgets/generic_avatar.dart';
import 'package:recon/widgets/sessions/session_view.dart';
-import 'package:flutter/material.dart';
class SessionTile extends StatelessWidget {
const SessionTile({required this.session, super.key});
@@ -33,7 +32,10 @@ class SessionTile extends StatelessWidget {
FormattedText(session.formattedName),
Text(
"${session.sessionUsers.length.toString().padLeft(2, "0")}/${session.maxUsers.toString().padLeft(2, "0")} active users",
- style: Theme.of(context).textTheme.labelMedium?.copyWith(color: Theme.of(context).colorScheme.onSurface.withOpacity(.6)),
+ style: Theme.of(context)
+ .textTheme
+ .labelMedium
+ ?.copyWith(color: Theme.of(context).colorScheme.onSurface.withOpacity(.6)),
)
],
),
diff --git a/lib/widgets/sessions/session_list_app_bar.dart b/lib/widgets/sessions/session_list_app_bar.dart
index c09b415..205eee7 100644
--- a/lib/widgets/sessions/session_list_app_bar.dart
+++ b/lib/widgets/sessions/session_list_app_bar.dart
@@ -1,8 +1,7 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
import 'package:recon/clients/session_client.dart';
import 'package:recon/widgets/sessions/session_filter_dialog.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:provider/provider.dart';
class SessionListAppBar extends StatefulWidget {
const SessionListAppBar({super.key});
diff --git a/lib/widgets/settings_app_bar.dart b/lib/widgets/settings_app_bar.dart
index 0a7846c..4a2ed02 100644
--- a/lib/widgets/settings_app_bar.dart
+++ b/lib/widgets/settings_app_bar.dart
@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
class SettingsAppBar extends StatelessWidget {
const SettingsAppBar({super.key});
diff --git a/macos/.gitignore b/macos/.gitignore
new file mode 100644
index 0000000..746adbb
--- /dev/null
+++ b/macos/.gitignore
@@ -0,0 +1,7 @@
+# Flutter-related
+**/Flutter/ephemeral/
+**/Pods/
+
+# Xcode-related
+**/dgph
+**/xcuserdata/
diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig
new file mode 100644
index 0000000..4b81f9b
--- /dev/null
+++ b/macos/Flutter/Flutter-Debug.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig
new file mode 100644
index 0000000..5caa9d1
--- /dev/null
+++ b/macos/Flutter/Flutter-Release.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
new file mode 100644
index 0000000..193930b
--- /dev/null
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -0,0 +1,36 @@
+//
+// Generated file. Do not edit.
+//
+
+import FlutterMacOS
+import Foundation
+
+import audio_session
+import dynamic_color
+import ffmpeg_kit_flutter_audio
+import file_selector_macos
+import flutter_local_notifications
+import flutter_secure_storage_macos
+import just_audio
+import package_info_plus
+import path_provider_foundation
+import record_darwin
+import share_plus
+import sqflite
+import url_launcher_macos
+
+func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
+ DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
+ FFmpegKitFlutterPlugin.register(with: registry.registrar(forPlugin: "FFmpegKitFlutterPlugin"))
+ FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
+ FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
+ FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
+ JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
+ FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
+ PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
+ RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin"))
+ SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
+ SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
+ UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
+}
diff --git a/macos/Podfile b/macos/Podfile
new file mode 100644
index 0000000..28f25fa
--- /dev/null
+++ b/macos/Podfile
@@ -0,0 +1,50 @@
+platform :osx, '10.15'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_macos_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
+ target 'RunnerTests' do
+ inherit! :search_paths
+ end
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_macos_build_settings(target)
+ target.build_configurations.each do |config|
+ config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '10.15'
+ xcconfig_path = config.base_configuration_reference.real_path
+ xcconfig = File.read(xcconfig_path)
+ xcconfig_mod = xcconfig.gsub(/DT_TOOLCHAIN_DIR/, "TOOLCHAIN_DIR")
+ File.open(xcconfig_path, "w") { |file| file << xcconfig_mod }
+ end
+ end
+end
diff --git a/macos/Podfile.lock b/macos/Podfile.lock
new file mode 100644
index 0000000..ee6bac5
--- /dev/null
+++ b/macos/Podfile.lock
@@ -0,0 +1,112 @@
+PODS:
+ - audio_session (0.0.1):
+ - FlutterMacOS
+ - dynamic_color (0.0.2):
+ - FlutterMacOS
+ - ffmpeg-kit-macos-audio (6.0)
+ - ffmpeg_kit_flutter_audio (6.0.3):
+ - ffmpeg_kit_flutter_audio/audio (= 6.0.3)
+ - FlutterMacOS
+ - ffmpeg_kit_flutter_audio/audio (6.0.3):
+ - ffmpeg-kit-macos-audio (= 6.0)
+ - FlutterMacOS
+ - file_selector_macos (0.0.1):
+ - FlutterMacOS
+ - flutter_local_notifications (0.0.1):
+ - FlutterMacOS
+ - flutter_secure_storage_macos (6.1.1):
+ - FlutterMacOS
+ - FlutterMacOS (1.0.0)
+ - FMDB (2.7.5):
+ - FMDB/standard (= 2.7.5)
+ - FMDB/standard (2.7.5)
+ - just_audio (0.0.1):
+ - FlutterMacOS
+ - package_info_plus (0.0.1):
+ - FlutterMacOS
+ - path_provider_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - record_darwin (1.0.0):
+ - Flutter
+ - FlutterMacOS
+ - share_plus (0.0.1):
+ - FlutterMacOS
+ - sqflite (0.0.2):
+ - FlutterMacOS
+ - FMDB (>= 2.7.5)
+ - url_launcher_macos (0.0.1):
+ - FlutterMacOS
+
+DEPENDENCIES:
+ - audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
+ - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
+ - ffmpeg_kit_flutter_audio (from `Flutter/ephemeral/.symlinks/plugins/ffmpeg_kit_flutter_audio/macos`)
+ - file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
+ - flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
+ - flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
+ - FlutterMacOS (from `Flutter/ephemeral`)
+ - just_audio (from `Flutter/ephemeral/.symlinks/plugins/just_audio/macos`)
+ - package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
+ - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
+ - record_darwin (from `Flutter/ephemeral/.symlinks/plugins/record_darwin/macos`)
+ - share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
+ - sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/macos`)
+ - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
+
+SPEC REPOS:
+ trunk:
+ - ffmpeg-kit-macos-audio
+ - FMDB
+
+EXTERNAL SOURCES:
+ audio_session:
+ :path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos
+ dynamic_color:
+ :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
+ ffmpeg_kit_flutter_audio:
+ :path: Flutter/ephemeral/.symlinks/plugins/ffmpeg_kit_flutter_audio/macos
+ file_selector_macos:
+ :path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
+ flutter_local_notifications:
+ :path: Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos
+ flutter_secure_storage_macos:
+ :path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
+ FlutterMacOS:
+ :path: Flutter/ephemeral
+ just_audio:
+ :path: Flutter/ephemeral/.symlinks/plugins/just_audio/macos
+ package_info_plus:
+ :path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
+ path_provider_foundation:
+ :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
+ record_darwin:
+ :path: Flutter/ephemeral/.symlinks/plugins/record_darwin/macos
+ share_plus:
+ :path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
+ sqflite:
+ :path: Flutter/ephemeral/.symlinks/plugins/sqflite/macos
+ url_launcher_macos:
+ :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
+
+SPEC CHECKSUMS:
+ audio_session: dea1f41890dbf1718f04a56f1d6150fd50039b72
+ dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
+ ffmpeg-kit-macos-audio: d1fa3fe42922de39a494c1ac73985524f1c27131
+ ffmpeg_kit_flutter_audio: db530afe9b427a980f85036618c9fe9e043a4a39
+ file_selector_macos: 468fb6b81fac7c0e88d71317f3eec34c3b008ff9
+ flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
+ flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
+ FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
+ FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
+ just_audio: 9b67ca7b97c61cfc9784ea23cd8cc55eb226d489
+ package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
+ path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
+ record_darwin: 1f6619f2abac4d1ca91d3eeab038c980d76f1517
+ share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
+ sqflite: a5789cceda41d54d23f31d6de539d65bb14100ea
+ url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
+
+PODFILE CHECKSUM: 3efd3b4b57928fa6a5be6b71a1f5dc6e2a2b54af
+
+COCOAPODS: 1.12.1
diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..07ee6ce
--- /dev/null
+++ b/macos/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,818 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
+ buildPhases = (
+ 33CC111E2044C6BF0003C045 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = "Flutter Assemble";
+ productName = FLX;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+ 3EACF4532AF95E990009EB00 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 431AA3390577660559928839 /* Pods_Runner.framework */; };
+ F7455EB836601EB2BB27AA8C /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6D47E6FEAF464069014E11B /* Pods_RunnerTests.framework */; };
+ FC9F240BEF110BF52DFF7861 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 431AA3390577660559928839 /* Pods_Runner.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC10EC2044A3C60003C045;
+ remoteInfo = Runner;
+ };
+ 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC111A2044C6BA0003C045;
+ remoteInfo = FLX;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
+ 33CC10ED2044A3C60003C045 /* ReCon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReCon.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
+ 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
+ 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; };
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; };
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; };
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; };
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; };
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; };
+ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; };
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
+ 3EACF44B2AF931920009EB00 /* RunnerDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerDebug.entitlements; sourceTree = ""; };
+ 431AA3390577660559928839 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 717F60D9A7608595A8BC4295 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
+ 8D35D566ECE178A49F389506 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ 95E1F4689F640B445DC9634C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
+ C54AA7FCFEBCD9AECE64C0B5 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
+ D6D47E6FEAF464069014E11B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ DBEB9E171B7E5F80AA91D732 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; };
+ EF69B485C8780738FDFC8F3F /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 331C80D2294CF70F00263BE5 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F7455EB836601EB2BB27AA8C /* Pods_RunnerTests.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 33CC10EA2044A3C60003C045 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 3EACF4532AF95E990009EB00 /* Pods_Runner.framework in Frameworks */,
+ FC9F240BEF110BF52DFF7861 /* Pods_Runner.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 331C80D6294CF71000263BE5 /* RunnerTests */ = {
+ isa = PBXGroup;
+ children = (
+ 331C80D7294CF71000263BE5 /* RunnerTests.swift */,
+ );
+ path = RunnerTests;
+ sourceTree = "";
+ };
+ 33BA886A226E78AF003329D5 /* Configs */ = {
+ isa = PBXGroup;
+ children = (
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
+ );
+ path = Configs;
+ sourceTree = "";
+ };
+ 33CC10E42044A3C60003C045 = {
+ isa = PBXGroup;
+ children = (
+ 33FAB671232836740065AC1E /* Runner */,
+ 33CEB47122A05771004F2AC0 /* Flutter */,
+ 331C80D6294CF71000263BE5 /* RunnerTests */,
+ 33CC10EE2044A3C60003C045 /* Products */,
+ D73912EC22F37F3D000D13A0 /* Frameworks */,
+ EBAFFCB22FA330E74E1606C2 /* Pods */,
+ );
+ sourceTree = "";
+ };
+ 33CC10EE2044A3C60003C045 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10ED2044A3C60003C045 /* ReCon.app */,
+ 331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 33CC11242044D66E0003C045 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */,
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */,
+ 33CC10F72044A3C60003C045 /* Info.plist */,
+ );
+ name = Resources;
+ path = ..;
+ sourceTree = "";
+ };
+ 33CEB47122A05771004F2AC0 /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
+ );
+ path = Flutter;
+ sourceTree = "";
+ };
+ 33FAB671232836740065AC1E /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 3EACF44B2AF931920009EB00 /* RunnerDebug.entitlements */,
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
+ 33E51914231749380026EE4D /* Release.entitlements */,
+ 33CC11242044D66E0003C045 /* Resources */,
+ 33BA886A226E78AF003329D5 /* Configs */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 431AA3390577660559928839 /* Pods_Runner.framework */,
+ D6D47E6FEAF464069014E11B /* Pods_RunnerTests.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ EBAFFCB22FA330E74E1606C2 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ C54AA7FCFEBCD9AECE64C0B5 /* Pods-Runner.debug.xcconfig */,
+ 8D35D566ECE178A49F389506 /* Pods-Runner.release.xcconfig */,
+ 95E1F4689F640B445DC9634C /* Pods-Runner.profile.xcconfig */,
+ 717F60D9A7608595A8BC4295 /* Pods-RunnerTests.debug.xcconfig */,
+ EF69B485C8780738FDFC8F3F /* Pods-RunnerTests.release.xcconfig */,
+ DBEB9E171B7E5F80AA91D732 /* Pods-RunnerTests.profile.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 331C80D4294CF70F00263BE5 /* RunnerTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
+ buildPhases = (
+ 19C7D0AAF89CFCAA568E9768 /* [CP] Check Pods Manifest.lock */,
+ 331C80D1294CF70F00263BE5 /* Sources */,
+ 331C80D2294CF70F00263BE5 /* Frameworks */,
+ 331C80D3294CF70F00263BE5 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 331C80DA294CF71000263BE5 /* PBXTargetDependency */,
+ );
+ name = RunnerTests;
+ productName = RunnerTests;
+ productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 33CC10EC2044A3C60003C045 /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ BCE6E700323AE8EB48A0D444 /* [CP] Check Pods Manifest.lock */,
+ 33CC10E92044A3C60003C045 /* Sources */,
+ 33CC10EA2044A3C60003C045 /* Frameworks */,
+ 33CC10EB2044A3C60003C045 /* Resources */,
+ 3399D490228B24CF009A79C7 /* ShellScript */,
+ 457DC9EDFE75FA6884827546 /* [CP] Embed Pods Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */,
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 33CC10ED2044A3C60003C045 /* ReCon.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 33CC10E52044A3C60003C045 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 1430;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 331C80D4294CF70F00263BE5 = {
+ CreatedOnToolsVersion = 14.0;
+ TestTargetID = 33CC10EC2044A3C60003C045;
+ };
+ 33CC10EC2044A3C60003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 1100;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ 33CC111A2044C6BA0003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 33CC10E42044A3C60003C045;
+ productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 33CC10EC2044A3C60003C045 /* Runner */,
+ 331C80D4294CF70F00263BE5 /* RunnerTests */,
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 331C80D3294CF70F00263BE5 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 33CC10EB2044A3C60003C045 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 19C7D0AAF89CFCAA568E9768 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 3399D490228B24CF009A79C7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
+ };
+ 33CC111E2044C6BF0003C045 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ Flutter/ephemeral/FlutterInputs.xcfilelist,
+ );
+ inputPaths = (
+ Flutter/ephemeral/tripwire,
+ );
+ outputFileListPaths = (
+ Flutter/ephemeral/FlutterOutputs.xcfilelist,
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
+ };
+ 457DC9EDFE75FA6884827546 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ BCE6E700323AE8EB48A0D444 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 331C80D1294CF70F00263BE5 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 33CC10E92044A3C60003C045 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC10EC2044A3C60003C045 /* Runner */;
+ targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */;
+ };
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
+ targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 33CC10F52044A3C60003C045 /* Base */,
+ );
+ name = MainMenu.xib;
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 331C80DB294CF71000263BE5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 717F60D9A7608595A8BC4295 /* Pods-RunnerTests.debug.xcconfig */;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CURRENT_PROJECT_VERSION = 1;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/recon.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/recon";
+ };
+ name = Debug;
+ };
+ 331C80DC294CF71000263BE5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = EF69B485C8780738FDFC8F3F /* Pods-RunnerTests.release.xcconfig */;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CURRENT_PROJECT_VERSION = 1;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/recon.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/recon";
+ };
+ name = Release;
+ };
+ 331C80DD294CF71000263BE5 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = DBEB9E171B7E5F80AA91D732 /* Pods-RunnerTests.profile.xcconfig */;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CURRENT_PROJECT_VERSION = 1;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon.RunnerTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/recon.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/recon";
+ };
+ name = Profile;
+ };
+ 338D0CE9231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "Apple Development: grwdragon@gmail.com (GDFAMRH4F8)";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Profile;
+ };
+ 338D0CEA231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = P9AV4LPNLL;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ MARKETING_VERSION = 0.10.3;
+ PRODUCT_NAME = ReCon;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Profile;
+ };
+ 338D0CEB231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ FLUTTER_BUILD_NAME = 0.11.0;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Profile;
+ };
+ 33CC10F92044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "Apple Development: grwdragon@gmail.com (GDFAMRH4F8)";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ 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_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 33CC10FA2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ 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_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ 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_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "Apple Development: grwdragon@gmail.com (GDFAMRH4F8)";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ 33CC10FC2044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/RunnerDebug.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = P9AV4LPNLL;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ MARKETING_VERSION = 0.10.3;
+ PRODUCT_NAME = ReCon;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 33CC10FD2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
+ CODE_SIGN_IDENTITY = "Apple Development";
+ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = P9AV4LPNLL;
+ FLUTTER_BUILD_NAME = 0.10.3;
+ INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = ReCon;
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ MARKETING_VERSION = 0.10.3;
+ PRODUCT_NAME = ReCon;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 33CC111C2044C6BA0003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ FLUTTER_BUILD_NAME = 0.11.0;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 33CC111D2044C6BA0003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ FLUTTER_BUILD_NAME = 0.11.0;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 331C80DB294CF71000263BE5 /* Debug */,
+ 331C80DC294CF71000263BE5 /* Release */,
+ 331C80DD294CF71000263BE5 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10F92044A3C60003C045 /* Debug */,
+ 33CC10FA2044A3C60003C045 /* Release */,
+ 338D0CE9231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10FC2044A3C60003C045 /* Debug */,
+ 33CC10FD2044A3C60003C045 /* Release */,
+ 338D0CEA231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC111C2044C6BA0003C045 /* Debug */,
+ 33CC111D2044C6BA0003C045 /* Release */,
+ 338D0CEB231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 33CC10E52044A3C60003C045 /* Project object */;
+}
diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Flutter Assemble.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Flutter Assemble.xcscheme
new file mode 100644
index 0000000..44f8735
--- /dev/null
+++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Flutter Assemble.xcscheme
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..1c305fd
--- /dev/null
+++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..21a3cc1
--- /dev/null
+++ b/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift
new file mode 100644
index 0000000..d53ef64
--- /dev/null
+++ b/macos/Runner/AppDelegate.swift
@@ -0,0 +1,9 @@
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+ override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+ return true
+ }
+}
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_128x128.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_128x128.png
new file mode 100644
index 0000000..cb11e73
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_128x128.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_128x128@2x.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_128x128@2x.png
new file mode 100644
index 0000000..0d8dd82
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_128x128@2x.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_16x16.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_16x16.png
new file mode 100644
index 0000000..852fa9d
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_16x16.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_16x16@2x.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_16x16@2x.png
new file mode 100644
index 0000000..3f11af5
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_16x16@2x.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_256x256.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_256x256.png
new file mode 100644
index 0000000..77c99cf
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_256x256.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_256x256@2x.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_256x256@2x.png
new file mode 100644
index 0000000..8092952
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_256x256@2x.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_32x32.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_32x32.png
new file mode 100644
index 0000000..c81a6a8
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_32x32.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_32x32@2x.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_32x32@2x.png
new file mode 100644
index 0000000..3b4597e
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_32x32@2x.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_512x512.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_512x512.png
new file mode 100644
index 0000000..7eba3ee
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_512x512.png differ
diff --git a/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_512x512@2x.png b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_512x512@2x.png
new file mode 100644
index 0000000..78f84c3
Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.iconset/icon_512x512@2x.png differ
diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib
new file mode 100644
index 0000000..80e867a
--- /dev/null
+++ b/macos/Runner/Base.lproj/MainMenu.xib
@@ -0,0 +1,343 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig
new file mode 100644
index 0000000..dfb0963
--- /dev/null
+++ b/macos/Runner/Configs/AppInfo.xcconfig
@@ -0,0 +1,14 @@
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = recon
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = me.voidspace.recon
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = Copyright © 2023 me.voidspace. All rights reserved.
diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig
new file mode 100644
index 0000000..36b0fd9
--- /dev/null
+++ b/macos/Runner/Configs/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig
new file mode 100644
index 0000000..dff4f49
--- /dev/null
+++ b/macos/Runner/Configs/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig
new file mode 100644
index 0000000..42bcbf4
--- /dev/null
+++ b/macos/Runner/Configs/Warnings.xcconfig
@@ -0,0 +1,13 @@
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements
new file mode 100644
index 0000000..427bd01
--- /dev/null
+++ b/macos/Runner/DebugProfile.entitlements
@@ -0,0 +1,20 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.device.audio-input
+
+ com.apple.security.network.client
+
+ com.apple.security.network.server
+
+ keychain-access-groups
+
+ $(AppIdentifierPrefix)me.voidspace.recon
+
+
+
diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist
new file mode 100644
index 0000000..6635b56
--- /dev/null
+++ b/macos/Runner/Info.plist
@@ -0,0 +1,34 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+ AppIcon
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ $(PRODUCT_COPYRIGHT)
+ NSMainNibFile
+ MainMenu
+ NSPrincipalClass
+ NSApplication
+ UILaunchStoryboardName
+
+
+
diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift
new file mode 100644
index 0000000..3cc05eb
--- /dev/null
+++ b/macos/Runner/MainFlutterWindow.swift
@@ -0,0 +1,15 @@
+import Cocoa
+import FlutterMacOS
+
+class MainFlutterWindow: NSWindow {
+ override func awakeFromNib() {
+ let flutterViewController = FlutterViewController()
+ let windowFrame = self.frame
+ self.contentViewController = flutterViewController
+ self.setFrame(windowFrame, display: true)
+
+ RegisterGeneratedPlugins(registry: flutterViewController)
+
+ super.awakeFromNib()
+ }
+}
diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements
new file mode 100644
index 0000000..134af15
--- /dev/null
+++ b/macos/Runner/Release.entitlements
@@ -0,0 +1,16 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.device.audio-input
+
+ com.apple.security.network.client
+
+ keychain-access-groups
+
+ $(AppIdentifierPrefix)me.voidspace.recon
+
+
+
diff --git a/macos/Runner/RunnerDebug.entitlements b/macos/Runner/RunnerDebug.entitlements
new file mode 100644
index 0000000..427bd01
--- /dev/null
+++ b/macos/Runner/RunnerDebug.entitlements
@@ -0,0 +1,20 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.device.audio-input
+
+ com.apple.security.network.client
+
+ com.apple.security.network.server
+
+ keychain-access-groups
+
+ $(AppIdentifierPrefix)me.voidspace.recon
+
+
+
diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift
new file mode 100644
index 0000000..5418c9f
--- /dev/null
+++ b/macos/RunnerTests/RunnerTests.swift
@@ -0,0 +1,12 @@
+import FlutterMacOS
+import Cocoa
+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/pubspec.lock b/pubspec.lock
index 2cf87c9..d788584 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -25,6 +25,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.1.16"
+ background_downloader:
+ dependency: "direct main"
+ description:
+ name: background_downloader
+ sha256: f74abc807173daac213cd810769532c62755279936532311d994418079d16013
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.12.2"
boolean_selector:
dependency: transitive
description:
@@ -185,6 +193,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.0"
+ ffmpeg_kit_flutter_audio:
+ dependency: "direct main"
+ description:
+ name: ffmpeg_kit_flutter_audio
+ sha256: "1e6de4d6afdd1b842dde17ef55d9cfa8911d5c4a5858e80f4371487c29e42f8a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.3"
+ ffmpeg_kit_flutter_platform_interface:
+ dependency: transitive
+ description:
+ name: ffmpeg_kit_flutter_platform_interface
+ sha256: addf046ae44e190ad0101b2fde2ad909a3cd08a2a109f6106d2f7048b7abedee
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.1"
file:
dependency: transitive
description:
@@ -197,10 +221,10 @@ packages:
dependency: "direct main"
description:
name: file_picker
- sha256: "9d6e95ec73abbd31ec54d0e0df8a961017e165aba1395e462e5b31ea0c165daf"
+ sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6"
url: "https://pub.dev"
source: hosted
- version: "5.3.1"
+ version: "6.1.1"
file_selector_linux:
dependency: transitive
description:
@@ -254,30 +278,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.1.1"
- flutter_downloader:
- dependency: "direct main"
- description:
- name: flutter_downloader
- sha256: "4a03c705dc60b4f537796da937c80fd5bff63b175f4dd99e1539ab3ad5dbeda0"
- url: "https://pub.dev"
- source: hosted
- version: "1.11.4"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
- sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
+ sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
url: "https://pub.dev"
source: hosted
- version: "2.0.3"
+ version: "3.0.1"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
- sha256: "53c332ecee8e4d723269c1c2d0cdf7cbbff0a66cc0554d230a6f38cae81760d1"
+ sha256: "6d11ea777496061e583623aaf31923f93a9409ef8fcaeeefdd6cd78bf4fe5bb3"
url: "https://pub.dev"
source: hosted
- version: "14.1.4"
+ version: "16.1.0"
flutter_local_notifications_linux:
dependency: transitive
description:
@@ -314,10 +330,10 @@ packages:
dependency: "direct main"
description:
name: flutter_secure_storage
- sha256: "22dbf16f23a4bcf9d35e51be1c84ad5bb6f627750565edd70dab70f3ff5fff8f"
+ sha256: ffdbb60130e4665d2af814a0267c481bcf522c41ae2e43caf69fa0146876d685
url: "https://pub.dev"
source: hosted
- version: "8.1.0"
+ version: "9.0.0"
flutter_secure_storage_linux:
dependency: transitive
description:
@@ -354,10 +370,10 @@ packages:
dependency: transitive
description:
name: flutter_secure_storage_windows
- sha256: "38f9501c7cb6f38961ef0e1eacacee2b2d4715c63cc83fe56449c4d3d0b47255"
+ sha256: "5809c66f9dd3b4b93b0a6e2e8561539405322ee767ac2f64d084e2ab5429d108"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "3.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -396,10 +412,10 @@ packages:
dependency: "direct main"
description:
name: http
- sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
+ sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
url: "https://pub.dev"
source: hosted
- version: "0.13.6"
+ version: "1.1.0"
http_parser:
dependency: "direct main"
description:
@@ -412,10 +428,10 @@ packages:
dependency: "direct main"
description:
name: image_picker
- sha256: b6951e25b795d053a6ba03af5f710069c99349de9341af95155d52665cb4607c
+ sha256: "7d7f2768df2a8b0a3cefa5ef4f84636121987d403130e70b17ef7e2cf650ba84"
url: "https://pub.dev"
source: hosted
- version: "0.8.9"
+ version: "1.0.4"
image_picker_android:
dependency: transitive
description:
@@ -516,10 +532,10 @@ packages:
dependency: transitive
description:
name: lints
- sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
+ sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "3.0.0"
logging:
dependency: "direct main"
description:
@@ -580,10 +596,10 @@ packages:
dependency: "direct main"
description:
name: package_info_plus
- sha256: "10259b111176fba5c505b102e3a5b022b51dd97e30522e906d6922c745584745"
+ sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017"
url: "https://pub.dev"
source: hosted
- version: "3.1.2"
+ version: "4.2.0"
package_info_plus_platform_interface:
dependency: transitive
description:
@@ -652,18 +668,18 @@ packages:
dependency: "direct main"
description:
name: permission_handler
- sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5
+ sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8"
url: "https://pub.dev"
source: hosted
- version: "10.4.5"
+ version: "11.0.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
- sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47"
+ sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e
url: "https://pub.dev"
source: hosted
- version: "10.3.6"
+ version: "11.1.0"
permission_handler_apple:
dependency: transitive
description:
@@ -740,50 +756,58 @@ packages:
dependency: "direct main"
description:
name: record
- sha256: f703397f5a60d9b2b655b3acc94ba079b2d9a67dc0725bdb90ef2fee2441ebf7
+ sha256: be9b710f42edf94f939dda1a1688e82a68dcd391be0a836c01e639a249f133d3
url: "https://pub.dev"
source: hosted
- version: "4.4.4"
+ version: "5.0.1"
+ record_android:
+ dependency: transitive
+ description:
+ name: record_android
+ sha256: "5a96286f051cf46dffd1ae7cd5f1baa82cf6a983d26389c2f8d03d03dddc711b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.3"
+ record_darwin:
+ dependency: transitive
+ description:
+ name: record_darwin
+ sha256: "78dba641ae271e555035ee68b637f7605ba9f8c60ccfd5c03b835e0b77ea201f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
record_linux:
dependency: transitive
description:
name: record_linux
- sha256: "348db92c4ec1b67b1b85d791381c8c99d7c6908de141e7c9edc20dad399b15ce"
+ sha256: "7d0e70cd51635128fe9d37d89bafd6011d7cbba9af8dc323079ae60f23546aef"
url: "https://pub.dev"
source: hosted
- version: "0.4.1"
- record_macos:
- dependency: transitive
- description:
- name: record_macos
- sha256: d1d0199d1395f05e218207e8cacd03eb9dc9e256ddfe2cfcbbb90e8edea06057
- url: "https://pub.dev"
- source: hosted
- version: "0.2.2"
+ version: "0.7.1"
record_platform_interface:
dependency: transitive
description:
name: record_platform_interface
- sha256: "7a2d4ce7ac3752505157e416e4e0d666a54b1d5d8601701b7e7e5e30bec181b4"
+ sha256: "3a4b56e94ecd2a0b2b43eb1fa6f94c5b8484334f5d38ef43959c4bf97fb374cf"
url: "https://pub.dev"
source: hosted
- version: "0.5.0"
+ version: "1.0.2"
record_web:
dependency: transitive
description:
name: record_web
- sha256: "219ffb4ca59b4338117857db56d3ffadbde3169bcaf1136f5f4d4656f4a2372d"
+ sha256: be8c62759b385a04dbc4ae7f5d3f78e6f0c532e72935d288aee87432bbbbb8f6
url: "https://pub.dev"
source: hosted
- version: "0.5.0"
+ version: "1.0.3"
record_windows:
dependency: transitive
description:
name: record_windows
- sha256: "42d545155a26b20d74f5107648dbb3382dbbc84dc3f1adc767040359e57a1345"
+ sha256: "326bfbe6f5232dd773ad6b848cd94f78148f02557abff1dd4627d056b688dbdb"
url: "https://pub.dev"
source: hosted
- version: "0.7.1"
+ version: "1.0.0"
rxdart:
dependency: transitive
description:
@@ -821,6 +845,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.0"
+ sprintf:
+ dependency: transitive
+ description:
+ name: sprintf
+ sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
sqflite:
dependency: transitive
description:
@@ -977,10 +1009,10 @@ packages:
dependency: "direct main"
description:
name: uuid
- sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
+ sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7
url: "https://pub.dev"
source: hosted
- version: "3.0.7"
+ version: "4.1.0"
vector_math:
dependency: transitive
description:
@@ -1009,10 +1041,10 @@ packages:
dependency: transitive
description:
name: win32
- sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c"
+ sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
url: "https://pub.dev"
source: hosted
- version: "4.1.4"
+ version: "5.0.9"
workmanager:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 579c65a..88b7998 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -2,7 +2,7 @@ name: recon
description: A Resonite Contacts App for Android
# 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
+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
@@ -16,10 +16,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# 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: 0.10.3-beta+1
+version: 0.11.0-beta+1
environment:
- sdk: '>=3.0.1'
+ sdk: ">=3.0.1"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@@ -31,39 +31,40 @@ dependencies:
flutter:
sdk: flutter
- http: ^0.13.5
+ http: ^1.1.0
http_parser: ^4.0.2
- uuid: ^3.0.7
- flutter_secure_storage: ^8.0.0
+ uuid: ^4.1.0
+ flutter_secure_storage: ^9.0.0
intl: ^0.18.1
path: ^1.8.2
logging: ^1.1.1
cached_network_image: ^3.2.3
web_socket_channel: ^2.4.0
html: ^0.15.2
- just_audio: ^0.9.32
+ just_audio: ^0.9.35
flutter_phoenix: ^1.1.1
url_launcher: ^6.1.10
workmanager: ^0.5.1
- flutter_local_notifications: ^14.0.0+1
+ flutter_local_notifications: ^16.1.0
collection: ^1.17.0
- package_info_plus: ^3.1.2
+ package_info_plus: ^4.2.0
provider: ^6.0.5
photo_view: ^0.14.0
color: ^3.0.0
dynamic_color: ^1.6.5
hive: ^2.2.3
hive_flutter: ^1.1.0
- file_picker: ^5.3.0
- record: ^4.4.4
+ file_picker: ^6.1.1
+ record: ^5.0.1
camera: ^0.10.5
path_provider: ^2.0.15
crypto: ^3.0.3
- image_picker: ^0.8.7+5
- permission_handler: ^10.2.0
- flutter_downloader: ^1.10.4
+ image_picker: ^1.0.4
+ permission_handler: ^11.0.1
flutter_cube: ^0.1.1
share_plus: ^7.1.0
+ ffmpeg_kit_flutter_audio: ^6.0.3
+ background_downloader: ^7.12.2
dev_dependencies:
flutter_test:
@@ -74,14 +75,13 @@ dev_dependencies:
# 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_lints: ^3.0.1
# 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.
diff --git a/test/widget_test.dart b/test/widget_test.dart
new file mode 100644
index 0000000..7977cae
--- /dev/null
+++ b/test/widget_test.dart
@@ -0,0 +1,29 @@
+// 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:recon/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);
+ });
+}
diff --git a/web/favicon.png b/web/favicon.png
new file mode 100644
index 0000000..8aaa46a
Binary files /dev/null and b/web/favicon.png differ
diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png
new file mode 100644
index 0000000..b749bfe
Binary files /dev/null and b/web/icons/Icon-192.png differ
diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png
new file mode 100644
index 0000000..88cfd48
Binary files /dev/null and b/web/icons/Icon-512.png differ
diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png
new file mode 100644
index 0000000..eb9b4d7
Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ
diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png
new file mode 100644
index 0000000..d69c566
Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 0000000..04fd052
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ recon
+
+
+
+
+
+
+
+
+
+
diff --git a/web/manifest.json b/web/manifest.json
new file mode 100644
index 0000000..b2d225b
--- /dev/null
+++ b/web/manifest.json
@@ -0,0 +1,35 @@
+{
+ "name": "recon",
+ "short_name": "recon",
+ "start_url": ".",
+ "display": "standalone",
+ "background_color": "#0175C2",
+ "theme_color": "#0175C2",
+ "description": "A new Flutter project.",
+ "orientation": "portrait-primary",
+ "prefer_related_applications": false,
+ "icons": [
+ {
+ "src": "icons/Icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ },
+ {
+ "src": "icons/Icon-maskable-192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "icons/Icon-maskable-512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "maskable"
+ }
+ ]
+}
diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp
index b25e363..955ee30 100644
--- a/windows/runner/flutter_window.cpp
+++ b/windows/runner/flutter_window.cpp
@@ -31,6 +31,11 @@ bool FlutterWindow::OnCreate() {
this->Show();
});
+ // Flutter can complete the first frame before the "show window" callback is
+ // registered. The following call ensures a frame is pending to ensure the
+ // window is shown. It is a no-op if the first frame hasn't completed yet.
+ flutter_controller_->ForceRedraw();
+
return true;
}