diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index f2872cf47..4f8d4d245 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 9.0
+ 11.0
diff --git a/ios/Podfile b/ios/Podfile
index 015ad2565..867d660ff 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -38,7 +38,42 @@ post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
- config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET'
+ config.build_settings['ENABLE_BITCODE'] = 'NO'
+ config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
+ # You can remove unused permissions here
+ # for more infomation: https://github.com/BaseflowIT/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h
+ # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0'
+ config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
+ '$(inherited)',
+ ## dart: PermissionGroup.calendar
+ 'PERMISSION_EVENTS=0',
+ ## dart: PermissionGroup.reminders
+ 'PERMISSION_REMINDERS=0',
+ ## dart: PermissionGroup.contacts
+ 'PERMISSION_CONTACTS=0',
+ ## dart: PermissionGroup.camera
+ 'PERMISSION_CAMERA=1',
+ ## dart: PermissionGroup.microphone
+ 'PERMISSION_MICROPHONE=0',
+ ## dart: PermissionGroup.speech
+ 'PERMISSION_SPEECH_RECOGNIZER=0',
+ ## dart: PermissionGroup.photos
+ 'PERMISSION_PHOTOS=0',
+ ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
+ 'PERMISSION_LOCATION=0',
+ ## dart: PermissionGroup.notification
+ 'PERMISSION_NOTIFICATIONS=1',
+ ## dart: PermissionGroup.mediaLibrary
+ 'PERMISSION_MEDIA_LIBRARY=0',
+ ## dart: PermissionGroup.sensors
+ 'PERMISSION_SENSORS=0',
+ ## dart: PermissionGroup.bluetooth
+ 'PERMISSION_BLUETOOTH=0',
+ ## dart: PermissionGroup.appTrackingTransparency
+ 'PERMISSION_APP_TRACKING_TRANSPARENCY=0',
+ ## dart: PermissionGroup.criticalAlerts
+ 'PERMISSION_CRITICAL_ALERTS=0',
+ ]
end
end
end
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 6cad51494..a03e82a17 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,12 +3,12 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 50;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
0DA36CBD26D4E8F400CDA64B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 0DA36CBC26D4E8F400CDA64B /* GoogleService-Info.plist */; };
- 0DCCE7B526CE7AA30029E1D5 /* BuildFile in Resources */ = {isa = PBXBuildFile; };
+ 0DCCE7B526CE7AA30029E1D5 /* (null) in Resources */ = {isa = PBXBuildFile; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
@@ -173,13 +173,12 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1300;
+ LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
- DevelopmentTeam = 627QALYL3B;
- LastSwiftMigration = 0910;
+ LastSwiftMigration = "";
};
};
};
@@ -210,7 +209,7 @@
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
- 0DCCE7B526CE7AA30029E1D5 /* BuildFile in Resources */,
+ 0DCCE7B526CE7AA30029E1D5 /* (null) in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
0DA36CBD26D4E8F400CDA64B /* GoogleService-Info.plist in Resources */,
@@ -222,10 +221,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -236,6 +237,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -256,7 +258,7 @@
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework",
- "${BUILT_PRODUCTS_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework",
+ "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework",
"${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework",
"${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework",
"${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework",
@@ -264,28 +266,29 @@
"${BUILT_PRODUCTS_DIR}/GoogleToolboxForMac/GoogleToolboxForMac.framework",
"${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework",
"${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework",
- "${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework",
+ "${BUILT_PRODUCTS_DIR}/ReachabilitySwift/Reachability.framework",
"${BUILT_PRODUCTS_DIR}/SwiftyRSA/SwiftyRSA.framework",
"${BUILT_PRODUCTS_DIR}/Toast/Toast.framework",
- "${BUILT_PRODUCTS_DIR}/catcher/catcher.framework",
+ "${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
"${BUILT_PRODUCTS_DIR}/device_info_plus/device_info_plus.framework",
+ "${BUILT_PRODUCTS_DIR}/flutter_local_notifications/flutter_local_notifications.framework",
"${BUILT_PRODUCTS_DIR}/flutter_mailer/flutter_mailer.framework",
"${BUILT_PRODUCTS_DIR}/flutter_secure_storage/flutter_secure_storage.framework",
"${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework",
- "${BUILT_PRODUCTS_DIR}/local_auth/local_auth.framework",
+ "${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework",
"${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework",
"${BUILT_PRODUCTS_DIR}/native_device_orientation/native_device_orientation.framework",
- "${BUILT_PRODUCTS_DIR}/package_info/package_info.framework",
"${BUILT_PRODUCTS_DIR}/package_info_plus/package_info_plus.framework",
+ "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework",
"${BUILT_PRODUCTS_DIR}/pi_authenticator_legacy/pi_authenticator_legacy.framework",
- "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework",
+ "${BUILT_PRODUCTS_DIR}/shared_preferences_foundation/shared_preferences_foundation.framework",
"${BUILT_PRODUCTS_DIR}/uni_links/uni_links.framework",
- "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework",
+ "${BUILT_PRODUCTS_DIR}/url_launcher_ios/url_launcher_ios.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreDiagnostics.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework",
@@ -293,23 +296,24 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleToolboxForMac.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyRSA.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Toast.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/catcher.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/device_info_plus.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_local_notifications.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_mailer.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_secure_storage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/native_device_orientation.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/package_info_plus.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/pi_authenticator_legacy.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences_foundation.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/uni_links.framework",
- "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework",
+ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher_ios.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -418,7 +422,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -441,13 +445,18 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = "privacyIDEA Authenticator";
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- MARKETING_VERSION = 3.1.1;
+ MARKETING_VERSION = "$(FLUTTER_BUILD_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = privacyidea.authenticator;
PRODUCT_NAME = "privacyIDEA Authenticator";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -504,7 +513,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -554,7 +563,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
@@ -578,13 +587,18 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = "privacyIDEA Authenticator";
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- MARKETING_VERSION = 3.1.1;
+ MARKETING_VERSION = "$(FLUTTER_BUILD_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = privacyidea.authenticator;
PRODUCT_NAME = "privacyIDEA Authenticator";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -609,13 +623,18 @@
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
+ INFOPLIST_KEY_CFBundleDisplayName = "privacyIDEA Authenticator";
+ INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- MARKETING_VERSION = 3.1.1;
+ MARKETING_VERSION = "$(FLUTTER_BUILD_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = privacyidea.authenticator;
PRODUCT_NAME = "privacyIDEA Authenticator";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 8dc3b542c..b9671f2b0 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
- NSFaceIDUsageDescription
- Use face id to prevent unauthorized access to tokens.
- ITSAppUsesNonExemptEncryption
-
+ CADisableMinimumFrameDurationOnPhone
+
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
@@ -27,6 +25,19 @@
$(FLUTTER_BUILD_NAME)
CFBundleSignature
????
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ it.netknights.otpauth
+ CFBundleURLSchemes
+
+ otpauth
+
+
+
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
FIREBASE_ANALYTICS_COLLECTION_DISABLED
@@ -35,10 +46,18 @@
FirebaseScreenReportingEnabled
+ ITSAppUsesNonExemptEncryption
+
LSRequiresIPhoneOS
NSCameraUsageDescription
Camera permission is required for scanning QR codes.
+ NSFaceIDUsageDescription
+ Use face id to prevent unauthorized access to tokens.
+ NSLocalNetworkUsageDescription
+ Network access is required to roll out push tokens.
+ UIApplicationSupportsIndirectInputEvents
+
UIBackgroundModes
fetch
@@ -50,33 +69,18 @@
Main
UISupportedInterfaceOrientations
- UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationPortrait
UISupportedInterfaceOrientations~ipad
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
UIViewControllerBasedStatusBarAppearance
- CFBundleURLTypes
-
-
- CFBundleTypeRole
- Editor
- CFBundleURLName
- it.netknights.otpauth
- CFBundleURLSchemes
-
- otpauth
-
-
-
- NSLocalNetworkUsageDescription
- Network access is required to roll out push tokens.
diff --git a/lib/l10n/app_cs.arb b/lib/l10n/app_cs.arb
index ac0758fd6..5b7613374 100644
--- a/lib/l10n/app_cs.arb
+++ b/lib/l10n/app_cs.arb
@@ -678,10 +678,16 @@
"description": "errorRollOutSSLHandshakeFailed",
"type": "text"
},
- "errorWhenPullingChallenges": "Při dotazování na výzvy došlo k chybě.",
+ "errorWhenPullingChallenges": "Při dotazování na výzvy {name} došlo k chybě.",
"@errorWhenPullingChallenges": {
"description": "errorWhenPullingChallenges",
- "type": "text"
+ "type": "text",
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "PUSH1234A"
+ }
+ }
},
"errorRollOutTokenExpired": "Roll-out tohoto tokenu již není možný.\nPlatnost tokenu {name} vypršela.",
"@errorRollOutTokenExpired": {
diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb
index 5585fe688..a7b5350cf 100644
--- a/lib/l10n/app_de.arb
+++ b/lib/l10n/app_de.arb
@@ -648,10 +648,16 @@
"description": "imageUrl",
"type": "text"
},
- "errorWhenPullingChallenges": "Fehler beim Abrufen der Authentifizierungsanfragen.",
+ "errorWhenPullingChallenges": "Fehler beim Abrufen der Authentifizierungsanfragen von {name}",
"@errorWhenPullingChallenges": {
"description": "errorWhenPullingChallenges",
- "type": "text"
+ "type": "text",
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "PUSH1234A"
+ }
+ }
},
"errorRollOutNoConnectionToServer": "Der Rollout von Token {name} ist fehlgeschlagen, der Server konnte nicht erreicht werden.",
"@errorRollOutNoConnectionToServer": {
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index 668fa25b7..8624668e6 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -663,10 +663,16 @@
"description": "Tells the user that the roll-out failed because the SSL handshake failed.",
"type": "text"
},
- "errorWhenPullingChallenges": "An error occured when polling for challenges",
+ "errorWhenPullingChallenges": "An error occured when polling for challenges of {name}",
"@errorWhenPullingChallenges": {
"description": "errorWhenPullingChallenges",
- "type": "text"
+ "type": "text",
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "PUSH1234A"
+ }
+ }
},
"errorRollOutTokenExpired": "Rolling out this Token is not possible anymore.\nThe token {name} has expired.",
"@errorRollOutTokenExpired": {
diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb
index 69e67bb53..4cd3fb4f0 100644
--- a/lib/l10n/app_es.arb
+++ b/lib/l10n/app_es.arb
@@ -678,10 +678,16 @@
"description": "errorRollOutSSLHandshakeFailed",
"type": "text"
},
- "errorWhenPullingChallenges": "Se ha producido un error al buscar retos.",
+ "errorWhenPullingChallenges": "Se ha producido un error al buscar retos de {name}",
"@errorWhenPullingChallenges": {
"description": "errorWhenPullingChallenges",
- "type": "text"
+ "type": "text",
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "PUSH1234A"
+ }
+ }
},
"errorRollOutTokenExpired": "El despliegue de este token ya no es posible.\nEl token {name} ha caducado.",
"@errorRollOutTokenExpired": {
diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb
index 3b4629ed7..0e4ad4b9f 100644
--- a/lib/l10n/app_fr.arb
+++ b/lib/l10n/app_fr.arb
@@ -673,10 +673,16 @@
"description": "errorRollOutSSLHandshakeFailed",
"type": "text"
},
- "errorWhenPullingChallenges": "Une erreur s'est produite lors de l'interrogation des défis",
+ "errorWhenPullingChallenges": "Une erreur s'est produite lors de l'interrogation des défis de {name}",
"@errorWhenPullingChallenges": {
"description": "errorWhenPullingChallenges",
- "type": "text"
+ "type": "text",
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "PUSH1234A"
+ }
+ }
},
"errorRollOutTokenExpired": "Le déploiement de ce jeton n'est plus possible. Le jeton {name} a expiré.",
"@errorRollOutTokenExpired": {
diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb
index a0e82547f..589acc423 100644
--- a/lib/l10n/app_nl.arb
+++ b/lib/l10n/app_nl.arb
@@ -667,10 +667,16 @@
"description": "Message for the rollout process",
"type": "text"
},
- "errorWhenPullingChallenges": "Er is een fout opgetreden bij het peilen naar uitdagingen",
+ "errorWhenPullingChallenges": "Er is een fout opgetreden bij het zoeken naar uitdagingen van {name}",
"@errorWhenPullingChallenges": {
"description": "errorWhenPullingChallenges",
- "type": "text"
+ "type": "text",
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "PUSH1234A"
+ }
+ }
},
"errorRollOutTokenExpired": "Het uitrollen van dit token is niet meer mogelijk.\nHet token {name} is verlopen.",
"@errorRollOutTokenExpired": {
diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb
index 8e7a8a62e..5765d27ca 100644
--- a/lib/l10n/app_pl.arb
+++ b/lib/l10n/app_pl.arb
@@ -667,10 +667,16 @@
"description": "errorRollOutSSLHandshakeFailed",
"type": "text"
},
- "errorWhenPullingChallenges": "An error occured when polling for challenges",
+ "errorWhenPullingChallenges": "Wystąpił błąd podczas odpytywania o wyzwania {name}",
"@errorWhenPullingChallenges": {
"description": "errorWhenPullingChallenges",
- "type": "text"
+ "type": "text",
+ "placeholders": {
+ "name": {
+ "type": "String",
+ "example": "PUSH1234A"
+ }
+ }
},
"errorRollOutTokenExpired": "Wstać z łóżka tego tokena nie jest już możliwe.\nToken {name} wygasł.",
"@errorRollOutTokenExpired": {
diff --git a/lib/main.dart b/lib/main.dart
index 90c057774..0c6f2ff68 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -109,7 +109,7 @@ class _SplashScreenState extends ConsumerState {
@override
void initState() {
super.initState();
-
+ Logger.info('Starting app.', name: 'main.dart#initState');
Future.delayed(_splashScreenDelay, () {
if (mounted) {
setState(() {
diff --git a/lib/model/enums/schemes.dart b/lib/model/enums/schemes.dart
new file mode 100644
index 000000000..a55c9f1f4
--- /dev/null
+++ b/lib/model/enums/schemes.dart
@@ -0,0 +1,4 @@
+enum UriSchemes {
+ otpauth,
+ pia,
+}
diff --git a/lib/model/token_folder.g.dart b/lib/model/token_folder.g.dart
index a3815e6db..a7ebd95c2 100644
--- a/lib/model/token_folder.g.dart
+++ b/lib/model/token_folder.g.dart
@@ -14,7 +14,8 @@ TokenFolder _$TokenFolderFromJson(Map json) => TokenFolder(
sortIndex: json['sortIndex'] as int?,
);
-Map _$TokenFolderToJson(TokenFolder instance) => {
+Map _$TokenFolderToJson(TokenFolder instance) =>
+ {
'label': instance.label,
'folderId': instance.folderId,
'isExpanded': instance.isExpanded,
diff --git a/lib/model/tokens/push_token.dart b/lib/model/tokens/push_token.dart
index 6d68adc56..64b4bf363 100644
--- a/lib/model/tokens/push_token.dart
+++ b/lib/model/tokens/push_token.dart
@@ -154,7 +154,6 @@ class PushToken extends Token {
'sortIndex: $sortIndex, '
'pin: $pin, '
'publicServerKey: $publicServerKey, '
- 'privateTokenKey: $privateTokenKey, '
'publicTokenKey: $publicTokenKey, '
'pushRequests: $pushRequests, '
'tokenImage: $tokenImage, '
diff --git a/lib/state_notifiers/deeplink_notifier.dart b/lib/state_notifiers/deeplink_notifier.dart
new file mode 100644
index 000000000..53a1dc700
--- /dev/null
+++ b/lib/state_notifiers/deeplink_notifier.dart
@@ -0,0 +1,59 @@
+import 'dart:async';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:privacyidea_authenticator/utils/logger.dart';
+import 'package:uni_links/uni_links.dart';
+
+StreamSubscription? _sub;
+bool _initialUriIsHandled = false;
+
+class DeeplinkNotifier extends StateNotifier {
+ DeeplinkNotifier() : super(null) {
+ _handleInitialUri();
+ _handleIncomingLinks();
+ }
+
+ /// Handle incoming links - the ones that the app will recieve from the OS
+ /// while already started.
+ void _handleIncomingLinks() {
+ if (_sub != null) {
+ _sub?.cancel();
+ _sub = null;
+ }
+ if (!kIsWeb) {
+ // It will handle app links while the app is already started - be it in
+ // the foreground or in the background.
+ _sub = uriLinkStream.listen((Uri? uri) {
+ Logger.info('Got uri from listening: $uri');
+ if (!mounted) return;
+ if (uri == null) return;
+ state = uri;
+ }, onError: (Object err) {
+ if (!mounted) return;
+ Logger.warning('Got error on Uri: $err');
+ });
+ }
+ }
+
+ Future _handleInitialUri() async {
+ if (!_initialUriIsHandled) {
+ _initialUriIsHandled = true;
+ Logger.info('_handleInitialUri called');
+ try {
+ final uri = await getInitialUri();
+ if (uri == null) return;
+ Logger.info('Got initial uri: $uri');
+ if (!mounted) return;
+ state = uri;
+ } on PlatformException {
+ // Platform messages may fail but we ignore the exception
+ Logger.warning('falied to get initial uri');
+ } on FormatException catch (_) {
+ if (!mounted) return;
+ Logger.warning('malformed initial uri');
+ }
+ }
+ }
+}
diff --git a/lib/state_notifiers/push_request_notifier.dart b/lib/state_notifiers/push_request_notifier.dart
index a480850ad..da2334e41 100644
--- a/lib/state_notifiers/push_request_notifier.dart
+++ b/lib/state_notifiers/push_request_notifier.dart
@@ -53,10 +53,8 @@ class PushRequestNotifier extends StateNotifier {
handleIncomingMessage: (RemoteMessage message) => _handleIncomingAuthRequest(message),
backgroundMessageHandler: _firebaseMessagingBackgroundHandler,
);
-
- if (pollingEnabled) {
- PushProvider.pollForChallenges();
- }
+ Logger.info('PushProvider initialized. Polling for Challenges', name: 'main_screen.dart#_initStateAsync');
+ PushProvider.pollForChallenges();
_startOrStopPolling();
}
diff --git a/lib/state_notifiers/settings_notifier.dart b/lib/state_notifiers/settings_notifier.dart
index fc45465b2..2d679ffe0 100644
--- a/lib/state_notifiers/settings_notifier.dart
+++ b/lib/state_notifiers/settings_notifier.dart
@@ -1,6 +1,7 @@
import 'dart:ui';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:privacyidea_authenticator/utils/logger.dart';
import '../model/states/settings_state.dart';
import '../repo/settings_repository.dart';
@@ -20,38 +21,78 @@ class SettingsNotifier extends StateNotifier {
}
void _loadFromRepo() async {
state = await _repo.loadSettings();
+ Logger.info('Loading settings from repo: $state', name: 'settings_notifier.dart#_loadFromRepo');
}
void _saveToRepo() async {
+ Logger.info('Saving settings to repo: $state', name: 'settings_notifier.dart#_saveToRepo');
await _repo.saveSettings(state);
}
void addCrashReportRecipient(String email) {
+ Logger.info('Crash report recipient added: $email', name: 'settings_notifier.dart#addCrashReportRecipient');
var updatedSet = state.crashReportRecipients..add(email);
state = state.copyWith(crashReportRecipients: updatedSet);
}
- set isFirstRun(bool value) => state = state.copyWith(isFirstRun: value);
+ set isFirstRun(bool value) {
+ Logger.info('First run set to $value', name: 'settings_notifier.dart#setFirstRun');
+ state = state.copyWith(isFirstRun: value);
+ }
- set hideOTPs(bool value) => state = state.copyWith(hideOpts: value);
+ set hideOTPs(bool value) {
+ Logger.info('Hide OTPs set to $value', name: 'settings_notifier.dart#setHideOTPs');
+ state = state.copyWith(hideOpts: value);
+ }
- set showGuideOnStart(bool value) => state = state.copyWith(showGuideOnStart: value);
+ set showGuideOnStart(bool value) {
+ Logger.info('Show guide on start set to $value', name: 'settings_notifier.dart#setShowGuideOnStart');
+ state = state.copyWith(showGuideOnStart: value);
+ }
- void setLocalePreference(Locale locale) => state = state.copyWith(localePreference: locale);
+ void setLocalePreference(Locale locale) {
+ Logger.info('Locale set to $locale', name: 'settings_notifier.dart#setLocalePreference');
+ state = state.copyWith(localePreference: locale);
+ }
- void setUseSystemLocale(bool value) => state = state.copyWith(useSystemLocale: value);
+ void setUseSystemLocale(bool value) {
+ Logger.info('Use system locale set to $value', name: 'settings_notifier.dart#setUseSystemLocale');
+ state = state.copyWith(useSystemLocale: value);
+ }
- void enablePolling() => state = state.copyWith(enablePolling: true);
+ void enablePolling() {
+ Logger.info('Polling set to true', name: 'settings_notifier.dart#enablePolling');
+ state = state.copyWith(enablePolling: true);
+ }
- void disablePolling() => state = state.copyWith(enablePolling: false);
+ void disablePolling() {
+ Logger.info('Polling set to false', name: 'settings_notifier.dart#disablePolling');
+ state = state.copyWith(enablePolling: false);
+ }
- void setPolling(bool value) => state = state.copyWith(enablePolling: value);
+ void setPolling(bool value) {
+ Logger.info('Polling set to $value', name: 'settings_notifier.dart#setPolling');
+ state = state.copyWith(enablePolling: value);
+ }
- void setLocale(Locale locale) => state = state.copyWith(localePreference: locale);
+ void setLocale(Locale locale) {
+ Logger.info('Locale set to $locale', name: 'settings_notifier.dart#setLocale');
+ state = state.copyWith(localePreference: locale);
+ }
- void setVerboseLogging(bool value) => state = state.copyWith(verboseLogging: value);
+ void setVerboseLogging(bool value) {
+ Logger.info('Verbose logging set to $value', name: 'settings_notifier.dart#setVerboseLogging');
+ state = state.copyWith(verboseLogging: value);
+ }
- void toggleVerboseLogging() => state = state.copyWith(verboseLogging: !state.verboseLogging);
+ void toggleVerboseLogging() {
+ final value = !state.verboseLogging;
+ Logger.info('Verbose logging set to $value', name: 'settings_notifier.dart#setVerboseLogging');
+ state = state.copyWith(verboseLogging: value);
+ }
- void setFirstRun(bool value) => state = state.copyWith(isFirstRun: value);
+ void setFirstRun(bool value) {
+ Logger.info('First run set to $value', name: 'settings_notifier.dart#setFirstRun');
+ state = state.copyWith(isFirstRun: value);
+ }
}
diff --git a/lib/state_notifiers/token_notifier.dart b/lib/state_notifiers/token_notifier.dart
index 346238a39..67c89b170 100644
--- a/lib/state_notifiers/token_notifier.dart
+++ b/lib/state_notifiers/token_notifier.dart
@@ -12,6 +12,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart';
import 'package:pi_authenticator_legacy/pi_authenticator_legacy.dart';
import 'package:pointycastle/asymmetric/api.dart';
+import 'package:privacyidea_authenticator/model/enums/schemes.dart';
import 'package:privacyidea_authenticator/utils/riverpod_providers.dart';
import '../model/push_request.dart';
@@ -41,9 +42,15 @@ class TokenNotifier extends StateNotifier {
Future _loadTokenList() async {
List tokens = await StorageUtil.loadAllTokens();
- final pushTokens = tokens.whereType().where((element) => !element.isRolledOut).toList();
+ Logger.info('Loaded tokens from storage: $tokens', name: 'token_notifier.dart#_loadTokenList');
+ final pushTokens = tokens.whereType();
+ if (pushTokens.isNotEmpty) {
+ checkNotificationPermission();
+ }
+
+ final pushTokensNotRolledOut = pushTokens.where((element) => !element.isRolledOut).toList();
state = TokenState(tokens: tokens);
- for (final pushToken in pushTokens) {
+ for (final pushToken in pushTokensNotRolledOut) {
rolloutPushToken(pushToken);
}
}
@@ -51,6 +58,7 @@ class TokenNotifier extends StateNotifier {
void refreshTokens() async {
List tokens = await StorageUtil.loadAllTokens();
final rolledOutPushToken = tokens.whereType().where((element) => element.isRolledOut).toList();
+ Logger.info('Refreshed Pushtokens from storage: $tokens', name: 'token_notifier.dart#refreshTokens');
state = state.updateTokens(rolledOutPushToken);
}
@@ -119,6 +127,23 @@ class TokenNotifier extends StateNotifier {
}
}
+ void handleLink(Uri uri) {
+ if (uri.scheme == enumAsString(UriSchemes.otpauth)) {
+ addTokenFromOtpAuth(otpAuth: uri.toString(), context: globalNavigatorKey.currentContext!);
+ return;
+ }
+ if (uri.scheme == enumAsString(UriSchemes.pia)) {
+ addTokenFromPia(pia: uri.toString(), context: globalNavigatorKey.currentContext!);
+ return;
+ }
+ showMessage(message: 'Scheme "${uri.scheme}" is not supported', duration: const Duration(seconds: 3));
+ }
+
+ void addTokenFromPia({required String pia, required BuildContext context}) async {
+ // TODO: Implement pia:// scheme
+ showMessage(message: 'Scheme "pia" is not implemented yet', duration: const Duration(seconds: 3));
+ }
+
void addTokenFromOtpAuth({required String otpAuth, required BuildContext context}) async {
Logger.info(
'Try to handle otpAuth:',
@@ -169,7 +194,7 @@ class TokenNotifier extends StateNotifier {
Future addPushRequestToToken(PushRequest pr) async {
PushToken? token = state.tokens.whereType().firstWhereOrNull((t) => t.serial == pr.serial && t.isRolledOut);
-
+ Logger.info('Adding push request ${pr.id} to token ${token?.id}', name: 'main_screen.dart#_handleIncomingChallenge', error: pr.serial);
if (token == null) {
Logger.warning('The requested token does not exist or is not rolled out.', name: 'main_screen.dart#_handleIncomingChallenge', error: pr.serial);
} else {
@@ -230,6 +255,7 @@ class TokenNotifier extends StateNotifier {
Future rolloutPushToken(PushToken token) async {
token = getTokenFromId(token.id) as PushToken? ?? token;
+ Logger.info('Rolling out token ${token.serial}', name: 'token_widgets.dart#rolloutPushToken');
if (token.isRolledOut) return true;
if (token.rolloutState != PushTokenRollOutState.rolloutNotStarted &&
token.rolloutState != PushTokenRollOutState.generatingRSAKeyPairFailed &&
diff --git a/lib/utils/logger.dart b/lib/utils/logger.dart
index bbc06c368..dcb4bcb0e 100644
--- a/lib/utils/logger.dart
+++ b/lib/utils/logger.dart
@@ -13,6 +13,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:logger/logger.dart' as printer;
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
+import 'package:privacyidea_authenticator/utils/app_customizer.dart';
import '../views/settings_view/settings_view_widgets/send_error_dialog.dart';
import 'customizations.dart';
@@ -67,8 +68,9 @@ class Logger {
bool _flutterIsRunning = false;
String get _mailRecipient => 'app-crash@netknights.it';
- String get _mailSubject =>
- _platformInfos != null ? '(${_platformInfos!.version}) ${_platformInfos!.appName} >>> $_lastError' : 'PrivacyIDEA Authenticator >>> $_lastError';
+ String get _mailSubject => _platformInfos != null
+ ? '(${_platformInfos!.version}+${_platformInfos!.buildNumber}) ${_platformInfos!.appName} >>> $_lastError'
+ : '${ApplicationCustomizer.appName} >>> $_lastError';
String get _filename => 'logfile.txt';
String? get _fullPath => _logPath != null ? '$_logPath/$_filename' : null;
bool get _verbose {
diff --git a/lib/utils/push_provider.dart b/lib/utils/push_provider.dart
index f26e097ca..fc62a2a50 100644
--- a/lib/utils/push_provider.dart
+++ b/lib/utils/push_provider.dart
@@ -190,16 +190,18 @@ abstract class PushProvider {
List pushTokens = globalRef?.read(tokenProvider).tokens.whereType().where((t) => t.isRolledOut && t.url != null).toList() ?? [];
// Disable polling if no push tokens exist
- if (pushTokens.isEmpty) {
+ if (pushTokens.isEmpty && globalRef?.read(settingsProvider).enablePolling == true) {
Logger.info('No push token is available for polling, polling is disabled.', name: 'push_provider.dart#pollForChallenges');
globalRef?.read(settingsProvider.notifier).disablePolling();
return null;
}
// Start request for each token
+ Logger.info('Polling for challenges: ${pushTokens.length} Tokens', name: 'push_provider.dart#pollForChallenges');
for (PushToken p in pushTokens) {
pollForChallenge(p).then((errorMessage) {
if (errorMessage != null && showMessageForEachToken) {
+ Logger.warning(errorMessage, name: 'push_provider.dart#pollForChallenges');
showMessage(message: errorMessage);
}
});
@@ -240,23 +242,16 @@ abstract class PushProvider {
break;
case 403:
- Logger.warning('Polling push tokens failed with status code ${response.statusCode}',
+ Logger.warning('Polling push token ${token.serial} failed with status code ${response.statusCode}',
name: 'push_provider.dart#pollForChallenge', error: getErrorMessageFromResponse(response));
return null;
default:
var error = getErrorMessageFromResponse(response);
- Logger.warning('Polling push tokens failed with status code ${response.statusCode}', name: 'push_provider.dart#pollForChallenge', error: error);
- return "${AppLocalizations.of(globalNavigatorKey.currentContext!)!.errorWhenPullingChallenges}\n$error";
+ return "${AppLocalizations.of(globalNavigatorKey.currentContext!)!.errorWhenPullingChallenges(token.serial)}\n$error";
}
- } catch (e, s) {
- Logger.warning(
- 'An error occured when polling for challenges',
- name: 'push_provider.dart#pollForChallenge',
- error: e,
- stackTrace: s,
- );
- return "${AppLocalizations.of(globalNavigatorKey.currentContext!)!.errorWhenPullingChallenges}\n${e.toString()}";
+ } catch (e) {
+ return "${AppLocalizations.of(globalNavigatorKey.currentContext!)!.errorWhenPullingChallenges(token.serial)}\n${e.toString()}";
}
return null;
}
diff --git a/lib/utils/riverpod_providers.dart b/lib/utils/riverpod_providers.dart
index 1c616a3e8..89f29c2f6 100644
--- a/lib/utils/riverpod_providers.dart
+++ b/lib/utils/riverpod_providers.dart
@@ -1,5 +1,7 @@
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:privacyidea_authenticator/state_notifiers/deeplink_notifier.dart';
+import 'package:privacyidea_authenticator/utils/push_provider.dart';
import '../model/mixins/sortable_mixin.dart';
import '../model/platform_info/platform_info.dart';
@@ -25,24 +27,24 @@ WidgetRef? globalRef;
final tokenProvider = StateNotifierProvider((ref) {
final tokenNotifier = TokenNotifier();
- Logger.info("appStateProvider.addListener ${tokenNotifier.hashCode.toString()}");
+ deeplinkProvider.addListener(
+ ref.container,
+ (previous, next) {
+ if (next == null) return;
+ Logger.info("tokenProvider received new deeplink");
+ tokenNotifier.handleLink(next);
+ },
+ onError: (err, _) => throw err,
+ onDependencyMayHaveChanged: () {},
+ fireImmediately: false,
+ );
+
appStateProvider.addListener(
ref.container,
(previous, next) {
- switch (next) {
- case AppState.resume:
- //startPolling();
- if (previous == AppState.pause) {
- Logger.info('refreshing tokens on resume');
- tokenNotifier.refreshTokens();
- ref.read(appStateProvider.notifier).setAppState(AppState.running);
- }
- break;
- case AppState.pause:
- //stopPolling();
- break;
- default:
- break;
+ if (previous == AppState.pause && next == AppState.resume) {
+ Logger.info('Refreshing tokens on resume');
+ tokenNotifier.refreshTokens();
}
},
onError: (err, stack) {
@@ -56,12 +58,13 @@ final tokenProvider = StateNotifierProvider((ref) {
ref.container,
(previous, next) {
if (next == null) return;
- Logger.warning('next: $next');
if (next.accepted == null) {
+ Logger.info("tokenProvider received new pushRequest");
tokenNotifier.addPushRequestToToken(next);
return;
}
if (next.accepted != null) {
+ Logger.info("tokenProvider received pushRequest with accepted=${next.accepted}... removing it from state.");
tokenNotifier.removePushRequest(next);
FlutterLocalNotificationsPlugin().cancelAll();
return;
@@ -86,9 +89,26 @@ final platformInfoProvider = StateProvider(
);
final pushRequestProvider = StateNotifierProvider(
- (ref) => PushRequestNotifier(null, pollingEnabled: ref.watch(settingsProvider).enablePolling),
+ (ref) {
+ final pushRequestNotifier = PushRequestNotifier(null, pollingEnabled: ref.watch(settingsProvider).enablePolling);
+ appStateProvider.addListener(
+ ref.container,
+ (previous, next) {
+ if (previous == AppState.pause && next == AppState.resume) {
+ Logger.info('Polling for challenges on resume');
+ PushProvider.pollForChallenges();
+ }
+ },
+ onError: (_, __) {},
+ onDependencyMayHaveChanged: () {},
+ fireImmediately: false,
+ );
+ return pushRequestNotifier;
+ },
);
+final deeplinkProvider = StateNotifierProvider((ref) => DeeplinkNotifier());
+
final appStateProvider = StateNotifierProvider(
(ref) => AppStateNotifier(),
);
diff --git a/lib/utils/themes.dart b/lib/utils/themes.dart
index 5721410bd..4e59b4714 100644
--- a/lib/utils/themes.dart
+++ b/lib/utils/themes.dart
@@ -38,6 +38,7 @@ var lightThemeData = ThemeData(
shadowColor: ApplicationCustomizer.themeColorDark,
elevation: 0,
),
+ floatingActionButtonTheme: const FloatingActionButtonThemeData(elevation: 0),
navigationBarTheme: const NavigationBarThemeData().copyWith(
backgroundColor: ApplicationCustomizer.themeColorLight,
shadowColor: ApplicationCustomizer.themeColorDark,
@@ -112,6 +113,7 @@ var darkThemeData = ThemeData(
shadowColor: ApplicationCustomizer.themeColorLight,
elevation: 0,
),
+ floatingActionButtonTheme: const FloatingActionButtonThemeData(elevation: 0),
navigationBarTheme: const NavigationBarThemeData().copyWith(
backgroundColor: ApplicationCustomizer.themeColorDark,
shadowColor: ApplicationCustomizer.themeColorLight,
diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart
index 4579acb32..85f166ba9 100644
--- a/lib/utils/utils.dart
+++ b/lib/utils/utils.dart
@@ -30,6 +30,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:hex/hex.dart' as HexConverter;
import 'package:otp/otp.dart' as OTPLibrary;
import 'package:permission_handler/permission_handler.dart';
+import 'package:privacyidea_authenticator/utils/logger.dart';
import 'identifiers.dart';
@@ -84,12 +85,15 @@ bool equalsIgnoreCase(String s1, String s2) {
/// If permission is already given, this function does nothing
void checkNotificationPermission() async {
var status = await Permission.notification.status;
+ Logger.info('Notification permission status: $status');
// TODO what to do if permanently denied?
// Add a dialog before requesting?
if (!status.isPermanentlyDenied) {
if (status.isDenied) {
await Permission.notification.request();
}
+ } else {
+ Logger.info('Notification permission is permanently denied!');
}
}
diff --git a/lib/views/main_view/main_view.dart b/lib/views/main_view/main_view.dart
index f8ca9acdd..20b2d638c 100644
--- a/lib/views/main_view/main_view.dart
+++ b/lib/views/main_view/main_view.dart
@@ -24,15 +24,17 @@ class MainView extends ConsumerStatefulWidget {
class _MainViewState extends ConsumerState with LifecycleMixin {
final globalKey = GlobalKey();
+
@override
- void onResume() {
- Logger.info('onResume');
+ void onAppResume() {
+ Logger.info('MainView Resume', name: 'main_view.dart#onAppResume');
globalRef?.read(appStateProvider.notifier).setAppState(AppState.resume);
+ WidgetsBinding.instance.addPostFrameCallback((_) => globalRef?.read(appStateProvider.notifier).setAppState(AppState.running));
}
@override
- void onPause() {
- Logger.info('onPause');
+ void onAppPause() {
+ Logger.info('MainView Pause', name: 'main_view.dart#onAppPause');
globalRef?.read(appStateProvider.notifier).setAppState(AppState.pause);
}
diff --git a/lib/views/main_view/main_view_widgets/main_view_navigation_buttons.dart b/lib/views/main_view/main_view_widgets/main_view_navigation_buttons.dart
index 9fd5db484..723044135 100644
--- a/lib/views/main_view/main_view_widgets/main_view_navigation_buttons.dart
+++ b/lib/views/main_view/main_view_widgets/main_view_navigation_buttons.dart
@@ -65,7 +65,7 @@ class MainViewNavigationButtions extends StatelessWidget {
height: size.height * 0.3,
),
applicationLegalese: ApplicationCustomizer.websiteLink,
- applicationVersion: globalRef?.read(platformInfoProvider).appVersion,
+ applicationVersion: '${globalRef?.read(platformInfoProvider).appVersion}+${globalRef?.read(platformInfoProvider).buildNumber}',
),
),
);
diff --git a/lib/views/main_view/main_view_widgets/token_widgets/day_password_token_widgets/day_password_token_widget_tile.dart b/lib/views/main_view/main_view_widgets/token_widgets/day_password_token_widgets/day_password_token_widget_tile.dart
index 644131222..3701b1732 100644
--- a/lib/views/main_view/main_view_widgets/token_widgets/day_password_token_widgets/day_password_token_widget_tile.dart
+++ b/lib/views/main_view/main_view_widgets/token_widgets/day_password_token_widgets/day_password_token_widget_tile.dart
@@ -24,16 +24,21 @@ class DayPasswordTokenWidgetTile extends ConsumerStatefulWidget {
class _DayPasswordTokenWidgetTileState extends ConsumerState {
double secondsLeft = 0;
+ late DateTime lastCount;
final ValueNotifier isHidden = ValueNotifier(true);
@override
void initState() {
super.initState();
secondsLeft = widget.token.durationUntilNextOTP.inMilliseconds / 1000;
- _countDown(0);
+ lastCount = DateTime.now();
+ _startCountDown();
}
- void _countDown(int msSinceLastCount) {
+ void _startCountDown() {
+ final now = DateTime.now();
+ final msSinceLastCount = now.difference(lastCount).inMilliseconds;
+ lastCount = now;
if (!mounted) return;
if (secondsLeft - (msSinceLastCount / 1000) > 0) {
setState(() => secondsLeft -= msSinceLastCount / 1000);
@@ -41,11 +46,7 @@ class _DayPasswordTokenWidgetTileState extends ConsumerState secondsLeft = widget.token.durationUntilNextOTP.inMilliseconds / 1000);
}
final msUntilNextSecond = (secondsLeft * 1000).toInt() % 1000 + 1; // +1 to avoid 0
- Future.delayed(
- Duration(
- milliseconds: msUntilNextSecond,
- ),
- () => _countDown(msUntilNextSecond));
+ Future.delayed(Duration(milliseconds: msUntilNextSecond), () => _startCountDown());
}
void _copyOtpValue() {
diff --git a/lib/views/main_view/main_view_widgets/token_widgets/totp_token_widgets/totp_token_widget_tile.dart b/lib/views/main_view/main_view_widgets/token_widgets/totp_token_widgets/totp_token_widget_tile.dart
index 61cf27a5e..ecdc44fb3 100644
--- a/lib/views/main_view/main_view_widgets/token_widgets/totp_token_widgets/totp_token_widget_tile.dart
+++ b/lib/views/main_view/main_view_widgets/token_widgets/totp_token_widgets/totp_token_widget_tile.dart
@@ -24,6 +24,7 @@ class TOTPTokenWidgetTile extends ConsumerStatefulWidget {
class _TOTPTokenWidgetTileState extends ConsumerState with SingleTickerProviderStateMixin {
double secondsLeft = 0;
late AnimationController animation;
+ late DateTime lastCount;
final ValueNotifier isHidden = ValueNotifier(true);
void _copyOtpValue() {
@@ -49,13 +50,14 @@ class _TOTPTokenWidgetTileState extends ConsumerState with
duration: Duration(seconds: widget.token.period),
);
animation.forward(from: 1 - widget.token.secondsUntilNextOTP / widget.token.period);
- _countDown(0);
- ref.read(appStateProvider.notifier).addListener(_onAppStateChange);
+ secondsLeft = widget.token.secondsUntilNextOTP;
+ lastCount = DateTime.now();
+ _startCountDown();
isHidden.addListener(() {
if (mounted) {
setState(() {
if (isHidden.value == false) {
- Future.delayed(Duration(milliseconds: (widget.token.period * 1000 + (widget.token.secondsUntilNextOTP * 1000).toInt())), () {
+ Future.delayed(Duration(milliseconds: (widget.token.period * 1000 + (secondsLeft * 1000).toInt())), () {
isHidden.value = true;
});
}
@@ -83,16 +85,26 @@ class _TOTPTokenWidgetTileState extends ConsumerState with
super.dispose();
}
- void _countDown(int msSinceLastCount) {
+ void _startCountDown() {
+ final now = DateTime.now();
+ final msSinceLastCount = now.difference(lastCount).inMilliseconds;
+ lastCount = now;
if (!mounted) return;
- setState(() => secondsLeft = widget.token.secondsUntilNextOTP);
- animation.forward(from: 1 - secondsLeft / widget.token.period);
+ if (secondsLeft - (msSinceLastCount / 1000) > 0) {
+ setState(() => secondsLeft -= msSinceLastCount / 1000);
+ } else {
+ setState(() => secondsLeft = widget.token.secondsUntilNextOTP);
+ animation.forward(from: 1 - secondsLeft / widget.token.period);
+ }
+
final msUntilNextSecond = (secondsLeft * 1000).toInt() % 1000 + 1; // +1 to avoid 0
- Future.delayed(Duration(milliseconds: msUntilNextSecond), () => _countDown(msUntilNextSecond));
+ Future.delayed(Duration(milliseconds: msUntilNextSecond), () => _startCountDown());
}
@override
Widget build(BuildContext context) {
+ final appstate = ref.watch(appStateProvider);
+ _onAppStateChange(appstate);
return TokenWidgetTile(
key: Key('${widget.token.hashCode}TokenWidgetTile'),
tokenImage: widget.token.tokenImage,
@@ -130,11 +142,11 @@ class _TOTPTokenWidgetTileState extends ConsumerState with
children: [
Center(
child: Text(
- '${secondsLeft.ceil()}',
+ '${secondsLeft.round()}',
overflow: TextOverflow.fade,
softWrap: false,
),
- ), // ceil to show 30 -> 1 instead of 29 -> 0
+ ),
Center(
child: CircularProgressIndicator(
value: animation.value,
diff --git a/pubspec.lock b/pubspec.lock
index a0a91d488..3550349b0 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -13,10 +13,10 @@ packages:
dependency: transitive
description:
name: _flutterfire_internals
- sha256: "1a5e13736d59235ce0139621b4bbe29bc89839e202409081bc667eb3cd20674c"
+ sha256: "2d8e8e123ca3675625917f535fcc0d3a50092eef44334168f9b18adc050d4c6e"
url: "https://pub.dev"
source: hosted
- version: "1.3.5"
+ version: "1.3.6"
analyzer:
dependency: transitive
description:
@@ -29,10 +29,10 @@ packages:
dependency: transitive
description:
name: archive
- sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
+ sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e
url: "https://pub.dev"
source: hosted
- version: "3.3.7"
+ version: "3.3.9"
args:
dependency: transitive
description:
@@ -101,10 +101,10 @@ packages:
dependency: transitive
description:
name: build_resolvers
- sha256: "6c4dd11d05d056e76320b828a1db0fc01ccd376922526f8e9d6c796a5adbac20"
+ sha256: d912852cce27c9e80a93603db721c267716894462e7033165178b91138587972
url: "https://pub.dev"
source: hosted
- version: "2.2.1"
+ version: "2.3.2"
build_runner:
dependency: "direct dev"
description:
@@ -133,10 +133,10 @@ packages:
dependency: transitive
description:
name: built_value
- sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166"
+ sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74
url: "https://pub.dev"
source: hosted
- version: "8.6.1"
+ version: "8.6.3"
characters:
dependency: transitive
description:
@@ -173,10 +173,10 @@ packages:
dependency: transitive
description:
name: code_builder
- sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189"
+ sha256: "315a598c7fbe77f22de1c9da7cfd6fd21816312f16ffa124453b4fc679e540f1"
url: "https://pub.dev"
source: hosted
- version: "4.5.0"
+ version: "4.6.0"
collection:
dependency: "direct main"
description:
@@ -229,10 +229,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
- sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
+ sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
url: "https://pub.dev"
source: hosted
- version: "1.0.5"
+ version: "1.0.6"
dart_style:
dependency: transitive
description:
@@ -317,10 +317,10 @@ packages:
dependency: "direct main"
description:
name: firebase_core
- sha256: c78132175edda4bc532a71e01a32964e4b4fcf53de7853a422d96dac3725f389
+ sha256: "675c209c94a1817649137cbd113fc4c9ae85e48d03dd578629abbec6d8a4d93d"
url: "https://pub.dev"
source: hosted
- version: "2.15.1"
+ version: "2.16.0"
firebase_core_platform_interface:
dependency: transitive
description:
@@ -333,34 +333,34 @@ packages:
dependency: transitive
description:
name: firebase_core_web
- sha256: "4cf4d2161530332ddc3c562f19823fb897ff37a9a774090d28df99f47370e973"
+ sha256: e8c408923cd3a25bd342c576a114f2126769cd1a57106a4edeaa67ea4a84e962
url: "https://pub.dev"
source: hosted
- version: "2.7.0"
+ version: "2.8.0"
firebase_messaging:
dependency: "direct main"
description:
name: firebase_messaging
- sha256: db4a38be54fd84849c21be1ae1b44f0d4637eec1069bf5c49ea95e81f582bbc0
+ sha256: "4544524c22de3ffdc7e0ffaeeba212a04d09e76d0549ae6f42ce285d9d8f0513"
url: "https://pub.dev"
source: hosted
- version: "14.6.6"
+ version: "14.6.8"
firebase_messaging_platform_interface:
dependency: transitive
description:
name: firebase_messaging_platform_interface
- sha256: "164119eed47ff19284e28bea9165a03da110c56ea09dd996622cfccad14d0efd"
+ sha256: a6e1fae8242a14d5d8f5ab1cf94693511f06bab49ff1d46e3d83c0af3c4becb8
url: "https://pub.dev"
source: hosted
- version: "4.5.5"
+ version: "4.5.7"
firebase_messaging_web:
dependency: transitive
description:
name: firebase_messaging_web
- sha256: "6196d20731733834d7afb175c4345be57ddbd5daebca83cd52a430d62c2279fe"
+ sha256: a9fe837dc2dcdd3e32e6109a6b0ce62592d7a44cb8f69cb5b73190865c5aa28e
url: "https://pub.dev"
source: hosted
- version: "3.5.5"
+ version: "3.5.7"
fixnum:
dependency: transitive
description:
@@ -399,18 +399,18 @@ packages:
dependency: "direct main"
description:
name: flutter_lints
- sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
+ sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.dev"
source: hosted
- version: "2.0.2"
+ version: "2.0.3"
flutter_local_notifications:
dependency: "direct main"
description:
name: flutter_local_notifications
- sha256: "3cc40fe8c50ab8383f3e053a499f00f975636622ecdc8e20a77418ece3b1e975"
+ sha256: "3002092e5b8ce2f86c3361422e52e6db6776c23ee21e0b2f71b892bf4259ef04"
url: "https://pub.dev"
source: hosted
- version: "15.1.0+1"
+ version: "15.1.1"
flutter_local_notifications_linux:
dependency: transitive
description:
@@ -444,74 +444,74 @@ packages:
dependency: "direct main"
description:
name: flutter_markdown
- sha256: "2b206d397dd7836ea60035b2d43825c8a303a76a5098e66f42d55a753e18d431"
+ sha256: a10979814c5f4ddbe2b6143fba25d927599e21e3ba65b3862995960606fae78f
url: "https://pub.dev"
source: hosted
- version: "0.6.17+1"
+ version: "0.6.17+3"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
- sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360"
+ sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c
url: "https://pub.dev"
source: hosted
- version: "2.0.15"
+ version: "2.0.16"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
- sha256: b6cb0041c6c11cefb2dcb97ef436eba43c6d41287ac6d8ca93e02a497f53a4f3
+ sha256: "1bd39b04f1bcd217a969589777ca6bd642d116e3e5de65c3e6a8e8bdd8b178ec"
url: "https://pub.dev"
source: hosted
- version: "2.3.7"
+ version: "2.4.0"
flutter_secure_storage:
dependency: "direct main"
description:
name: flutter_secure_storage
- sha256: "98352186ee7ad3639ccc77ad7924b773ff6883076ab952437d20f18a61f0a7c5"
+ sha256: ffdbb60130e4665d2af814a0267c481bcf522c41ae2e43caf69fa0146876d685
url: "https://pub.dev"
source: hosted
- version: "8.0.0"
+ version: "9.0.0"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
- sha256: "0912ae29a572230ad52d8a4697e5518d7f0f429052fd51df7e5a7952c7efe2a3"
+ sha256: "3d5032e314774ee0e1a7d0a9f5e2793486f0dff2dd9ef5a23f4e3fb2a0ae6a9e"
url: "https://pub.dev"
source: hosted
- version: "1.1.3"
+ version: "1.2.0"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
- sha256: "083add01847fc1c80a07a08e1ed6927e9acd9618a35e330239d4422cd2a58c50"
+ sha256: bd33935b4b628abd0b86c8ca20655c5b36275c3a3f5194769a7b3f37c905369c
url: "https://pub.dev"
source: hosted
- version: "3.0.0"
+ version: "3.0.1"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
- sha256: b3773190e385a3c8a382007893d678ae95462b3c2279e987b55d140d3b0cb81b
+ sha256: "0d4d3a5dd4db28c96ae414d7ba3b8422fd735a8255642774803b2532c9a61d7e"
url: "https://pub.dev"
source: hosted
- version: "1.0.1"
+ version: "1.0.2"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
- sha256: "42938e70d4b872e856e678c423cc0e9065d7d294f45bc41fc1981a4eb4beaffe"
+ sha256: "30f84f102df9dcdaa2241866a958c2ec976902ebdaa8883fbfe525f1f2f3cf20"
url: "https://pub.dev"
source: hosted
- version: "1.1.1"
+ version: "1.1.2"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
- sha256: fc2910ec9b28d60598216c29ea763b3a96c401f0ce1d13cdf69ccb0e5c93c3ee
+ sha256: "5809c66f9dd3b4b93b0a6e2e8561539405322ee767ac2f64d084e2ab5429d108"
url: "https://pub.dev"
source: hosted
- version: "2.0.0"
+ version: "3.0.0"
flutter_slidable:
dependency: "direct main"
description:
@@ -534,10 +534,10 @@ packages:
dependency: "direct main"
description:
name: flutterlifecyclehooks
- sha256: "16e143ea8d549afd54f214661ef5c20ca58e8366ea0923b1a4d5f3ff22e2fc43"
+ sha256: "25c16ff88513445c049735013ed66ddd364530c9467b5784a5667ee0e644dd67"
url: "https://pub.dev"
source: hosted
- version: "3.0.2"
+ version: "4.0.0"
fluttertoast:
dependency: "direct main"
description:
@@ -659,10 +659,10 @@ packages:
dependency: "direct main"
description:
name: lifecycle
- sha256: "460440bf148efc9a01f52b08758b7c6fd1d0d60beb7c2fb1cc714823508094b9"
+ sha256: ad96a411440e8ab5b8dd63eb6345b1385863f33a09ae073e0ea110159ea81787
url: "https://pub.dev"
source: hosted
- version: "0.7.0"
+ version: "0.8.0"
lints:
dependency: transitive
description:
@@ -675,50 +675,50 @@ packages:
dependency: "direct main"
description:
name: local_auth
- sha256: "0cf238be2bfa51a6c9e7e9cfc11c05ea39f2a3a4d3e5bb255d0ebc917da24401"
+ sha256: "7e6c63082e399b61e4af71266b012e767a5d4525dd6e9ba41e174fd42d76e115"
url: "https://pub.dev"
source: hosted
- version: "2.1.6"
+ version: "2.1.7"
local_auth_android:
dependency: "direct main"
description:
name: local_auth_android
- sha256: "36a78898198386d36d4e152b8cb46059b18f0e2017f813a0e833e216199f8950"
+ sha256: "9ad0b1ffa6f04f4d91e38c2d4c5046583e23f4cae8345776a994e8670df57fb1"
url: "https://pub.dev"
source: hosted
- version: "1.0.32"
+ version: "1.0.34"
local_auth_ios:
dependency: "direct main"
description:
name: local_auth_ios
- sha256: edc2977c5145492f3451db9507a2f2f284ee4f408950b3e16670838726761940
+ sha256: "26a8d1ad0b4ef6f861d29921be8383000fda952e323a5b6752cf82ca9cf9a7a9"
url: "https://pub.dev"
source: hosted
- version: "1.1.3"
+ version: "1.1.4"
local_auth_platform_interface:
dependency: transitive
description:
name: local_auth_platform_interface
- sha256: "9e160d59ef0743e35f1b50f4fb84dc64f55676b1b8071e319ef35e7f3bc13367"
+ sha256: fc5bd537970a324260fda506cfb61b33ad7426f37a8ea5c461cf612161ebba54
url: "https://pub.dev"
source: hosted
- version: "1.0.7"
+ version: "1.0.8"
local_auth_windows:
dependency: transitive
description:
name: local_auth_windows
- sha256: "5af808e108c445d0cf702a8c5f8242f1363b7970320334f82e6e1e8ad0b0d7d4"
+ sha256: "505ba3367ca781efb1c50d3132e44a2446bccc4163427bc203b9b4d8994d97ea"
url: "https://pub.dev"
source: hosted
- version: "1.0.9"
+ version: "1.0.10"
logger:
dependency: "direct main"
description:
name: logger
- sha256: "66cb048220ca51cf9011da69fa581e4ee2bed4be6e82870d9e9baae75739da49"
+ sha256: ba3bc83117b2b49bdd723c0ea7848e8285a0fbc597ba09203b20d329d020c24a
url: "https://pub.dev"
source: hosted
- version: "2.0.1"
+ version: "2.0.2"
logging:
dependency: transitive
description:
@@ -859,66 +859,66 @@ packages:
dependency: "direct main"
description:
name: path_provider
- sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0"
+ sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
- sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8"
+ sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1"
url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.2.0"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
- sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5"
+ sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev"
source: hosted
- version: "2.3.0"
+ version: "2.3.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
- sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3
+ sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
- sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84
+ sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
- sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da
+ sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.2.1"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
- sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81"
+ sha256: ad65ba9af42a3d067203641de3fd9f547ded1410bad3b84400c2b4899faede70
url: "https://pub.dev"
source: hosted
- version: "10.4.3"
+ version: "11.0.0"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
- sha256: "2ffaf52a21f64ac9b35fe7369bb9533edbd4f698e5604db8645b1064ff4cf221"
+ sha256: "740c9c9d3090a29cd2fd1f193bba457ac1d2cef1da0ef91f2630d3d9e3c01c15"
url: "https://pub.dev"
source: hosted
- version: "10.3.3"
+ version: "11.0.2"
permission_handler_apple:
dependency: transitive
description:
@@ -931,10 +931,10 @@ packages:
dependency: transitive
description:
name: permission_handler_platform_interface
- sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9"
+ sha256: f2343e9fa9c22ae4fd92d4732755bfe452214e7189afcc097380950cf567b4b2
url: "https://pub.dev"
source: hosted
- version: "3.11.3"
+ version: "3.11.5"
permission_handler_windows:
dependency: transitive
description:
@@ -970,10 +970,10 @@ packages:
dependency: transitive
description:
name: plugin_platform_interface
- sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd"
+ sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
url: "https://pub.dev"
source: hosted
- version: "2.1.5"
+ version: "2.1.6"
pointycastle:
dependency: "direct main"
description:
@@ -1026,66 +1026,66 @@ packages:
dependency: transitive
description:
name: riverpod
- sha256: b0657b5b30c81a3184bdaab353045f0a403ebd60bb381591a8b7ad77dcade793
+ sha256: a600120d6f213a9922860eea1abc32597436edd5b2c4e73b91410f8c2af67d22
url: "https://pub.dev"
source: hosted
- version: "2.3.7"
+ version: "2.4.0"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
- sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1"
+ sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.2.1"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
- sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076
+ sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.2.1"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
- sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef
+ sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7"
url: "https://pub.dev"
source: hosted
- version: "2.3.3"
+ version: "2.3.4"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
- sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1"
+ sha256: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a
url: "https://pub.dev"
source: hosted
- version: "2.3.0"
+ version: "2.3.1"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
- sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1"
+ sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
url: "https://pub.dev"
source: hosted
- version: "2.3.0"
+ version: "2.3.1"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
- sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a"
+ sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.2.1"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
- sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d
+ sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f
url: "https://pub.dev"
source: hosted
- version: "2.3.0"
+ version: "2.3.1"
shelf:
dependency: transitive
description:
@@ -1163,6 +1163,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.0"
+ sprintf:
+ dependency: transitive
+ description:
+ name: sprintf
+ sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
stack_trace:
dependency: transitive
description:
@@ -1303,74 +1311,74 @@ packages:
dependency: "direct main"
description:
name: url_launcher
- sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e"
+ sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27"
url: "https://pub.dev"
source: hosted
- version: "6.1.12"
+ version: "6.1.14"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
- sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025"
+ sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330
url: "https://pub.dev"
source: hosted
- version: "6.0.38"
+ version: "6.1.0"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
- sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
+ sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f"
url: "https://pub.dev"
source: hosted
- version: "6.1.4"
+ version: "6.1.5"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
- sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5"
+ sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e
url: "https://pub.dev"
source: hosted
- version: "3.0.5"
+ version: "3.0.6"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
- sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1"
+ sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88
url: "https://pub.dev"
source: hosted
- version: "3.0.6"
+ version: "3.0.7"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
- sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea
+ sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618"
url: "https://pub.dev"
source: hosted
- version: "2.1.3"
+ version: "2.1.5"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
- sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4
+ sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5"
url: "https://pub.dev"
source: hosted
- version: "2.0.18"
+ version: "2.0.20"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
- sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422"
+ sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069"
url: "https://pub.dev"
source: hosted
- version: "3.0.7"
+ version: "3.0.8"
uuid:
dependency: "direct main"
description:
name: uuid
- sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
+ sha256: e03928880bdbcbf496fb415573f5ab7b1ea99b9b04f669c01104d085893c3134
url: "https://pub.dev"
source: hosted
- version: "3.0.7"
+ version: "4.0.0"
vector_math:
dependency: transitive
description:
@@ -1431,34 +1439,34 @@ packages:
dependency: transitive
description:
name: webkit_inspection_protocol
- sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
+ sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
win32:
dependency: transitive
description:
name: win32
- sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0
+ sha256: c97defd418eef4ec88c0d1652cdce84b9f7b63dd7198e266d06ac1710d527067
url: "https://pub.dev"
source: hosted
- version: "5.0.6"
+ version: "5.0.8"
win32_registry:
dependency: transitive
description:
name: win32_registry
- sha256: e4506d60b7244251bc59df15656a3093501c37fb5af02105a944d73eb95be4c9
+ sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a"
url: "https://pub.dev"
source: hosted
- version: "1.1.1"
+ version: "1.1.2"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
- sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247
+ sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
url: "https://pub.dev"
source: hosted
- version: "1.0.2"
+ version: "1.0.3"
xml:
dependency: transitive
description:
@@ -1476,5 +1484,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
- dart: ">=3.1.0-185.0.dev <4.0.0"
- flutter: ">=3.10.0"
+ dart: ">=3.1.0 <4.0.0"
+ flutter: ">=3.13.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index dfe9ba85b..5ab116668 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -14,7 +14,7 @@ publish_to: none
# 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: 4.2.0+402015 # TODO Set the right version number
+version: 4.2.0+402018 # TODO Set the right version number
# version: major.minor.build + 2x major|2x minor|3x build
# version: version number + build number (optional)
# android: build-name + versionCode
@@ -35,7 +35,7 @@ dependencies:
base32: ^2.1.1
otp: ^3.0.1
qr_mobile_vision: ^4.1.3
- flutter_secure_storage: ^8.0.0
+ flutter_secure_storage: ^9.0.0
json_annotation: ^4.8.1
flutter_slidable: ^3.0.0
package_info_plus: ^4.0.2
@@ -43,13 +43,13 @@ dependencies:
flutter_markdown: ^0.6.8
url_launcher: ^6.0.12
fluttertoast: ^8.2.1
- uuid: ^3.0.5
+ uuid: ^4.0.0
http: ^1.1.0
pointycastle: ^3.4.0
mutex: ^3.0.0
flutter_lints: ^2.0.2
expandable: ^5.0.1
- flutterlifecyclehooks: ^3.0.2
+ flutterlifecyclehooks: ^4.0.0
streaming_shared_preferences: ^2.0.0
easy_dynamic_theme: ^2.2.0
firebase_messaging: ^14.6.4
@@ -62,12 +62,12 @@ dependencies:
lottie: ^2.4.0
flare_flutter: ^3.0.2
flutter_mailer: ^2.1.1
- permission_handler: ^10.2.0
+ permission_handler: ^11.0.0
path_provider: ^2.0.15
logger: ^2.0.0
flutter_riverpod: ^2.3.6
shared_preferences: ^2.2.0
- lifecycle: ^0.7.0
+ lifecycle: ^0.8.0
flutter_launcher_icons: ^0.13.1
flutter_local_notifications: ^15.1.0+1
extended_nested_scroll_view: ^6.1.2