diff --git a/android/gradle.properties b/android/gradle.properties index d786ccb6f687d13ef64ab84562938745769f4ae6..6d538ee650c8ec589c0c43845e1e24c0e2e54db0 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=1.0.26 -app.versionCode=27 +app.versionName=1.0.27 +app.versionCode=28 diff --git a/assets/translations/en.json b/assets/translations/en.json index c042445a0b6721bbd268a51ec551919311858151..75ccbde48e9c653bf70476448a8e38fdc027155d 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -1,5 +1,5 @@ { - "app_name": "Random application", + "app_name": "Sandbox App", "bottom_nav_sample": "Sample", "bottom_nav_chart": "Graph", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 484f9137b72e42d572192acba9ba0deaf686e78a..0ede7bfefabb91d9293ff1930da4b9614442ae5f 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -1,5 +1,5 @@ { - "app_name": "Random application", + "app_name": "App de test", "bottom_nav_sample": "Démo", "bottom_nav_chart": "Graph", diff --git a/lib/config/app_colors.dart b/lib/config/app_colors.dart new file mode 100644 index 0000000000000000000000000000000000000000..a1ca589a1cef364687bbb2ee76e4073ce17ea650 --- /dev/null +++ b/lib/config/app_colors.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +class AppColors { + static const Color primary = contentColorCyan; + static const Color menuBackground = Color(0xFF090912); + static const Color itemsBackground = Color(0xFF1B2339); + static const Color pageBackground = Color(0xFF282E45); + static const Color mainTextColor1 = Colors.white; + static const Color mainTextColor2 = Colors.white70; + static const Color mainTextColor3 = Colors.white38; + static const Color mainGridLineColor = Colors.white10; + static const Color borderColor = Colors.white54; + static const Color gridLinesColor = Color(0x11FFFFFF); + + static const Color contentColorBlack = Colors.black; + static const Color contentColorWhite = Colors.white; + static const Color contentColorBlue = Color(0xFF2196F3); + static const Color contentColorYellow = Color(0xFFFFC300); + static const Color contentColorOrange = Color(0xFFFF683B); + static const Color contentColorGreen = Color(0xFF3BFF49); + static const Color contentColorPurple = Color(0xFF6E1BFF); + static const Color contentColorPink = Color(0xFFFF3AF2); + static const Color contentColorRed = Color(0xFFE80054); + static const Color contentColorCyan = Color(0xFF50E4FF); +} diff --git a/lib/main.dart b/lib/main.dart index e7d191c3c40a776bda596b322c26c69ca4a44509..94737296f54ba826f3e980aad5bf9e1b20a7c415 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,8 +6,8 @@ import 'package:hive/hive.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:random/ui/screens/skeleton_screen.dart'; -import 'package:random/config/theme.dart'; +import 'ui/screens/skeleton_screen.dart'; +import 'config/theme.dart'; void main() async { /// Initialize packages diff --git a/lib/painters/GraphPainter.dart b/lib/ui/painters/graph_painter.dart similarity index 63% rename from lib/painters/GraphPainter.dart rename to lib/ui/painters/graph_painter.dart index a088d81f45a9a94d18e48770cf44b02a44db919a..e5173b8d8f5df87494724a60f4053b66239f598a 100644 --- a/lib/painters/GraphPainter.dart +++ b/lib/ui/painters/graph_painter.dart @@ -1,11 +1,25 @@ import 'dart:math'; + import 'package:flutter/material.dart'; +import '../../config/app_colors.dart'; + class GraphPainter extends CustomPainter { const GraphPainter(); double random(double max) { - return Random().nextDouble() * max; + return 0.1 * max + Random().nextDouble() * max * 0.8; + } + + Color getRandomColor() { + const List<Color> availableColors = [ + AppColors.contentColorCyan, + AppColors.contentColorGreen, + AppColors.contentColorOrange, + AppColors.contentColorPurple, + ]; + + return availableColors[Random().nextInt(availableColors.length)]; } @override @@ -19,12 +33,14 @@ class GraphPainter extends CustomPainter { canvas.drawRect(rectBackground, paintBackground); // Draw some lines - final paintLine = Paint(); - paintLine.color = Colors.red; + Paint paintLine = Paint(); paintLine.style = PaintingStyle.fill; + paintLine.strokeWidth = 2.0; - int linesCount = 500; + int linesCount = 300; for (int i = 0; i < linesCount; i++) { + paintLine.color = getRandomColor(); + Offset lineStart = Offset(random(size.width), random(size.height)); Offset lineStop = Offset(random(size.width), random(size.height)); canvas.drawLine(lineStart, lineStop, paintLine); diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/about_page.dart index 9ad2fcfe02ce9129c8489e9bcec904a7c3095afa..6c76ab1f6d4d24710844411aed3fc6f32985a9ae 100644 --- a/lib/ui/screens/about_page.dart +++ b/lib/ui/screens/about_page.dart @@ -1,6 +1,8 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import '../widgets/header.dart'; + class AboutPage extends StatelessWidget { const AboutPage({super.key}); @@ -11,12 +13,8 @@ class AboutPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: <Widget>[ - SizedBox(height: 50), - Text( - 'about_title', - textAlign: TextAlign.start, - style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), - ).tr(), + SizedBox(height: 8), + Header(text: 'about_title'), Text('about_content').tr(), ], ); diff --git a/lib/activities/ActivityDemoPage.dart b/lib/ui/screens/demo_page.dart similarity index 64% rename from lib/activities/ActivityDemoPage.dart rename to lib/ui/screens/demo_page.dart index 18e0e0f65473302bcc72fa99f46d7fa2597e8a55..4eff438f610d2eefd0165a6b11633c139dd99dfd 100644 --- a/lib/activities/ActivityDemoPage.dart +++ b/lib/ui/screens/demo_page.dart @@ -1,43 +1,34 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:ionicons/ionicons.dart'; -import 'package:random/config/theme.dart'; -import 'package:random/cubit/data_cubit.dart'; -import 'package:random/cubit/settings_cubit.dart'; +import '../../config/theme.dart'; -class ActivityDemoPage extends StatelessWidget { - const ActivityDemoPage({super.key}); +import '../../cubit/data_cubit.dart'; +import '../../cubit/settings_cubit.dart'; + +import '../widgets/header.dart'; + +class DemoPage extends StatelessWidget { + const DemoPage({super.key}); @override Widget build(BuildContext context) { - return SizedBox.expand( - child: Container( - child: FittedBox( - fit: BoxFit.contain, - alignment: Alignment.center, - child: SizedBox( - height: (MediaQuery.of(context).size.height), - width: (MediaQuery.of(context).size.width), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: <Widget>[ - Text('TOP').tr(), - SizedBox(height: 20), - persistedCounterBlock(), - SizedBox(height: 20), - fakeApiCall(), - SizedBox(height: 20), - Text('BOTTOM').tr(), - ], - ), - ), - ), - ), + return Material( + color: Theme.of(context).colorScheme.background, + child: ListView( + padding: const EdgeInsets.symmetric(horizontal: 4), + physics: const BouncingScrollPhysics(), + children: <Widget>[ + SizedBox(height: 8), + Header(text: 'TOP'), + SizedBox(height: 20), + persistedCounterBlock(), + SizedBox(height: 20), + fakeApiCall(), + SizedBox(height: 20), + Header(text: 'BOTTOM'), + ], ), ); } diff --git a/lib/activities/ActivityGraphPage.dart b/lib/ui/screens/graph_page.dart similarity index 91% rename from lib/activities/ActivityGraphPage.dart rename to lib/ui/screens/graph_page.dart index 33fb267fcc2121e9e81f2df2477f74821669f3e6..899eb042cfab416fd5490b341fddf272ede376a7 100644 --- a/lib/activities/ActivityGraphPage.dart +++ b/lib/ui/screens/graph_page.dart @@ -1,8 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:random/painters/GraphPainter.dart'; -class ActivityGraphPage extends StatelessWidget { - const ActivityGraphPage({super.key}); +import '../painters/graph_painter.dart'; + +class GraphPage extends StatelessWidget { + const GraphPage({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart index 133372a54a9659f2508508a381e3addf4beb2ea0..1cd8e333e355e2bf3f1b60f77cf6ad9968798e42 100644 --- a/lib/ui/screens/settings_page.dart +++ b/lib/ui/screens/settings_page.dart @@ -1,7 +1,7 @@ -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:random/ui/widgets/settings_form.dart'; +import '../widgets/header.dart'; +import '../widgets/settings_form.dart'; class SettingsPage extends StatelessWidget { const SettingsPage({super.key}); @@ -13,12 +13,8 @@ class SettingsPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.max, children: <Widget>[ - SizedBox(height: 50), - Text( - 'settings_title', - textAlign: TextAlign.start, - style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), - ).tr(), + SizedBox(height: 8), + Header(text: 'settings_title'), SizedBox(height: 8), SettingsForm(), ], diff --git a/lib/ui/screens/skeleton_screen.dart b/lib/ui/screens/skeleton_screen.dart index 412847e212f29e1505cd30eb7204ab2087b01ba2..2af9954e55c7b3c4c698e5ed1cb52f89ad729c2b 100644 --- a/lib/ui/screens/skeleton_screen.dart +++ b/lib/ui/screens/skeleton_screen.dart @@ -1,23 +1,30 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:random/activities/ActivityDemoPage.dart'; -import 'package:random/activities/ActivityGraphPage.dart'; -import 'package:random/cubit/bottom_nav_cubit.dart'; -import 'package:random/cubit/settings_cubit.dart'; -import 'package:random/ui/screens/about_page.dart'; -import 'package:random/ui/screens/settings_page.dart'; -import 'package:random/ui/widgets/custom_app_bar.dart'; -import 'package:random/ui/widgets/bottom_nav_bar.dart'; +import '../../cubit/bottom_nav_cubit.dart'; +import '../../cubit/settings_cubit.dart'; -class SkeletonScreen extends StatelessWidget { +import '../widgets/app_bar.dart'; +import '../widgets/bottom_nav_bar.dart'; + +import 'demo_page.dart'; +import 'graph_page.dart'; +import 'about_page.dart'; +import 'settings_page.dart'; + +class SkeletonScreen extends StatefulWidget { const SkeletonScreen({super.key}); + @override + State<SkeletonScreen> createState() => _SkeletonScreenState(); +} + +class _SkeletonScreenState extends State<SkeletonScreen> { @override Widget build(BuildContext context) { const List<Widget> pageNavigation = <Widget>[ - ActivityDemoPage(), - ActivityGraphPage(), + DemoPage(), + GraphPage(), SettingsPage(), AboutPage(), ]; @@ -27,8 +34,8 @@ class SkeletonScreen extends StatelessWidget { child: BlocProvider<BottomNavCubit>( create: (BuildContext context) => BottomNavCubit(), child: Scaffold( - extendBodyBehindAppBar: true, - appBar: const CustomAppBarGone(), + extendBodyBehindAppBar: false, + appBar: StandardAppBar(), body: BlocBuilder<BottomNavCubit, int>( builder: (BuildContext context, int state) { return AnimatedSwitcher( diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart new file mode 100644 index 0000000000000000000000000000000000000000..32cbde9168fbff3240b13a4ca206d2640fc5c045 --- /dev/null +++ b/lib/ui/widgets/app_bar.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:unicons/unicons.dart'; + +import '../widgets/header.dart'; + +class StandardAppBar extends StatelessWidget implements PreferredSizeWidget { + const StandardAppBar({super.key}); + + @override + Widget build(BuildContext context) { + return AppBar( + title: const Header(text: 'app_name'), + actions: [ + IconButton( + onPressed: () {}, + icon: const Icon(UniconsSolid.refresh), + ), + ], + ); + } + + @override + Size get preferredSize => const Size.fromHeight(50); +} diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart index 445b4f5ad9bc945bbf2b5a1fd1e02c8a09e24f6d..ea33889bf698eff47c9cd4e2a5170bd11611df4b 100644 --- a/lib/ui/widgets/bottom_nav_bar.dart +++ b/lib/ui/widgets/bottom_nav_bar.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:ionicons/ionicons.dart'; -import 'package:random/cubit/bottom_nav_cubit.dart'; +import '../../cubit/bottom_nav_cubit.dart'; class BottomNavBar extends StatelessWidget { const BottomNavBar({super.key}); diff --git a/lib/ui/widgets/custom_app_bar.dart b/lib/ui/widgets/custom_app_bar.dart deleted file mode 100644 index 93c477e9160589a31be400f5542e7809727851bf..0000000000000000000000000000000000000000 --- a/lib/ui/widgets/custom_app_bar.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -class CustomAppBarGone extends StatelessWidget implements PreferredSizeWidget { - const CustomAppBarGone({super.key}); - - @override - Widget build(BuildContext context) { - final Brightness brightness = Theme.of(context).colorScheme.brightness; - - return AppBar( - systemOverlayStyle: SystemUiOverlayStyle( - statusBarBrightness: brightness, - systemStatusBarContrastEnforced: false, - statusBarColor: Theme.of(context).colorScheme.background, - statusBarIconBrightness: - brightness == Brightness.dark ? Brightness.light : Brightness.dark, - ), - backgroundColor: Colors.transparent, - excludeHeaderSemantics: true, - shadowColor: Colors.transparent, - scrolledUnderElevation: 0, - surfaceTintColor: Colors.transparent, - foregroundColor: Colors.transparent, - elevation: 0, - bottomOpacity: 0, - toolbarOpacity: 0, - ); - } - - @override - Size get preferredSize => const Size.fromHeight(0); -} diff --git a/lib/ui/widgets/error.dart b/lib/ui/widgets/error.dart new file mode 100644 index 0000000000000000000000000000000000000000..e65f242fd0b657ce06ee235ea8f574689bf7089f --- /dev/null +++ b/lib/ui/widgets/error.dart @@ -0,0 +1,17 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +class ShowErrorWidget extends StatelessWidget { + const ShowErrorWidget({super.key, required this.message}); + + final String message; + + @override + Widget build(BuildContext context) { + return Text( + '⚠️ ' + tr(message), + textAlign: TextAlign.start, + style: TextStyle(color: Colors.red), + ); + } +} diff --git a/lib/ui/widgets/header.dart b/lib/ui/widgets/header.dart new file mode 100644 index 0000000000000000000000000000000000000000..2187ef84a2dbad4dd0cfa7986bdb4473b0af0462 --- /dev/null +++ b/lib/ui/widgets/header.dart @@ -0,0 +1,17 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +class Header extends StatelessWidget { + const Header({super.key, required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + return Text( + tr(text), + textAlign: TextAlign.start, + style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2), + ); + } +} diff --git a/lib/ui/widgets/settings_form.dart b/lib/ui/widgets/settings_form.dart index e0a6e853c0968c178fa14e797e59809ff91d81fc..9a8bc830c2ccc18e91768eae146630f0618f27f1 100644 --- a/lib/ui/widgets/settings_form.dart +++ b/lib/ui/widgets/settings_form.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:unicons/unicons.dart'; -import 'package:random/cubit/bottom_nav_cubit.dart'; -import 'package:random/cubit/settings_cubit.dart'; +import '../../cubit/bottom_nav_cubit.dart'; +import '../../cubit/settings_cubit.dart'; class SettingsForm extends StatefulWidget { const SettingsForm({super.key}); diff --git a/pubspec.yaml b/pubspec.yaml index dfa6e18b1cab9270697726fc6c0da22fc3fc7eb1..2c42e12b84a4d63f84c4334a9ba7e7201b0871c6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A random application, for testing purpose only. publish_to: 'none' -version: 1.0.26+27 +version: 1.0.27+28 environment: sdk: '^3.0.0'