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

Merge branch '74-use-flutter_toolbox-lib' into 'master'

Resolve "Use flutter_toolbox lib"

Closes #74

See merge request !84
parents 9f0982fb a3b9cc0e
No related branches found
No related tags found
1 merge request!84Resolve "Use flutter_toolbox lib"
Pipeline #6497 passed
Showing
with 21 additions and 531 deletions
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:unicons/unicons.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/ui/screens/about_page.dart';
import 'package:random/ui/screens/api_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:hydrated_bloc/hydrated_bloc.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.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 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/config/menu.dart';
......
import 'package:equatable/equatable.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
part 'data_state.dart';
......
import 'package:equatable/equatable.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:random/models/game/game.dart';
......
import 'package:equatable/equatable.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:random/models/interface_type.dart';
......
import 'package:equatable/equatable.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
part 'theme_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/flutter_toolbox.dart';
import 'package:random/config/app_colors.dart';
import 'package:random/utils/color_extensions.dart';
class CellPainter extends CustomPainter {
const CellPainter({required this.value});
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:random/ui/widgets/header_app.dart';
......@@ -15,7 +14,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(),
......
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_custom_toolbox/flutter_toolbox.dart';
import 'package:random/cubit/api_cubit.dart';
import 'package:random/models/api_status.dart';
......@@ -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) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment