diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..998e955 --- /dev/null +++ b/.env.sample @@ -0,0 +1 @@ +IPIFY_API_KEY= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0fa6b67..a817e7b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.env.development +.env.production + # Miscellaneous *.class *.log diff --git a/lib/app/modules/home/global/binding.dart b/lib/app/modules/home/global/binding.dart new file mode 100644 index 0000000..0fc2391 --- /dev/null +++ b/lib/app/modules/home/global/binding.dart @@ -0,0 +1,21 @@ + + +import 'package:get/get.dart'; +import 'package:speed_test_app/app/data/providers/speedtest/storage_provider.dart'; +import 'package:speed_test_app/app/data/services/storage/repository.dart'; +import 'package:speed_test_app/app/modules/home/controller.dart'; +import 'package:speed_test_app/app/modules/home/global/controller.dart'; +import 'package:speed_test_app/app/modules/settings/controller.dart'; + +class GlobalBinding implements Bindings { + + @override + void dependencies() { + Get.lazyPut(() => GlobalController()); + Get.lazyPut(() => HomeController( + speedtestRepository: SpeedtestRepository( + speedtestStorageProvider: SpeedtestStorageProvider()))); + Get.lazyPut(() => SettingsController()); + } + +} \ No newline at end of file diff --git a/lib/app/modules/home/global/controller.dart b/lib/app/modules/home/global/controller.dart new file mode 100644 index 0000000..68c9605 --- /dev/null +++ b/lib/app/modules/home/global/controller.dart @@ -0,0 +1,17 @@ +import 'package:get/get.dart'; + +class GlobalController extends GetxController { + + final pageIndex = 0.obs; + + GlobalController(); + + void changePageIndex(int index) { + pageIndex.value = index != 2 ? index : 0; + } + + int getPageIndex() { + return pageIndex.value; + } + +} \ No newline at end of file diff --git a/lib/app/modules/home/global/view.dart b/lib/app/modules/home/global/view.dart new file mode 100644 index 0000000..bb10f0e --- /dev/null +++ b/lib/app/modules/home/global/view.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:speed_test_app/app/core/values/colors.dart'; +import 'package:speed_test_app/app/modules/home/global/controller.dart'; +import 'package:speed_test_app/app/modules/home/global/widgets/bottom_nav_bar.dart'; +import 'package:speed_test_app/app/modules/home/view.dart'; +import 'package:speed_test_app/app/modules/settings/view.dart'; + +class GlobalPage extends GetView { + + const GlobalPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Obx(() => IndexedStack( + index: controller.getPageIndex(), + children: [ + const HomePage(), + const SizedBox(), + const SizedBox(), + const SizedBox(), + SettingsPage() + ], + )), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + backgroundColor: primary, + elevation: 0, + enableFeedback: true, + child: Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.white, width: 2), + borderRadius: BorderRadius.circular(50) + ), + child: const Icon(Icons.arrow_upward_rounded) + ), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + bottomNavigationBar: BottomNavBar() + ); + } + +} \ No newline at end of file diff --git a/lib/app/modules/home/global/widgets/bottom_nav_bar.dart b/lib/app/modules/home/global/widgets/bottom_nav_bar.dart new file mode 100644 index 0000000..cf2f7f4 --- /dev/null +++ b/lib/app/modules/home/global/widgets/bottom_nav_bar.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:speed_test_app/app/core/values/colors.dart'; +import 'package:speed_test_app/app/modules/home/global/controller.dart'; + +class BottomNavBar extends StatelessWidget { + + final controller = Get.find(); + + BottomNavBar({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + border: Border(top: BorderSide(color: Colors.grey[200]!)) + ), + child: Obx(() => BottomNavigationBar( + onTap: (int index) => controller.changePageIndex(index), + elevation: 0, + currentIndex: controller.pageIndex.value, + showSelectedLabels: false, + showUnselectedLabels: false, + enableFeedback: true, + unselectedItemColor: primary, + selectedItemColor: accent, + type: BottomNavigationBarType.fixed, + items: const [ + BottomNavigationBarItem( + label: 'home', + tooltip: "", + icon: Icon(Icons.cottage_outlined) + ), + BottomNavigationBarItem( + label: 'statistics', + tooltip: "", + icon: Icon(Icons.bar_chart) + ), + BottomNavigationBarItem( + label: '', + tooltip: "", + icon: Icon(Icons.arrow_upward_outlined, color: Colors.transparent) + ), + BottomNavigationBarItem( + label: 'history', + tooltip: "", + icon: Icon(Icons.check_circle_outlined) + ), + BottomNavigationBarItem( + label: 'settings', + tooltip: "", + icon: Icon(Icons.settings_outlined) + ) + ], + )) + ); + } +} diff --git a/lib/app/modules/home/view.dart b/lib/app/modules/home/view.dart index 3645aba..f9fca43 100644 --- a/lib/app/modules/home/view.dart +++ b/lib/app/modules/home/view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:speed_test_app/app/core/values/colors.dart'; import 'package:speed_test_app/app/core/values/sizes.dart'; @@ -18,146 +19,115 @@ class HomePage extends GetView { return Scaffold( body: SafeArea( - child: SingleChildScrollView( - physics: const ClampingScrollPhysics(), - child: Column( - children: [ - const TopAppBar(), - SizedBox( - height: 13.0.wp, - child: Divider(color: Colors.grey[200], thickness: 1) - ), - Padding( - padding: container, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const TextInfo(label: "Remaining Quota", text: "120 GB"), - Container( - padding: EdgeInsets.symmetric(vertical: 1.0.wp, horizontal: 3.0.wp), + child: SingleChildScrollView( + physics: const ClampingScrollPhysics(), + child: Column( + children: [ + TopAppBar( + title: "Data Usage", + icon: Container( decoration: BoxDecoration( - color: secondary, - borderRadius: BorderRadius.circular(26) + border: Border.all(color: Colors.grey[300]!, width: 2), + borderRadius: BorderRadius.circular(50) ), - child: Wrap( - crossAxisAlignment: WrapCrossAlignment.center, - alignment: WrapAlignment.center, + child: Stack( children: [ - Text("Add Quota", - style: TextStyle(fontSize: 12.0.sp, fontWeight: FontWeight.bold)), - const Icon(Icons.add, size: 22) + IconButton( + onPressed: () { + HapticFeedback.vibrate(); + }, + enableFeedback: true, + splashRadius: 25, + iconSize: 25, + highlightColor: Colors.transparent, + splashColor: Colors.grey[400], + icon: const Icon(Icons.notifications_outlined, color: primary) + ), + Positioned( + top: 3.75.wp, + right: 3.5.wp, + child: Container( + height: 8, + width: 8, + decoration: BoxDecoration( + color: primary, + borderRadius: BorderRadius.circular(50), + border: Border.all(color: Colors.white, width: 1.5) + ), + ), + ) ], - ), - ) - ], + ) + ), ), - ), - SizedBox(height: 7.5.wp), - Padding( - padding: container, - child: Row( - children: [ - const TextInfo(label: "Download", text: "45 GB"), - SizedBox(width: 15.0.wp), - const TextInfo(label: "Upload", text: "18 GB"), - ], + Padding( + padding: container, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const TextInfo(label: "Remaining Quota", text: "120 GB"), + Container( + padding: EdgeInsets.symmetric(vertical: 1.0.wp, horizontal: 3.0.wp), + decoration: BoxDecoration( + color: secondary, + borderRadius: BorderRadius.circular(26) + ), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + alignment: WrapAlignment.center, + children: [ + Text("Add Quota", + style: TextStyle(fontSize: 12.0.sp, fontWeight: FontWeight.bold)), + const Icon(Icons.add, size: 22) + ], + ), + ) + ], + ), ), - ), - SizedBox(height: 7.5.wp), - Padding( - padding: container, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey[300]!), - borderRadius: BorderRadius.circular(30) - ), - child: TabDate() + SizedBox(height: 7.5.wp), + Padding( + padding: container, + child: Row( + children: [ + const TextInfo(label: "Download", text: "45 GB"), + SizedBox(width: 15.0.wp), + const TextInfo(label: "Upload", text: "18 GB"), + ], + ), ), - ), - SizedBox(height: 7.5.wp), - Padding( - padding: container, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text("Analysis", - style: TextStyle(fontSize: 22.0.sp, fontWeight: FontWeight.w900)), - SizedBox(height: 7.5.wp), - BarGraph( - height: 20.0.hp, - barSettings: [ - BarSettings(title: "Mon", percent: 60, label: "4.8 GB"), - BarSettings(title: "Tue", percent: 80, label: "7.1 GB"), - BarSettings(title: "Wed", percent: 70, label: "5.2 GB", selected: true), - BarSettings(title: "Thu", percent: 100, label: "10 GB"), - BarSettings(title: "Fri", percent: 73, label: "5.5 GB"), - ] - ) - ], + SizedBox(height: 7.5.wp), + Padding( + padding: container, + child: TabDate(), ), - ) - ], - ), - ) - ), - floatingActionButton: FloatingActionButton( - onPressed: () {}, - backgroundColor: primary, - elevation: 0, - enableFeedback: true, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.white, width: 2), - borderRadius: BorderRadius.circular(50) - ), - child: const Icon(Icons.arrow_upward_rounded) - ), - ), - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, - bottomNavigationBar: Container( - decoration: BoxDecoration( - border: Border(top: BorderSide(color: Colors.grey[200]!)) - ), - child: BottomNavigationBar( - onTap: (int index) {}, - elevation: 0, - currentIndex: 0, - showSelectedLabels: false, - showUnselectedLabels: false, - enableFeedback: true, - unselectedItemColor: primary, - selectedItemColor: accent, - type: BottomNavigationBarType.fixed, - items: const [ - BottomNavigationBarItem( - label: 'home', - tooltip: "", - icon: Icon(Icons.cottage_outlined) - ), - BottomNavigationBarItem( - label: 'statistics', - tooltip: "", - icon: Icon(Icons.bar_chart) - ), - BottomNavigationBarItem( - label: '', - tooltip: "", - icon: Icon(Icons.bar_chart, color: Colors.transparent) - ), - BottomNavigationBarItem( - label: 'history', - tooltip: "", - icon: Icon(Icons.check_circle_outlined) + SizedBox(height: 7.5.wp), + Padding( + padding: container, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Analysis", + style: TextStyle(fontSize: 22.0.sp, fontWeight: FontWeight.w900)), + SizedBox(height: 7.5.wp), + BarGraph( + height: 20.0.hp, + barSettings: [ + BarSettings(title: "Mon", percent: 60, label: "4.8 GB"), + BarSettings(title: "Tue", percent: 80, label: "7.1 GB"), + BarSettings(title: "Wed", percent: 70, label: "5.2 GB", selected: true), + BarSettings(title: "Thu", percent: 100, label: "10 GB"), + BarSettings(title: "Fri", percent: 73, label: "5.5 GB"), + ] + ) + ], + ), + ) + ], ), - BottomNavigationBarItem( - label: 'settings', - tooltip: "", - icon: Icon(Icons.settings_outlined) - ) - ], - ), - ), + ) + ) ); } diff --git a/lib/app/modules/home/widgets/tab_date.dart b/lib/app/modules/home/widgets/tab_date.dart index d2f48e3..9b08d6d 100644 --- a/lib/app/modules/home/widgets/tab_date.dart +++ b/lib/app/modules/home/widgets/tab_date.dart @@ -14,50 +14,56 @@ class TabDate extends StatelessWidget { @override Widget build(BuildContext context) { - return Obx(() => Stack( - alignment: Alignment.center, - children: [ - AnimatedAlign( - alignment: homeController.getTab(), - duration: const Duration(milliseconds: 200), - curve: Curves.easeInOut, - child: Container( - padding: const EdgeInsets.symmetric(vertical: 25), - margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 3), - width: 88.0.wp/3, - decoration: BoxDecoration( - color: primary, - borderRadius: BorderRadius.circular(26) + return Obx(() => Container( + decoration: BoxDecoration( + border: Border.all(color: Colors.grey[300]!), + borderRadius: BorderRadius.circular(30) + ), + child: Stack( + alignment: Alignment.center, + children: [ + AnimatedAlign( + alignment: homeController.getTab(), + duration: const Duration(milliseconds: 200), + curve: Curves.easeInOut, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 25), + margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 3), + width: 88.0.wp/3, + decoration: BoxDecoration( + color: primary, + borderRadius: BorderRadius.circular(26) + ), ), ), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: homeController.tab.asMap().entries.map((entry) { - Color? color = entry.key == homeController.tabIndex.value - ? Colors.white : Colors.grey[400]; + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: homeController.tab.asMap().entries.map((entry) { + Color? color = entry.key == homeController.tabIndex.value + ? Colors.white : Colors.grey[400]; - return Align( - alignment: homeController.getTab(index: entry.key), - child: GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () { - homeController.changeTabIndex(entry.key); - HapticFeedback.vibrate(); - }, - child: Container( - width: 88.0.wp/3, - padding: const EdgeInsets.symmetric(vertical: 15), - child: Text(entry.value, style: TextStyle( - color: color, fontSize: 12.0.sp), - textAlign: TextAlign.center), + return Align( + alignment: homeController.getTab(index: entry.key), + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + homeController.changeTabIndex(entry.key); + HapticFeedback.vibrate(); + }, + child: Container( + width: 88.0.wp/3, + padding: const EdgeInsets.symmetric(vertical: 15), + child: Text(entry.value, style: TextStyle( + color: color, fontSize: 12.0.sp), + textAlign: TextAlign.center), + ), ), - ), - ); + ); - }).toList() - ), - ] + }).toList() + ), + ] + ), )); } } diff --git a/lib/app/modules/home/widgets/top_app_bar.dart b/lib/app/modules/home/widgets/top_app_bar.dart index de99bf9..e050c70 100644 --- a/lib/app/modules/home/widgets/top_app_bar.dart +++ b/lib/app/modules/home/widgets/top_app_bar.dart @@ -1,59 +1,36 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:speed_test_app/app/core/utils/extension.dart'; -import 'package:speed_test_app/app/core/values/colors.dart'; import 'package:speed_test_app/app/core/values/sizes.dart'; class TopAppBar extends StatelessWidget { - const TopAppBar({Key? key}) : super(key: key); + + final String title; + final Widget? icon; + + const TopAppBar({Key? key, required this.title, required this.icon}) : super(key: key); @override Widget build(BuildContext context) { - return Container( - padding: container, - margin: EdgeInsets.only(top: 5.0.wp), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text("Data Usage", - style: TextStyle(fontSize: 22.0.sp, fontWeight: FontWeight.w900)), - Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey[300]!, width: 2), - borderRadius: BorderRadius.circular(50) - ), - child: Stack( - children: [ - IconButton( - onPressed: () { - HapticFeedback.vibrate(); - }, - enableFeedback: true, - splashRadius: 25, - iconSize: 25, - highlightColor: Colors.transparent, - splashColor: Colors.grey[400], - icon: const Icon(Icons.notifications_outlined, color: primary) - ), - Positioned( - top: 3.75.wp, - right: 3.5.wp, - child: Container( - height: 8, - width: 8, - decoration: BoxDecoration( - color: primary, - borderRadius: BorderRadius.circular(50), - border: Border.all(color: Colors.white, width: 1.5) - ), - ), - ) - ], - ) - ) - ], - ), + return Column( + children: [ + Container( + padding: container, + margin: EdgeInsets.only(top: 5.0.wp), + height: 13.0.wp, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(title, style: TextStyle(fontSize: 22.0.sp, fontWeight: FontWeight.w900)), + icon != null ? icon! : Container() + ], + ), + ), + SizedBox( + height: 13.0.wp, + child: Divider(color: Colors.grey[200], thickness: 1) + ), + ], ); } } diff --git a/lib/app/modules/settings/controller.dart b/lib/app/modules/settings/controller.dart new file mode 100644 index 0000000..44e94fd --- /dev/null +++ b/lib/app/modules/settings/controller.dart @@ -0,0 +1,49 @@ + + +import 'package:dart_ipify/dart_ipify.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:get/get.dart'; + +class Location { + late final latitude = 0.0.obs; + late final longitude = 0.0.obs; +} + +class SettingsController extends GetxController { + + late final ip = "".obs; + late final nameServer = "".obs; + late final Location location = Location(); + + @override + void onInit() { + loadNetworkData(); + super.onInit(); + } + + loadNetworkData() { + Ipify.geo(dotenv.env['IPIFY_API_KEY']!).then((value) { + ip.value = value.ip ?? "--.---.-.---"; + nameServer.value = value.as?.name ?? "undefined"; + location.longitude.value = value.location?.lng ?? 0; + location.latitude.value = value.location?.lat ?? 0; + }); + } + + String getIp() { + return ip.value; + } + + String getNameServer() { + return nameServer.value; + } + + double? getLocationLatitude() { + return location.latitude.value; + } + + double? getLocationLongitude() { + return location.longitude.value; + } + +} \ No newline at end of file diff --git a/lib/app/modules/settings/view.dart b/lib/app/modules/settings/view.dart new file mode 100644 index 0000000..8d76d3e --- /dev/null +++ b/lib/app/modules/settings/view.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:speed_test_app/app/core/values/colors.dart'; +import 'package:speed_test_app/app/core/values/sizes.dart'; +import 'package:speed_test_app/app/modules/home/global/controller.dart'; +import 'package:speed_test_app/app/modules/home/widgets/top_app_bar.dart'; +import 'package:speed_test_app/app/modules/settings/controller.dart'; +import 'package:speed_test_app/app/core/utils/extension.dart'; + +class SettingsPage extends GetView { + + final globalController = Get.find(); + + SettingsPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + + return Scaffold( + body: SafeArea( + child: Column( + children: [ + TopAppBar( + title: "Settings", + icon: GestureDetector( + onTap: () => globalController.changePageIndex(0), + child: const Icon(Icons.close), + ) + ), + Obx(() => Padding( + padding: container, + child: Container( + padding: EdgeInsets.all(7.0.wp), + decoration: BoxDecoration( + border: Border.all(width: 1, color: Colors.grey[300]!), + borderRadius: BorderRadius.circular(6) + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Icon(Icons.wifi, size: 50), + GestureDetector( + onTap: () => controller.loadNetworkData(), + child: Container( + padding: EdgeInsets.symmetric(vertical: 1.0.wp, horizontal: 3.0.wp), + decoration: BoxDecoration( + color: secondary, + borderRadius: BorderRadius.circular(26) + ), + child: Text("Change Server", + style: TextStyle(fontSize: 12.0.sp, fontWeight: FontWeight.bold)), + ), + ) + ], + ), + SizedBox(height: 5.0.wp), + Row( + children: [Text(controller.getNameServer(), style: TextStyle(fontSize: 20.0.sp))], + ), + SizedBox(height: 3.0.wp), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text("Current Connection", style: TextStyle(fontSize: 10.0.sp, color: Colors.grey)), + Text(controller.getIp(), style: TextStyle(fontSize: 13.0.sp)) + ], + ), + SizedBox(height: 3.0.wp), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('Latitude ${controller.getLocationLatitude()}', style: TextStyle(fontSize: 13.0.sp)), + Text('Longitude ${controller.getLocationLongitude()}', style: TextStyle(fontSize: 13.0.sp)) + ], + ), + ], + ), + ), + )), + SizedBox(height: 10.0.wp), + Padding( + padding: container, + child: Column( + children: [ + Row( + children: [Text("Global Settings", + style: TextStyle(fontSize: 22.0.sp, fontWeight: FontWeight.w900)),], + ), + SizedBox(height: 7.5.wp), + ], + ), + ) + ], + ) + ), + ); + } + + + +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 040f903..52fa518 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,17 +1,24 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:speed_test_app/app/core/utils/scroll_behavior.dart'; import 'package:speed_test_app/app/data/services/storage/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:speed_test_app/app/modules/home/binding.dart'; -import 'package:speed_test_app/app/modules/home/view.dart'; +import 'package:speed_test_app/app/modules/home/global/binding.dart'; +import 'package:speed_test_app/app/modules/home/global/view.dart'; import 'package:google_fonts/google_fonts.dart'; -main() async { +class Environment { + static String get fileName => kReleaseMode ? ".env.production" : ".env.development"; +} + +Future main() async { + await dotenv.load(fileName: Environment.fileName); await GetStorage.init(); await Get.putAsync(() => StorageService().init()); - runApp(Application()); + runApp(const Application()); } class Application extends StatelessWidget { @@ -23,10 +30,10 @@ class Application extends StatelessWidget { title: "Speedtest", debugShowCheckedModeBanner: false, theme: ThemeData( - fontFamily: GoogleFonts.roboto().fontFamily + fontFamily: GoogleFonts.roboto().fontFamily, ), - home: const HomePage(), - initialBinding: HomeBinding(), + home: GlobalPage(), + initialBinding: GlobalBinding(), builder: (context, child) { child = EasyLoading.init()(context, child); child = ScrollConfiguration(behavior: MyBehavior(), child: child); diff --git a/pubspec.lock b/pubspec.lock index cd96c2b..8ca8765 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -71,6 +71,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.4" + dart_ipify: + dependency: "direct main" + description: + name: dart_ipify + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" fake_async: dependency: transitive description: @@ -97,6 +104,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_dotenv: + dependency: "direct main" + description: + name: flutter_dotenv + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.2" flutter_easyloading: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 7e67f7b..82098b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.2 + flutter_dotenv: ^5.0.2 get: ^4.6.1 get_storage: ^2.0.3 flutter_easyloading: ^3.0.3 @@ -20,6 +21,7 @@ dependencies: internet_speed_test: ^1.5.0 google_fonts: ^2.2.0 flutter_layout_grid: ^1.0.3 + dart_ipify: ^1.1.1 dev_dependencies: flutter_test: @@ -30,6 +32,8 @@ flutter: uses-material-design: true assets: - assets/images/ + - .env.development + - .env.production flutter_icons: android: "launcher_icon"