Skip to content
Snippets Groups Projects
Commit 0527df5c authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Use flutter custom toolbox lib

parent 9f0982fb
No related branches found
No related tags found
No related merge requests found
Pipeline #6421 failed
This commit is part of merge request !84. Comments created here will be created in the context of that merge request.
Showing
with 22 additions and 527 deletions
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:unicons/unicons.dart';
import 'package:random/ui/screens/about_page.dart';
......
import 'package:flutter/material.dart';
/// Colors from Tailwind CSS (v3.0) - June 2022
///
/// https://tailwindcss.com/docs/customizing-colors
const int _primaryColor = 0xFF6366F1;
const MaterialColor primarySwatch = MaterialColor(_primaryColor, <int, Color>{
50: Color(0xFFEEF2FF), // indigo-50
100: Color(0xFFE0E7FF), // indigo-100
200: Color(0xFFC7D2FE), // indigo-200
300: Color(0xFFA5B4FC), // indigo-300
400: Color(0xFF818CF8), // indigo-400
500: Color(_primaryColor), // indigo-500
600: Color(0xFF4F46E5), // indigo-600
700: Color(0xFF4338CA), // indigo-700
800: Color(0xFF3730A3), // indigo-800
900: Color(0xFF312E81), // indigo-900
});
const int _textColor = 0xFF64748B;
const MaterialColor textSwatch = MaterialColor(_textColor, <int, Color>{
50: Color(0xFFF8FAFC), // slate-50
100: Color(0xFFF1F5F9), // slate-100
200: Color(0xFFE2E8F0), // slate-200
300: Color(0xFFCBD5E1), // slate-300
400: Color(0xFF94A3B8), // slate-400
500: Color(_textColor), // slate-500
600: Color(0xFF475569), // slate-600
700: Color(0xFF334155), // slate-700
800: Color(0xFF1E293B), // slate-800
900: Color(0xFF0F172A), // slate-900
});
const Color errorColor = Color(0xFFDC2626); // red-600
final ColorScheme lightColorScheme = ColorScheme.light(
primary: primarySwatch.shade500,
secondary: primarySwatch.shade500,
onSecondary: Colors.white,
error: errorColor,
onSurface: textSwatch.shade500,
surface: textSwatch.shade50,
surfaceContainerHighest: Colors.white,
shadow: textSwatch.shade900.withOpacity(.1),
);
final ColorScheme darkColorScheme = ColorScheme.dark(
primary: primarySwatch.shade500,
secondary: primarySwatch.shade500,
onSecondary: Colors.white,
error: errorColor,
onSurface: textSwatch.shade300,
surface: const Color(0xFF262630),
surfaceContainerHighest: const Color(0xFF282832),
shadow: textSwatch.shade900.withOpacity(.2),
);
final ThemeData lightTheme = ThemeData(
colorScheme: lightColorScheme,
fontFamily: 'Nunito',
textTheme: TextTheme(
displayLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
displayMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
displaySmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
headlineLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
headlineMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
headlineSmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
titleLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
titleMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
titleSmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
bodyLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
bodyMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
bodySmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
labelLarge: TextStyle(
color: textSwatch.shade700,
fontFamily: 'Nunito',
),
labelMedium: TextStyle(
color: textSwatch.shade600,
fontFamily: 'Nunito',
),
labelSmall: TextStyle(
color: textSwatch.shade500,
fontFamily: 'Nunito',
),
),
);
final ThemeData darkTheme = lightTheme.copyWith(
colorScheme: darkColorScheme,
textTheme: TextTheme(
displayLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
displayMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
displaySmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
headlineLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
headlineMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
headlineSmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
titleLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
titleMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
titleSmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
bodyLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
bodyMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
bodySmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
labelLarge: TextStyle(
color: textSwatch.shade200,
fontFamily: 'Nunito',
),
labelMedium: TextStyle(
color: textSwatch.shade300,
fontFamily: 'Nunito',
),
labelSmall: TextStyle(
color: textSwatch.shade400,
fontFamily: 'Nunito',
),
),
);
final ThemeData appTheme = darkTheme;
import 'package:equatable/equatable.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:random/models/api_failure.dart';
import 'package:random/models/api_data.dart';
import 'package:random/repository/api.dart';
import 'package:random/utils/tools.dart';
part 'api_state.dart';
......
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/config/theme.dart';
import 'package:random/cubit/api_cubit.dart';
import 'package:random/cubit/bottom_nav_cubit.dart';
import 'package:random/cubit/data_cubit.dart';
......
import 'dart:math';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/models/game/game_board.dart';
import 'package:random/models/game/game_cell.dart';
import 'package:random/models/game/game_settings.dart';
import 'package:random/utils/tools.dart';
class Game {
GameBoard board;
......
import 'dart:math';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/models/game/game_cell.dart';
import 'package:random/models/game/game_settings.dart';
import 'package:random/utils/tools.dart';
class GameBoard {
final List<List<GameCell>> cells;
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
enum InterfaceType {
basic,
......
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/models/api_failure.dart';
import 'package:random/utils/tools.dart';
class ApiService {
final Dio _dio = Dio();
......
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/models/api_data.dart';
import 'package:random/network/api.dart';
import 'package:random/utils/tools.dart';
class ApiRepository {
const ApiRepository({required this.apiService});
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
class AppHeader extends StatelessWidget {
const AppHeader({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),
);
}
}
class AppTitle extends StatelessWidget {
const AppTitle({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.titleLarge!.apply(fontWeightDelta: 2),
);
}
}
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:random/utils/color_extensions.dart';
class StyledButton extends StatelessWidget {
const StyledButton({
super.key,
required this.color,
required this.onPressed,
this.onLongPress,
required this.child,
});
final Color color;
final VoidCallback? onPressed;
final VoidCallback? onLongPress;
final Widget child;
factory StyledButton.text({
Key? key,
required VoidCallback? onPressed,
VoidCallback? onLongPress,
required String caption,
required Color color,
}) {
final Widget captionWidget = AutoSizeText(
caption,
maxLines: 1,
style: TextStyle(
inherit: true,
fontWeight: FontWeight.w900,
color: color.darken(60),
shadows: [
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(2, 2),
),
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(2, -2),
),
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(-2, 2),
),
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(-2, -2),
),
],
),
);
return StyledButton(
color: color,
onPressed: onPressed,
onLongPress: onLongPress,
child: captionWidget,
);
}
factory StyledButton.icon({
Key? key,
required VoidCallback? onPressed,
VoidCallback? onLongPress,
required Icon icon,
required Color color,
required double iconSize,
}) {
return StyledButton(
color: color,
onPressed: onPressed,
onLongPress: onLongPress,
child: Icon(
icon.icon,
color: icon.color ?? color.darken(60),
size: iconSize,
shadows: [
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(2, 2),
),
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(2, -2),
),
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(-2, 2),
),
Shadow(
blurRadius: 5.0,
color: color.lighten(60),
offset: const Offset(-2, -2),
),
],
),
);
}
@override
Widget build(BuildContext context) {
const double borderWidth = 4;
final Color borderColor = color.darken(40);
const double borderRadius = 10;
return Container(
margin: const EdgeInsets.all(2),
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: color,
border: Border.all(
color: borderColor,
width: borderWidth,
),
borderRadius: BorderRadius.circular(borderRadius),
),
child: CustomPaint(
painter: StyledButtonPainter(
baseColor: color,
),
child: MaterialButton(
onPressed: onPressed,
onLongPress: onLongPress,
padding: const EdgeInsets.all(8),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
minWidth: 40,
child: child,
),
),
);
}
}
class StyledButtonPainter extends CustomPainter {
StyledButtonPainter({
required this.baseColor,
});
final Color baseColor;
@override
void paint(Canvas canvas, Size size) {
final Color lightColor = baseColor.lighten(20);
final Color darkColor = baseColor.darken(20);
final Paint paint = Paint()..style = PaintingStyle.fill;
const double cornerRadius = 6;
Path topPath = Path()
..moveTo(cornerRadius, 0)
..lineTo(size.width - cornerRadius, 0)
..arcToPoint(
Offset(size.width, cornerRadius),
radius: const Radius.circular(cornerRadius),
)
..lineTo(size.width, size.height * .35)
..quadraticBezierTo(
size.width * .4,
size.height * .1,
0,
size.height * .3,
)
..lineTo(0, cornerRadius)
..arcToPoint(
const Offset(cornerRadius, 0),
radius: const Radius.circular(cornerRadius),
);
Path bottomPath = Path()
..moveTo(cornerRadius, size.height)
..lineTo(size.width - cornerRadius, size.height)
..arcToPoint(
Offset(size.width, size.height - cornerRadius),
radius: const Radius.circular(cornerRadius),
clockwise: false,
)
..lineTo(size.width, size.height * .7)
..quadraticBezierTo(
size.width * .6,
size.height * .9,
0,
size.height * .7,
)
..lineTo(0, size.height - cornerRadius)
..arcToPoint(
Offset(cornerRadius, size.height),
radius: const Radius.circular(cornerRadius),
clockwise: false,
);
paint.color = lightColor;
canvas.drawPath(topPath, paint);
paint.color = darkColor;
canvas.drawPath(bottomPath, paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
import 'package:flutter/material.dart';
class StyledContainer extends StatelessWidget {
const StyledContainer({
super.key,
required this.child,
this.borderWidth = 20,
this.borderRadius = 6,
this.depth = 7,
this.lowerColor,
this.upperColor,
});
final Widget child;
final double borderWidth;
final double borderRadius;
final int depth;
final Color? lowerColor;
final Color? upperColor;
Widget nestedContainers({
required Widget child,
required int containerDepth,
required Color lowerColor,
required Color upperColor,
}) {
final double singleBorderWidth = borderWidth / depth;
final Color borderColor =
Color.lerp(upperColor, lowerColor, (containerDepth / depth - 0.5).abs() * 2) ??
Colors.white;
final double radius = borderRadius + borderRadius * (containerDepth / depth);
return Container(
decoration: BoxDecoration(
color: borderColor,
border: Border.all(
color: borderColor,
width: singleBorderWidth,
),
borderRadius: BorderRadius.circular(radius),
),
child: containerDepth == 0
? Padding(
padding: const EdgeInsets.all(8),
child: child,
)
: nestedContainers(
child: child,
containerDepth: containerDepth - 1,
lowerColor: lowerColor,
upperColor: upperColor,
),
);
}
@override
Widget build(BuildContext context) {
return nestedContainers(
child: child,
containerDepth: depth,
lowerColor: lowerColor ?? Theme.of(context).colorScheme.surface,
upperColor: upperColor ?? Theme.of(context).colorScheme.onSurface,
);
}
}
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/utils/color_extensions.dart';
import 'package:random/config/app_colors.dart';
import 'package:random/utils/color_extensions.dart';
class CellPainter extends CustomPainter {
const CellPainter({required this.value});
......
......@@ -15,7 +15,7 @@ class AboutPage extends StatelessWidget {
mainAxisSize: MainAxisSize.max,
children: <Widget>[
const SizedBox(height: 8),
const AppHeader(text: 'about_title'),
const AppHeaderCustom(text: 'about_title'),
const Text('about_content').tr(),
FutureBuilder<PackageInfo>(
future: PackageInfo.fromPlatform(),
......
......@@ -18,7 +18,7 @@ class ApiPage extends StatelessWidget {
physics: const BouncingScrollPhysics(),
children: <Widget>[
const SizedBox(height: 8),
const AppHeader(text: 'api_page_title'),
const AppHeaderCustom(text: 'api_page_title'),
const SizedBox(height: 20),
BlocBuilder<ApiDataCubit, ApiDataState>(
builder: (BuildContext context, ApiDataState apiDataState) {
......
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:unicons/unicons.dart';
import 'package:random/config/theme.dart';
import 'package:random/cubit/data_cubit.dart';
import 'package:random/cubit/settings_cubit.dart';
import 'package:random/ui/widgets/header_app.dart';
import 'package:random/ui/helpers/styled_button.dart';
import 'package:random/ui/helpers/styled_container.dart';
import 'package:random/utils/tools.dart';
class DemoPage extends StatelessWidget {
const DemoPage({super.key});
......@@ -22,7 +19,7 @@ class DemoPage extends StatelessWidget {
physics: const BouncingScrollPhysics(),
children: <Widget>[
const SizedBox(height: 8),
const AppHeader(text: 'TOP'),
const AppHeaderCustom(text: 'TOP'),
const SizedBox(height: 20),
StyledContainer(
child: persistedCounterBlock(BlocProvider.of<DataCubit>(context)),
......@@ -48,7 +45,7 @@ class DemoPage extends StatelessWidget {
const SizedBox(height: 8),
fakeApiCall(),
const SizedBox(height: 8),
const AppHeader(text: 'BOTTOM'),
const AppHeaderCustom(text: 'BOTTOM'),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
......
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/ui/painters/graph_painter.dart';
import 'package:random/utils/tools.dart';
class GraphPage extends StatefulWidget {
const GraphPage({super.key});
......
......@@ -14,7 +14,7 @@ class SettingsPage extends StatelessWidget {
mainAxisSize: MainAxisSize.max,
children: <Widget>[
SizedBox(height: 8),
AppHeader(text: 'settings_title'),
AppHeaderCustom(text: 'settings_title'),
SizedBox(height: 8),
SettingsForm(),
],
......
import 'package:flutter/material.dart';
import 'package:flutter_custom_toolbox/widgets/show_error.dart';
import 'package:random/models/api_data.dart';
import 'package:random/models/api_status.dart';
import 'package:random/ui/widgets/error.dart';
class ApiDataWidget extends StatelessWidget {
const ApiDataWidget({
......
......@@ -8,7 +8,7 @@ class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
return AppBar(
title: const AppHeader(text: 'app_name'),
title: const AppHeaderCustom(text: 'app_name'),
actions: const [
//
],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment