diff --git a/.gitignore b/.gitignore
index d118433..bd4de7c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,13 @@ app.*.map.json
*.g.dart
*.gr.dart
*.freezed.dart
+
+# environment variables
+/env
+
+# firebase
+**/google-services.json
+**/GoogleService-Info.plist
+**/firebase_app_id_file.json
+**/firebase_options.dart
+
diff --git a/analysis_options.yaml b/analysis_options.yaml
index e0e35ac..b27cf50 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -6,6 +6,7 @@ analyzer:
exclude:
- "**.g.dart"
- "**.freezed.dart"
+ - "/**firebase_options.dart"
linter:
rules:
file_names: false
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 102552d..ee3a862 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -2,6 +2,8 @@ plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
+ id "com.google.gms.google-services"
+ id "com.google.firebase.crashlytics"
}
def localProperties = new Properties()
diff --git a/android/settings.gradle b/android/settings.gradle
index ef9e4af..9c40733 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -20,6 +20,8 @@ plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.4.2" apply false
id "org.jetbrains.kotlin.android" version "1.9.22" apply false
+ id "com.google.gms.google-services" version "4.4.0" apply false
+ id "com.google.firebase.crashlytics" version "2.9.9" apply false
}
include ":app"
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 9625e10..7c56964 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 11.0
+ 12.0
diff --git a/ios/Podfile b/ios/Podfile
index 88359b2..279576f 100644
--- a/ios/Podfile
+++ b/ios/Podfile
@@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
-# platform :ios, '11.0'
+# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index bcc2866..5b71fee 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,20 +1,87 @@
PODS:
+ - Firebase/CoreOnly (10.22.0):
+ - FirebaseCore (= 10.22.0)
+ - Firebase/Crashlytics (10.22.0):
+ - Firebase/CoreOnly
+ - FirebaseCrashlytics (~> 10.22.0)
+ - firebase_core (2.27.1):
+ - Firebase/CoreOnly (= 10.22.0)
+ - Flutter
+ - firebase_crashlytics (3.4.19):
+ - Firebase/Crashlytics (= 10.22.0)
+ - firebase_core
+ - Flutter
+ - FirebaseCore (10.22.0):
+ - FirebaseCoreInternal (~> 10.0)
+ - GoogleUtilities/Environment (~> 7.12)
+ - GoogleUtilities/Logger (~> 7.12)
+ - FirebaseCoreExtension (10.22.0):
+ - FirebaseCore (~> 10.0)
+ - FirebaseCoreInternal (10.22.0):
+ - "GoogleUtilities/NSData+zlib (~> 7.8)"
+ - FirebaseCrashlytics (10.22.0):
+ - FirebaseCore (~> 10.5)
+ - FirebaseInstallations (~> 10.0)
+ - FirebaseSessions (~> 10.5)
+ - GoogleDataTransport (~> 9.2)
+ - GoogleUtilities/Environment (~> 7.8)
+ - nanopb (< 2.30911.0, >= 2.30908.0)
+ - PromisesObjC (~> 2.1)
+ - FirebaseInstallations (10.22.0):
+ - FirebaseCore (~> 10.0)
+ - GoogleUtilities/Environment (~> 7.8)
+ - GoogleUtilities/UserDefaults (~> 7.8)
+ - PromisesObjC (~> 2.1)
+ - FirebaseSessions (10.23.0):
+ - FirebaseCore (~> 10.5)
+ - FirebaseCoreExtension (~> 10.0)
+ - FirebaseInstallations (~> 10.0)
+ - GoogleDataTransport (~> 9.2)
+ - GoogleUtilities/Environment (~> 7.10)
+ - nanopb (< 2.30911.0, >= 2.30908.0)
+ - PromisesSwift (~> 2.1)
- Flutter (1.0.0)
- flutter_native_splash (0.0.1):
- Flutter
+ - GoogleDataTransport (9.4.1):
+ - GoogleUtilities/Environment (~> 7.7)
+ - nanopb (< 2.30911.0, >= 2.30908.0)
+ - PromisesObjC (< 3.0, >= 1.2)
+ - GoogleUtilities/Environment (7.13.0):
+ - GoogleUtilities/Privacy
+ - PromisesObjC (< 3.0, >= 1.2)
+ - GoogleUtilities/Logger (7.13.0):
+ - GoogleUtilities/Environment
+ - GoogleUtilities/Privacy
+ - "GoogleUtilities/NSData+zlib (7.13.0)":
+ - GoogleUtilities/Privacy
+ - GoogleUtilities/Privacy (7.13.0)
+ - GoogleUtilities/UserDefaults (7.13.0):
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Privacy
- in_app_review (0.2.0):
- Flutter
+ - nanopb (2.30910.0):
+ - nanopb/decode (= 2.30910.0)
+ - nanopb/encode (= 2.30910.0)
+ - nanopb/decode (2.30910.0)
+ - nanopb/encode (2.30910.0)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
+ - PromisesObjC (2.4.0)
+ - PromisesSwift (2.4.0):
+ - PromisesObjC (= 2.4.0)
- share_plus (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter
DEPENDENCIES:
+ - firebase_core (from `.symlinks/plugins/firebase_core/ios`)
+ - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
- Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
@@ -23,7 +90,26 @@ DEPENDENCIES:
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
+SPEC REPOS:
+ trunk:
+ - Firebase
+ - FirebaseCore
+ - FirebaseCoreExtension
+ - FirebaseCoreInternal
+ - FirebaseCrashlytics
+ - FirebaseInstallations
+ - FirebaseSessions
+ - GoogleDataTransport
+ - GoogleUtilities
+ - nanopb
+ - PromisesObjC
+ - PromisesSwift
+
EXTERNAL SOURCES:
+ firebase_core:
+ :path: ".symlinks/plugins/firebase_core/ios"
+ firebase_crashlytics:
+ :path: ".symlinks/plugins/firebase_crashlytics/ios"
Flutter:
:path: Flutter
flutter_native_splash:
@@ -40,14 +126,28 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/url_launcher_ios/ios"
SPEC CHECKSUMS:
- Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
- flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
+ Firebase: 797fd7297b7e1be954432743a0b3f90038e45a71
+ firebase_core: d6dfb4cb86a9ebd92464bb8736075fe967211c97
+ firebase_crashlytics: 0be8c89a6b91fd964a7a8fe574109fd528d310bb
+ FirebaseCore: 0326ec9b05fbed8f8716cddbf0e36894a13837f7
+ FirebaseCoreExtension: 6394c00b887d0bebadbc7049c464aa0cbddc5d41
+ FirebaseCoreInternal: bca337352024b18424a61e478460547d46c4c753
+ FirebaseCrashlytics: e568d68ce89117c80cddb04073ab9018725fbb8c
+ FirebaseInstallations: 763814908793c0da14c18b3dcffdec71e29ed55e
+ FirebaseSessions: f06853e30f99fe42aa511014d7ee6c8c319f08a3
+ Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
+ flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778
+ GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a
+ GoogleUtilities: d053d902a8edaa9904e1bd00c37535385b8ed152
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
- package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
- path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
+ nanopb: 438bc412db1928dac798aa6fd75726007be04262
+ package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c
+ path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
+ PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
+ PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
- url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86
+ url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586
-PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
+PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011
-COCOAPODS: 1.11.3
+COCOAPODS: 1.14.3
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 5fc4cde..9d4e078 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -13,6 +13,7 @@
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 */; };
+ CE2C8C38E2953B6831D3AC9D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6F110F54F1D9780F415898DB /* GoogleService-Info.plist */; };
FE36318640B1BA534A57B353 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7C72D3776DF8835C5ED10945 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
@@ -36,6 +37,7 @@
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
454D6FDBAD08AA9AAB10944C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
6651C203B376476D69DB3086 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ 6F110F54F1D9780F415898DB /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.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 = ""; };
@@ -80,6 +82,7 @@
97C146EF1CF9000F007C117D /* Products */,
D46A21369FDB488674476679 /* Pods */,
D41E5151D67274DCF9CCD160 /* Frameworks */,
+ 6F110F54F1D9780F415898DB /* GoogleService-Info.plist */,
);
sourceTree = "";
};
@@ -140,6 +143,7 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
8144507F31782B87B24B5159 /* [CP] Embed Pods Frameworks */,
+ ADF5B00798207F89CAF29939 /* [firebase_crashlytics] Crashlytics Upload Symbols */,
);
buildRules = (
);
@@ -156,7 +160,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1430;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -192,6 +196,7 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
+ CE2C8C38E2953B6831D3AC9D /* GoogleService-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -268,6 +273,29 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
+ ADF5B00798207F89CAF29939 /* [firebase_crashlytics] Crashlytics Upload Symbols */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}\"",
+ "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/\"",
+ "\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"",
+ "\"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)\"",
+ "\"$(PROJECT_DIR)/firebase_app_id_file.json\"",
+ );
+ name = "[firebase_crashlytics] Crashlytics Upload Symbols";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" ";
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -343,7 +371,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -420,7 +448,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -469,7 +497,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a6b826d..5e31d3d 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
get supportedLocales => [
diff --git a/lib/app/theme/constants/theme_constants.dart b/lib/app/theme/constants/theme_constants.dart
index e6e67b6..21b7a1f 100644
--- a/lib/app/theme/constants/theme_constants.dart
+++ b/lib/app/theme/constants/theme_constants.dart
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
abstract final class ThemeConstants {
+ ThemeConstants._();
+
static BorderRadius borderRadiusCircular = BorderRadius.circular(12);
static Radius radiusCircular = const Radius.circular(12);
}
diff --git a/lib/app/theme/cubit/theme_cubit.freezed.dart b/lib/app/theme/cubit/theme_cubit.freezed.dart
index 6b48118..eb734cc 100644
--- a/lib/app/theme/cubit/theme_cubit.freezed.dart
+++ b/lib/app/theme/cubit/theme_cubit.freezed.dart
@@ -12,7 +12,7 @@ part of 'theme_cubit.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$ThemeState {
@@ -103,7 +103,7 @@ class _$ThemeStateImpl extends _ThemeState {
}
@override
- bool operator ==(dynamic other) {
+ bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ThemeStateImpl &&
diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart
new file mode 100644
index 0000000..a6eac38
--- /dev/null
+++ b/lib/app/view/app.dart
@@ -0,0 +1,78 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_localized_locales/flutter_localized_locales.dart';
+import 'package:password_generator/app/constants/string_constants.dart';
+import 'package:password_generator/app/l10n/cubit/l10n_cubit.dart';
+import 'package:password_generator/app/l10n/extensions/app_l10n_extensions.dart';
+import 'package:password_generator/app/router/app_router.dart';
+import 'package:password_generator/app/theme/cubit/theme_cubit.dart';
+import 'package:password_generator/app/theme/dark/app_theme_dark.dart';
+import 'package:password_generator/app/theme/light/app_theme_light.dart';
+import 'package:password_generator/core/extensions/context_extensions.dart';
+import 'package:password_generator/features/generate_password/data/repository/generate_password_repository.dart';
+import 'package:password_generator/features/generate_password/presentation/cubit/generate_password_cubit.dart';
+import 'package:password_generator/features/password_history/cubit/password_history_cubit.dart';
+
+class App extends StatelessWidget {
+ App({super.key});
+
+ final _appRouter = AppRouter();
+
+ @override
+ Widget build(BuildContext context) {
+ // Injecting Blocs to the widget tree
+ return MultiBlocProvider(
+ providers: [
+ BlocProvider(
+ create: (_) => L10nCubit(),
+ ),
+ BlocProvider(
+ create: (_) => ThemeCubit(),
+ ),
+ BlocProvider(
+ create: (_) => PasswordHistoryCubit(),
+ ),
+ BlocProvider(
+ create: (_) => GeneratePasswordCubit(
+ generatePasswordRepository: GeneratePasswordRepositoryImpl(),
+ )..generatePassword(),
+ ),
+ ],
+ child: BlocBuilder(
+ builder: (context, l10nState) {
+ return BlocBuilder(
+ builder: (context, themeState) {
+ return MaterialApp.router(
+ debugShowCheckedModeBanner: false,
+ title: StringConstants.appName,
+
+ // Theme
+ theme: AppThemeLight().theme,
+ darkTheme: AppThemeDark().theme,
+ themeMode: themeState.themeMode,
+
+ // Localization
+ locale: l10nState.locale,
+ supportedLocales: AppLocalizations.supportedLocales,
+ localizationsDelegates: const [
+ ...AppLocalizations.localizationsDelegates,
+ LocaleNamesLocalizationsDelegate(),
+ ],
+
+ // Routing
+ routerDelegate: _appRouter.delegate(),
+ routeInformationParser: _appRouter.defaultRouteParser(),
+
+ builder: (context, child) => MediaQuery(
+ // Disables font scaling and bold text
+ data: context.mediaQuery.copyWith(boldText: false, textScaler: TextScaler.noScaling),
+ child: child!,
+ ),
+ );
+ },
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart
new file mode 100644
index 0000000..737cf25
--- /dev/null
+++ b/lib/bootstrap.dart
@@ -0,0 +1,57 @@
+import 'dart:async';
+
+import 'package:firebase_core/firebase_core.dart';
+import 'package:firebase_crashlytics/firebase_crashlytics.dart';
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_native_splash/flutter_native_splash.dart';
+import 'package:hive_flutter/hive_flutter.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+import 'package:password_generator/app/env/env.dart';
+import 'package:password_generator/core/clients/cache/cache_migration_client.dart';
+import 'package:password_generator/core/utils/encryption/encryption_utils.dart';
+import 'package:password_generator/core/utils/logger/logger_utils.dart';
+import 'package:password_generator/core/utils/package_info/package_info_utils.dart';
+import 'package:password_generator/firebase_options.dart';
+import 'package:path_provider/path_provider.dart';
+
+Future bootstrap({required FutureOr Function() builder}) async {
+ WidgetsFlutterBinding.ensureInitialized();
+ FlutterNativeSplash();
+ await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
+ await FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(kReleaseMode);
+ // Register error handlers. For more info, see:
+ // https://docs.flutter.dev/testing/errors
+ // Pass all uncaught Flutter framework exceptions to Crashlytics
+ FlutterError.onError = (FlutterErrorDetails details) {
+ FirebaseCrashlytics.instance.recordFlutterError(details);
+ LoggerUtils.instance.logFatalError(details.exceptionAsString(), details.stack);
+ };
+ // Pass all uncaught asynchronous errors that aren't handled by the Flutter framework to Crashlytics
+ PlatformDispatcher.instance.onError = (error, stack) {
+ FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
+ LoggerUtils.instance.logFatalError(error.toString(), stack);
+ return true;
+ };
+
+ await Future.wait([
+ Hive.initFlutter(),
+ PackageInfoUtils.init(),
+ SystemChrome.setPreferredOrientations(
+ [DeviceOrientation.portraitUp],
+ ),
+ ]);
+
+ final encryptionKey = EncryptionUtils.generateEncryptionKeyFromSecretKey(Env.secretKey);
+ final cacheMigrationClient = CacheMigrationClient();
+ await cacheMigrationClient.migrate(encryptionKey: encryptionKey);
+
+ // Initialize Hydrated Bloc
+ HydratedBloc.storage = await HydratedStorage.build(
+ storageDirectory: await getApplicationDocumentsDirectory(),
+ encryptionCipher: HydratedAesCipher(encryptionKey),
+ );
+
+ runApp(await builder());
+}
diff --git a/lib/core/clients/cache/cache_migration_client.dart b/lib/core/clients/cache/cache_migration_client.dart
new file mode 100644
index 0000000..0350d02
--- /dev/null
+++ b/lib/core/clients/cache/cache_migration_client.dart
@@ -0,0 +1,86 @@
+import 'package:hive_flutter/hive_flutter.dart';
+import 'package:password_generator/app/constants/cache_constants.dart';
+import 'package:password_generator/core/utils/logger/logger_utils.dart';
+
+enum MigrationStatus {
+ completed(true),
+ notCompleted(false);
+
+ const MigrationStatus(this.value);
+
+ final bool value;
+}
+
+class CacheMigrationClient {
+ Future migrate({required List encryptionKey}) async {
+ try {
+ final hasHydratedBox = await _boxExists(CacheConstants.hydratedBox);
+ final migrationStatus = await _getMigrationStatus();
+
+ if (hasHydratedBox && migrationStatus == MigrationStatus.notCompleted) {
+ await _migrateToEncryptedBox(
+ hydratedBoxName: CacheConstants.hydratedBox,
+ tempBoxName: CacheConstants.tempBox,
+ encryptionKey: encryptionKey,
+ );
+ } else {
+ await _setMigrationStatus(MigrationStatus.completed);
+ }
+ } catch (e) {
+ LoggerUtils.instance.logError('Error during migration: $e');
+ }
+ }
+
+ Future _boxExists(String boxName) async {
+ return Hive.boxExists(boxName);
+ }
+
+ Future _setMigrationStatus(MigrationStatus status) async {
+ final migrationBox = await Hive.openBox(CacheConstants.migrationBox);
+ await migrationBox.put(CacheConstants.migrationCompleted, status.value);
+ }
+
+ Future _getMigrationStatus() async {
+ final migrationBox = await Hive.openBox(CacheConstants.migrationBox);
+ final migrationCompleted = migrationBox.get(CacheConstants.migrationCompleted);
+ return migrationCompleted == true ? MigrationStatus.completed : MigrationStatus.notCompleted;
+ }
+
+ Future _migrateToEncryptedBox({
+ required String hydratedBoxName,
+ required String tempBoxName,
+ required List encryptionKey,
+ }) async {
+ // Open the existing hydrated box.
+ final oldHydratedBox = await Hive.openBox(hydratedBoxName);
+ // Create a new temporary box to hold the data from the hydrated box
+ final tempBox = await Hive.openBox(tempBoxName);
+
+ // Migrate data from the existing box to the temporary box
+ for (final key in oldHydratedBox.keys) {
+ final value = oldHydratedBox.get(key);
+ await tempBox.put(key, value);
+ }
+ // Delete the old hydrated box from the disk
+ await oldHydratedBox.deleteFromDisk();
+
+ // Open a new hydrated box with the given encryption key
+ final newHydratedBox = await Hive.openBox(
+ hydratedBoxName,
+ encryptionCipher: HiveAesCipher(encryptionKey),
+ );
+ // Migrate the data from the temporary box to the new encrypted box
+ for (final key in tempBox.keys) {
+ final value = tempBox.get(key);
+ await newHydratedBox.put(key, value);
+ }
+ // Complete the migration by closing the new box, deleting the temp box, and updating the migration status
+ await Future.wait(
+ [
+ newHydratedBox.close(),
+ tempBox.deleteFromDisk(),
+ _setMigrationStatus(MigrationStatus.completed),
+ ],
+ );
+ }
+}
diff --git a/lib/core/utils/encryption/encryption_utils.dart b/lib/core/utils/encryption/encryption_utils.dart
new file mode 100644
index 0000000..def1b01
--- /dev/null
+++ b/lib/core/utils/encryption/encryption_utils.dart
@@ -0,0 +1,10 @@
+import 'dart:convert';
+import 'package:crypto/crypto.dart';
+
+abstract final class EncryptionUtils {
+ EncryptionUtils._();
+
+ static List generateEncryptionKeyFromSecretKey(String password) {
+ return sha256.convert(utf8.encode(password)).bytes;
+ }
+}
diff --git a/lib/core/utils/logger/logger_utils.dart b/lib/core/utils/logger/logger_utils.dart
new file mode 100644
index 0000000..7133dd9
--- /dev/null
+++ b/lib/core/utils/logger/logger_utils.dart
@@ -0,0 +1,32 @@
+// ignore_for_file: prefer_constructors_over_static_methods
+
+import 'package:logger/logger.dart';
+
+class LoggerUtils {
+ LoggerUtils._();
+
+ static LoggerUtils? _instance;
+
+ static LoggerUtils get instance {
+ _instance ??= LoggerUtils._();
+ return _instance!;
+ }
+
+ final Logger _logger = Logger(printer: PrettyPrinter(stackTraceBeginIndex: 2));
+
+ void logInfo(String message) {
+ _logger.i(message);
+ }
+
+ void logWarning(String message) {
+ _logger.w(message);
+ }
+
+ void logError(String message) {
+ _logger.e(message);
+ }
+
+ void logFatalError(String message, StackTrace? stackTrace) {
+ _logger.f(message, stackTrace: stackTrace);
+ }
+}
diff --git a/lib/core/utils/package_info/package_info_utils.dart b/lib/core/utils/package_info/package_info_utils.dart
index 40b4da2..35d7db0 100644
--- a/lib/core/utils/package_info/package_info_utils.dart
+++ b/lib/core/utils/package_info/package_info_utils.dart
@@ -1,6 +1,8 @@
import 'package:package_info_plus/package_info_plus.dart';
abstract final class PackageInfoUtils {
+ PackageInfoUtils._();
+
static late final PackageInfo _packageInfo;
static Future init() async {
diff --git a/lib/core/utils/rate_app/rate_app_utils.dart b/lib/core/utils/rate_app/rate_app_utils.dart
index e1a8018..3ab72c1 100644
--- a/lib/core/utils/rate_app/rate_app_utils.dart
+++ b/lib/core/utils/rate_app/rate_app_utils.dart
@@ -1,6 +1,8 @@
import 'package:in_app_review/in_app_review.dart';
abstract final class RateAppUtils {
+ RateAppUtils._();
+
static Future rateApp() async {
final inAppReview = InAppReview.instance;
diff --git a/lib/core/utils/share_app/share_app_utils.dart b/lib/core/utils/share_app/share_app_utils.dart
index 525ada8..2cbc4bc 100644
--- a/lib/core/utils/share_app/share_app_utils.dart
+++ b/lib/core/utils/share_app/share_app_utils.dart
@@ -2,6 +2,8 @@ import 'package:password_generator/app/constants/string_constants.dart';
import 'package:share_plus/share_plus.dart';
abstract final class ShareAppUtils {
+ ShareAppUtils._();
+
static Future shareApp() async {
await Share.share(StringConstants.googlePlayUrl);
}
diff --git a/lib/core/utils/snackbar/snackbar_utils.dart b/lib/core/utils/snackbar/snackbar_utils.dart
index 56ccc4c..cd158c4 100644
--- a/lib/core/utils/snackbar/snackbar_utils.dart
+++ b/lib/core/utils/snackbar/snackbar_utils.dart
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:password_generator/core/extensions/context_extensions.dart';
abstract final class SnackbarUtils {
+ SnackbarUtils._();
+
static void showSnackbar({required BuildContext context, required String message}) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
diff --git a/lib/core/utils/url_launcher/url_launcher_utils.dart b/lib/core/utils/url_launcher/url_launcher_utils.dart
index ccef5c6..f9ed579 100644
--- a/lib/core/utils/url_launcher/url_launcher_utils.dart
+++ b/lib/core/utils/url_launcher/url_launcher_utils.dart
@@ -1,6 +1,8 @@
import 'package:url_launcher/url_launcher_string.dart';
abstract final class UrlLauncherUtils {
+ UrlLauncherUtils._();
+
static Future launchUrlFromString({required String url}) async {
final isLaunched = await launchUrlString(url);
return isLaunched;
diff --git a/lib/features/generate_password/data/model/password_settings.freezed.dart b/lib/features/generate_password/data/model/password_settings.freezed.dart
index 43185e4..85b4026 100644
--- a/lib/features/generate_password/data/model/password_settings.freezed.dart
+++ b/lib/features/generate_password/data/model/password_settings.freezed.dart
@@ -12,7 +12,7 @@ part of 'password_settings.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$PasswordSettings {
@@ -171,7 +171,7 @@ class _$PasswordSettingsImpl extends _PasswordSettings {
}
@override
- bool operator ==(dynamic other) {
+ bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PasswordSettingsImpl &&
diff --git a/lib/features/generate_password/presentation/cubit/generate_password_cubit.freezed.dart b/lib/features/generate_password/presentation/cubit/generate_password_cubit.freezed.dart
index 0e21670..a3746d6 100644
--- a/lib/features/generate_password/presentation/cubit/generate_password_cubit.freezed.dart
+++ b/lib/features/generate_password/presentation/cubit/generate_password_cubit.freezed.dart
@@ -12,7 +12,7 @@ part of 'generate_password_cubit.dart';
T _$identity(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
- 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+ 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$GeneratePasswordState {
@@ -150,7 +150,7 @@ class _$GeneratePasswordStateImpl implements _GeneratePasswordState {
}
@override
- bool operator ==(dynamic other) {
+ bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$GeneratePasswordStateImpl &&
diff --git a/lib/main.dart b/lib/main.dart
index 467709c..b2de0d9 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,101 +1,6 @@
-import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_localized_locales/flutter_localized_locales.dart';
-import 'package:flutter_native_splash/flutter_native_splash.dart';
-import 'package:hydrated_bloc/hydrated_bloc.dart';
-import 'package:password_generator/app/constants/string_constants.dart';
-import 'package:password_generator/app/l10n/cubit/l10n_cubit.dart';
-import 'package:password_generator/app/l10n/extensions/app_l10n_extensions.dart';
-import 'package:password_generator/app/router/app_router.dart';
-import 'package:password_generator/app/theme/cubit/theme_cubit.dart';
-import 'package:password_generator/app/theme/dark/app_theme_dark.dart';
-import 'package:password_generator/app/theme/light/app_theme_light.dart';
-import 'package:password_generator/core/extensions/context_extensions.dart';
-import 'package:password_generator/core/utils/package_info/package_info_utils.dart';
-import 'package:password_generator/features/generate_password/data/repository/generate_password_repository.dart';
-import 'package:password_generator/features/generate_password/presentation/cubit/generate_password_cubit.dart';
-import 'package:password_generator/features/password_history/cubit/password_history_cubit.dart';
-import 'package:path_provider/path_provider.dart';
+import 'package:password_generator/app/view/app.dart';
+import 'package:password_generator/bootstrap.dart';
Future main() async {
- WidgetsFlutterBinding.ensureInitialized();
- // Initialize Flutter Native Splash
- FlutterNativeSplash();
- // Initialize Hydrated Bloc
- HydratedBloc.storage = await HydratedStorage.build(
- storageDirectory: await getApplicationDocumentsDirectory(),
- );
- // Initialize PackageInfoPlus
- await PackageInfoUtils.init();
- // Set Screen Orientation
- await SystemChrome.setPreferredOrientations(
- [DeviceOrientation.portraitUp],
- );
-
- runApp(PasswordGenerator());
-}
-
-class PasswordGenerator extends StatelessWidget {
- PasswordGenerator({super.key});
-
- final _appRouter = AppRouter();
-
- @override
- Widget build(BuildContext context) {
- // Injecting Blocs to the widget tree
- return MultiBlocProvider(
- providers: [
- BlocProvider(
- create: (_) => L10nCubit(),
- ),
- BlocProvider(
- create: (_) => ThemeCubit(),
- ),
- BlocProvider(
- create: (_) => PasswordHistoryCubit(),
- ),
- BlocProvider(
- create: (_) => GeneratePasswordCubit(
- generatePasswordRepository: GeneratePasswordRepositoryImpl(),
- )..generatePassword(),
- ),
- ],
- child: BlocBuilder(
- builder: (context, l10nState) {
- return BlocBuilder(
- builder: (context, themeState) {
- return MaterialApp.router(
- debugShowCheckedModeBanner: false,
- title: StringConstants.appName,
-
- // Theme
- theme: AppThemeLight().theme,
- darkTheme: AppThemeDark().theme,
- themeMode: themeState.themeMode,
-
- // Localization
- locale: l10nState.locale,
- supportedLocales: AppLocalizations.supportedLocales,
- localizationsDelegates: const [
- ...AppLocalizations.localizationsDelegates,
- LocaleNamesLocalizationsDelegate(),
- ],
-
- // Routing
- routerDelegate: _appRouter.delegate(),
- routeInformationParser: _appRouter.defaultRouteParser(),
-
- builder: (context, child) => MediaQuery(
- // Disables font scaling and bold text
- data: context.mediaQuery.copyWith(boldText: false, textScaler: TextScaler.noScaling),
- child: child!,
- ),
- );
- },
- );
- },
- ),
- );
- }
+ await bootstrap(builder: App.new);
}
diff --git a/pubspec.lock b/pubspec.lock
index b6cf10a..8801773 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,18 +5,26 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
- sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
+ sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
url: "https://pub.dev"
source: hosted
- version: "64.0.0"
+ version: "67.0.0"
+ _flutterfire_internals:
+ dependency: transitive
+ description:
+ name: _flutterfire_internals
+ sha256: "554f148e71e9e016d9c04d4af6b103ca3f74a1ceed7d7307b70a0f41e991eb77"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.26"
analyzer:
dependency: transitive
description:
name: analyzer
- sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
+ sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
url: "https://pub.dev"
source: hosted
- version: "6.2.0"
+ version: "6.4.1"
ansicolor:
dependency: transitive
description:
@@ -29,10 +37,10 @@ packages:
dependency: transitive
description:
name: archive
- sha256: "7e0d52067d05f2e0324268097ba723b71cb41ac8a6a2b24d1edf9c536b987b03"
+ sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
url: "https://pub.dev"
source: hosted
- version: "3.4.6"
+ version: "3.4.10"
args:
dependency: transitive
description:
@@ -53,10 +61,10 @@ packages:
dependency: "direct main"
description:
name: auto_route
- sha256: "82f8df1d177416bc6b7a449127d0270ff1f0f633a91f2ceb7a85d4f07c3affa1"
+ sha256: eb33554581a0a4aa7e6da0f13a44291a55bf71359012f1d9feb41634ff908ff8
url: "https://pub.dev"
source: hosted
- version: "7.8.4"
+ version: "7.9.2"
auto_route_generator:
dependency: "direct dev"
description:
@@ -69,10 +77,10 @@ packages:
dependency: transitive
description:
name: bloc
- sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49"
+ sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e
url: "https://pub.dev"
source: hosted
- version: "8.1.2"
+ version: "8.1.3"
boolean_selector:
dependency: transitive
description:
@@ -101,34 +109,34 @@ packages:
dependency: transitive
description:
name: build_daemon
- sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
+ sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1"
url: "https://pub.dev"
source: hosted
- version: "4.0.0"
+ version: "4.0.1"
build_resolvers:
dependency: transitive
description:
name: build_resolvers
- sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8"
+ sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
url: "https://pub.dev"
source: hosted
- version: "2.4.1"
+ version: "2.4.2"
build_runner:
dependency: "direct dev"
description:
name: build_runner
- sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b"
+ sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21"
url: "https://pub.dev"
source: hosted
- version: "2.4.7"
+ version: "2.4.8"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
- sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185
+ sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799"
url: "https://pub.dev"
source: hosted
- version: "7.2.11"
+ version: "7.3.0"
built_collection:
dependency: transitive
description:
@@ -141,10 +149,10 @@ packages:
dependency: transitive
description:
name: built_value
- sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e"
+ sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e
url: "https://pub.dev"
source: hosted
- version: "8.7.0"
+ version: "8.9.1"
characters:
dependency: transitive
description:
@@ -165,10 +173,10 @@ packages:
dependency: transitive
description:
name: cli_util
- sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
+ sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
url: "https://pub.dev"
source: hosted
- version: "0.4.0"
+ version: "0.4.1"
clock:
dependency: transitive
description:
@@ -181,10 +189,10 @@ packages:
dependency: transitive
description:
name: code_builder
- sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
+ sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
url: "https://pub.dev"
source: hosted
- version: "4.7.0"
+ version: "4.10.0"
collection:
dependency: transitive
description:
@@ -205,12 +213,12 @@ packages:
dependency: transitive
description:
name: cross_file
- sha256: "445db18de832dba8d851e287aff8ccf169bed30d2e94243cb54c7d2f1ed2142c"
+ sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
url: "https://pub.dev"
source: hosted
- version: "0.3.3+6"
+ version: "0.3.4+1"
crypto:
- dependency: transitive
+ dependency: "direct main"
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
@@ -229,10 +237,26 @@ packages:
dependency: transitive
description:
name: dart_style
- sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334
+ sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
url: "https://pub.dev"
source: hosted
- version: "2.3.3"
+ version: "2.3.6"
+ envied:
+ dependency: "direct main"
+ description:
+ name: envied
+ sha256: dab29e21452c3d57ec10889d96b06b4a006b01375d4df10b33c9704800c208c4
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.5.3"
+ envied_generator:
+ dependency: "direct dev"
+ description:
+ name: envied_generator
+ sha256: b8655d5cb39b4d1d449a79ff6f1367b252c23955ff17ec7c03aacdff938598bd
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.5.3"
fake_async:
dependency: transitive
description:
@@ -245,10 +269,10 @@ packages:
dependency: transitive
description:
name: ffi
- sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
+ sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.2"
file:
dependency: transitive
description:
@@ -257,6 +281,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
+ firebase_core:
+ dependency: "direct main"
+ description:
+ name: firebase_core
+ sha256: "67bf0d5fd78f12f51c6b54a72f6141314136a1a90e98b1b7c45e7fac883254ed"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.27.1"
+ firebase_core_platform_interface:
+ dependency: transitive
+ description:
+ name: firebase_core_platform_interface
+ sha256: c437ae5d17e6b5cc7981cf6fd458a5db4d12979905f9aafd1fea930428a9fe63
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.0.0"
+ firebase_core_web:
+ dependency: transitive
+ description:
+ name: firebase_core_web
+ sha256: "5377eaac3b9fe8aaf22638d87f92b62784f23572e132dfc029195e84d6cb37de"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.12.0"
+ firebase_crashlytics:
+ dependency: "direct main"
+ description:
+ name: firebase_crashlytics
+ sha256: cf120df5b473f5f8cd24f9de663edc8aed3a1888d29d805076be0448bdee249e
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.4.19"
+ firebase_crashlytics_platform_interface:
+ dependency: transitive
+ description:
+ name: firebase_crashlytics_platform_interface
+ sha256: "99656cc39228e8f2b845cddb4d43307bb44294a03e7d00b4d8e35536889bc65c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.6.26"
fixnum:
dependency: transitive
description:
@@ -274,10 +338,10 @@ packages:
dependency: "direct main"
description:
name: flutter_bloc
- sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae
+ sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
url: "https://pub.dev"
source: hosted
- version: "8.1.3"
+ version: "8.1.4"
flutter_launcher_icons:
dependency: "direct main"
description:
@@ -303,10 +367,10 @@ packages:
dependency: "direct main"
description:
name: flutter_native_splash
- sha256: "141b20f15a2c4fe6e33c49257ca1bc114fc5c500b04fcbc8d75016bb86af672f"
+ sha256: edf39bcf4d74aca1eb2c1e43c3e445fd9f494013df7f0da752fefe72020eedc0
url: "https://pub.dev"
source: hosted
- version: "2.3.8"
+ version: "2.4.0"
flutter_test:
dependency: "direct dev"
description: flutter
@@ -329,10 +393,10 @@ packages:
dependency: "direct dev"
description:
name: freezed
- sha256: "21bf2825311de65501d22e563e3d7605dff57fb5e6da982db785ae5372ff018a"
+ sha256: "57247f692f35f068cae297549a46a9a097100685c6780fe67177503eea5ed4e5"
url: "https://pub.dev"
source: hosted
- version: "2.4.5"
+ version: "2.4.7"
freezed_annotation:
dependency: "direct main"
description:
@@ -373,6 +437,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.3"
+ hive_flutter:
+ dependency: "direct main"
+ description:
+ name: hive_flutter
+ sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
html:
dependency: transitive
description:
@@ -385,10 +457,10 @@ packages:
dependency: transitive
description:
name: http
- sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
+ sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.2.1"
http_multi_server:
dependency: transitive
description:
@@ -409,26 +481,26 @@ packages:
dependency: "direct main"
description:
name: hydrated_bloc
- sha256: "24994e61f64904d911683cce1a31dc4ef611619da5253f1de2b7b8fc6f79a118"
+ sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d"
url: "https://pub.dev"
source: hosted
- version: "9.1.2"
+ version: "9.1.4"
image:
dependency: transitive
description:
name: image
- sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271"
+ sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
url: "https://pub.dev"
source: hosted
- version: "4.1.3"
+ version: "4.1.7"
in_app_review:
dependency: "direct main"
description:
name: in_app_review
- sha256: "41ec6f30427ab09eb6ae1c85c4a2a624a145fc5d726f023de4d97170ec9e5466"
+ sha256: "99869244d09adc76af16bf8fd731dd13cef58ecafd5917847589c49f378cbb30"
url: "https://pub.dev"
source: hosted
- version: "2.0.8"
+ version: "2.0.9"
in_app_review_platform_interface:
dependency: transitive
description:
@@ -493,6 +565,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
+ logger:
+ dependency: "direct main"
+ description:
+ name: logger
+ sha256: "8c94b8c219e7e50194efc8771cd0e9f10807d8d3e219af473d89b06cc2ee4e04"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
logging:
dependency: transitive
description:
@@ -529,10 +609,10 @@ packages:
dependency: transitive
description:
name: mime
- sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
+ sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
url: "https://pub.dev"
source: hosted
- version: "1.0.4"
+ version: "1.0.5"
nested:
dependency: transitive
description:
@@ -553,10 +633,10 @@ packages:
dependency: "direct main"
description:
name: package_info_plus
- sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
+ sha256: cb44f49b6e690fa766f023d5b22cac6b9affe741dd792b6ac7ad4fabe0d7b097
url: "https://pub.dev"
source: hosted
- version: "5.0.1"
+ version: "6.0.0"
package_info_plus_platform_interface:
dependency: transitive
description:
@@ -577,26 +657,26 @@ packages:
dependency: "direct main"
description:
name: path_provider
- sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
+ sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
- sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
+ sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
url: "https://pub.dev"
source: hosted
- version: "2.2.1"
+ version: "2.2.2"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
- sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
+ sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
url: "https://pub.dev"
source: hosted
- version: "2.3.1"
+ version: "2.3.2"
path_provider_linux:
dependency: transitive
description:
@@ -609,10 +689,10 @@ packages:
dependency: transitive
description:
name: path_provider_platform_interface
- sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
@@ -633,26 +713,26 @@ packages:
dependency: transitive
description:
name: platform
- sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
+ sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
url: "https://pub.dev"
source: hosted
- version: "3.1.3"
+ version: "3.1.4"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
- sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.dev"
source: hosted
- version: "2.1.6"
+ version: "2.1.8"
pointycastle:
dependency: transitive
description:
name: pointycastle
- sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
+ sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
url: "https://pub.dev"
source: hosted
- version: "3.7.3"
+ version: "3.7.4"
pool:
dependency: transitive
description:
@@ -665,10 +745,10 @@ packages:
dependency: transitive
description:
name: provider
- sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
+ sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
url: "https://pub.dev"
source: hosted
- version: "6.0.5"
+ version: "6.1.2"
pub_semver:
dependency: transitive
description:
@@ -685,22 +765,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.3"
+ recase:
+ dependency: transitive
+ description:
+ name: recase
+ sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.0"
share_plus:
dependency: "direct main"
description:
name: share_plus
- sha256: f74fc3f1cbd99f39760182e176802f693fa0ec9625c045561cfad54681ea93dd
+ sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
url: "https://pub.dev"
source: hosted
- version: "7.2.1"
+ version: "7.2.2"
share_plus_platform_interface:
dependency: transitive
description:
name: share_plus_platform_interface
- sha256: df08bc3a07d01f5ea47b45d03ffcba1fa9cd5370fb44b3f38c70e42cced0f956
+ sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496"
url: "https://pub.dev"
source: hosted
- version: "3.3.1"
+ version: "3.4.0"
shelf:
dependency: transitive
description:
@@ -726,10 +814,10 @@ packages:
dependency: transitive
description:
name: source_gen
- sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16
+ sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
url: "https://pub.dev"
source: hosted
- version: "1.4.0"
+ version: "1.5.0"
source_span:
dependency: transitive
description:
@@ -782,10 +870,10 @@ packages:
dependency: transitive
description:
name: synchronized
- sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
+ sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
url: "https://pub.dev"
source: hosted
- version: "3.1.0"
+ version: "3.1.0+1"
term_glyph:
dependency: transitive
description:
@@ -830,34 +918,34 @@ packages:
dependency: "direct main"
description:
name: url_launcher
- sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86
+ sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e"
url: "https://pub.dev"
source: hosted
- version: "6.2.2"
+ version: "6.2.5"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
- sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def"
+ sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745
url: "https://pub.dev"
source: hosted
- version: "6.2.0"
+ version: "6.3.0"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
- sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a"
+ sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5"
url: "https://pub.dev"
source: hosted
- version: "6.2.0"
+ version: "6.2.5"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
- sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd"
+ sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811
url: "https://pub.dev"
source: hosted
- version: "3.1.0"
+ version: "3.1.1"
url_launcher_macos:
dependency: transitive
description:
@@ -870,34 +958,34 @@ packages:
dependency: transitive
description:
name: url_launcher_platform_interface
- sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50"
+ sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.3.2"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
- sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2"
+ sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d"
url: "https://pub.dev"
source: hosted
- version: "2.2.0"
+ version: "2.3.0"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
- sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc"
+ sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7
url: "https://pub.dev"
source: hosted
- version: "3.1.0"
+ version: "3.1.1"
uuid:
dependency: transitive
description:
name: uuid
- sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7
+ sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
url: "https://pub.dev"
source: hosted
- version: "4.1.0"
+ version: "4.3.3"
vector_math:
dependency: transitive
description:
@@ -934,34 +1022,34 @@ packages:
dependency: transitive
description:
name: web
- sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
+ sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
url: "https://pub.dev"
source: hosted
- version: "0.3.0"
+ version: "0.5.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
- sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
+ sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2"
url: "https://pub.dev"
source: hosted
- version: "2.4.0"
+ version: "2.4.4"
win32:
dependency: transitive
description:
name: win32
- sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
+ sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
url: "https://pub.dev"
source: hosted
- version: "5.0.9"
+ version: "5.3.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
- sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
+ sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
url: "https://pub.dev"
source: hosted
- version: "1.0.3"
+ version: "1.0.4"
xml:
dependency: transitive
description:
@@ -979,5 +1067,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
- dart: ">=3.2.0 <4.0.0"
- flutter: ">=3.13.0"
+ dart: ">=3.3.0 <4.0.0"
+ flutter: ">=3.19.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 25ab654..75e295b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -10,14 +10,24 @@ dependencies:
#state management
flutter_bloc: ^8.1.3
- hydrated_bloc: ^9.1.2
+ hydrated_bloc: ^9.1.4
+
+ # caching
+ hive_flutter: ^1.1.0
+
+ # firebase
+ firebase_core: ^2.27.1
+ firebase_crashlytics: ^3.4.19
#utility
+ crypto: ^3.0.3
+ envied: ^0.5.3
+ logger: ^2.2.0
share_plus: ^7.2.1
in_app_review: ^2.0.8
url_launcher: ^6.2.2
path_provider: ^2.1.1
- package_info_plus: ^5.0.1
+ package_info_plus: ^6.0.0
#localization
flutter_localizations:
@@ -47,6 +57,7 @@ dev_dependencies:
#code gen
freezed: ^2.4.5
build_runner: ^2.4.7
+ envied_generator: ^0.5.3
auto_route_generator: ^7.3.2
flutter_launcher_icons: