diff --git a/.gitignore b/.gitignore index 48c3273..81fc631 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .idea/ *.last_build_id +**/google-services.json diff --git a/audio_call/.gitignore b/audio_call/.gitignore index 8f72d2d..55f97e6 100644 --- a/audio_call/.gitignore +++ b/audio_call/.gitignore @@ -8,6 +8,7 @@ .buildlog/ .history .svn/ +migrate_working_dir/ # IntelliJ related *.iml @@ -22,6 +23,7 @@ # Flutter/Dart/Pub related **/doc/api/ +**/ios/Flutter/.last_build_id .dart_tool/ .flutter-plugins .flutter-plugins-dependencies @@ -30,51 +32,15 @@ .pub/ /build/ -# Android related -**/android/**/gradle-wrapper.jar -**/android/.gradle -**/android/captures/ -**/android/gradlew -**/android/gradlew.bat -**/android/local.properties -**/android/**/GeneratedPluginRegistrant.java -**/android/gradle/ +# Symbolication related +app.*.symbols -# iOS/XCode related -**/ios/**/*.mode1v3 -**/ios/**/*.mode2v3 -**/ios/**/*.moved-aside -**/ios/**/*.pbxuser -**/ios/**/*.perspectivev3 -**/ios/**/*sync/ -**/ios/**/.sconsign.dblite -**/ios/**/.tags* -**/ios/**/.vagrant/ -**/ios/**/DerivedData/ -**/ios/**/Icon? -**/ios/**/Pods/ -**/ios/**/.symlinks/ -**/ios/**/profile -**/ios/**/xcuserdata -**/ios/.generated/ -**/ios/Flutter/App.framework -**/ios/Flutter/Flutter.framework -**/ios/Flutter/Generated.xcconfig -**/ios/Flutter/app.flx -**/ios/Flutter/app.zip -**/ios/Flutter/flutter_assets/ -**/ios/ServiceDefinitions.json -**/ios/Runner/GeneratedPluginRegistrant.* -**/ios/Flutter/flutter_export_environment.sh -**/ios/Runner.xcworkspace/xcshareddata/** +# Obfuscation related +app.*.map.json -**/ios/Flutter/Flutter.podspec +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release -# Exceptions to above rules. -!**/ios/**/default.mode1v3 -!**/ios/**/default.mode2v3 -!**/ios/**/default.pbxuser -!**/ios/**/default.perspectivev3 -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages - -**/android/app/google-services.json +**/android/google-services.json diff --git a/audio_call/.metadata b/audio_call/.metadata deleted file mode 100644 index e023651..0000000 --- a/audio_call/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 20e59316b8b8474554b38493b8ca888794b0234a - channel: stable - -project_type: app diff --git a/audio_call/analysis_options.yaml b/audio_call/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/audio_call/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/audio_call/android/.gitignore b/audio_call/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/audio_call/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/audio_call/android/app/build.gradle b/audio_call/android/app/build.gradle index 1640ece..cf2c694 100644 --- a/audio_call/android/app/build.gradle +++ b/audio_call/android/app/build.gradle @@ -22,50 +22,38 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" +apply plugin: 'com.google.gms.google-services' android { - compileSdkVersion 30 + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion - lintOptions { - disable 'InvalidPackage' + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.voximplant.flutter.audiocall" - minSdkVersion 16 - targetSdkVersion 30 + // set minSdk to 21 since multidex is enabled by default since this version + minSdkVersion 21 + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { + // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug } } - - packagingOptions { - exclude 'META-INF/proguard/androidx-annotations.pro' - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } } flutter { source '../..' } - -dependencies { - implementation 'com.google.firebase:firebase-messaging:20.3.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' -} - -apply plugin: 'com.google.gms.google-services' diff --git a/audio_call/android/app/src/debug/AndroidManifest.xml b/audio_call/android/app/src/debug/AndroidManifest.xml index 411da15..d675ce0 100644 --- a/audio_call/android/app/src/debug/AndroidManifest.xml +++ b/audio_call/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,7 @@ - diff --git a/audio_call/android/app/src/main/AndroidManifest.xml b/audio_call/android/app/src/main/AndroidManifest.xml index 9b87d2b..46ab9d1 100644 --- a/audio_call/android/app/src/main/AndroidManifest.xml +++ b/audio_call/android/app/src/main/AndroidManifest.xml @@ -1,26 +1,25 @@ - - - + - + + diff --git a/audio_call/android/app/src/main/ic_launcher-web.png b/audio_call/android/app/src/main/ic_launcher-web.png deleted file mode 100644 index 09bb2b3..0000000 Binary files a/audio_call/android/app/src/main/ic_launcher-web.png and /dev/null differ diff --git a/audio_call/android/app/src/main/java/com/voximplant/flutter/audiocall/Application.java b/audio_call/android/app/src/main/java/com/voximplant/flutter/audiocall/Application.java deleted file mode 100644 index fe15323..0000000 --- a/audio_call/android/app/src/main/java/com/voximplant/flutter/audiocall/Application.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.voximplant.flutter.audiocall; - -import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin; -import com.example.flutter_voip_push_notification.FlutterVoipPushNotificationPlugin; - -import io.flutter.app.FlutterApplication; -import io.flutter.plugin.common.PluginRegistry; -import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin; -import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService; -import io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin; - -public class Application extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback { - @Override - public void onCreate() { - super.onCreate(); - FlutterFirebaseMessagingService.setPluginRegistrant(this); - } - - @Override - public void registerWith(PluginRegistry registry) { - FlutterVoipPushNotificationPlugin.registerWith(registry.registrarFor("com.example.flutter_voip_push_notification.FlutterVoipPushNotificationPlugin")); - com.voximplant.flutter_voximplant.VoximplantPlugin.registerWith(registry.registrarFor("com.voximplant.flutter_voximplant.VoximplantPlugin")); - com.baseflow.permissionhandler.PermissionHandlerPlugin.registerWith(registry.registrarFor("com.baseflow.permissionhandler.PermissionHandlerPlugin")); - FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin")); - SharedPreferencesPlugin.registerWith(registry.registrarFor("io.flutter.plugins.sharedpreferences.SharedPreferencesPlugin")); - FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin")); - } -} diff --git a/audio_call/android/app/src/main/java/com/voximplant/flutter/audiocall/MainActivity.java b/audio_call/android/app/src/main/java/com/voximplant/flutter/audiocall/MainActivity.java index d26411d..ec27ebe 100644 --- a/audio_call/android/app/src/main/java/com/voximplant/flutter/audiocall/MainActivity.java +++ b/audio_call/android/app/src/main/java/com/voximplant/flutter/audiocall/MainActivity.java @@ -2,4 +2,5 @@ import io.flutter.embedding.android.FlutterActivity; -public class MainActivity extends FlutterActivity { } +public class MainActivity extends FlutterActivity { +} diff --git a/audio_call/android/app/src/main/res/drawable-mdpi/ic_vox_notification.png b/audio_call/android/app/src/main/res/drawable-mdpi/ic_vox_notification.png deleted file mode 100644 index ad0e6e4..0000000 Binary files a/audio_call/android/app/src/main/res/drawable-mdpi/ic_vox_notification.png and /dev/null differ diff --git a/audio_call/android/app/src/main/res/drawable-hdpi/ic_vox_notification.png b/audio_call/android/app/src/main/res/drawable-v21/ic_notification.png similarity index 100% rename from audio_call/android/app/src/main/res/drawable-hdpi/ic_vox_notification.png rename to audio_call/android/app/src/main/res/drawable-v21/ic_notification.png diff --git a/audio_call/android/app/src/main/res/drawable-v21/launch_background.xml b/audio_call/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/audio_call/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/audio_call/android/app/src/main/res/drawable-xhdpi/ic_vox_notification.png b/audio_call/android/app/src/main/res/drawable-xhdpi/ic_vox_notification.png deleted file mode 100644 index 5bb929c..0000000 Binary files a/audio_call/android/app/src/main/res/drawable-xhdpi/ic_vox_notification.png and /dev/null differ diff --git a/audio_call/android/app/src/main/res/drawable-xxhdpi/ic_vox_notification.png b/audio_call/android/app/src/main/res/drawable-xxhdpi/ic_vox_notification.png deleted file mode 100644 index c0482db..0000000 Binary files a/audio_call/android/app/src/main/res/drawable-xxhdpi/ic_vox_notification.png and /dev/null differ diff --git a/audio_call/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/audio_call/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 036d09b..0000000 --- a/audio_call/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/audio_call/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/audio_call/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 036d09b..0000000 --- a/audio_call/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/audio_call/android/app/src/main/res/values-night/styles.xml b/audio_call/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/audio_call/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/audio_call/android/app/src/main/res/values/ic_launcher_background.xml b/audio_call/android/app/src/main/res/values/ic_launcher_background.xml deleted file mode 100644 index c5d5899..0000000 --- a/audio_call/android/app/src/main/res/values/ic_launcher_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - #FFFFFF - \ No newline at end of file diff --git a/audio_call/android/app/src/main/res/values/styles.xml b/audio_call/android/app/src/main/res/values/styles.xml index 00fa441..cb1ef88 100644 --- a/audio_call/android/app/src/main/res/values/styles.xml +++ b/audio_call/android/app/src/main/res/values/styles.xml @@ -1,8 +1,18 @@ - + + diff --git a/audio_call/android/app/src/profile/AndroidManifest.xml b/audio_call/android/app/src/profile/AndroidManifest.xml index 411da15..d675ce0 100644 --- a/audio_call/android/app/src/profile/AndroidManifest.xml +++ b/audio_call/android/app/src/profile/AndroidManifest.xml @@ -1,6 +1,7 @@ - diff --git a/audio_call/android/build.gradle b/audio_call/android/build.gradle index a4546b8..13c7096 100644 --- a/audio_call/android/build.gradle +++ b/audio_call/android/build.gradle @@ -1,20 +1,21 @@ buildscript { + ext.kotlin_version = '1.7.10' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.0.2' - classpath 'com.google.gms:google-services:4.3.4' - classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10' + classpath 'com.android.tools.build:gradle:7.2.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.google.gms:google-services:4.3.8' } } allprojects { repositories { google() - jcenter() + mavenCentral() } } diff --git a/audio_call/android/gradle.properties b/audio_call/android/gradle.properties index 38c8d45..94adc3a 100644 --- a/audio_call/android/gradle.properties +++ b/audio_call/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M -android.enableR8=true android.useAndroidX=true android.enableJetifier=true diff --git a/audio_call/android/gradle/wrapper/gradle-wrapper.properties b/audio_call/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/audio_call/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/audio_call/android/settings.gradle b/audio_call/android/settings.gradle index 5a2f14f..44e62bc 100644 --- a/audio_call/android/settings.gradle +++ b/audio_call/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/audio_call/ios/.gitignore b/audio_call/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/audio_call/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/audio_call/ios/Flutter/AppFrameworkInfo.plist b/audio_call/ios/Flutter/AppFrameworkInfo.plist index f2872cf..9625e10 100644 --- a/audio_call/ios/Flutter/AppFrameworkInfo.plist +++ b/audio_call/ios/Flutter/AppFrameworkInfo.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) + en CFBundleExecutable App CFBundleIdentifier @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/audio_call/ios/Flutter/Debug.xcconfig b/audio_call/ios/Flutter/Debug.xcconfig index e8efba1..ec97fc6 100644 --- a/audio_call/ios/Flutter/Debug.xcconfig +++ b/audio_call/ios/Flutter/Debug.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/audio_call/ios/Flutter/Release.xcconfig b/audio_call/ios/Flutter/Release.xcconfig index 399e934..c4855bf 100644 --- a/audio_call/ios/Flutter/Release.xcconfig +++ b/audio_call/ios/Flutter/Release.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/audio_call/ios/Podfile b/audio_call/ios/Podfile index 894c815..88359b2 100644 --- a/audio_call/ios/Podfile +++ b/audio_call/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -15,7 +15,7 @@ def flutter_root 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 @@ -30,68 +30,12 @@ flutter_ios_podfile_setup target 'Runner' do use_frameworks! use_modular_headers! - + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) end post_install do |installer| installer.pods_project.targets.each do |target| - target.build_configurations.each do |config| - config.build_settings['ENABLE_BITCODE'] = 'NO' - # You can enable the permissions needed here. For example to enable camera - # permission, just remove the `#` character in front so it looks like this: - # - # ## dart: PermissionGroup.camera - # 'PERMISSION_CAMERA=1' - # - # Preprocessor definitions can be found in: https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h - config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ - '$(inherited)', - - ## dart: PermissionGroup.calendar - # 'PERMISSION_EVENTS=1', - - ## dart: PermissionGroup.reminders - # 'PERMISSION_REMINDERS=1', - - ## dart: PermissionGroup.contacts - # 'PERMISSION_CONTACTS=1', - - ## dart: PermissionGroup.camera - # 'PERMISSION_CAMERA=1', - - ##dart: PermissionGroup.microphone - 'PERMISSION_MICROPHONE=1', - - ## dart: PermissionGroup.speech - # 'PERMISSION_SPEECH_RECOGNIZER=1', - - ## dart: PermissionGroup.photos - # 'PERMISSION_PHOTOS=1', - - ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse] - # 'PERMISSION_LOCATION=1', - - ## dart: PermissionGroup.notification - # 'PERMISSION_NOTIFICATIONS=1', - - ## dart: PermissionGroup.mediaLibrary - # 'PERMISSION_MEDIA_LIBRARY=1', - - ## dart: PermissionGroup.sensors - # 'PERMISSION_SENSORS=1', - - ## dart: PermissionGroup.bluetooth - # 'PERMISSION_BLUETOOTH=1', - - ## dart: PermissionGroup.appTrackingTransparency - # 'PERMISSION_APP_TRACKING_TRANSPARENCY=1', - - ## dart: PermissionGroup.criticalAlerts - # 'PERMISSION_CRITICAL_ALERTS=1' - ] - # End of the permission_handler configuration - end flutter_additional_ios_build_settings(target) end end diff --git a/audio_call/ios/Podfile.lock b/audio_call/ios/Podfile.lock index 7b3ae25..a8e18d7 100644 --- a/audio_call/ios/Podfile.lock +++ b/audio_call/ios/Podfile.lock @@ -1,87 +1,79 @@ PODS: - - Firebase/CoreOnly (6.33.0): - - FirebaseCore (= 6.10.3) - - Firebase/Messaging (6.33.0): + - Firebase/CoreOnly (10.6.0): + - FirebaseCore (= 10.6.0) + - Firebase/Messaging (10.6.0): - Firebase/CoreOnly - - FirebaseMessaging (~> 4.7.0) - - firebase_core (0.5.3): - - Firebase/CoreOnly (~> 6.33.0) + - FirebaseMessaging (~> 10.6.0) + - firebase_core (2.8.0): + - Firebase/CoreOnly (= 10.6.0) - Flutter - - firebase_messaging (7.0.3): - - Firebase/CoreOnly (~> 6.33.0) - - Firebase/Messaging (~> 6.33.0) + - firebase_messaging (14.3.0): + - Firebase/Messaging (= 10.6.0) - firebase_core - Flutter - - FirebaseCore (6.10.3): - - FirebaseCoreDiagnostics (~> 1.6) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/Logger (~> 6.7) - - FirebaseCoreDiagnostics (1.7.0): - - GoogleDataTransport (~> 7.4) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/Logger (~> 6.7) - - nanopb (~> 1.30906.0) - - FirebaseInstallations (1.7.0): - - FirebaseCore (~> 6.10) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/UserDefaults (~> 6.7) - - PromisesObjC (~> 1.2) - - FirebaseInstanceID (4.8.0): - - FirebaseCore (~> 6.10) - - FirebaseInstallations (~> 1.6) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/UserDefaults (~> 6.7) - - FirebaseMessaging (4.7.1): - - FirebaseCore (~> 6.10) - - FirebaseInstanceID (~> 4.7) - - GoogleUtilities/AppDelegateSwizzler (~> 6.7) - - GoogleUtilities/Environment (~> 6.7) - - GoogleUtilities/Reachability (~> 6.7) - - GoogleUtilities/UserDefaults (~> 6.7) - - Protobuf (>= 3.9.2, ~> 3.9) + - FirebaseCore (10.6.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Logger (~> 7.8) + - FirebaseCoreInternal (10.8.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseInstallations (10.8.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - PromisesObjC (~> 2.1) + - FirebaseMessaging (10.6.0): + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - GoogleDataTransport (~> 9.2) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Reachability (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - nanopb (< 2.30910.0, >= 2.30908.0) - Flutter (1.0.0) - - "flutter_callkit_voximplant (1.2.0+3)": + - flutter_callkit_voximplant (2.1.0): - Flutter - flutter_local_notifications (0.0.1): - Flutter - - flutter_voip_push_notification (0.0.1): + - flutter_voximplant (3.8.0): - Flutter - - flutter_voximplant (3.5.1): - - Flutter - - VoxImplantSDK (= 2.46.10) - - GoogleDataTransport (7.5.1): - - nanopb (~> 1.30906.0) - - GoogleUtilities/AppDelegateSwizzler (6.7.2): + - VoxImplantSDK (= 2.46.12) + - GoogleDataTransport (9.2.2): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30910.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.11.1): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (6.7.2): - - PromisesObjC (~> 1.2) - - GoogleUtilities/Logger (6.7.2): + - GoogleUtilities/Environment (7.11.1): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.11.1): - GoogleUtilities/Environment - - GoogleUtilities/Network (6.7.2): + - GoogleUtilities/Network (7.11.1): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (6.7.2)" - - GoogleUtilities/Reachability (6.7.2): + - "GoogleUtilities/NSData+zlib (7.11.1)" + - GoogleUtilities/Reachability (7.11.1): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (6.7.2): + - GoogleUtilities/UserDefaults (7.11.1): - GoogleUtilities/Logger - - nanopb (1.30906.0): - - nanopb/decode (= 1.30906.0) - - nanopb/encode (= 1.30906.0) - - nanopb/decode (1.30906.0) - - nanopb/encode (1.30906.0) - - "permission_handler (5.0.1+1)": + - nanopb (2.30909.0): + - nanopb/decode (= 2.30909.0) + - nanopb/encode (= 2.30909.0) + - nanopb/decode (2.30909.0) + - nanopb/encode (2.30909.0) + - permission_handler_apple (9.0.4): - Flutter - - PromisesObjC (1.2.12) - - Protobuf (3.21.5) - - shared_preferences (0.0.1): + - PromisesObjC (2.2.0) + - shared_preferences_foundation (0.0.1): - Flutter - - VoxImplantSDK (2.46.10): - - VoxImplantSDK/Core (= 2.46.10) - - VoxImplantSDK/Core (2.46.10): + - FlutterMacOS + - VoxImplantSDK (2.46.12): + - VoxImplantSDK/Core (= 2.46.12) + - VoxImplantSDK/Core (2.46.12): - VoxImplantWebRTC (= 93.0.0) - VoxImplantWebRTC (93.0.0) @@ -91,24 +83,21 @@ DEPENDENCIES: - Flutter (from `Flutter`) - flutter_callkit_voximplant (from `.symlinks/plugins/flutter_callkit_voximplant/ios`) - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - - flutter_voip_push_notification (from `.symlinks/plugins/flutter_voip_push_notification/ios`) - flutter_voximplant (from `.symlinks/plugins/flutter_voximplant/ios`) - - permission_handler (from `.symlinks/plugins/permission_handler/ios`) - - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) SPEC REPOS: trunk: - Firebase - FirebaseCore - - FirebaseCoreDiagnostics + - FirebaseCoreInternal - FirebaseInstallations - - FirebaseInstanceID - FirebaseMessaging - GoogleDataTransport - GoogleUtilities - nanopb - PromisesObjC - - Protobuf - VoxImplantSDK - VoxImplantWebRTC @@ -123,39 +112,34 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_callkit_voximplant/ios" flutter_local_notifications: :path: ".symlinks/plugins/flutter_local_notifications/ios" - flutter_voip_push_notification: - :path: ".symlinks/plugins/flutter_voip_push_notification/ios" flutter_voximplant: :path: ".symlinks/plugins/flutter_voximplant/ios" - permission_handler: - :path: ".symlinks/plugins/permission_handler/ios" - shared_preferences: - :path: ".symlinks/plugins/shared_preferences/ios" + permission_handler_apple: + :path: ".symlinks/plugins/permission_handler_apple/ios" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/ios" SPEC CHECKSUMS: - Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5 - firebase_core: 5d6a02f3d85acd5f8321c2d6d62877626a670659 - firebase_messaging: 0aea2cd5885b65e19ede58ee3507f485c992cc75 - FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd - FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1 - FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2 - FirebaseInstanceID: bd3ffc24367f901a43c063b36c640b345a4a5dd1 - FirebaseMessaging: 5eca4ef173de76253352511aafef774caa1cba2a - Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a - flutter_callkit_voximplant: 3a3645b8265af3d61050087056ba1440ef9a5eaf + Firebase: f13680471b021937f2230ea8503c7809d8c29806 + firebase_core: 58542d7399889ebdbb034baa72d081e54c5c814d + firebase_messaging: 01a8db2962f81ea190d08db767aba2e7e805e647 + FirebaseCore: fa80ad16a62d52f67274b5b88304c3a318bbf9a4 + FirebaseCoreInternal: fa2899eb1f340054858d289e5a0fb935a0a74e52 + FirebaseInstallations: b2a05a3fe707df764345d68685534d07d0664af3 + FirebaseMessaging: fd93783258c53ae5cdb9b41bf0c51606a677f2d5 + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + flutter_callkit_voximplant: 9e1128135757ea8a21ae7bbc06ff4a37e906ccc5 flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 - flutter_voip_push_notification: f28f3ce1c6b835a3fa9e833f37f33dc1291ab888 - flutter_voximplant: 5e54116ff1f9cd0fd973f62950e61b39bac3bd57 - GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833 - GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 - nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc - permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6 - PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97 - Protobuf: 7504b04fffcf6662ad629694db8231f5e744327f - shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d - VoxImplantSDK: db660ef67c89e3df0e07ca270369c496effab6e5 + flutter_voximplant: 40c3110cc9943047f36fb9847f8803350237480a + GoogleDataTransport: 8378d1fa8ac49753ea6ce70d65a7cb70ce5f66e6 + GoogleUtilities: 9aa0ad5a7bc171f8bae016300bfcfa3fb8425749 + nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 + permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce + PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef + shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472 + VoxImplantSDK: 577259786bc3da6ed3cf3d4ee1a8e08245c19ce6 VoxImplantWebRTC: 8ddd8a63d0c20afa604fec22a2552c32b0371974 -PODFILE CHECKSUM: 20d5202926f5ac9150a51c202a7ded0a3b174026 +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.0 diff --git a/audio_call/ios/Runner.xcodeproj/project.pbxproj b/audio_call/ios/Runner.xcodeproj/project.pbxproj index a066bda..eab0823 100644 --- a/audio_call/ios/Runner.xcodeproj/project.pbxproj +++ b/audio_call/ios/Runner.xcodeproj/project.pbxproj @@ -3,19 +3,17 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 7EA25A1D25377B0B00A806B2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EA25A1C25377B0B00A806B2 /* AppDelegate.swift */; }; - 920FECDC255462D5005D467B /* fennelliott_beeping.wav in Resources */ = {isa = PBXBuildFile; fileRef = 920FECDB255462D5005D467B /* fennelliott_beeping.wav */; }; - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; + 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 */; }; - B20899292382FA590097FF08 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B20899282382FA580097FF08 /* GoogleService-Info.plist */; }; + F2E7AB6029F1B4D600B9DCA1 /* fennelliott_beeping.wav in Resources */ = {isa = PBXBuildFile; fileRef = F2E7AB5F29F1B4D600B9DCA1 /* fennelliott_beeping.wav */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -35,11 +33,9 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7EA25A1B25377B0B00A806B2 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 7EA25A1C25377B0B00A806B2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 8EF31FC2236B1B9500682CB7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; - 920FECDB255462D5005D467B /* fennelliott_beeping.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = fennelliott_beeping.wav; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -47,7 +43,8 @@ 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 = ""; }; - B20899282382FA580097FF08 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + F2E7AB5E29F192B300B9DCA1 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + F2E7AB5F29F1B4D600B9DCA1 /* fennelliott_beeping.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = fennelliott_beeping.wav; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -61,13 +58,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 525C86CF0F5831913430637B /* Pods */ = { - isa = PBXGroup; - children = ( - ); - path = Pods; - sourceTree = ""; - }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -85,7 +75,7 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - 525C86CF0F5831913430637B /* Pods */, + AB711A1BF76F92D99C0EA15C /* Pods */, ); sourceTree = ""; }; @@ -100,27 +90,25 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( - 920FECDB255462D5005D467B /* fennelliott_beeping.wav */, - B20899282382FA580097FF08 /* GoogleService-Info.plist */, - 8EF31FC2236B1B9500682CB7 /* Runner.entitlements */, + F2E7AB5F29F1B4D600B9DCA1 /* fennelliott_beeping.wav */, + F2E7AB5E29F192B300B9DCA1 /* Runner.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 7EA25A1C25377B0B00A806B2 /* AppDelegate.swift */, - 7EA25A1B25377B0B00A806B2 /* Runner-Bridging-Header.h */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, ); path = Runner; sourceTree = ""; }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { + AB711A1BF76F92D99C0EA15C /* Pods */ = { isa = PBXGroup; children = ( ); - name = "Supporting Files"; + path = Pods; sourceTree = ""; }; /* End PBXGroup section */ @@ -153,17 +141,16 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 1300; - ORGANIZATIONNAME = "The Chromium Authors"; + ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = W9BHJBL635; - LastSwiftMigration = 1200; + LastSwiftMigration = 1100; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; + compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -187,11 +174,9 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, - 920FECDC255462D5005D467B /* fennelliott_beeping.wav in Resources */, + F2E7AB6029F1B4D600B9DCA1 /* fennelliott_beeping.wav in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - B20899292382FA590097FF08 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -200,6 +185,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -210,10 +196,11 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; + 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 = ( ); @@ -224,7 +211,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; /* End PBXShellScriptBuildPhase section */ @@ -233,7 +220,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7EA25A1D25377B0B00A806B2 /* AppDelegate.swift in Sources */, + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -301,9 +288,10 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -319,20 +307,11 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = W9BHJBL635; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.voximplant.flutter.audioCall; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -388,7 +367,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -437,9 +416,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -455,20 +437,11 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = W9BHJBL635; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.voximplant.flutter.audioCall; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -488,20 +461,11 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = W9BHJBL635; ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); PRODUCT_BUNDLE_IDENTIFIER = com.voximplant.flutter.audioCall; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/audio_call/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/audio_call/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/audio_call/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/audio_call/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/audio_call/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/audio_call/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/audio_call/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/audio_call/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 3db53b6..c87d15a 100644 --- a/audio_call/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/audio_call/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -27,8 +27,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + - - + + + + IDEDidComputeMac32BitWarning + + + diff --git a/audio_call/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/audio_call/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/audio_call/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/audio_call/ios/Runner/AppDelegate.swift b/audio_call/ios/Runner/AppDelegate.swift index aa7c7e3..4bb1feb 100644 --- a/audio_call/ios/Runner/AppDelegate.swift +++ b/audio_call/ios/Runner/AppDelegate.swift @@ -1,56 +1,46 @@ +import UIKit import Flutter import PushKit -import CallKit import flutter_callkit_voximplant -import flutter_voip_push_notification -import shared_preferences import flutter_voximplant -import permission_handler @UIApplicationMain -final class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate { +@objc class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate { + private let voipRegistry: PKPushRegistry = PKPushRegistry(queue: .main) override func application( _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { - // Registering plugins manually, because on iOS FLTFirebaseMessagingPlugin and FlutterLocalNotificationsPlugin - // are not used and should not be registered - FlutterCallkitPlugin.register(with: registrar(forPlugin: "FlutterCallkitPlugin")!) - FlutterVoipPushNotificationPlugin.register(with: registrar(forPlugin: "FlutterVoipPushNotificationPlugin")!) - VoximplantPlugin.register(with: registrar(forPlugin: "VoximplantPlugin")!) - PermissionHandlerPlugin.register(with: registrar(forPlugin: "PermissionHandlerPlugin")!) - FLTSharedPreferencesPlugin.register(with: registrar(forPlugin: "FLTSharedPreferencesPlugin")!) + GeneratedPluginRegistrant.register(with: self) + PushKitPlugin.register(with: self.registrar(forPlugin: "PushKitPlugin")!) + + PushKitPlugin.shared.setPKPushRegistry(voipRegistry) + voipRegistry.delegate = self + voipRegistry.desiredPushTypes = [.voIP] + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } - // MARK: - PKPushRegistryDelegate - - func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { - FlutterVoipPushNotificationPlugin.didUpdate(pushCredentials, forType: type.rawValue) - } - func pushRegistry(_ registry: PKPushRegistry, - didReceiveIncomingPushWith payload: PKPushPayload, - for type: PKPushType - ) { - processPush(with: payload, type: type, and: nil) + func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { + PushKitPlugin.shared.updatePushCredentials(pushCredentials, for: type) } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, - completion: @escaping () -> Void - ) { + completion: @escaping () -> Void) { processPush(with: payload, type: type, and: completion) } private func processPush(with payload: PKPushPayload, type: PKPushType, and completion: (() -> Void)?) { print("Push received: \(payload)") - - FlutterVoipPushNotificationPlugin.didReceiveIncomingPush(with: payload, forType: type.rawValue) - + + PushKitPlugin.shared.reportIncomingPushWith(payload: payload, for: type) + let callKitPlugin = FlutterCallkitPlugin.sharedInstance - + guard let content = payload.dictionaryPayload.content, UIApplication.shared.applicationState != .active, @@ -83,6 +73,7 @@ final class AppDelegate: FlutterAppDelegate, PKPushRegistryDelegate { } } + fileprivate extension Dictionary where Key == AnyHashable { var content: [String: Any]? { self["voximplant"] as? [String:Any] @@ -98,3 +89,82 @@ fileprivate extension Dictionary where Key == String { self["userid"] as! String } } + +class PushKitPlugin: NSObject, FlutterPlugin, FlutterStreamHandler { + static let shared = PushKitPlugin() + private var pushKitEventChannel: FlutterEventChannel? + private var eventSink: FlutterEventSink? + private var voipRegistry: PKPushRegistry? + + public static func register(with registrar: FlutterPluginRegistrar) { + print("YULIA: register") + let channel = FlutterMethodChannel(name: "plugins.voximplant.com/pushkit", binaryMessenger: registrar.messenger()) + let instance = PushKitPlugin.shared + instance.setup(with: registrar) + registrar.addMethodCallDelegate(instance, channel: channel) + } + + private override init() { + super.init() + } + + private func setup(with registrar: FlutterPluginRegistrar) { + pushKitEventChannel = FlutterEventChannel(name: "plugins.voximplant.com/pushkitevents", binaryMessenger: registrar.messenger()) + pushKitEventChannel?.setStreamHandler(self) + } + + public func setPKPushRegistry(_ registry: PKPushRegistry) { + self.voipRegistry = registry + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + if (call.method == "voipToken") { + guard let voipToken = voipRegistry?.pushToken(for: .voIP) else { + result(nil) + return + } + let token = convertTokenToString(data: voipToken) + result(token) + } + } + + public func updatePushCredentials(_ pushCredentials: PKPushCredentials, for type: PKPushType) { + guard let eventSink = self.eventSink else { + print("[PushKitPlugin]: updatePushCredentials: eventSink is not initialized") + return + } + let token = self.convertTokenToString(data: pushCredentials.token) + eventSink(["event": "didUpdatePushCredentials", "token": token]) + } + + public func reportIncomingPushWith(payload: PKPushPayload, for type: PKPushType) { + guard let eventSink = self.eventSink else { + print("[PushKitPlugin]: reportIncomingPushWith: eventSink is not initialized") + return + } + eventSink(["event": "didReceiveIncomingPushWithPayload", + "payload": payload.dictionaryPayload] as [String : Any]) + } + + public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { + if let type = arguments as? String { + if (type == "pushkit") { + self.eventSink = events + } + } + return nil + } + + public func onCancel(withArguments arguments: Any?) -> FlutterError? { + if let type = arguments as? String { + if (type == "pushkit") { + self.eventSink = nil + } + } + return nil + } + + private func convertTokenToString(data: Data) -> String { + return data.map { String(format: "%02.2hhx", $0) }.joined() + } +} diff --git a/audio_call/ios/Runner/Assets.xcassets/Contents.json b/audio_call/ios/Runner/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/audio_call/ios/Runner/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/audio_call/ios/Runner/GoogleService-Info.plist b/audio_call/ios/Runner/GoogleService-Info.plist deleted file mode 100644 index a35d940..0000000 --- a/audio_call/ios/Runner/GoogleService-Info.plist +++ /dev/null @@ -1,34 +0,0 @@ - - - - - CLIENT_ID - qwerqwer.apps.googleusercontent.com - REVERSED_CLIENT_ID - com.googleusercontent.apps.qwerqwer - API_KEY - qwer1111 - GCM_SENDER_ID - 1111 - PLIST_VERSION - 1 - BUNDLE_ID - com.voximplant.flutter.audioCall - PROJECT_ID - qwer - STORAGE_BUCKET - qwer.appspot.com - IS_ADS_ENABLED - - IS_ANALYTICS_ENABLED - - IS_APPINVITE_ENABLED - - IS_GCM_ENABLED - - IS_SIGNIN_ENABLED - - GOOGLE_APP_ID - 1:1111:ios:2222 - - diff --git a/audio_call/ios/Runner/Info.plist b/audio_call/ios/Runner/Info.plist index e7506db..32b9d0d 100644 --- a/audio_call/ios/Runner/Info.plist +++ b/audio_call/ios/Runner/Info.plist @@ -2,8 +2,12 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Audio Call CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -11,7 +15,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - Audio call + $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString @@ -22,9 +26,13 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + NSMicrophoneUsageDescription + To make audio calls + UIApplicationSupportsIndirectInputEvents + UIBackgroundModes - audio + processing remote-notification voip @@ -47,65 +55,5 @@ UIViewControllerBasedStatusBarAppearance - CADisableMinimumFrameDurationOnPhone - - - - NSLocationWhenInUseUsageDescription - Need location when in use - NSLocationAlwaysAndWhenInUseUsageDescription - Always and when in use! - NSLocationUsageDescription - Older devices need location. - NSLocationAlwaysUsageDescription - Can I have location always? - - - NSAppleMusicUsageDescription - Music! - kTCCServiceMediaLibrary - media - - - NSCalendarsUsageDescription - Calendars - - - NSCameraUsageDescription - camera - - - NSContactsUsageDescription - contacts - - - NSMicrophoneUsageDescription - Access to the microphone for calls - - - NSSpeechRecognitionUsageDescription - speech - - - NSMotionUsageDescription - motion - - - NSPhotoLibraryUsageDescription - photos - - - NSRemindersUsageDescription - reminders - - - NSBluetoothAlwaysUsageDescription - bluetooth - NSBluetoothPeripheralUsageDescription - bluetooth - - - NSUserTrackingUsageDescription - appTrackingTransparency diff --git a/audio_call/lib/main.dart b/audio_call/lib/main.dart index 3ffc155..0a607e3 100644 --- a/audio_call/lib/main.dart +++ b/audio_call/lib/main.dart @@ -21,7 +21,7 @@ import 'package:flutter_voximplant/flutter_voximplant.dart'; class SimpleBlocDelegate extends BlocObserver { @override - void onEvent(Bloc bloc, Object event) { + void onEvent(Bloc bloc, Object? event) { super.onEvent(bloc, event); log(event); } @@ -33,13 +33,13 @@ class SimpleBlocDelegate extends BlocObserver { } @override - void onError(Cubit cubit, Object error, StackTrace stackTrace) { - super.onError(cubit, error, stackTrace); + void onError(BlocBase bloc, Object error, StackTrace stackTrace) { + super.onError(bloc, error, stackTrace); log(error); } } -VIClientConfig get defaultConfig => VIClientConfig(); +VIClientConfig get defaultConfig => VIClientConfig(bundleId: 'com.voximplant.flutter.audioCall'); void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -55,11 +55,11 @@ void main() { NotificationHelper(); } - runApp(App()); + runApp(const App()); } class App extends StatelessWidget { - App({Key key}) : super(key: key); + const App({super.key}); @override Widget build(BuildContext context) { @@ -87,13 +87,16 @@ class App extends StatelessWidget { ), ); } else if (routeSettings.name == AppRoutes.activeCall) { - ActiveCallPageArguments arguments = routeSettings.arguments; + final routingArguments = routeSettings.arguments as ActiveCallPageArguments; + ActiveCallPageArguments arguments = routingArguments; return PageRouteBuilder( - pageBuilder: (_, a1, a2) => BlocProvider( - create: (_) => - ActiveCallBloc(arguments.isIncoming, arguments.endpoint), - child: ActiveCallPage(), - ), + pageBuilder: (_, a1, a2) => + BlocProvider( + create: (_) => + ActiveCallBloc( + arguments.isIncoming, arguments.endpoint), + child: ActiveCallPage(), + ), ); } else if (routeSettings.name == AppRoutes.incomingCall) { return PageRouteBuilder( diff --git a/audio_call/lib/screens/active_call/active_call_page.dart b/audio_call/lib/screens/active_call/active_call_page.dart index 78e7ff9..5e55cea 100644 --- a/audio_call/lib/screens/active_call/active_call_page.dart +++ b/audio_call/lib/screens/active_call/active_call_page.dart @@ -1,7 +1,5 @@ /// Copyright (c) 2011-2020, Zingaya, Inc. All rights reserved. import 'package:audio_call/screens/active_call/active_call.dart'; -import 'package:audio_call/screens/active_call/bloc/active_call_event.dart'; -import 'package:audio_call/screens/active_call/bloc/active_call_state.dart'; import 'package:audio_call/screens/call_failed/call_failed.dart'; import 'package:audio_call/theme/voximplant_theme.dart'; import 'package:audio_call/utils/navigation_helper.dart'; @@ -17,29 +15,28 @@ class ActiveCallPage extends StatefulWidget { } class _ActiveCallPageState extends State { - ActiveCallBloc _bloc; - - _ActiveCallPageState(); + late ActiveCallBloc _bloc; @override void initState() { super.initState(); _bloc = BlocProvider.of(context); + context.read().add(ReadyToStartCallEvent()); } @override Widget build(BuildContext context) { - void _hangup() => _bloc.add(HangupPressedEvent()); + void hangup() => _bloc.add(HangupPressedEvent()); - void _hold(bool hold) => _bloc.add(HoldPressedEvent(hold: hold)); + void _hold(bool hold) => _bloc.add(HoldPressedEvent(hold)); - void _mute(bool mute) => _bloc.add(MutePressedEvent(mute: mute)); + void _mute(bool mute) => _bloc.add(MutePressedEvent(mute)); - void _selectAudioDevice(VIAudioDevice device) => _bloc.add( - SelectAudioDevicePressedEvent(device: device), + void selectAudioDevice(VIAudioDevice device) => _bloc.add( + SelectAudioDevicePressedEvent(device), ); - IconData _getIconForDevice(VIAudioDevice device) { + IconData getIconForDevice(VIAudioDevice device) { switch (device) { case VIAudioDevice.Bluetooth: return Icons.bluetooth_audio; @@ -52,22 +49,22 @@ class _ActiveCallPageState extends State { } } - String _getNameForDevice(VIAudioDevice device) { + String getNameForDevice(VIAudioDevice device) { List splitted = device.toString().split('.'); - if (splitted != null && splitted.length >= 2) { + if (splitted.length >= 2) { return splitted[1]; } else { return device.toString(); } } - _showAvailableAudioDevices(List devices) { + showAvailableAudioDevices(List devices) { return showDialog( context: context, barrierDismissible: true, builder: (BuildContext context) { return AlertDialog( - title: Text('Select audio device'), + title: const Text('Select audio device'), content: SingleChildScrollView( child: Container( width: 100, @@ -75,13 +72,13 @@ class _ActiveCallPageState extends State { child: ListView.builder( itemCount: devices.length, itemBuilder: (_, int index) { - return FlatButton( + return TextButton( child: Text( - _getNameForDevice(devices[index]), - style: TextStyle(fontSize: 16), + getNameForDevice(devices[index]), + style: const TextStyle(fontSize: 16), ), onPressed: () { - _selectAudioDevice(devices[index]); + selectAudioDevice(devices[index]); }, ); }, @@ -111,7 +108,7 @@ class _ActiveCallPageState extends State { builder: (context, state) { return Scaffold( appBar: AppBar( - title: Text('Call'), + title: const Text('Call'), ), backgroundColor: VoximplantColors.white, body: SafeArea( @@ -125,13 +122,13 @@ class _ActiveCallPageState extends State { children: [ Text( state.endpointName, - style: TextStyle( + style: const TextStyle( fontSize: 26, ), ), Text( state.callStatus, - style: TextStyle( + style: const TextStyle( fontSize: 18, ), ), @@ -151,7 +148,7 @@ class _ActiveCallPageState extends State { bottom: 20, ), child: Ink( - decoration: ShapeDecoration( + decoration: const ShapeDecoration( color: VoximplantColors.white, shape: CircleBorder( side: BorderSide( @@ -181,7 +178,7 @@ class _ActiveCallPageState extends State { left: 20, ), child: Ink( - decoration: ShapeDecoration( + decoration: const ShapeDecoration( color: VoximplantColors.white, shape: CircleBorder( side: BorderSide( @@ -211,7 +208,7 @@ class _ActiveCallPageState extends State { bottom: 20, ), child: Ink( - decoration: ShapeDecoration( + decoration: const ShapeDecoration( color: VoximplantColors.white, shape: CircleBorder( side: BorderSide( @@ -223,13 +220,13 @@ class _ActiveCallPageState extends State { ), child: IconButton( onPressed: () { - _showAvailableAudioDevices( + showAvailableAudioDevices( state.availableAudioDevices, ); }, iconSize: 40, icon: Icon( - _getIconForDevice(state.activeAudioDevice), + getIconForDevice(state.activeAudioDevice), color: VoximplantColors.button, ), tooltip: 'Select audio device', @@ -248,7 +245,7 @@ class _ActiveCallPageState extends State { bottom: 20, ), child: Ink( - decoration: ShapeDecoration( + decoration: const ShapeDecoration( color: VoximplantColors.white, shape: CircleBorder( side: BorderSide( @@ -259,9 +256,9 @@ class _ActiveCallPageState extends State { ), ), child: IconButton( - onPressed: _hangup, + onPressed: hangup, iconSize: 40, - icon: Icon( + icon: const Icon( Icons.call_end, color: VoximplantColors.red, ), diff --git a/audio_call/lib/screens/active_call/active_call_page_arguments.dart b/audio_call/lib/screens/active_call/active_call_page_arguments.dart index 26b139b..f0d90ee 100644 --- a/audio_call/lib/screens/active_call/active_call_page_arguments.dart +++ b/audio_call/lib/screens/active_call/active_call_page_arguments.dart @@ -7,6 +7,6 @@ class ActiveCallPageArguments { bool isIncoming; ActiveCallPageArguments( - {@required this.endpoint, - @required this.isIncoming}); + {required this.endpoint, + required this.isIncoming}); } diff --git a/audio_call/lib/screens/active_call/bloc/active_call_bloc.dart b/audio_call/lib/screens/active_call/bloc/active_call_bloc.dart index 82a446e..1ef19aa 100644 --- a/audio_call/lib/screens/active_call/bloc/active_call_bloc.dart +++ b/audio_call/lib/screens/active_call/bloc/active_call_bloc.dart @@ -11,153 +11,177 @@ import 'package:audio_call/services/call/callkit_service.dart'; import 'package:audio_call/utils/log.dart'; import 'package:bloc/bloc.dart'; import 'package:flutter_callkit_voximplant/flutter_callkit_voximplant.dart'; +import 'package:flutter_voximplant/flutter_voximplant.dart'; class ActiveCallBloc extends Bloc { final CallService _callService = CallService(); - final CallKitService _callKitService = + final CallKitService? _callKitService = Platform.isIOS ? CallKitService() : null; - StreamSubscription _callStateSubscription; - StreamSubscription _audioDeviceSubscription; + StreamSubscription? _callStateSubscription; + StreamSubscription? _audioDeviceSubscription; - ActiveCallBloc(bool isIncoming, String endpoint) - : super(ActiveCallState( + bool _isIncoming; + String _endpoint; + + ActiveCallBloc(this._isIncoming, this._endpoint) + : super(const ActiveCallState( isOnHold: false, isMuted: false, - activeAudioDevice: null, + activeAudioDevice: VIAudioDevice.Earpiece, availableAudioDevices: [], endpointName: '', callStatus: '', )) { - add(ReadyToStartCallEvent( - isIncoming: isIncoming, - endpoint: endpoint, - )); + on(_readyToStartCall); + on(_handleCallChanged); + on(_holdCall); + on(_muteAudio); + on(_hangupCall); + on(_selectAudioDevice); + on(_handleAudioDevicesChanged); } @override Future close() { - if (_callStateSubscription != null) { - _callStateSubscription.cancel(); - } - if (_audioDeviceSubscription != null) { - _audioDeviceSubscription.cancel(); - } + _callStateSubscription?.cancel(); + _audioDeviceSubscription?.cancel(); return super.close(); } - @override - Stream mapEventToState(ActiveCallEvent event) async* { - if (event is ReadyToStartCallEvent) { - _callStateSubscription = _callService.subscribeToCallEvents().listen( - (event) { - add(CallChangedEvent(event: event)); - }, - ); - _audioDeviceSubscription = - _callService.subscribeToAudioDeviceEvents().listen( - (event) { - add(AudioDevicesChanged(event: event)); - }, - ); - try { - if (event.isIncoming) { - if (Platform.isAndroid) { - if (_callService.hasActiveCall) { + Future _readyToStartCall( + ReadyToStartCallEvent event, + Emitter emit) async { + _callStateSubscription = _callService.subscribeToCallEvents().listen( + (event) { + add(CallChangedEvent(event)); + }, + ); + _audioDeviceSubscription = + _callService.subscribeToAudioDeviceEvents().listen( + (event) { + add(AudioDevicesChanged(event)); + }, + ); + try { + if (_isIncoming) { + if (Platform.isAndroid) { + if (_callService.hasActiveCall) { + await _callService.answerCall(); + } else { + _callService.onIncomingCall = (_) async { await _callService.answerCall(); - } else { - _callService.onIncomingCall = (_) async { - await _callService.answerCall(); - }; - } - } - } else /* if (direction == outgoing) */ { - if (Platform.isAndroid) { - await _callService.makeCall(callTo: event.endpoint); - } else if (Platform.isIOS) { - await _callKitService.startOutgoingCall(event.endpoint); + }; } } - yield state.copyWith( - callStatus: _makeStringFromCallState(_callService.callState), - endpointName: _callService?.endpoint?.displayName ?? - _callService?.endpoint?.userName ?? - event.endpoint ?? - '', - availableAudioDevices: _callService.availableAudioDevices, - activeAudioDevice: _callService.activeAudioDevice, - ); - } catch (e) { - add(CallChangedEvent(event: OnFailedCallEvent(reason: e.toString()))); - } - } else if (event is CallChangedEvent) { - CallEvent callEvent = event.event; - - if (callEvent is OnFailedCallEvent) { - _log('onFailed event'); - await _callKitService?.reportCallEnded( - reason: FCXCallEndedReason.failed, - ); - yield CallEndedActiveCallState( - reason: callEvent.reason, - failed: true, - endpointName: state.endpointName, - activeAudioDevice: state.activeAudioDevice, - ); - } else if (callEvent is OnDisconnectedCallEvent) { - _log('onDisconnected event'); - if (Platform.isIOS) { - await _callKitService?.reportCallEnded( - reason: FCXCallEndedReason.remoteEnded, - ); + } else /* if (direction == outgoing) */ { + if (Platform.isAndroid) { + await _callService.makeCall(callTo: _endpoint); + } else if (Platform.isIOS) { + await _callKitService?.startOutgoingCall(_endpoint); } - yield CallEndedActiveCallState( - reason: 'Disconnected', - failed: false, - endpointName: state.endpointName, - activeAudioDevice: state.activeAudioDevice, - ); - } else if (callEvent is OnHoldCallEvent) { - _log('onHold event'); - bool isOnHold = callEvent.hold; - String status = isOnHold ? 'Is on hold' : 'Connected'; - yield state.copyWith(isOnHold: isOnHold, callStatus: status); - } else if (callEvent is OnMuteCallEvent) { - _log('onMute event'); - yield state.copyWith(isMuted: callEvent.muted); - } else if (callEvent is OnConnectedCallEvent) { - _log('onConnected event'); - String name = callEvent.displayName ?? callEvent.username ?? ''; - yield state.copyWith(callStatus: 'Connected', endpointName: name); - await _callKitService?.reportConnected( - callEvent.username, - callEvent.displayName, - ); - } else if (callEvent is OnRingingCallEvent) { - _log('onRinging event'); - yield state.copyWith(callStatus: 'Ringing'); } - } else if (event is HoldPressedEvent) { + emit(state.copyWith( + callStatus: _makeStringFromCallState(_callService.callState), + endpointName: _callService.endpoint?.displayName ?? + _callService.endpoint?.userName ?? + _endpoint ?? + '', + availableAudioDevices: _callService.availableAudioDevices, + activeAudioDevice: _callService.activeAudioDevice, + )); + } catch (e) { + add(CallChangedEvent(OnFailedCallEvent(reason: e.toString()))); + } + } + + Future _handleCallChanged( + CallChangedEvent event, + Emitter emit) async { + CallEvent callEvent = event.event; + + if (callEvent is OnFailedCallEvent) { + _log('onFailed event'); + await _callKitService?.reportCallEnded( + reason: FCXCallEndedReason.failed, + ); + emit(CallEndedActiveCallState( + reason: callEvent.reason, + failed: true, + endpointName: state.endpointName, + activeAudioDevice: state.activeAudioDevice, + )); + } else if (callEvent is OnDisconnectedCallEvent) { + _log('onDisconnected event'); + await _callKitService?.reportCallEnded( + reason: FCXCallEndedReason.remoteEnded, + ); + emit(CallEndedActiveCallState( + reason: 'Disconnected', + failed: false, + endpointName: state.endpointName, + activeAudioDevice: state.activeAudioDevice, + )); + } else if (callEvent is OnHoldCallEvent) { + _log('onHold event'); + bool isOnHold = callEvent.hold; + String status = isOnHold ? 'Is on hold' : 'Connected'; + emit(state.copyWith(isOnHold: isOnHold, callStatus: status)); + } else if (callEvent is OnMuteCallEvent) { + _log('onMute event'); + emit(state.copyWith(isMuted: callEvent.muted)); + } else if (callEvent is OnConnectedCallEvent) { + _log('onConnected event'); + String name = callEvent.displayName ?? callEvent.username ?? ''; + emit(state.copyWith(callStatus: 'Connected', endpointName: name)); + await _callKitService?.reportConnected( + callEvent.username, + callEvent.displayName, + ); + } else if (callEvent is OnRingingCallEvent) { + _log('onRinging event'); + emit(state.copyWith(callStatus: 'Ringing')); + } + } + + Future _holdCall( + HoldPressedEvent event, + Emitter emit) async { Platform.isIOS - ? await _callKitService.holdCall(event.hold) - : await _callService.holdCall(hold: event.hold); - } else if (event is MutePressedEvent) { + ? await _callKitService?.holdCall(event.hold) + : await _callService.holdCall(hold: event.hold); + } + + Future _muteAudio( + MutePressedEvent event, + Emitter emit) async { Platform.isIOS - ? await _callKitService.muteCall(event.mute) - : await _callService.muteCall(mute: event.mute); - } else if (event is HangupPressedEvent) { + ? await _callKitService?.muteCall(event.mute) + : await _callService.muteCall(mute: event.mute); + } + + Future _hangupCall( + HangupPressedEvent event, + Emitter emit) async { Platform.isIOS - ? await _callKitService.endCall() - : await _callService.hangup(); - } else if (event is SelectAudioDevicePressedEvent) { - await _callService.selectAudioDevice(device: event.device); - } else if (event is AudioDevicesChanged) { - AudioDeviceEvent audioEvent = event.event; - if (audioEvent is OnActiveAudioDeviceChanged) { - yield state.copyWith(activeAudioDevice: audioEvent.device); - } else if (audioEvent is OnAvailableAudioDevicesListChanged) { - yield state.copyWith(availableAudioDevices: audioEvent.devices); - } + ? await _callKitService?.endCall() + : await _callService.hangup(); + } + + Future _selectAudioDevice( + SelectAudioDevicePressedEvent event, + Emitter emit) async { + await _callService.selectAudioDevice(device: event.device); + } + + Future _handleAudioDevicesChanged( + AudioDevicesChanged event, + Emitter emit) async { + AudioDeviceEvent audioEvent = event.event; + if (audioEvent is OnActiveAudioDeviceChanged) { + emit(state.copyWith(activeAudioDevice: audioEvent.device)); + } else if (audioEvent is OnAvailableAudioDevicesListChanged) { + emit(state.copyWith(availableAudioDevices: audioEvent.devices)); } } diff --git a/audio_call/lib/screens/active_call/bloc/active_call_event.dart b/audio_call/lib/screens/active_call/bloc/active_call_event.dart index cff074e..38e76a9 100644 --- a/audio_call/lib/screens/active_call/bloc/active_call_event.dart +++ b/audio_call/lib/screens/active_call/bloc/active_call_event.dart @@ -8,53 +8,36 @@ import 'package:flutter_voximplant/flutter_voximplant.dart'; abstract class ActiveCallEvent { } class ReadyToStartCallEvent implements ActiveCallEvent { - final bool isIncoming; - final String endpoint; - - ReadyToStartCallEvent({ - @required this.isIncoming, - @required this.endpoint, - }); + ReadyToStartCallEvent(); } class CallChangedEvent implements ActiveCallEvent { final CallEvent event; - - CallChangedEvent({ - @required this.event, - }); + CallChangedEvent(this.event); } class AudioDevicesChanged implements ActiveCallEvent { final AudioDeviceEvent event; - AudioDevicesChanged({ - @required this.event, - }); + AudioDevicesChanged(this.event); } class HoldPressedEvent implements ActiveCallEvent { final bool hold; - HoldPressedEvent({ - @required this.hold, - }); + HoldPressedEvent(this.hold); } class SelectAudioDevicePressedEvent implements ActiveCallEvent { final VIAudioDevice device; - SelectAudioDevicePressedEvent({ - @required this.device, - }); + SelectAudioDevicePressedEvent(this.device); } class MutePressedEvent implements ActiveCallEvent { final bool mute; - MutePressedEvent({ - @required this.mute, - }); + MutePressedEvent(this.mute); } class HangupPressedEvent implements ActiveCallEvent { } diff --git a/audio_call/lib/screens/active_call/bloc/active_call_state.dart b/audio_call/lib/screens/active_call/bloc/active_call_state.dart index e133eba..9a0dcbf 100644 --- a/audio_call/lib/screens/active_call/bloc/active_call_state.dart +++ b/audio_call/lib/screens/active_call/bloc/active_call_state.dart @@ -12,22 +12,22 @@ class ActiveCallState implements Equatable { final bool isOnHold; final bool isMuted; - ActiveCallState({ - @required this.endpointName, - @required this.callStatus, - @required this.activeAudioDevice, - @required this.availableAudioDevices, - @required this.isOnHold, - @required this.isMuted, + const ActiveCallState({ + required this.endpointName, + required this.callStatus, + required this.activeAudioDevice, + required this.availableAudioDevices, + required this.isOnHold, + required this.isMuted, }); ActiveCallState copyWith({ - String endpointName, - String callStatus, - VIAudioDevice activeAudioDevice, - List availableAudioDevices, - bool isOnHold, - bool isMuted, + String? endpointName, + String? callStatus, + VIAudioDevice? activeAudioDevice, + List? availableAudioDevices, + bool? isOnHold, + bool? isMuted, }) => ActiveCallState( endpointName: endpointName ?? this.endpointName, @@ -59,10 +59,10 @@ class CallEndedActiveCallState extends ActiveCallState { final String reason; CallEndedActiveCallState({ - @required this.reason, - @required this.failed, - @required endpointName, - @required activeAudioDevice, + required this.reason, + required this.failed, + required endpointName, + required activeAudioDevice, }) : super( endpointName: endpointName, callStatus: failed ? 'Failed' : 'Disconnected', diff --git a/audio_call/lib/screens/call_failed/call_failed_page.dart b/audio_call/lib/screens/call_failed/call_failed_page.dart index 9ee049c..8ecd5e0 100644 --- a/audio_call/lib/screens/call_failed/call_failed_page.dart +++ b/audio_call/lib/screens/call_failed/call_failed_page.dart @@ -25,27 +25,24 @@ class CallFailedPage extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - Container( - child: Column( - children: [ - Widgets.textWithPadding( - text: 'Call failed', - textColor: VoximplantColors.white, - fontSize: 40, - ), - Widgets.textWithPadding( - text: _endpoint, - textColor: VoximplantColors.white, - fontSize: 30, - verticalPadding: 30, - ), - Widgets.textWithPadding( - text: _failureReason, - textColor: VoximplantColors.white, - fontSize: 25, - ), - ], - ), + Column( + children: [ + Widgets.textWithPadding( + text: 'Call failed', + textColor: VoximplantColors.white, + fontSize: 40, + ), + Widgets.textWithPadding( + text: _endpoint, + textColor: VoximplantColors.white, + verticalPadding: 30, + ), + Widgets.textWithPadding( + text: _failureReason, + textColor: VoximplantColors.white, + fontSize: 25, + ), + ], ), Widgets.iconButton( icon: Icons.close, diff --git a/audio_call/lib/screens/call_failed/call_failed_page_arguments.dart b/audio_call/lib/screens/call_failed/call_failed_page_arguments.dart index bb4f7c7..402f9d0 100644 --- a/audio_call/lib/screens/call_failed/call_failed_page_arguments.dart +++ b/audio_call/lib/screens/call_failed/call_failed_page_arguments.dart @@ -7,7 +7,7 @@ class CallFailedPageArguments { final String endpoint; CallFailedPageArguments({ - @required this.failureReason, - @required this.endpoint, + required this.failureReason, + required this.endpoint, }); } diff --git a/audio_call/lib/screens/incoming_call/bloc/incoming_call_bloc.dart b/audio_call/lib/screens/incoming_call/bloc/incoming_call_bloc.dart index 15dce6b..178c249 100644 --- a/audio_call/lib/screens/incoming_call/bloc/incoming_call_bloc.dart +++ b/audio_call/lib/screens/incoming_call/bloc/incoming_call_bloc.dart @@ -12,43 +12,47 @@ import 'incoming_call_state.dart'; class IncomingCallBloc extends Bloc { final CallService _callService = CallService(); - StreamSubscription _callStateSubscription; + StreamSubscription? _callStateSubscription; IncomingCallBloc() : super(IncomingCallState.callIncoming) { _callStateSubscription = _callService.subscribeToCallEvents().listen(onCallEvent); + on(_checkPermissions); + on(_declineCall); + on(_callDisconnected); } @override - Stream mapEventToState(IncomingCallEvent event) async* { - switch (event) { - case IncomingCallEvent.checkPermissions: - bool granted = await checkPermissions(); - if (granted) { - yield IncomingCallState.permissionsGranted; - } - break; - case IncomingCallEvent.declineCall: - await _callService.decline(); - yield IncomingCallState.callCancelled; - break; - case IncomingCallEvent.callDisconnected: - yield IncomingCallState.callCancelled; - break; - } + Future close() { + _callStateSubscription?.cancel(); + return super.close(); } - @override - Future close() { - if (_callStateSubscription != null) { - _callStateSubscription.cancel(); + Future _checkPermissions( + CheckPermissions event, + Emitter emit) async { + bool granted = await checkPermissions(); + if (granted) { + emit(IncomingCallState.permissionsGranted); } - return super.close(); + } + + Future _declineCall( + DeclineCall event, + Emitter emit) async { + await _callService.decline(); + emit(IncomingCallState.callCancelled); + } + + Future _callDisconnected( + CallDisconnected event, + Emitter emit) async { + emit(IncomingCallState.callCancelled); } void onCallEvent(CallEvent event) { if (event is OnDisconnectedCallEvent || event is OnFailedCallEvent) { - add(IncomingCallEvent.callDisconnected); + add(CallDisconnected()); } } } diff --git a/audio_call/lib/screens/incoming_call/bloc/incoming_call_event.dart b/audio_call/lib/screens/incoming_call/bloc/incoming_call_event.dart index 36f1755..74e38e4 100644 --- a/audio_call/lib/screens/incoming_call/bloc/incoming_call_event.dart +++ b/audio_call/lib/screens/incoming_call/bloc/incoming_call_event.dart @@ -1,3 +1,16 @@ /// Copyright (c) 2011-2020, Zingaya, Inc. All rights reserved. -enum IncomingCallEvent { checkPermissions, declineCall, callDisconnected } +abstract class IncomingCallEvent {} + +class CheckPermissions implements IncomingCallEvent { + CheckPermissions(); +} + +class DeclineCall implements IncomingCallEvent { + DeclineCall(); +} + +class CallDisconnected implements IncomingCallEvent { + CallDisconnected(); +} + diff --git a/audio_call/lib/screens/incoming_call/incoming_call_page.dart b/audio_call/lib/screens/incoming_call/incoming_call_page.dart index d81effc..221a299 100644 --- a/audio_call/lib/screens/incoming_call/incoming_call_page.dart +++ b/audio_call/lib/screens/incoming_call/incoming_call_page.dart @@ -16,7 +16,7 @@ class IncomingCallPage extends StatefulWidget { final String _endpoint; - IncomingCallPage({@required IncomingCallPageArguments arguments}) + IncomingCallPage({required IncomingCallPageArguments arguments}) : _endpoint = arguments.endpoint; @override @@ -26,7 +26,7 @@ class IncomingCallPage extends StatefulWidget { class _IncomingCallPageState extends State { final String _endpoint; - IncomingCallBloc _bloc; + late IncomingCallBloc _bloc; @override void initState() { @@ -37,9 +37,9 @@ class _IncomingCallPageState extends State { @override Widget build(BuildContext context) { - void _answerCall() => _bloc.add(IncomingCallEvent.checkPermissions); + void answerCall() => _bloc.add(CheckPermissions()); - void _declineCall() => _bloc.add(IncomingCallEvent.declineCall); + void declineCall() => _bloc.add(DeclineCall()); return BlocListener( listener: (context, state) { @@ -66,7 +66,6 @@ class _IncomingCallPageState extends State { Widgets.textWithPadding( text: 'Incoming call from', textColor: VoximplantColors.white, - fontSize: 30, verticalPadding: 20, ), Widgets.textWithPadding( @@ -75,7 +74,7 @@ class _IncomingCallPageState extends State { fontSize: 25, ), Padding( - padding: EdgeInsets.only(top: 80), + padding: const EdgeInsets.only(top: 80), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ @@ -83,13 +82,13 @@ class _IncomingCallPageState extends State { icon: Icons.call, color: VoximplantColors.button, tooltip: 'Answer', - onPressed: _answerCall, + onPressed: answerCall, ), Widgets.iconButton( icon: Icons.call_end, color: VoximplantColors.red, tooltip: 'Decline', - onPressed: _declineCall, + onPressed: declineCall, ) ], ), diff --git a/audio_call/lib/screens/incoming_call/incoming_call_page_arguments.dart b/audio_call/lib/screens/incoming_call/incoming_call_page_arguments.dart index 3c3e488..db4a4b8 100644 --- a/audio_call/lib/screens/incoming_call/incoming_call_page_arguments.dart +++ b/audio_call/lib/screens/incoming_call/incoming_call_page_arguments.dart @@ -2,5 +2,5 @@ class IncomingCallPageArguments { String endpoint; - IncomingCallPageArguments({this.endpoint}); + IncomingCallPageArguments({required this.endpoint}); } diff --git a/audio_call/lib/screens/login/bloc/login_bloc.dart b/audio_call/lib/screens/login/bloc/login_bloc.dart index d0e710f..f58a9f5 100644 --- a/audio_call/lib/screens/login/bloc/login_bloc.dart +++ b/audio_call/lib/screens/login/bloc/login_bloc.dart @@ -11,41 +11,47 @@ class LoginBloc extends Bloc { final AuthService _authService = AuthService(); LoginBloc() : super(LoginInitial()) { - add(LoadLastUser()); + on(_loadLastUser); + on(_loginWithPassword); } - @override - Stream mapEventToState(LoginEvent event) async* { - if (event is LoadLastUser) { - if (Platform.isAndroid && - await NotificationHelper().didNotificationLaunchApp()) { - print('Launched from notification, skipping autologin'); - return; - } - String lastUser = await _authService.getUsername(); - yield LoginLastUserLoaded(lastUser: lastUser); - bool canUseAccessToken = await _authService.canUseAccessToken(); - if (canUseAccessToken) { - yield LoginInProgress(); - try { - await _authService.loginWithAccessToken(); - yield LoginSuccess(); - } on VIException catch (e) { - yield LoginFailure(errorCode: e.code, errorDescription: e.message); - } - } + Future _loadLastUser( + LoadLastUser event, + Emitter emit) async { + // TODO(yulia) + // if (Platform.isAndroid && + // await NotificationHelper().didNotificationLaunchApp()) { + // print('Launched from notification, skipping autologin'); + // return; + // } + final lastUser = await _authService.getUsername(); + if (lastUser != null) { + emit(LoginLastUserLoaded(lastUser: lastUser)); } - if (event is LoginWithPassword) { - yield LoginInProgress(); + bool canUseAccessToken = await _authService.canUseAccessToken(); + if (canUseAccessToken) { + emit(LoginInProgress()); try { - await _authService.loginWithPassword( - event.username + '.voximplant.com', - event.password, - ); - yield LoginSuccess(); + await _authService.loginWithAccessToken(); + emit(LoginSuccess()); } on VIException catch (e) { - yield LoginFailure(errorCode: e.code, errorDescription: e.message); + emit(LoginFailure(errorCode: e.code, errorDescription: e.message ?? 'Unknown error')); } } } + + Future _loginWithPassword( + LoginWithPassword event, + Emitter emit) async { + emit(LoginInProgress()); + try { + await _authService.loginWithPassword( + '${event.username}.voximplant.com', + event.password, + ); + emit(LoginSuccess()); + } on VIException catch (e) { + emit(LoginFailure(errorCode: e.code, errorDescription: e.message ?? 'Unknown error')); + } + } } diff --git a/audio_call/lib/screens/login/bloc/login_event.dart b/audio_call/lib/screens/login/bloc/login_event.dart index c90441f..1b646ba 100644 --- a/audio_call/lib/screens/login/bloc/login_event.dart +++ b/audio_call/lib/screens/login/bloc/login_event.dart @@ -15,7 +15,7 @@ class LoginWithPassword extends LoginEvent { final String username; final String password; - LoginWithPassword({@required this.username, @required this.password}); + const LoginWithPassword({required this.username, required this.password}); @override List get props => [username, password]; diff --git a/audio_call/lib/screens/login/bloc/login_state.dart b/audio_call/lib/screens/login/bloc/login_state.dart index a7ccdfa..a113ac5 100644 --- a/audio_call/lib/screens/login/bloc/login_state.dart +++ b/audio_call/lib/screens/login/bloc/login_state.dart @@ -16,7 +16,7 @@ class LoginInitial extends LoginState {} class LoginLastUserLoaded extends LoginState { final String lastUser; - const LoginLastUserLoaded({@required this.lastUser}); + const LoginLastUserLoaded({required this.lastUser}); @override List get props => [lastUser]; @@ -31,10 +31,10 @@ class LoginFailure extends LoginState { final String errorDescription; const LoginFailure({ - @required this.errorCode, - @required this.errorDescription, + required this.errorCode, + required this.errorDescription, }); @override List get props => [errorCode, errorDescription]; -} \ No newline at end of file +} diff --git a/audio_call/lib/screens/login/login_page.dart b/audio_call/lib/screens/login/login_page.dart index b07ef7c..fd4db6c 100644 --- a/audio_call/lib/screens/login/login_page.dart +++ b/audio_call/lib/screens/login/login_page.dart @@ -18,7 +18,7 @@ class _LoginPageState extends State { final _passwordController = TextEditingController(); final _formKey = GlobalKey(); - LoginBloc _bloc; + late LoginBloc _bloc; bool _isUsernameValid = true; bool _isPasswordValid = true; @@ -27,6 +27,7 @@ class _LoginPageState extends State { void initState() { super.initState(); _bloc = BlocProvider.of(context); + context.read().add(LoadLastUser()); } @override @@ -38,29 +39,29 @@ class _LoginPageState extends State { @override Widget build(BuildContext context) { - void _login() => _bloc.add( + void login() => _bloc.add( LoginWithPassword( username: _usernameController.text, password: _passwordController.text, ), ); - void _handleLoginFailed(String errorCode, String errorDescription) { + void handleLoginFailed(String errorCode, String errorDescription) { if (errorCode == 'ERROR_INVALID_USERNAME') { setState(() => _isUsernameValid = false); } else if (errorCode == 'ERROR_INVALID_PASSWORD') { setState(() => _isPasswordValid = false); } else { - Scaffold.of(context).showSnackBar( + ScaffoldMessenger.of(context).showSnackBar( SnackBar( - content: Text('$errorDescription'), + content: Text(errorDescription), backgroundColor: Colors.red, ), ); } } - Widget _loginForm() { + Widget loginForm() { return Center( child: Form( key: _formKey, @@ -71,7 +72,6 @@ class _LoginPageState extends State { children: [ Widgets.textWithPadding( text: 'Audio call', - fontSize: 30, textColor: VoximplantColors.white, verticalPadding: 30, ), @@ -94,7 +94,7 @@ class _LoginPageState extends State { ), Widgets.maxWidthRaisedButton( text: 'Log in', - onPressed: _login, + onPressed: login, ), ], ), @@ -103,8 +103,8 @@ class _LoginPageState extends State { ); } - Widget _loginInProgress() { - return Center( + Widget loginInProgress() { + return const Center( child: CircularProgressIndicator(), ); } @@ -115,7 +115,7 @@ class _LoginPageState extends State { _usernameController.text = state.lastUser; } if (state is LoginFailure) { - _handleLoginFailed(state.errorCode, state.errorDescription); + handleLoginFailed(state.errorCode, state.errorDescription); } if (state is LoginSuccess) { setState(() { @@ -126,8 +126,8 @@ class _LoginPageState extends State { } if (state is! LoginInProgress && state is! LoginSuccess) { Future.delayed( - Duration(milliseconds: 100), - () => _formKey?.currentState?.validate(), + const Duration(milliseconds: 100), + () => _formKey.currentState?.validate(), ); } }, @@ -137,8 +137,8 @@ class _LoginPageState extends State { backgroundColor: VoximplantColors.primary, body: SafeArea( child: (state is LoginInProgress || state is LoginSuccess) - ? _loginInProgress() - : _loginForm(), + ? loginInProgress() + : loginForm(), ), ); }, diff --git a/audio_call/lib/screens/main/bloc/main_bloc.dart b/audio_call/lib/screens/main/bloc/main_bloc.dart index 0575298..33dc62f 100644 --- a/audio_call/lib/screens/main/bloc/main_bloc.dart +++ b/audio_call/lib/screens/main/bloc/main_bloc.dart @@ -15,56 +15,73 @@ import 'package:flutter_voximplant/flutter_voximplant.dart'; class MainBloc extends Bloc { final AuthService _authService = AuthService(); final CallService _callService = CallService(); - final CallKitService _callKitService = + final CallKitService? _callKitService = Platform.isIOS ? CallKitService() : null; - StreamSubscription _callStateSubscription; + late StreamSubscription _callStateSubscription; - MainBloc() : super(MainInitial(myDisplayName: AuthService().displayName)) { + MainBloc() : super(MainInitial(myDisplayName: AuthService().displayName ?? 'Unknown user')) { _authService.onDisconnected = () => add(ConnectionClosed()); _callStateSubscription = _callService.subscribeToCallEvents().listen(onCallEvent); + on(_checkPermissions); + on(_logout); + on(_connectionClosed); + on(_reconnect); + on(_receivedIncomingCall); } @override Future close() { - if (_callStateSubscription != null) { - _callStateSubscription.cancel(); - } + _callStateSubscription.cancel(); return super.close(); } - @override - Stream mapEventToState(MainEvent event) async* { - if (event is CheckPermissionsForCall) { - yield await checkPermissions() - ? PermissionCheckSuccess(myDisplayName: _authService.displayName) - : PermissionCheckFail(myDisplayName: _authService.displayName); - } - if (event is LogOut) { - await _authService.logout(); - yield LoggedOut(networkIssues: false); - } - if (event is ReceivedIncomingCall) { - yield IncomingCall( - caller: event.displayName, - myDisplayName: _authService.displayName, - ); + Future _checkPermissions( + CheckPermissionsForCall event, + Emitter emit) async { + bool permissionsGranted = await checkPermissions(); + if (permissionsGranted) { + emit(PermissionCheckSuccess(myDisplayName: _authService.displayName ?? 'Unknown user')); + } else { + emit(PermissionCheckFail(myDisplayName: _authService.displayName ?? 'Unknown user')); } - if (event is ConnectionClosed) { - yield LoggedOut(networkIssues: true); - } - if (event is Reconnect) { - try { - String displayName = await _authService.loginWithAccessToken(); - if (displayName == null) { - return; - } - yield ReconnectSuccess(myDisplayName: displayName); - } on VIException { - _authService.onDisconnected = null; - yield ReconnectFailed(); + } + + Future _logout( + LogOut event, + Emitter emit) async { + await _authService.logout(); + emit(const LoggedOut(networkIssues: false)); + } + + Future _connectionClosed( + ConnectionClosed event, + Emitter emit) async { + emit(const LoggedOut(networkIssues: true)); + } + + void _receivedIncomingCall( + ReceivedIncomingCall event, + Emitter emit) { + emit(IncomingCall( + caller: event.displayName, + myDisplayName: _authService.displayName ?? 'Unknown user', + )); + } + + Future _reconnect( + Reconnect event, + Emitter emit) async { + try { + final displayName = await _authService.loginWithAccessToken(); + if (displayName == null) { + return; } + emit(ReconnectSuccess(myDisplayName: displayName)); + } on VIException { + _authService.onDisconnected = null; + emit(const ReconnectFailed()); } } @@ -75,15 +92,18 @@ class MainBloc extends Bloc { ); } else if (event is OnIncomingCallEvent) { if (Platform.isIOS) { - await _callKitService.createIncomingCall( - _callService.callKitUUID, - event.username, - event.displayName, - ); + final callKitUUID = _callService.callKitUUID; + if (callKitUUID != null) { + await _callKitService?.createIncomingCall( + callKitUUID, + event.username, + event.displayName, + ); + } } else if (Platform.isAndroid) { add( ReceivedIncomingCall( - displayName: event.displayName ?? event.username, + displayName: event.displayName, ), ); } diff --git a/audio_call/lib/screens/main/bloc/main_event.dart b/audio_call/lib/screens/main/bloc/main_event.dart index 0393743..3c2d1a6 100644 --- a/audio_call/lib/screens/main/bloc/main_event.dart +++ b/audio_call/lib/screens/main/bloc/main_event.dart @@ -17,7 +17,7 @@ class LogOut extends MainEvent {} class ReceivedIncomingCall extends MainEvent { final String displayName; - ReceivedIncomingCall({@required this.displayName}); + ReceivedIncomingCall({required this.displayName}); @override List get props => [displayName]; @@ -25,4 +25,4 @@ class ReceivedIncomingCall extends MainEvent { class ConnectionClosed extends MainEvent {} -class Reconnect extends MainEvent {} \ No newline at end of file +class Reconnect extends MainEvent {} diff --git a/audio_call/lib/screens/main/bloc/main_state.dart b/audio_call/lib/screens/main/bloc/main_state.dart index 33fb013..f212e16 100644 --- a/audio_call/lib/screens/main/bloc/main_state.dart +++ b/audio_call/lib/screens/main/bloc/main_state.dart @@ -15,36 +15,36 @@ abstract class MainState extends Equatable { } class MainInitial extends MainState { - const MainInitial({@required String myDisplayName}) : super(myDisplayName); + const MainInitial({required String myDisplayName}) : super(myDisplayName); } class PermissionCheckFail extends MainState { - const PermissionCheckFail({@required String myDisplayName}) + const PermissionCheckFail({required String myDisplayName}) : super(myDisplayName); } class PermissionCheckSuccess extends MainState { - const PermissionCheckSuccess({@required String myDisplayName}) + const PermissionCheckSuccess({required String myDisplayName}) : super(myDisplayName); } class LoggedOut extends MainState { final bool networkIssues; - const LoggedOut({@required this.networkIssues}) : super(null); + const LoggedOut({required this.networkIssues}) : super(""); } class IncomingCall extends MainState { final String caller; - const IncomingCall({@required this.caller, @required String myDisplayName}) + const IncomingCall({required this.caller, required String myDisplayName}) : super(myDisplayName); } class ReconnectSuccess extends MainState { - const ReconnectSuccess({@required String myDisplayName}) + const ReconnectSuccess({required String myDisplayName}) : super(myDisplayName); } class ReconnectFailed extends MainState { - const ReconnectFailed() : super(null); + const ReconnectFailed() : super(""); } diff --git a/audio_call/lib/screens/main/main_page.dart b/audio_call/lib/screens/main/main_page.dart index 404a82f..bc5532a 100644 --- a/audio_call/lib/screens/main/main_page.dart +++ b/audio_call/lib/screens/main/main_page.dart @@ -20,7 +20,7 @@ class MainPage extends StatefulWidget { } class _MainPageState extends State with WidgetsBindingObserver { - MainBloc _bloc; + late MainBloc _bloc; final _callToController = TextEditingController(); @@ -58,26 +58,26 @@ class _MainPageState extends State with WidgetsBindingObserver { @override Widget build(BuildContext context) { - void _makeCall() { + void makeCall() { if (_callToController.text == '') { return; } _bloc.add(CheckPermissionsForCall()); } - void _logout() => _bloc.add(LogOut()); + void logout() => _bloc.add(LogOut()); - void _showPermissionCheckError() { + void showPermissionCheckError() { showDialog( context: context, builder: (context) { return AlertDialog( - title: Text('Permissions missing'), + title: const Text('Permissions missing'), content: - Text('Please give "record audio" permissions to make calls'), + const Text('Please give "record audio" permissions to make calls'), actions: [ - FlatButton( - child: Text('Close'), + TextButton( + child: const Text('Close'), onPressed: () { Navigator.of(context).pop(); }, @@ -109,7 +109,7 @@ class _MainPageState extends State with WidgetsBindingObserver { ); } if (state is PermissionCheckFail) { - _showPermissionCheckError(); + showPermissionCheckError(); } if (state is IncomingCall) { Navigator.of(context).pushReplacementNamed( @@ -125,11 +125,11 @@ class _MainPageState extends State with WidgetsBindingObserver { builder: (context, state) { return Scaffold( appBar: AppBar( - title: Text('Voximplant'), + title: const Text('Voximplant'), actions: [ IconButton( - icon: Icon(Icons.exit_to_app), - onPressed: _logout, + icon: const Icon(Icons.exit_to_app), + onPressed: logout, ) ], ), @@ -148,7 +148,7 @@ class _MainPageState extends State with WidgetsBindingObserver { labelText: 'user or number'), Widgets.maxWidthRaisedButton( text: 'Call', - onPressed: _makeCall, + onPressed: makeCall, ), ], ), @@ -157,10 +157,9 @@ class _MainPageState extends State with WidgetsBindingObserver { Align( alignment: Alignment.bottomCenter, child: Padding( - padding: EdgeInsets.only(bottom: 20), + padding: const EdgeInsets.only(bottom: 20), child: Text( - state.myDisplayName != null && - state.myDisplayName.isNotEmpty + state.myDisplayName.isNotEmpty ? 'Logged in as ${state.myDisplayName}' : '', ), diff --git a/audio_call/lib/services/auth_service.dart b/audio_call/lib/services/auth_service.dart index f9b2858..f41dcd4 100644 --- a/audio_call/lib/services/auth_service.dart +++ b/audio_call/lib/services/auth_service.dart @@ -4,59 +4,69 @@ import 'package:audio_call/utils/log.dart'; import 'package:flutter_voximplant/flutter_voximplant.dart'; import 'package:shared_preferences/shared_preferences.dart'; -typedef void Disconnected(); +typedef Disconnected = void Function(); class AuthService { VIClient _client; - String _displayName; + String? _displayName; - String get displayName => _displayName; - Disconnected onDisconnected; + String? get displayName => _displayName; + Disconnected? onDisconnected; - String _voipToken; + String? _voipToken; set voipToken(token) { if (token == null || token == '') { _log('voip token cleared'); - _client.unregisterFromPushNotifications(_voipToken); + final voipToken = _voipToken; + if (voipToken != null) { + _client.unregisterFromPushNotifications(voipToken); + } } _voipToken = token; } VIClientState clientState = VIClientState.Disconnected; - factory AuthService() => _cache ?? AuthService._(); - static AuthService _cache; + factory AuthService() { + return _instance; + } + static final AuthService _instance = AuthService._(); AuthService._() : _client = Voximplant().getClient(defaultConfig) { _log('initialize'); _client.clientStateStream.listen((state) { clientState = state; _log('client state is changed to: $state'); if (state == VIClientState.Disconnected && onDisconnected != null) { - onDisconnected(); + onDisconnected?.call(); } }); - _cache = this; } Future loginWithPassword(String username, String password) async { _log('loginWithPassword'); VIClientState clientState = await _client.getClientState(); if (clientState == VIClientState.LoggedIn) { - return _displayName; + final displayName = _displayName; + if (displayName != null) { + return displayName; + } } if (clientState == VIClientState.Disconnected) { await _client.connect(); } VIAuthResult authResult = await _client.login(username, password); if (_voipToken != null) { - await _client.registerForPushNotifications(_voipToken); + final voipToken = _voipToken; + if (voipToken != null) { + await _client.registerForPushNotifications(voipToken); + } } await _saveAuthDetails(username, authResult.loginTokens); _displayName = authResult.displayName; - return _displayName; + return _displayName ?? "Unknown user"; } - Future loginWithAccessToken([String username]) async { + Future loginWithAccessToken() async { VIClientState clientState = await _client.getClientState(); if (clientState == VIClientState.LoggedIn) { return _displayName; @@ -68,27 +78,32 @@ class AuthService { } _log('loginWithAccessToken'); SharedPreferences prefs = await SharedPreferences.getInstance(); - VILoginTokens loginTokens = _getAuthDetails(prefs); - String user = username ?? prefs.getString('username'); - - VIAuthResult authResult = - await _client.loginWithAccessToken(user, loginTokens.accessToken); - if (_voipToken != null) { - await _client.registerForPushNotifications(_voipToken); + final loginTokens = _getAuthDetails(prefs); + String? user = prefs.getString('username'); + if (user != null && loginTokens != null) { + VIAuthResult authResult = await _client.loginWithAccessToken(user, loginTokens.accessToken); + await _saveAuthDetails(user, authResult.loginTokens); + _displayName = authResult.displayName; + } + final voipToken = _voipToken; + if (voipToken != null) { + await _client.registerForPushNotifications(voipToken); } - await _saveAuthDetails(user, authResult.loginTokens); - _displayName = authResult.displayName; return _displayName; } Future logout() async { _log('logout'); await _client.disconnect(); - VILoginTokens loginTokens = VILoginTokens(); - _saveAuthDetails(null, loginTokens); + final SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.remove('username'); + prefs.remove('accessToken'); + prefs.remove('refreshToken'); + prefs.remove('accessExpire'); + prefs.remove('refreshExpire'); } - Future getUsername() async { + Future getUsername() async { SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getString('username')?.replaceAll('.voximplant.com', ''); } @@ -99,7 +114,10 @@ class AuthService { } Future _saveAuthDetails( - String username, VILoginTokens loginTokens) async { + String username, VILoginTokens? loginTokens) async { + if (loginTokens == null) { + return; + } final SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setString('username', username); prefs.setString('accessToken', loginTokens.accessToken); @@ -108,14 +126,21 @@ class AuthService { prefs.setInt('refreshExpire', loginTokens.refreshExpire); } - VILoginTokens _getAuthDetails(SharedPreferences prefs) { - VILoginTokens loginTokens = VILoginTokens(); - loginTokens.accessToken = prefs.getString('accessToken'); - loginTokens.accessExpire = prefs.getInt('accessExpire'); - loginTokens.refreshExpire = prefs.getInt('refreshExpire'); - loginTokens.refreshToken = prefs.getString('refreshToken'); - - return loginTokens; + VILoginTokens? _getAuthDetails(SharedPreferences prefs) { + final accessToken = prefs.getString('accessToken'); + final refreshToken = prefs.getString('refreshToken'); + final refreshExpire = prefs.getInt('refreshExpire'); + final accessExpire = prefs.getInt('accessExpire'); + if (accessToken != null && refreshToken != null && refreshExpire != null && accessExpire != null) { + VILoginTokens loginTokens = VILoginTokens( + accessToken: accessToken, + refreshToken: refreshToken, + accessExpire: accessExpire, + refreshExpire: refreshExpire + ); + return loginTokens; + } + return null; } Future pushNotificationReceived(Map payload) async { diff --git a/audio_call/lib/services/call/audio_device_event.dart b/audio_call/lib/services/call/audio_device_event.dart index 38283f3..66cd4d4 100644 --- a/audio_call/lib/services/call/audio_device_event.dart +++ b/audio_call/lib/services/call/audio_device_event.dart @@ -9,7 +9,7 @@ class OnActiveAudioDeviceChanged implements AudioDeviceEvent { final VIAudioDevice device; OnActiveAudioDeviceChanged({ - @required this.device, + required this.device, }); } @@ -17,6 +17,6 @@ class OnAvailableAudioDevicesListChanged implements AudioDeviceEvent { final List devices; OnAvailableAudioDevicesListChanged({ - @required this.devices, + required this.devices, }); } diff --git a/audio_call/lib/services/call/call_event.dart b/audio_call/lib/services/call/call_event.dart index 3caf78b..fb37b79 100644 --- a/audio_call/lib/services/call/call_event.dart +++ b/audio_call/lib/services/call/call_event.dart @@ -9,8 +9,8 @@ class OnIncomingCallEvent implements CallEvent { final String displayName; OnIncomingCallEvent({ - @required this.username, - @required this.displayName, + required this.username, + required this.displayName, }); } @@ -21,8 +21,8 @@ class OnConnectedCallEvent implements CallEvent { final String displayName; OnConnectedCallEvent({ - @required this.username, - @required this.displayName, + required this.username, + required this.displayName, }); } @@ -30,7 +30,7 @@ class OnDisconnectedCallEvent implements CallEvent { final bool answeredElsewhere; OnDisconnectedCallEvent({ - @required this.answeredElsewhere, + required this.answeredElsewhere, }); } @@ -38,7 +38,7 @@ class OnFailedCallEvent implements CallEvent { final String reason; OnFailedCallEvent({ - @required this.reason, + required this.reason, }); } @@ -46,7 +46,7 @@ class OnHoldCallEvent implements CallEvent { final bool hold; OnHoldCallEvent({ - @required this.hold, + required this.hold, }); } @@ -54,6 +54,6 @@ class OnMuteCallEvent implements CallEvent { final bool muted; OnMuteCallEvent({ - @required this.muted, + required this.muted, }); -} \ No newline at end of file +} diff --git a/audio_call/lib/services/call/call_service.dart b/audio_call/lib/services/call/call_service.dart index d980257..0474897 100644 --- a/audio_call/lib/services/call/call_service.dart +++ b/audio_call/lib/services/call/call_service.dart @@ -10,36 +10,36 @@ import 'package:audio_call/utils/notification_helper.dart'; import 'package:flutter_voximplant/flutter_voximplant.dart'; import 'package:meta/meta.dart'; -enum CallState { connecting, ringing, connected, ended } +enum CallState { none, connecting, ringing, connected, ended } class CallService { final VIClient _client; final VIAudioDeviceManager _audioDeviceManager; - VICall _activeCall; + VICall? _activeCall; bool get hasActiveCall => _activeCall != null; bool get hasNoActiveCalls => _activeCall == null; - String get callKitUUID => _activeCall?.callKitUUID; - set callKitUUID(String uuid) => _activeCall?.callKitUUID = uuid; + String? get callKitUUID => _activeCall?.callKitUUID; + set callKitUUID(String? uuid) => _activeCall?.callKitUUID = uuid; - Function onIncomingCall; + Function? onIncomingCall; - StreamController _callStreamController; - StreamController _audioDeviceStreamController; + StreamController _callStreamController = StreamController.broadcast(); + StreamController _audioDeviceStreamController = StreamController.broadcast(); CallState get callState => _callState; - CallState _callState; + CallState _callState = CallState.none; - VIEndpoint get endpoint => _endpoint; - VIEndpoint _endpoint; + VIEndpoint? get endpoint => _endpoint; + VIEndpoint? _endpoint; - VIAudioDevice get activeAudioDevice => __activeAudioDevice; - VIAudioDevice __activeAudioDevice; + VIAudioDevice? get activeAudioDevice => __activeAudioDevice; + VIAudioDevice? __activeAudioDevice; set _activeAudioDevice(VIAudioDevice device) { _log('onAudioDeviceChanged'); __activeAudioDevice = device; - _audioDeviceStreamController?.add( + _audioDeviceStreamController.add( OnActiveAudioDeviceChanged( device: device, ), @@ -47,11 +47,11 @@ class CallService { } get availableAudioDevices => __availableAudioDevices; - List __availableAudioDevices; + late List __availableAudioDevices; set _availableAudioDevices(List devices) { _log('onAudioDeviceListChanged'); __availableAudioDevices = devices; - _audioDeviceStreamController?.add( + _audioDeviceStreamController.add( OnAvailableAudioDevicesListChanged( devices: devices, ), @@ -63,9 +63,10 @@ class CallService { final VIAudioFile _progressTone; - factory CallService() => _cache ?? CallService._(); - static CallService _cache; - + factory CallService() { + return _instance; + } + static final CallService _instance = CallService._(); CallService._() : _client = Voximplant().getClient(defaultConfig), _audioDeviceManager = Voximplant().audioDeviceManager, @@ -79,7 +80,6 @@ class CallService { _client.onPushDidExpire = _pushDidExpire; _configureAudioDevices(); _configureAudioFiles(); - _cache = this; } void _configureAudioFiles() async { @@ -109,18 +109,18 @@ class CallService { } Stream subscribeToCallEvents() { - _callStreamController?.close(); + _callStreamController.close(); _callStreamController = StreamController.broadcast(); - return _callStreamController?.stream; + return _callStreamController.stream; } Stream subscribeToAudioDeviceEvents() { - _audioDeviceStreamController?.close(); + _audioDeviceStreamController.close(); _audioDeviceStreamController = StreamController.broadcast(); - return _audioDeviceStreamController?.stream; + return _audioDeviceStreamController.stream; } - Future makeCall({@required String callTo}) async { + Future makeCall({required String callTo}) async { if (hasActiveCall) { throw ('There is already an active call'); } @@ -137,50 +137,50 @@ class CallService { } VICallSettings callSettings = VICallSettings(); callSettings.videoFlags = _defaultFlags; - await _activeCall.answer(settings: callSettings); + await _activeCall?.answer(settings: callSettings); } Future hangup() async { if (hasNoActiveCalls) { throw 'Tried to hangup having no active call'; } - await _activeCall.hangup(); + await _activeCall?.hangup(); } Future decline() async { if (hasNoActiveCalls) { throw 'Tried to decline having no active call'; } - await _activeCall.decline(); + await _activeCall?.decline(); } - Future muteCall({@required bool mute}) async { + Future muteCall({required bool mute}) async { if (hasNoActiveCalls) { throw 'Tried to mute having no active call'; } - await _activeCall.sendAudio(!mute); - _callStreamController?.add(OnMuteCallEvent(muted: mute)); + await _activeCall?.sendAudio(!mute); + _callStreamController.add(OnMuteCallEvent(muted: mute)); } - Future holdCall({@required bool hold}) async { + Future holdCall({required bool hold}) async { if (hasNoActiveCalls) { throw 'Tried to hold having no active call'; } - await _activeCall.hold(hold); - _callStreamController?.add(OnHoldCallEvent(hold: hold)); + await _activeCall?.hold(hold); + _callStreamController.add(OnHoldCallEvent(hold: hold)); } - Future selectAudioDevice({@required VIAudioDevice device}) async => + Future selectAudioDevice({required VIAudioDevice device}) async => await _audioDeviceManager.selectAudioDevice(device); Future _onIncomingCall( VIClient client, VICall call, bool video, - Map headers, + Map? headers, ) async { _log('_onIncomingCall'); - if (hasActiveCall && _activeCall.callId != call.callId) { + if (hasActiveCall && _activeCall?.callId != call.callId) { await call.reject(); return; } @@ -188,14 +188,14 @@ class CallService { _callState = CallState.connecting; _endpoint = call.endpoints.first; _listenToActiveCallEvents(); - _callStreamController?.add( + _callStreamController.add( OnIncomingCallEvent( - username: call?.endpoints?.first?.userName, - displayName: call?.endpoints?.first?.displayName, + username: call.endpoints.first.userName ?? 'Unknown user', + displayName: call.endpoints.first.displayName ?? 'Unknown user', ), ); if (onIncomingCall != null) { - onIncomingCall(); + onIncomingCall?.call(); onIncomingCall = null; } } @@ -209,22 +209,22 @@ class CallService { } void _pushDidExpire(VIClient client, String callKitUUID) { - _callStreamController?.add( + _callStreamController.add( OnDisconnectedCallEvent(answeredElsewhere: false), ); } void _onCallDisconnected( VICall call, - Map headers, + Map? headers, bool answeredElsewhere, ) async { _log('onCallDisconnected'); - if (call.callId == _activeCall.callId) { + if (call.callId == _activeCall?.callId) { _activeCall = null; _callState = CallState.ended; _endpoint = null; - _callStreamController?.add( + _callStreamController.add( OnDisconnectedCallEvent(answeredElsewhere: answeredElsewhere), ); if (Platform.isAndroid) { @@ -242,14 +242,14 @@ class CallService { VICall call, int code, String description, - Map headers, + Map? headers, ) async { _log('onCallFailed($code, $description)'); if (call.callId == _activeCall?.callId) { _activeCall = null; _callState = CallState.ended; _endpoint = null; - _callStreamController?.add(OnFailedCallEvent(reason: description)); + _callStreamController.add(OnFailedCallEvent(reason: description)); try { await _progressTone.stop(); } catch (e) { @@ -258,26 +258,26 @@ class CallService { } } - void _onCallConnected(VICall call, Map headers) async { + void _onCallConnected(VICall call, Map? headers) async { _log('_onCallConnected'); if (call.callId == _activeCall?.callId) { _activeCall = call; _callState = CallState.connected; _endpoint = call.endpoints.first; - _callStreamController?.add( + _callStreamController.add( OnConnectedCallEvent( - username: call.endpoints?.first?.userName, - displayName: call.endpoints?.first?.displayName, + username: call.endpoints.first.userName ?? 'Unknown user', + displayName: call.endpoints.first.displayName ?? 'Unknown user', ), ); } } - void _onCallRinging(VICall call, Map headers) async { + void _onCallRinging(VICall call, Map? headers) async { _log('_onCallRinging'); - if (call.callId == _activeCall.callId) { + if (call.callId == _activeCall?.callId) { _callState = CallState.ringing; - _callStreamController?.add(OnRingingCallEvent()); + _callStreamController.add(OnRingingCallEvent()); try { await _progressTone.play(true); } catch (e) { diff --git a/audio_call/lib/services/call/callkit_service.dart b/audio_call/lib/services/call/callkit_service.dart index 8a9b206..f8863b5 100644 --- a/audio_call/lib/services/call/callkit_service.dart +++ b/audio_call/lib/services/call/callkit_service.dart @@ -10,27 +10,27 @@ import 'package:flutter_voximplant/flutter_voximplant.dart'; import 'package:uuid/uuid.dart'; // to generate uuids for callKit -var _uuid = Uuid(); +var _uuid = const Uuid(); // to remember a call even when only uuid available class CallWrapper { final String uuid; - FCXCall call; + FCXCall? call; CallWrapper(this.uuid); - CallWrapper.withCall(this.call) : this.uuid = call.uuid; + CallWrapper.withCall(FCXCall this.call) : uuid = call.uuid; } class CallKitService { - final AuthService _authService; - final CallService _callService; + final AuthService _authService = AuthService(); + final CallService _callService = CallService(); - final FCXPlugin _plugin; - final FCXProvider _provider; - final FCXCallController _callController; + final FCXPlugin _plugin = FCXPlugin(); + final FCXProvider _provider = FCXProvider(); + final FCXCallController _callController = FCXCallController(); - CallWrapper _activeCall; + CallWrapper? _activeCall; bool get _hasActiveCall => _activeCall != null; @@ -39,24 +39,21 @@ class CallKitService { bool _callStarting = false; // To handle late push, which call already been ended - List _endedCalls = []; + final List _endedCalls = []; bool _alreadyEnded(String uuid) => _endedCalls.contains(uuid); - factory CallKitService() => _cache ?? CallKitService._(); - static CallKitService _cache; + factory CallKitService() { + return _instance; + } + + static final CallKitService _instance = CallKitService._(); - CallKitService._() - : this._authService = AuthService(), - this._callService = CallService(), - this._plugin = FCXPlugin(), - this._provider = FCXProvider(), - this._callController = FCXCallController() { + CallKitService._() { _configure(); - _cache = this; _callService.subscribeToCallEvents().listen((event) { if (event is OnDisconnectedCallEvent && _hasActiveCall) { - _reportEnded(_activeCall.uuid, FCXCallEndedReason.declinedElsewhere); + _reportEnded(_activeCall?.uuid, FCXCallEndedReason.declinedElsewhere); } }); } @@ -68,7 +65,7 @@ class CallKitService { } try { if (_hasActiveCall) { - if (_activeCall.uuid != uuid) { + if (_activeCall?.uuid != uuid) { await _reportEnded(uuid, FCXCallEndedReason.failed); } return; @@ -85,7 +82,7 @@ class CallKitService { _provider.performStartCallAction = (startCallAction) async { if (_hasActiveCall) { - if (_activeCall.uuid != startCallAction.callUuid) { + if (_activeCall?.uuid != startCallAction.callUuid) { startCallAction.fail(); return; } @@ -124,8 +121,11 @@ class CallKitService { await _commitTransactions(); } catch (e) { _log('There was an error $e, failing'); - await _provider.reportCallEnded( - _callService.callKitUUID, null, FCXCallEndedReason.failed); + final callKitUUID = _callService.callKitUUID; + if (callKitUUID != null) { + await _provider.reportCallEnded( + callKitUUID, null, FCXCallEndedReason.failed); + } } } loginAndCommitTransactions(); @@ -141,7 +141,7 @@ class CallKitService { return; } - Future _end() async { + Future end() async { try { (_activeCall?.call?.outgoing ?? false) || (_activeCall?.call?.hasConnected ?? false) @@ -158,10 +158,10 @@ class CallKitService { // if already received call via Voximplant if (_callService.hasActiveCall) { - await _end(); + await end(); // else should wait till Voximplant send onIncomingCall } else { - _callService.onIncomingCall = () async => await _end(); + _callService.onIncomingCall = () async => await end(); } }; @@ -172,9 +172,9 @@ class CallKitService { return; } - NavigationHelper.pushToActiveCall(isIncoming: true, callTo: null); + NavigationHelper.pushToActiveCall(isIncoming: true, callTo: ""); - Future _answer() async { + Future answer() async { try { await Voximplant().audioDeviceManager.callKitConfigureAudioSession(); await _callService.answerCall(); @@ -187,10 +187,10 @@ class CallKitService { // if already received call via Voximplant if (_callService.hasActiveCall) { - await _answer(); + await answer(); // else should wait till Voximplant send onIncomingCall } else { - _callService.onIncomingCall = () async => await _answer(); + _callService.onIncomingCall = () async => await answer(); } }; @@ -244,8 +244,8 @@ class CallKitService { return; } - if (call.uuid == _activeCall.uuid) { - _activeCall.call = call; + if (call.uuid == _activeCall?.uuid) { + _activeCall?.call = call; } else { await _reportEnded(call.uuid, FCXCallEndedReason.failed); } @@ -271,25 +271,46 @@ class CallKitService { List actions = await transaction.getActions(); for (final action in actions) { if (action is FCXStartCallAction) { - _provider.performStartCallAction(action); + final perform = _provider.performStartCallAction; + if (perform != null) { + perform(action); + } } if (action is FCXAnswerCallAction) { - _provider.performAnswerCallAction(action); + final perform = _provider.performAnswerCallAction; + if (perform != null) { + perform(action); + } } if (action is FCXEndCallAction) { - _provider.performEndCallAction(action); + final perform = _provider.performEndCallAction; + if (perform != null) { + perform(action); + } } if (action is FCXSetHeldCallAction) { - _provider.performSetHeldCallAction(action); + final perform = _provider.performSetHeldCallAction; + if (perform != null) { + perform(action); + } } if (action is FCXSetMutedCallAction) { - _provider.performSetMutedCallAction(action); + final perform = _provider.performSetMutedCallAction; + if (perform != null) { + perform(action); + } } if (action is FCXSetGroupCallAction) { - _provider.performSetGroupCallAction(action); + final perform = _provider.performSetGroupCallAction; + if (perform != null) { + perform(action); + } } if (action is FCXPlayDTMFCallAction) { - _provider.performPlayDTMFCallAction(action); + final perform = _provider.performPlayDTMFCallAction; + if (perform != null) { + perform(action); + } } } } @@ -301,7 +322,7 @@ class CallKitService { String displayName, ) async { if (_hasActiveCall) { - if (_activeCall.uuid == uuid) { + if (_activeCall?.uuid == uuid) { return; } else { throw 'There is already an active call'; @@ -336,59 +357,72 @@ class CallKitService { if (_hasNoActiveCalls) { throw 'Active call is null, reportConnected failed'; } - _activeCall.call.outgoing + final call = _activeCall?.call; + if (call == null) { + return; + } + call.outgoing ? await _reportOutgoingCallConnected() : await _reportUpdated(username, displayName); } Future _reportOutgoingCallConnected() async { - if (_activeCall.call.hasConnected) { + final call = _activeCall?.call; + if (call == null || call.hasConnected) { return; } - await _provider.reportOutgoingCallConnected(_activeCall?.uuid, null); + await _provider.reportOutgoingCallConnected(call.uuid, null); } - Future _reportUpdated(String username, String displayName) async => - await _provider.reportCallUpdated( - _activeCall?.uuid, - FCXCallUpdate( - remoteHandle: FCXHandle(FCXHandleType.Generic, username), - hasVideo: false, - localizedCallerName: displayName, - ), - ); + Future _reportUpdated(String username, String displayName) async { + final call = _activeCall?.call; + if (call == null) { + return; + } + await _provider.reportCallUpdated( + call.uuid, + FCXCallUpdate( + remoteHandle: FCXHandle(FCXHandleType.Generic, username), + hasVideo: false, + localizedCallerName: displayName, + ), + ); + } Future holdCall(bool hold) async { if (_hasNoActiveCalls) { throw 'Active call is null, holdCall failed'; } - if (!_activeCall.call.hasConnected) { - _log('Cant hold due to call not being connected yet'); + final call = _activeCall?.call; + if (call == null || call.hasConnected) { return; } await _callController.requestTransactionWithAction( - FCXSetHeldCallAction(_activeCall.uuid, hold)); + FCXSetHeldCallAction(call.uuid, hold)); } Future muteCall(bool mute) async { if (_hasNoActiveCalls) { throw 'Active call is null, muteCall failed'; } - if (!_activeCall.call.hasConnected) { - _log('Cant mute due to call not being connected yet'); + final call = _activeCall?.call; + if (call == null || call.hasConnected) { return; } await _callController.requestTransactionWithAction( - FCXSetMutedCallAction(_activeCall.uuid, mute)); + FCXSetMutedCallAction(call.uuid, mute)); } Future endCall() async { if (_hasNoActiveCalls) { throw 'Active call is null, endCall failed'; } - + final call = _activeCall?.call; + if (call == null) { + return; + } await _callController - .requestTransactionWithAction(FCXEndCallAction(_activeCall.uuid)); + .requestTransactionWithAction(FCXEndCallAction(call.uuid)); } Future reportCallEnded( @@ -400,12 +434,12 @@ class CallKitService { if (!_alreadyEnded(uuid)) { _endedCalls.add(uuid); } - if (uuid == _activeCall.uuid) { + if (uuid == _activeCall?.uuid) { _activeCall = null; } } - Future _reportEnded(String uuid, FCXCallEndedReason reason) async { + Future _reportEnded(String? uuid, FCXCallEndedReason reason) async { if (uuid == null) { return; } @@ -419,11 +453,14 @@ class CallKitService { Future _failTransactions() async { List actions = []; - (await _provider.getPendingTransactions()) - .forEach((t) async => actions.addAll(await t.getActions())); + for (var transaction in (await _provider.getPendingTransactions())) { + actions.addAll(await transaction.getActions()); + } if (actions.isNotEmpty) { - actions.forEach((a) async => await a.fail()); + for (var action in actions) { + await action.fail(); + } } } diff --git a/audio_call/lib/services/push/push_service_android.dart b/audio_call/lib/services/push/push_service_android.dart index 6a70d5f..1e4550b 100644 --- a/audio_call/lib/services/push/push_service_android.dart +++ b/audio_call/lib/services/push/push_service_android.dart @@ -5,44 +5,74 @@ import 'package:audio_call/services/auth_service.dart'; import 'package:audio_call/utils/log.dart'; import 'package:audio_call/utils/notification_helper.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:firebase_core/firebase_core.dart'; + +@pragma('vm:entry-point') +Future onBackgroundMessage(RemoteMessage message) async { + print('PushServiceAndroid: _onBackgroundMessage data: ${message.data}'); + await Firebase.initializeApp(); + Map callDetails = jsonDecode(message.data['voximplant']); + final String displayName = callDetails['display_name']; + + NotificationHelper().displayNotification( + title: 'Incoming call', + description: "from $displayName", + payload: displayName, + ); +} class PushServiceAndroid { - final FirebaseMessaging _firebaseMessaging; + late FirebaseMessaging _firebaseMessaging; + static final PushServiceAndroid _instance = PushServiceAndroid._(); - factory PushServiceAndroid() => _cache ?? PushServiceAndroid._(); - static PushServiceAndroid _cache; - PushServiceAndroid._() : _firebaseMessaging = FirebaseMessaging() { + factory PushServiceAndroid() { + return _instance; + } + PushServiceAndroid._() { _configure(); - _cache = this; } Future _configure() async { _log('configure'); - _firebaseMessaging.configure(onBackgroundMessage: backgroundMessageHandler); + await Firebase.initializeApp(); + _firebaseMessaging = FirebaseMessaging.instance; + FirebaseMessaging.onMessage.listen(_onMessage); + FirebaseMessaging.onBackgroundMessage(onBackgroundMessage); _firebaseMessaging.onTokenRefresh.listen(_onToken); - String token = await _firebaseMessaging.getToken(); + String? token = await _firebaseMessaging.getToken(); _onToken(token); - return Future.value(); } - static Future backgroundMessageHandler( - Map message, - ) async { - _log('onBackgroundMessage: $message'); - if (!message.containsKey('data')) { - return Future.value(); - } + // static Future backgroundMessageHandler( + // Map message, + // ) async { + // _log('onBackgroundMessage: $message'); + // if (!message.containsKey('data')) { + // return Future.value(); + // } + // + // final Map data = + // Map.from(message['data']); + // + // if (!data.containsKey('voximplant')) { + // return Future.value(); + // } + // + // await AuthService().pushNotificationReceived(data); + // + // Map callDetails = jsonDecode(data['voximplant']); + // final String displayName = callDetails['display_name']; + // + // NotificationHelper().displayNotification( + // title: 'Incoming call', + // description: "from $displayName", + // payload: displayName, + // ); + // } - final Map data = - Map.from(message['data']); - - if (!data.containsKey('voximplant')) { - return Future.value(); - } - - await AuthService().pushNotificationReceived(data); - - Map callDetails = jsonDecode(data['voximplant']); + Future _onMessage(RemoteMessage message) async { + _log('PushServiceAndroid: onMessage data: ${message.data}'); + Map callDetails = jsonDecode(message.data['voximplant']); final String displayName = callDetails['display_name']; NotificationHelper().displayNotification( @@ -50,12 +80,10 @@ class PushServiceAndroid { description: "from $displayName", payload: displayName, ); - - return null; } - Future _onToken(String token) async { - _log("onToken: " + token); + Future _onToken(String? token) async { + _log("onToken: $token"); AuthService().voipToken = token; } diff --git a/audio_call/lib/services/push/push_service_ios.dart b/audio_call/lib/services/push/push_service_ios.dart index e4c0ee3..a37050a 100644 --- a/audio_call/lib/services/push/push_service_ios.dart +++ b/audio_call/lib/services/push/push_service_ios.dart @@ -1,45 +1,48 @@ /// Copyright (c) 2011-2020, Zingaya, Inc. All rights reserved. -import 'package:flutter_voip_push_notification/flutter_voip_push_notification.dart'; import 'package:audio_call/services/auth_service.dart'; import 'package:audio_call/utils/log.dart'; +import 'package:flutter/services.dart'; class PushServiceIOS { - final FlutterVoipPushNotification _voipPushNotification = - FlutterVoipPushNotification(); + final MethodChannel _channel = const MethodChannel('plugins.voximplant.com/pushkit'); + final EventChannel _pushKitEventChannel = const EventChannel('plugins.voximplant.com/pushkitevents'); - factory PushServiceIOS() => _cache ?? PushServiceIOS._(); - static PushServiceIOS _cache; + factory PushServiceIOS() { + return _instance; + } + static final PushServiceIOS _instance = PushServiceIOS._(); PushServiceIOS._() { + _log('configure'); + _pushKitEventChannel.receiveBroadcastStream('pushkit').listen(_pushKitEventListener); _configure(); - _cache = this; } Future _configure() async { - _log('configure'); - await _voipPushNotification.requestNotificationPermissions(); - // listen to voip device token changes - _voipPushNotification.onTokenRefresh.listen(_onToken); - // do configure voip push - _voipPushNotification.configure(onMessage: onMessage, onResume: onResume); - } - - Future onMessage(bool isLocal, Map payload) { - // handle foreground notification - _log('onMessage: $payload'); - AuthService().pushNotificationReceived(payload); - return Future.value(); - } - - Future onResume(bool isLocal, Map payload) { - // handle background notification - _log('onResume: $payload'); - return Future.value(); + final token = await _channel.invokeMethod("voipToken"); + if (token != null) { + _log('configure: token $token}'); + AuthService().voipToken = token; + } } - Future _onToken(String token) async { - _log('onToken: $token'); - AuthService().voipToken = token; + void _pushKitEventListener(dynamic event) { + final Map map = event; + if (map['event'] == 'didUpdatePushCredentials') { + final token = map["token"]; + if (token != null) { + _log('didUpdatePushCredentials: token $token}'); + AuthService().voipToken = token; + } + } + if (map['event'] == 'didReceiveIncomingPushWithPayload') { + final payload = map['payload']; + if (payload != null) { + _log('didReceiveIncomingPushWithPayload: payload $payload}'); + Map pushPayload = Map.from(payload); + AuthService().pushNotificationReceived(pushPayload); + } + } } void _log(T message) { diff --git a/audio_call/lib/theme/voximplant_theme.dart b/audio_call/lib/theme/voximplant_theme.dart index c8179c6..c615cdb 100644 --- a/audio_call/lib/theme/voximplant_theme.dart +++ b/audio_call/lib/theme/voximplant_theme.dart @@ -3,11 +3,11 @@ import 'package:flutter/material.dart'; class VoximplantColors { - static const Color primary = const Color(0xff1c0b43); - static const Color primaryDark = const Color(0xff392b5b); - static const Color accent = const Color(0xff8b61ff); - static const Color button = const Color(0xff662eff); - static const Color white = const Color(0xffffffff); - static const Color red = const Color(0xfff54b5e); - static const Color grey = const Color(0xff212121); -} \ No newline at end of file + static const Color primary = Color(0xff1c0b43); + static const Color primaryDark = Color(0xff392b5b); + static const Color accent = Color(0xff8b61ff); + static const Color button = Color(0xff662eff); + static const Color white = Color(0xffffffff); + static const Color red = Color(0xfff54b5e); + static const Color grey = Color(0xff212121); +} diff --git a/audio_call/lib/utils/navigation_helper.dart b/audio_call/lib/utils/navigation_helper.dart index 642b424..332ec90 100644 --- a/audio_call/lib/utils/navigation_helper.dart +++ b/audio_call/lib/utils/navigation_helper.dart @@ -12,19 +12,19 @@ class NavigationHelper { static final GlobalKey navigatorKey = GlobalKey(); - static Future pushToIncomingCall({ - @required String caller, - }) => - navigatorKey.currentState.pushReplacementNamed( - AppRoutes.incomingCall, - arguments: IncomingCallPageArguments(endpoint: caller), - ); - + // static Future pushToIncomingCall({ + // String? caller, + // }) => + // navigatorKey.currentState!.pushReplacementNamed( + // AppRoutes.incomingCall, + // arguments: IncomingCallPageArguments(endpoint: caller), + // ); + // static Future pushToActiveCall({ - @required bool isIncoming, - @required String callTo, + required bool isIncoming, + required String callTo, }) => - navigatorKey.currentState.pushReplacementNamed( + navigatorKey.currentState!.pushReplacementNamed( AppRoutes.activeCall, arguments: ActiveCallPageArguments( isIncoming: isIncoming, @@ -32,13 +32,13 @@ class NavigationHelper { ), ); - static Future pop() => navigatorKey.currentState.maybePop(); + static Future pop() => navigatorKey.currentState!.maybePop(); } class AppRoutes { - static final String login = LoginPage.routeName; - static final String main = MainPage.routeName; - static final String incomingCall = IncomingCallPage.routeName; - static final String activeCall = ActiveCallPage.routeName; - static final String callFailed = CallFailedPage.routeName; -} \ No newline at end of file + static const String login = LoginPage.routeName; + static const String main = MainPage.routeName; + static const String incomingCall = IncomingCallPage.routeName; + static const String activeCall = ActiveCallPage.routeName; + static const String callFailed = CallFailedPage.routeName; +} diff --git a/audio_call/lib/utils/notification_helper.dart b/audio_call/lib/utils/notification_helper.dart index 44dfed6..a9204bd 100644 --- a/audio_call/lib/utils/notification_helper.dart +++ b/audio_call/lib/utils/notification_helper.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'package:audio_call/utils/log.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'navigation_helper.dart'; @@ -14,42 +13,45 @@ class NotificationHelper { int _notificationId = 100; final FlutterLocalNotificationsPlugin _plugin; - factory NotificationHelper() => _cached ?? NotificationHelper._(); - static NotificationHelper _cached; + static final NotificationHelper _instance = NotificationHelper._(); + + factory NotificationHelper() { + return _instance; + } + NotificationHelper._() : _plugin = FlutterLocalNotificationsPlugin() { _configure(); - _cached = this; } Future _configure() async { print('NotificationHelper: _configure'); await _plugin.initialize( - InitializationSettings( + const InitializationSettings( android: AndroidInitializationSettings('ic_notification'), ), - onSelectNotification: (payload) async { - print('NotificationHelper onSelect $payload'); - await NavigationHelper.pushToIncomingCall(caller: payload); + onDidReceiveNotificationResponse: (notificationResponse) async { + _log('NotificationHelper onSelect $notificationResponse'); + // await NavigationHelper.pushToIncomingCall(caller: notificationResponse.payload); return Future.value(); }, ); } Future displayNotification({ - @required String title, - @required String description, - String payload, + required String title, + required String description, + required String payload, }) async { _log('displayNotification title: $title, description: $description'); await _plugin.show( _notificationId, title, description, - NotificationDetails( + const NotificationDetails( android: AndroidNotificationDetails( 'VoximplantChannelIncomingCalls', 'CallChannel', - 'Incoming calls notifications', + channelDescription: 'Incoming calls notifications', importance: Importance.max, priority: Priority.max, ticker: 'incoming call', @@ -57,7 +59,7 @@ class NotificationHelper { ), payload: payload, ); - Timer(Duration(seconds: 15), () { + Timer(const Duration(seconds: 15), () { cancelNotification(); }); } @@ -66,10 +68,10 @@ class NotificationHelper { await _plugin.cancelAll(); } - Future didNotificationLaunchApp() async { + Future didNotificationLaunchApp() async { var details = await _plugin.getNotificationAppLaunchDetails(); - _log('didNotificationLaunchApp: ${details.didNotificationLaunchApp}'); - return details.didNotificationLaunchApp; + _log('didNotificationLaunchApp: ${details?.didNotificationLaunchApp}'); + return details?.didNotificationLaunchApp; } void _log(T message) { diff --git a/audio_call/lib/utils/permissions_helper.dart b/audio_call/lib/utils/permissions_helper.dart index 976a54a..b92eb5a 100644 --- a/audio_call/lib/utils/permissions_helper.dart +++ b/audio_call/lib/utils/permissions_helper.dart @@ -6,7 +6,7 @@ import 'package:permission_handler/permission_handler.dart'; Future checkPermissions() async { if (Platform.isAndroid) { PermissionStatus recordAudio = await Permission.microphone.status; - List requestPermissions = List(); + List requestPermissions = []; if (recordAudio != PermissionStatus.granted) { requestPermissions.add(Permission.microphone); } @@ -27,4 +27,4 @@ Future checkPermissions() async { //not supported platforms return false; } -} \ No newline at end of file +} diff --git a/audio_call/lib/widgets/widgets.dart b/audio_call/lib/widgets/widgets.dart index f2b16f8..f8475eb 100644 --- a/audio_call/lib/widgets/widgets.dart +++ b/audio_call/lib/widgets/widgets.dart @@ -5,13 +5,13 @@ import 'package:flutter/material.dart'; class Widgets { static Widget textFormField({ - @required TextEditingController controller, - @required bool darkBackground, - String labelText, - String suffixText, + required TextEditingController controller, + required bool darkBackground, + required String labelText, + String? suffixText, bool obscureText = false, TextInputType inputType = TextInputType.text, - FormFieldValidator validator, + FormFieldValidator? validator, }) { return Padding( padding: const EdgeInsets.symmetric( @@ -22,8 +22,8 @@ class Widgets { data: ThemeData( primaryColor: darkBackground ? VoximplantColors.white : VoximplantColors.button, - cursorColor: - darkBackground ? VoximplantColors.white : VoximplantColors.button, + // cursorColor: + // darkBackground ? VoximplantColors.white : VoximplantColors.button, hintColor: darkBackground ? VoximplantColors.white : VoximplantColors.button, ), @@ -60,8 +60,8 @@ class Widgets { } static Widget maxWidthRaisedButton({ - @required String text, - @required VoidCallback onPressed, + required String text, + required VoidCallback onPressed, }) { return Padding( padding: const EdgeInsets.symmetric( @@ -71,9 +71,8 @@ class Widgets { child: SizedBox( width: double.infinity, height: 50, - child: RaisedButton( - textColor: VoximplantColors.white, - color: VoximplantColors.button, + child: ElevatedButton( + style: ElevatedButton.styleFrom(textStyle: const TextStyle(color: VoximplantColors.white)), onPressed: onPressed, child: Text(text), ), @@ -82,9 +81,9 @@ class Widgets { } static Widget textWithPadding({ - @required String text, - Color textColor, - double fontSize, + required String text, + required Color textColor, + double fontSize = 30.0, double verticalPadding = 0.0, double horizontalPadding = 0.0, }) { @@ -104,13 +103,13 @@ class Widgets { } static Widget iconButton({ - @required IconData icon, - @required Color color, - @required String tooltip, - @required VoidCallback onPressed, + required IconData icon, + required Color color, + required String tooltip, + required VoidCallback onPressed, }) { return Ink( - decoration: ShapeDecoration( + decoration: const ShapeDecoration( color: VoximplantColors.white, shape: CircleBorder(), ), @@ -125,4 +124,4 @@ class Widgets { ), ); } -} \ No newline at end of file +} diff --git a/audio_call/pubspec.lock b/audio_call/pubspec.lock index 7e39cf5..93563b3 100644 --- a/audio_call/pubspec.lock +++ b/audio_call/pubspec.lock @@ -1,177 +1,240 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "330d7fcbb72624f5b6d374af8b059b0ef4ba96ba5b8987f874964a1287eb617d" + url: "https://pub.dev" + source: hosted + version: "1.0.18" + args: + dependency: transitive + description: + name: args + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + url: "https://pub.dev" + source: hosted + version: "2.4.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.8.2" + version: "2.10.0" bloc: dependency: transitive description: name: bloc - url: "https://pub.dartlang.org" + sha256: "658a5ae59edcf1e58aac98b000a71c762ad8f46f1394c34a52050cafb3e11a80" + url: "https://pub.dev" source: hosted - version: "6.1.3" + version: "8.1.1" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.2.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" - convert: + version: "1.17.0" + crypto: dependency: transitive description: - name: convert - url: "https://pub.dartlang.org" + name: crypto + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted - version: "2.1.1" - crypto: + version: "3.0.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" + source: hosted + version: "1.0.5" + dbus: dependency: transitive description: - name: crypto - url: "https://pub.dartlang.org" + name: dbus + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "0.7.8" equatable: - dependency: "direct main" + dependency: "direct dev" description: name: equatable - url: "https://pub.dartlang.org" + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" source: hosted - version: "1.2.5" + version: "2.0.5" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted version: "6.1.4" firebase_core: - dependency: transitive + dependency: "direct dev" description: name: firebase_core - url: "https://pub.dartlang.org" + sha256: "75f747cafd7cbd6c00b908e3a7aa59fc31593d46ba8165d9ee8a79e69464a394" + url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "2.8.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - url: "https://pub.dartlang.org" + sha256: "0df0a064ab0cad7f8836291ca6f3272edd7b83ad5b3540478ee46a0849d8022b" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "4.6.0" firebase_core_web: dependency: transitive description: name: firebase_core_web - url: "https://pub.dartlang.org" + sha256: "347351a8f0518f3343d79a9a0690fa67ad232fc32e2ea270677791949eac792b" + url: "https://pub.dev" source: hosted - version: "0.2.1+1" + version: "2.3.0" firebase_messaging: - dependency: "direct main" + dependency: "direct dev" description: name: firebase_messaging - url: "https://pub.dartlang.org" + sha256: e82c99bcccf707db4d82ac3fb07be629a392c4cc2a6756aaf1a74c009114846f + url: "https://pub.dev" source: hosted - version: "7.0.3" + version: "14.3.0" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: "710bb139ff6e27fe47a0684ba88df4b7517a44d814dc6b7f54a2537568a82fcf" + url: "https://pub.dev" + source: hosted + version: "4.2.16" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "66ece031cb17fb771cda4b3328858395fa48aa4c3b3e6a5d1bcaff928086cacd" + url: "https://pub.dev" + source: hosted + version: "3.2.17" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" flutter_bloc: - dependency: "direct main" + dependency: "direct dev" description: name: flutter_bloc - url: "https://pub.dartlang.org" + sha256: "434951eea948dbe87f737b674281465f610b8259c16c097b8163ce138749a775" + url: "https://pub.dev" source: hosted - version: "6.0.6" + version: "8.1.2" flutter_callkit_voximplant: - dependency: "direct main" + dependency: "direct dev" description: name: flutter_callkit_voximplant - url: "https://pub.dartlang.org" + sha256: fe2c46e1ff9d12c7b5a1f7ec4c50ac20d42f5abbcb7ac988dc3e18ae09524a03 + url: "https://pub.dev" + source: hosted + version: "2.1.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted - version: "1.2.0+3" + version: "2.0.1" flutter_local_notifications: - dependency: "direct main" + dependency: "direct dev" description: name: flutter_local_notifications - url: "https://pub.dartlang.org" + sha256: "293995f94e120c8afce768981bd1fa9c5d6de67c547568e3b42ae2defdcbb4a0" + url: "https://pub.dev" + source: hosted + version: "13.0.0" + flutter_local_notifications_linux: + dependency: transitive + description: + name: flutter_local_notifications_linux + sha256: ccb08b93703aeedb58856e5637450bf3ffec899adb66dc325630b68994734b89 + url: "https://pub.dev" source: hosted - version: "2.0.1+1" + version: "3.0.0+1" flutter_local_notifications_platform_interface: dependency: transitive description: name: flutter_local_notifications_platform_interface - url: "https://pub.dartlang.org" + sha256: "5ec1feac5f7f7d9266759488bc5f76416152baba9aa1b26fe572246caa00d1ab" + url: "https://pub.dev" source: hosted - version: "2.0.0+1" + version: "6.0.0" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" - flutter_voip_push_notification: - dependency: "direct main" - description: - name: flutter_voip_push_notification - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.3" flutter_voximplant: - dependency: "direct main" + dependency: "direct dev" description: name: flutter_voximplant - url: "https://pub.dartlang.org" + sha256: "712fb316c1d6553326d29c43d17454cf69adc930527308af9136aa6c72921d4e" + url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "3.8.0" flutter_web_plugins: dependency: transitive description: flutter @@ -181,156 +244,218 @@ packages: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" + source: hosted + version: "0.6.5" + lints: + dependency: transitive + description: + name: lints + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "2.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.11" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.4" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted - version: "1.7.0" + version: "1.8.0" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted version: "1.0.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted - version: "1.8.1" + version: "1.8.2" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + url: "https://pub.dev" source: hosted - version: "0.0.1+2" + version: "2.1.10" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.0.6" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + url: "https://pub.dev" source: hosted - version: "0.0.5" + version: "2.1.5" permission_handler: - dependency: "direct main" + dependency: "direct dev" description: name: permission_handler - url: "https://pub.dartlang.org" + sha256: "33c6a1253d1f95fd06fa74b65b7ba907ae9811f9d5c1d3150e51417d04b8d6a8" + url: "https://pub.dev" + source: hosted + version: "10.2.0" + permission_handler_android: + dependency: transitive + description: + name: permission_handler_android + sha256: "8028362b40c4a45298f1cbfccd227c8dd6caf0e27088a69f2ba2ab15464159e2" + url: "https://pub.dev" + source: hosted + version: "10.2.0" + permission_handler_apple: + dependency: transitive + description: + name: permission_handler_apple + sha256: ee96ac32f5a8e6f80756e25b25b9f8e535816c8e6665a96b6d70681f8c4f7e85 + url: "https://pub.dev" source: hosted - version: "5.0.1+1" + version: "9.0.8" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - url: "https://pub.dartlang.org" + sha256: "68abbc472002b5e6dfce47fe9898c6b7d8328d58b5d2524f75e277c07a97eb84" + url: "https://pub.dev" + source: hosted + version: "3.9.0" + permission_handler_windows: + dependency: transitive + description: + name: permission_handler_windows + sha256: f67cab14b4328574938ecea2db3475dad7af7ead6afab6338772c5f88963e38b + url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "0.1.2" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" + source: hosted + version: "5.1.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "2.1.4" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" provider: dependency: transitive description: name: provider - url: "https://pub.dartlang.org" - source: hosted - version: "4.3.3" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "6.0.5" shared_preferences: - dependency: "direct main" + dependency: "direct dev" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: ee6257848f822b8481691f20c3e6d2bfee2e9eccb2a3d249907fcfb198c55b41 + url: "https://pub.dev" source: hosted - version: "0.5.12+2" - shared_preferences_linux: + version: "2.0.18" + shared_preferences_android: dependency: transitive description: - name: shared_preferences_linux - url: "https://pub.dartlang.org" + name: shared_preferences_android + sha256: "7fa90471a6875d26ad78c7e4a675874b2043874586891128dc5899662c97db46" + url: "https://pub.dev" source: hosted - version: "0.0.2+4" - shared_preferences_macos: + version: "2.1.2" + shared_preferences_foundation: dependency: transitive description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" + name: shared_preferences_foundation + sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07" + url: "https://pub.dev" source: hosted - version: "0.0.1+11" + version: "2.2.1" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" + url: "https://pub.dev" + source: hosted + version: "2.2.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d + url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.2.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" + url: "https://pub.dev" source: hosted - version: "0.1.2+7" + version: "2.1.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" + url: "https://pub.dev" source: hosted - version: "0.0.2+3" + version: "2.2.0" sky_engine: dependency: transitive description: flutter @@ -340,86 +465,106 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.8.2" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.4.16" timezone: dependency: transitive description: name: timezone - url: "https://pub.dartlang.org" + sha256: "24c8fcdd49a805d95777a39064862133ff816ebfffe0ceff110fb5960e557964" + url: "https://pub.dev" source: hosted - version: "0.5.9" + version: "0.9.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" uuid: - dependency: "direct main" + dependency: "direct dev" description: name: uuid - url: "https://pub.dartlang.org" + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "3.0.7" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4 + url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "3.1.4" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86 + url: "https://pub.dev" source: hosted - version: "0.1.2" + version: "0.2.0+3" + xml: + dependency: transitive + description: + name: xml + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" + source: hosted + version: "6.2.2" sdks: - dart: ">=2.17.0 <3.0.0" - flutter: ">=1.20.0" + dart: ">=2.19.4 <3.0.0" + flutter: ">=3.0.0" diff --git a/audio_call/pubspec.yaml b/audio_call/pubspec.yaml index 57e5306..aee6ff0 100644 --- a/audio_call/pubspec.yaml +++ b/audio_call/pubspec.yaml @@ -1,78 +1,33 @@ name: audio_call description: A new Flutter project. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.2.3 +version: 1.0.0+1 environment: - sdk: ">=2.2.2 <3.0.0" + sdk: '>=2.19.4 <3.0.0' dependencies: flutter: sdk: flutter - flutter_bloc: 6.0.6 - equatable: 1.2.5 - firebase_messaging: 7.0.3 - flutter_voximplant: 3.5.1 - flutter_callkit_voximplant: 1.2.0+3 - flutter_voip_push_notification: 0.0.3 - flutter_local_notifications: 2.0.1+1 - shared_preferences: 0.5.12+2 - permission_handler: 5.0.1+1 - uuid: ^2.2.2 + cupertino_icons: ^1.0.2 dev_dependencies: flutter_test: sdk: flutter - - -# 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. + flutter_lints: ^2.0.0 + flutter_bloc: 8.1.2 + flutter_voximplant: 3.8.0 + flutter_callkit_voximplant: 2.1.0 + uuid: 3.0.7 + flutter_local_notifications: 13.0.0 + permission_handler: 10.2.0 + shared_preferences: 2.0.18 + equatable: 2.0.5 + firebase_core: 2.8.0 + firebase_messaging: 14.3.0 + +# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages diff --git a/audio_call/test/widget_test.dart b/audio_call/test/widget_test.dart index 486c7e8..d1fd7c4 100644 --- a/audio_call/test/widget_test.dart +++ b/audio_call/test/widget_test.dart @@ -1,7 +1,7 @@ // This is a basic Flutter widget test. // // To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll +// 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. @@ -13,18 +13,18 @@ import 'package:audio_call/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(App()); - - // 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); + // 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); }); }