diff --git a/assets/main/app_bottom.png b/assets/main/app_bottom.png new file mode 100644 index 0000000..eb3fa7c Binary files /dev/null and b/assets/main/app_bottom.png differ diff --git a/assets/main/space_img.png b/assets/main/space_img.png new file mode 100644 index 0000000..e18f273 Binary files /dev/null and b/assets/main/space_img.png differ diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 352a13f..b2219a6 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0664D5550661B87DEBBC6817 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D45C6F829A78A6C8C24E02CC /* Pods_RunnerTests.framework */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; @@ -15,6 +16,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 */; }; + E26C8989D0C68D5DB464158B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA175B3A0D3E916AC27A0A44 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -41,11 +43,16 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 050052E57234D282C9FE0BF8 /* 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 = ""; }; + 0B14B00D5159CDD6C80C9153 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2041FD845ED16692F904D1BB /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 30CA92C31651997BD3BC0264 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 5AE4FDA3B70EE917ED395F4E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 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 = ""; }; 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -57,6 +64,9 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CA175B3A0D3E916AC27A0A44 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D45C6F829A78A6C8C24E02CC /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FF11067BF9CC9B4EB2B7FCD6 /* 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 = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,6 +74,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E26C8989D0C68D5DB464158B /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D1FADB0038EE039DF312CBE3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0664D5550661B87DEBBC6817 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -96,6 +115,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + A80C4EF8AC301ED587D8086F /* Pods */, + A1A9B7413C55A916DA829947 /* Frameworks */, ); sourceTree = ""; }; @@ -124,6 +145,29 @@ path = Runner; sourceTree = ""; }; + A1A9B7413C55A916DA829947 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CA175B3A0D3E916AC27A0A44 /* Pods_Runner.framework */, + D45C6F829A78A6C8C24E02CC /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + A80C4EF8AC301ED587D8086F /* Pods */ = { + isa = PBXGroup; + children = ( + FF11067BF9CC9B4EB2B7FCD6 /* Pods-Runner.debug.xcconfig */, + 050052E57234D282C9FE0BF8 /* Pods-Runner.release.xcconfig */, + 30CA92C31651997BD3BC0264 /* Pods-Runner.profile.xcconfig */, + 2041FD845ED16692F904D1BB /* Pods-RunnerTests.debug.xcconfig */, + 0B14B00D5159CDD6C80C9153 /* Pods-RunnerTests.release.xcconfig */, + 5AE4FDA3B70EE917ED395F4E /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -131,8 +175,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 101AA165AFB75325FBE6878F /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + D1FADB0038EE039DF312CBE3 /* Frameworks */, ); buildRules = ( ); @@ -148,12 +194,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 96179195EAB296DE04B2BB0F /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 6C235EC4F300ECD7625CDB9A /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -225,6 +273,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 101AA165AFB75325FBE6878F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -241,6 +311,45 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 6C235EC4F300ECD7625CDB9A /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 96179195EAB296DE04B2BB0F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -383,6 +492,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 2041FD845ED16692F904D1BB /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -400,6 +510,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 0B14B00D5159CDD6C80C9153 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -415,6 +526,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 5AE4FDA3B70EE917ED395F4E /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/lib/common/const/const_color.dart b/lib/common/const/const_color.dart new file mode 100644 index 0000000..f39406c --- /dev/null +++ b/lib/common/const/const_color.dart @@ -0,0 +1,19 @@ + +import 'dart:ui'; + +class ConstColor { + + // #100C08 + static Color themeColor = Color(0xff100C08); + // #EEEEEE + static Color btWhite = Color(0xffEEEEEE); + // #89F011 + static Color btGreen = Color(0xff89F011); + + static Color withValue(String value) { + String colorValue = value.replaceAll('#', ''); + String res = '0xff$colorValue'; + int valueInt = int.parse(res); + return Color(valueInt); + } +} \ No newline at end of file diff --git a/lib/common/const/const_string.dart b/lib/common/const/const_string.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/common/help/app_nav.dart b/lib/common/help/app_nav.dart new file mode 100644 index 0000000..a79da83 --- /dev/null +++ b/lib/common/help/app_nav.dart @@ -0,0 +1,117 @@ +import 'package:get/get.dart'; +import 'package:flutter/material.dart'; + +/// navigator +class AppNav { + /// clear all route + static Future? offAllNamed( + String newRouteName, { + Map? arguments, + RoutePredicate? predicate, + String? tag, + Map? parameters, + }) { + return Get.offAllNamed( + newRouteName, + arguments: arguments, + predicate: predicate, + parameters: {...?parameters}, + ); + } + + static Future? off(Widget page, {arguments, preventDuplicates}) { + return Get.off( + () => page, + arguments: arguments, + preventDuplicates: preventDuplicates ?? false, + ); + } + + static Future? offAll(Widget page, {arguments, preventDuplicates}) { + return Get.offAll(() => page, arguments: arguments); + } + + static Future? offNamed( + String newRouteName, { + arguments, + preventDuplicates, + }) { + return Get.offNamed( + newRouteName, + arguments: arguments, + preventDuplicates: preventDuplicates ?? true, + ); + } + + /// to name + static Future? toNamed( + String newRouteName, { + arguments, + String? tag, + Map? parameters, + }) { + return Get.toNamed( + newRouteName, + arguments: arguments, + parameters: {...?parameters}, + ); + } + + /// to route + static Future? to(Widget page, {arguments, binding}) { + return Get.to( + () => page, + arguments: arguments, + binding: binding, + preventDuplicates: false, + ); + } + + static void _until({String? routeName, T? result}) { + if (result == null) { + Get.back(result: result); + return; + } + // Get.back(result: result); + // + if (routeName == null) { + Get.back(result: result); + return; + } + } + + /// back pre + /// [result] + static void back({T? result, String? routeName}) { + _until(routeName: routeName, result: result); + } + + /// show dialog + static Future showDialog( + Widget child, { + bool barrierDismissible = false, + }) { + return Get.dialog( + Center(child: child), + barrierDismissible: barrierDismissible, + ); + } + + /// show bottom sheet + static Future showBottom( + Widget child, { + Color? safeAreaColor, + + double? borderRadius, + bool isDismissible = false, + bool isScrollControlled = false, + bool? enableDrag, + }) { + return Get.bottomSheet( + child, + isScrollControlled: isScrollControlled, + enableDrag: enableDrag ?? true, + isDismissible: isDismissible, + ); + } +} diff --git a/lib/common/help/help_image.dart b/lib/common/help/help_image.dart new file mode 100644 index 0000000..6116356 --- /dev/null +++ b/lib/common/help/help_image.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; + +class ConstImage { + ConstImage._(); + + /// main + static const String appBottom = "assets/main/app_bottom.png"; + static const String pageBg = "assets/main/page_bg.png"; + static const String btHomeUnsel = "assets/main/bt_home_unsel.png"; + static const String btPlayUnsel = "assets/main/bt_play_unsel.png"; + static const String btCollectUnsel = "assets/main/bt_collect_unsel.png"; + static const String btMineUnsel = "assets/main/bt_mine_unsel.png"; + static const String btHomeSel = "assets/main/bt_home_seled.png"; + static const String btPlaySel = "assets/main/bt_play_seled.png"; + static const String btCollectSel = "assets/main/bt_collect_seled.png"; + static const String btMineSel = "assets/main/bt_mine_seled.png"; + static const String spaceImg = "assets/main/space_img.png"; + + +} + +class HelpImage { + static Widget asset( + String path, { + BoxFit? fit, + double? width, + double? height, + Color? color, + bool isDartData = false, + String? dartPath, + }) { + + return Image.asset( + path, + fit: fit, + width: width, + height: height, + color: color, + ); + } + + static Widget networkRadius( + String path, { + BoxFit? fit, + double? width, + double? height, + BoxShape? shape, + BorderRadius? borderRadius, + Widget? errorWidget, + }) { + return ClipRRect( + borderRadius: borderRadius ?? BorderRadius.circular(3), + child: network( + path, + fit: fit, + width: width, + height: height, + shape: shape, + errorWidget: errorWidget, + ), + ); + } + + /// load network + static Widget network( + String path, { + BoxFit? fit, + double? width, + double? height, + Color? color, + BoxShape? shape, + BorderRadius? borderRadius, + Widget? errorWidget, + }) { + + return FadeInImage.assetNetwork( + placeholder: ConstImage.spaceImg, + image: path, + width: width, height: height, fit: BoxFit.cover, + imageErrorBuilder: (context, error, stackTrace) { + return asset( + ConstImage.spaceImg, + fit: BoxFit.fill, + width: width, height: height + ); + }, + ); + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 244a702..763945d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,145 @@ import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:get/get.dart'; +import 'package:novyronst/root/lib_export.dart'; +import 'package:novyronst/root/root_page.dart'; void main() { - runApp(const MyApp()); + + WidgetsFlutterBinding.ensureInitialized(); + + runApp(const RootApp()); } + + + +class RootApp extends StatefulWidget { + const RootApp({ + super.key, + this.home, + this.locale + }); + + final Widget? home; + final Locale? locale; + + @override + State createState() { + return _RootAppState(); + } +} + +class _RootAppState extends State with WidgetsBindingObserver { + + bool _appInForeground = true; // + + + @override + Widget build(BuildContext context) { + return ScreenUtilInit( + designSize: Size(375, 812), + child: GetMaterialApp( + debugShowCheckedModeBanner: false, + // translations: AppLanguage(), + locale: widget.locale ?? Get.deviceLocale, + fallbackLocale: const Locale('en'), + initialBinding: AppBindings(), + // initialRoute: SkyPages.initial, + // getPages: SkyPages.routes, + theme: ThemeData( + colorScheme: ColorScheme.fromSeed( + seedColor: ConstColor.themeColor, + ), + appBarTheme: AppBarTheme(elevation: 0, centerTitle: true), + splashColor: Colors.transparent, + useMaterial3: true, + scaffoldBackgroundColor: Colors.white, + ), + builder: FlutterSmartDialog.init( + builder: (context, child) { + return MediaQuery( + data: MediaQuery.of( + context, + ).copyWith(textScaler: TextScaler.linear(1.0)), + child: child!, + ); + }, + ), + home: widget.home ?? RootPage(), + onInit: () {}, + ), + ); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + // _startPeriodicOnlineReport(); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + + switch (state) { + case AppLifecycleState.inactive: + case AppLifecycleState.paused: + // 应用进入后台或不活跃状态 + if (_appInForeground) { + print('💛应用不活跃'); + _appInForeground = false; + _onAppPaused(); + } + break; + case AppLifecycleState.resumed: + // 应用回到前台 + if (!_appInForeground) { + print('💚应用活跃'); + _appInForeground = true; + _onAppResumed(); + } + break; + case AppLifecycleState.detached: + case AppLifecycleState.hidden: + break; + } + } + + // 应用进入后台时的处理 + void _onAppPaused() { + try { + // EventClient.eventOLeaveApp(); + } catch (err) { print(err.toString()); } + } + + /// 应用回到前台时的处理 + void _onAppResumed() { + try { + // EventClient.eventEnterApp(); + // EventClient.eventOnline(); + } catch (err) { print(err.toString()); } + } +} + +class AppBindings extends Bindings { + + @override + void dependencies() { + // Get.lazyPut(() => UserController()); + } +} + + + class MyApp extends StatelessWidget { const MyApp({super.key}); @@ -13,110 +149,8 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( - // This is the theme of your application. - // - // TRY THIS: Try running your application with "flutter run". You'll see - // the application has a purple toolbar. Then, without quitting the app, - // try changing the seedColor in the colorScheme below to Colors.green - // and then invoke "hot reload" (save your changes or press the "hot - // reload" button in a Flutter-supported IDE, or press "r" if you used - // the command line to start the app). - // - // Notice that the counter didn't reset back to zero; the application - // state is not lost during the reload. To reset the state, use hot - // restart instead. - // - // This works for code too, not just values: Most code changes can be - // tested with just a hot reload. colorScheme: .fromSeed(seedColor: Colors.deepPurple), ), - home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: .center, - children: [ - const Text('You have pushed the button this many times:'), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), - ); - } -} +} \ No newline at end of file diff --git a/lib/pages/collect/pages/collection_page.dart b/lib/pages/collect/pages/collection_page.dart new file mode 100644 index 0000000..8493b0a --- /dev/null +++ b/lib/pages/collect/pages/collection_page.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class CollectionPage extends StatefulWidget { + const CollectionPage({super.key}); + + @override + State createState() { + return _RootPageState(); + } +} + +class _RootPageState extends State { + + @override + Widget build(BuildContext context) { + return Scaffold(); + } +} \ No newline at end of file diff --git a/lib/pages/first/pages/first_page.dart b/lib/pages/first/pages/first_page.dart new file mode 100644 index 0000000..b655946 --- /dev/null +++ b/lib/pages/first/pages/first_page.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class FirstPage extends StatefulWidget { + const FirstPage({super.key}); + + @override + State createState() { + return _RootPageState(); + } +} + +class _RootPageState extends State { + + @override + Widget build(BuildContext context) { + return Scaffold(); + } +} \ No newline at end of file diff --git a/lib/pages/my/pages/my_page.dart b/lib/pages/my/pages/my_page.dart new file mode 100644 index 0000000..df8f61f --- /dev/null +++ b/lib/pages/my/pages/my_page.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class MyPage extends StatefulWidget { + const MyPage({super.key}); + + @override + State createState() { + return _RootPageState(); + } +} + +class _RootPageState extends State { + + @override + Widget build(BuildContext context) { + return Scaffold(); + } +} \ No newline at end of file diff --git a/lib/pages/play/pages/play_page.dart b/lib/pages/play/pages/play_page.dart new file mode 100644 index 0000000..6c0f24c --- /dev/null +++ b/lib/pages/play/pages/play_page.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; + +class PlayPage extends StatefulWidget { + const PlayPage({super.key}); + + @override + State createState() { + return _RootPageState(); + } +} + +class _RootPageState extends State { + + @override + Widget build(BuildContext context) { + return Scaffold(); + } +} \ No newline at end of file diff --git a/lib/root/lib_export.dart b/lib/root/lib_export.dart new file mode 100644 index 0000000..a875b71 --- /dev/null +++ b/lib/root/lib_export.dart @@ -0,0 +1,7 @@ + +export 'package:novyronst/common/const/const_color.dart'; +export 'package:novyronst/common/const/const_string.dart'; +export 'package:novyronst/common/help/help_image.dart'; + + +export 'package:novyronst/tools/util/app_screen.dart'; \ No newline at end of file diff --git a/lib/root/root_page.dart b/lib/root/root_page.dart new file mode 100644 index 0000000..f52dee0 --- /dev/null +++ b/lib/root/root_page.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; +import 'package:novyronst/common/help/help_image.dart'; +import 'package:novyronst/pages/collect/pages/collection_page.dart'; +import 'package:novyronst/pages/first/pages/first_page.dart'; +import 'package:novyronst/pages/my/pages/my_page.dart'; +import 'package:novyronst/pages/play/pages/play_page.dart'; +import 'package:novyronst/root/lib_export.dart'; +import 'package:novyronst/tools/widgets/extend_widget.dart'; +import 'package:novyronst/tools/widgets/novy_com_widget.dart'; +import 'package:novyronst/tools/widgets/novy_keep_alive.dart'; + +class RootPage extends StatefulWidget { + const RootPage({super.key}); + + @override + State createState() { + return _RootPageState(); + } +} + +class _RootPageState extends State { + + final _pageController = PageController(); + final List _pages = [ + NovyKeepAlive(child: FirstPage()), + NovyKeepAlive(child: PlayPage()), + CollectionPage(), + NovyKeepAlive(child: MyPage()), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Stack( + children: [ + PageView( + physics: const NeverScrollableScrollPhysics(), + controller: _pageController, + children: _pages, + ), + Positioned( + left: 0, right: 0, bottom: 0, + child: SafeArea( + top: false, + child: AppBottomView( + onSelectedIndex: (index) { + _pageController.jumpToPage(index); + }, + ), + ), + ) + ], + ) + ); + } +} + +/// 底部tabbar +class AppBottomView extends StatefulWidget { + const AppBottomView({super.key, + required this.onSelectedIndex, + }); + + final Function(int) onSelectedIndex; + + @override + State createState() { + return _AppBottomViewState(); + } +} + +class _AppBottomViewState extends State { + + final List _unselectedIcons = [ + ConstImage.btHomeUnsel, ConstImage.btPlayUnsel, + ConstImage.btCollectUnsel, ConstImage.btMineUnsel + ]; + final List _selectedIcons = [ + ConstImage.btHomeSel, ConstImage.btPlaySel, + ConstImage.btCollectSel, ConstImage.btMineSel + ]; + final List _titles = ['Home', 'Play', 'Collect', 'Me']; + int _currentIndex = 0; + + @override + Widget build(BuildContext context) { + const double _height = 65; + return Container( + height: _height, + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Stack( + children: [ + HelpImage.asset(ConstImage.appBottom, + width: AppScreen.screenWidth-32, height: _height, + fit: BoxFit.fill, + ), + Positioned.fill( + child: Padding(padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: List.generate(_unselectedIcons.length, (index) { + return _buildTabItem(_titles[index], index, onTap: () { + setState(() { + _currentIndex = index; + }); + widget.onSelectedIndex(index); + + }); + }), + ), + ), + ) + ], + ), + ); + } + + Widget _buildTabItem(String title, int index, {required Function() onTap}) { + String icon = _currentIndex == index ? _selectedIcons[index] : _unselectedIcons[index]; + Color tcolor = _currentIndex == index ? ConstColor.btGreen : ConstColor.btWhite; + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + width: 60, height: 70, + child: Column( + children: [ + HelpImage.asset(icon, width: 32, height: 32), + const SizedBox(height: 2), + NovyText(title, fontSize: 11, + color: tcolor, + ) + ], + ) + ).addInkWell(onTap: onTap); + } +} \ No newline at end of file diff --git a/lib/tools/util/app_screen.dart b/lib/tools/util/app_screen.dart new file mode 100644 index 0000000..fdd62d5 --- /dev/null +++ b/lib/tools/util/app_screen.dart @@ -0,0 +1,51 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +/// AppScreen class +class AppScreen { + static double get screenWidth => _viewSize.width; + static double get screenHeight => _viewSize.height; + // static double get screenWidth => MediaQuery.of(Get.context!).size.width; + // static double get screenHeight => MediaQuery.of(Get.context!).size.height; + + static Size size(BuildContext context) { + return MediaQuery.of(context).size; + } + + static bool get isDebug => kDebugMode; + + static double get statusBarHeight => Get.statusBarHeight / Get.pixelRatio; + + static double get bottomBarHeight => Get.bottomBarHeight / Get.pixelRatio; + + // static double get tabBarHeight => kToolbarHeight; + + static double get navBarHeight => kToolbarHeight + statusBarHeight; + + static bool get isDark => Get.isDarkMode; + + static bool get isAndroid { + return GetPlatform.isAndroid; + } + + static bool get isIos { + return GetPlatform.isIOS; + } + + static Size get _viewSize { + if (Get.context != null) { + return MediaQuery.of(Get.context!).size; + } + + final view = WidgetsBinding.instance.platformDispatcher.views.first; + return view.physicalSize / view.devicePixelRatio; + } + + static double aRatioWidth({double? h, double aspectRatio = 1}) { + h ??= screenHeight; + return screenHeight * 1 / aspectRatio; + } + + static double get keyboardHeight => Get.mediaQuery.viewInsets.bottom; +} diff --git a/lib/tools/widgets/extend_widget.dart b/lib/tools/widgets/extend_widget.dart new file mode 100644 index 0000000..0559a13 --- /dev/null +++ b/lib/tools/widgets/extend_widget.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; + +extension ExtendWidget on Widget { + + Widget addContainer({ + Color? color, + double? height, + double? width, + EdgeInsets? margin, + EdgeInsets? padding, + double? radius, + BorderRadius? borderRadius, + Border? border, + GestureTapCallback? onTap, + AlignmentGeometry? alignment, + Gradient? gradient, + List? boxShadow, + BoxConstraints? constraints, + Matrix4? transform, + Clip clipBehavior = Clip.none, + DecorationImage? image, + BlendMode? backgroundBlendMode, + BoxShape shape = BoxShape.rectangle, + double? minWidth, + double? maxWidth, + double? minHeight, + double? maxHeight, + + /// 打印 widget size 只在 debug 有效 + bool isPrintSize = false, + }) { + return Container( + width: width, + height: height, + margin: margin, + padding: padding, + alignment: alignment, + clipBehavior: clipBehavior, + constraints: + constraints ?? + BoxConstraints( + minWidth: minWidth ?? 0.0, + maxWidth: maxWidth ?? double.infinity, + minHeight: minHeight ?? 0.0, + maxHeight: maxHeight ?? double.infinity, + ), + transform: transform, + decoration: BoxDecoration( + color: color, + boxShadow: boxShadow, + backgroundBlendMode: backgroundBlendMode, + shape: shape, + image: image, + gradient: gradient, + border: border, + borderRadius: radius != null + ? BorderRadius.circular(radius) + : borderRadius, + ), + child: this, + ).addInkWell(onTap: onTap); + } + + Widget addPadding({EdgeInsets? padding}) { + return Padding(padding: padding ?? EdgeInsets.zero, child: this); + } + + /// 在当前Widget外层添加一个Align + /// + /// 通过此方法可以设置控件的对齐方式 + Widget addAlign({AlignmentGeometry alignment = Alignment.centerLeft}) { + return Align(alignment: alignment, child: this); + } + + Widget addCenter() { + return Center(child: this); + } + + /// 在当前Widget外层添加一个GestureDetector + /// + /// 通过此方法可以为控件添加点击事件处理函数 + Widget addGestureDetector({ + GestureTapCallback? onTap, + GestureTapCallback? onDoubleTap, + GestureLongPressCallback? onLongPress, + }) { + return GestureDetector( + onTap: onTap, + onDoubleTap: onDoubleTap, + onLongPress: onLongPress, + child: this, + ); + // return GestureDetectorDebounced( + // onTap: onTap, + // child: this, + // ); + } + + /// 在当前Widget外层添加一个Visibility + /// + /// 通过此方法可以控制控件的显示和隐藏 + Widget addVisibility({bool visible = true}) { + return Visibility(visible: visible, child: this); + } + + + /// 在当前Widget外层添加一个InkWell + /// + /// 通过此方法可以为控件添加点击事件处理函数 + Widget addInkWell({GestureTapCallback? onTap}) { + if (onTap == null) { + return this; + } + return InkWell(onTap: onTap, child: this); + } + + /// 在当前Widget外层添加一个SizedBox + /// + /// 通过此方法可以设置控件的宽高 + Widget addSize({double? width, double? height}) { + return SizedBox(width: width, height: height, child: this); + } + + /// 在当前Widget外层添加一个Opacity + /// + /// 通过此方法可以设置控件的透明度 + Widget addOpacity({double opacity = 1}) { + return Opacity(opacity: opacity, child: this); + } +} + +extension OnRenderObjectWidget on RenderObjectWidget { + SliverPadding addPaddingSliver({EdgeInsets? padding}) { + return SliverPadding(padding: padding ?? EdgeInsets.zero, sliver: this); + } + + DecoratedSliver addDecoratedSliver({ + Color? color, + BorderRadius? borderRadius, + Border? border, + BoxShape? shape, + Gradient? gradient, + List? boxShadow, + EdgeInsets? padding, + }) { + return DecoratedSliver( + decoration: BoxDecoration( + color: color ?? Colors.white, + border: border, + borderRadius: borderRadius, + boxShadow: boxShadow, + gradient: gradient, + shape: shape ?? BoxShape.rectangle, + ), + sliver: addPaddingSliver(padding: padding), + ); + } +} diff --git a/lib/tools/widgets/novy_com_widget.dart b/lib/tools/widgets/novy_com_widget.dart new file mode 100644 index 0000000..0fd1d8c --- /dev/null +++ b/lib/tools/widgets/novy_com_widget.dart @@ -0,0 +1,277 @@ +import 'package:flutter/material.dart'; +import 'package:novyronst/common/const/const_color.dart'; +import 'package:novyronst/common/help/app_nav.dart'; + +import 'extend_widget.dart'; + + +class NovyText extends StatelessWidget { + const NovyText( this.text, { + super.key, + this.color = Colors.white, + this.fontSize = 14, + this.shadow, + this.decoration, + this.decorationColor, + this.textAlign, + this.fontWeight, + this.maxLines, + this.lineHeight, + this.letterSpacing, + this.overflow = TextOverflow.ellipsis, + this.softWrap, + this.fontFamily, + }); + + + final String text; + final Color? color; + final double? fontSize; + final TextDecoration? decoration; + final Color? decorationColor; + final TextAlign? textAlign; + final FontWeight? fontWeight; + final int? maxLines; + final Shadow? shadow; + final double? lineHeight; + final double? letterSpacing; + final TextOverflow? overflow; + final bool? softWrap; + final String? fontFamily; + + + @override + Widget build(BuildContext context) { + final FontWeight resolvedWeight = fontWeight ?? FontWeight.normal; + + return Text(text, style: TextStyle( + fontSize: fontSize, + fontWeight: resolvedWeight, + decoration: decoration, + fontFamily: fontFamily ?? 'Inter', + color: color, + shadows: shadow == null ? null : [shadow!], + decorationColor: decorationColor, + height: lineHeight, + letterSpacing: letterSpacing, + ), maxLines: maxLines, + overflow: overflow, + softWrap: softWrap, + textAlign: textAlign, + ); + } + +} + + + + + + + + + + + + + + + + + + + + + + +class ComConfirmWidget extends StatelessWidget { + + final String? title; + final String? content; + final Widget? contentWidget; + final String? cancelStr, confirmStr; + final double? height; + final Function? onConfirmed; + final Function? onCanceled; + final bool? showCancel; + final bool? clickHideAlert; + + const ComConfirmWidget({ + super.key, + this.title, + this.content, + this.contentWidget, + this.cancelStr, + this.confirmStr, + this.height, + this.onConfirmed, + this.onCanceled, + this.showCancel = true, + this.clickHideAlert = true, + }); + + @override + Widget build(BuildContext context) { + return Container( + height: height ?? 160, + margin: EdgeInsets.only(left: 25, right: 25), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + ), + child: Column( + // mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 15,), + + title==null ? SizedBox() : Padding(padding: EdgeInsets.only(left:15, right: 15, bottom: 5), + child: NovyText(title!, fontSize: 16, color: Colors.black, + ) + ), + const SizedBox(height: 10), + Expanded( + child: Padding(padding: EdgeInsets.only(left:14, right: 14), + child: contentWidget ?? Center( + child: NovyText(content!, + fontSize: 15, color: ConstColor.themeColor, + maxLines: 3), + ), + ) + ), + + const SizedBox(height: 10), + Divider(thickness: 0.6, height: 1), + SizedBox( + height: 44, + child: IntrinsicHeight( + child: showCancel! ? Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + + TextButton(onPressed: () { + Navigator.pop(context); + onCanceled?.call(); + }, + child: Center( + child: NovyText(cancelStr ?? 'Cancel', + color: Colors.grey, fontSize: 14)) + ), + + VerticalDivider(width: 5, thickness: 0.6,), + + TextButton(onPressed: () { + + if (clickHideAlert == true) { + Navigator.pop(context); + } + onConfirmed?.call(); + }, + child: Center( + child:NovyText(confirmStr ?? 'Confirm', + color: ConstColor.themeColor, fontSize: 14)) + ), + ], + ) : TextButton(onPressed: () { + + Navigator.pop(context); + onConfirmed?.call(); + }, + child: Center( + child:NovyText(confirmStr ?? 'Confirm', + color: ConstColor.themeColor, fontSize: 14,)) + ), + ) + ) + ], + ), + ); + } +} + + + + + + + + +class ComSheetWidget extends StatelessWidget { + + final Function(int)? onSelected; + final String? title; + final List items; + final TextAlign? textAlign; + + const ComSheetWidget({super.key, + this.onSelected, + this.title, + this.textAlign = TextAlign.left, + required this.items, + }); + + @override + Widget build(BuildContext context) { + return SafeArea(child: _mainView()); + } + + _mainView() { + return Container( + padding: EdgeInsets.only(top: 10), + height: items.length>5 ? 360 : 40+items.length*47 + 50, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20) + ), + ), + child: _ifElseWidget(), + ); + } + + _ifElseWidget() { + if (title != null) { + return Column( + children: [ + const SizedBox(height: 6), + Text('$title', style: TextStyle( + color: Colors.black, fontSize: 16 + )), + const SizedBox(height: 5), + const Divider(height: 8, thickness: 0.6,), + // Divider(), + const SizedBox(height: 5), + Expanded(child: ListView.separated(itemBuilder: (context, index) { + return _itemCreateer(index); + + }, separatorBuilder: (context, index) { + return Divider( indent: 15, endIndent: 15, thickness: 0.6,); + }, itemCount: items.length)) + ], + ); + } else { + return ListView.separated(itemBuilder: (context, index) { + return _itemCreateer(index); + + }, separatorBuilder: (context, index) { + return Divider(indent: 15, endIndent: 15, thickness: 0.6,); + }, itemCount: items.length); + } + } + + _itemCreateer(int index) { + return SizedBox( + height: 47, + child: Center( + child: Text(items[index], style: TextStyle( + fontSize: 15, color: Colors.black, + )), + ).addInkWell( + onTap: () { + + AppNav.back(); + onSelected?.call(index); + }) + ); + } +} \ No newline at end of file diff --git a/lib/tools/widgets/novy_keep_alive.dart b/lib/tools/widgets/novy_keep_alive.dart new file mode 100644 index 0000000..3ca2dfa --- /dev/null +++ b/lib/tools/widgets/novy_keep_alive.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +/// keep alive +class NovyKeepAlive extends StatefulWidget { + final Widget child; + final bool? wantKeepAlive; + + const NovyKeepAlive( + {super.key, required this.child, this.wantKeepAlive = true}); + + @override + State createState() => _CmKeepAlivePageState(); +} + +class _CmKeepAlivePageState extends State + with AutomaticKeepAliveClientMixin { + @override + Widget build(BuildContext context) { + super.build(context); + return widget.child; + } + + @override + bool get wantKeepAlive => widget.wantKeepAlive!; +} diff --git a/pubspec.lock b/pubspec.lock index a951010..50c91a1 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -97,6 +97,22 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.3" + dio: + dependency: "direct main" + description: + name: dio + sha256: ea2bad3c89a27635ce2d85cce4d6b199da49a5a48ec77b03e45b65a3b90922b0 + url: "https://pub.dev" + source: hosted + version: "5.10.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: dd58dc3861eb36edb13b217efc006a1c21e5bbc341de8c229b85634fa5e362e4 + url: "https://pub.dev" + source: hosted + version: "2.2.0" fake_async: dependency: transitive description: @@ -190,6 +206,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.2" + flutter_smart_dialog: + dependency: "direct main" + description: + name: flutter_smart_dialog + sha256: "18ee3a53e898e4b0c2898e498bb61ab65cedf56f00fc412ac66d986d33e246bf" + url: "https://pub.dev" + source: hosted + version: "5.1.0" flutter_test: dependency: "direct dev" description: flutter @@ -328,6 +352,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" objective_c: dependency: transitive description: @@ -448,6 +480,62 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf + url: "https://pub.dev" + source: hosted + version: "2.5.5" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53 + url: "https://pub.dev" + source: hosted + version: "2.4.23" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" sky_engine: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 1d53528..592ab7e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,6 +23,10 @@ dependencies: get_storage: ^2.1.1 package_info_plus: ^8.3.0 device_info_plus: ^11.5.0 + + dio: ^5.9.2 + shared_preferences: ^2.5.3 + flutter_smart_dialog: ^5.1.0 flutter_secure_storage: ^9.2.4 android_id: ^0.5.1