From 2642d5a39c584dbcdc78b1d3afd1a151d7e1daf7 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:12:38 +0300 Subject: [PATCH 01/54] create AdaptWidgetSize --- lib/core/widgets/adapt_widget_size.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 lib/core/widgets/adapt_widget_size.dart diff --git a/lib/core/widgets/adapt_widget_size.dart b/lib/core/widgets/adapt_widget_size.dart new file mode 100644 index 0000000..5bcf11f --- /dev/null +++ b/lib/core/widgets/adapt_widget_size.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; + +class AdaptWidgetSize extends StatelessWidget { + const AdaptWidgetSize({required this.builder, super.key}); + final Widget Function(double adaptSize) builder; + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, constraints) { + final size = constraints.maxWidth > constraints.maxHeight + ? constraints.maxHeight + : constraints.maxWidth; + + final newSize = size * 0.35; + final adapt = newSize > 50 ? 80.0 : newSize; + + return builder(adapt); + }, + ); + } +} From 725888a24de2f121445d197b8fa89a839c0e7833 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:12:50 +0300 Subject: [PATCH 02/54] create _RPadding for general padding --- .../adaptive/padding/adaptive_padding.dart | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/adaptive_padding.dart diff --git a/lib/core/widgets/adaptive/padding/adaptive_padding.dart b/lib/core/widgets/adaptive/padding/adaptive_padding.dart new file mode 100644 index 0000000..8cb072a --- /dev/null +++ b/lib/core/widgets/adaptive/padding/adaptive_padding.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +part 'all_padding.dart'; +part 'bottom_padding.dart'; +part 'top_padding.dart'; +part 'start_padding.dart'; +part 'end_padding.dart'; +part 'vertical_padding.dart'; +part 'horizontal_padding.dart'; +part 'symmetric_padding.dart'; +part 'only_padding.dart'; + +class _RPadding extends StatelessWidget { + const _RPadding({required this.padding, required this.child}); + final Widget child; + final EdgeInsetsGeometry padding; + @override + Widget build(BuildContext context) { + return Padding(padding: padding, child: child); + } +} From dfcaf60c33caa3a0d10373adc984fb1b4593d862 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:12:57 +0300 Subject: [PATCH 03/54] create _AdaptiveText for general texts --- .../widgets/adaptive/text/adaptive_text.dart | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 lib/core/widgets/adaptive/text/adaptive_text.dart diff --git a/lib/core/widgets/adaptive/text/adaptive_text.dart b/lib/core/widgets/adaptive/text/adaptive_text.dart new file mode 100644 index 0000000..ea73c28 --- /dev/null +++ b/lib/core/widgets/adaptive/text/adaptive_text.dart @@ -0,0 +1,108 @@ +import 'package:algorithm_visualizer/core/resources/font_manager.dart'; +import 'package:algorithm_visualizer/core/resources/styles_manager.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +part 'light_text.dart'; +part 'regular_text.dart'; +part 'semi_bold_text.dart'; +part 'bold_text.dart'; +part 'medium_text.dart'; + +class _AdaptiveText extends StatelessWidget { + const _AdaptiveText( + this.text, { + this.fontSize = 16, + this.decoration = TextDecoration.none, + this.fontStyle = FontStyle.normal, + this.color, + this.shadows, + this.fontWeight = FontWeightManager.regular, + this.maxLines = 2, + this.letterSpacing = 0, + this.translate = true, + required this.textAlign, + super.key, + }); + + final String text; + final bool translate; + final double fontSize; + final double letterSpacing; + final int maxLines; + final ThemeEnum? color; + final FontStyle fontStyle; + final TextDecoration decoration; + final FontWeight fontWeight; + final TextAlign? textAlign; + final List? shadows; + @override + Widget build(BuildContext context) { + final color = this.color; + + /// todo: tr + + final text = (translate + ? this.text + // .tr + : this.text) + .trim(); + + // final actualWeight = text.getExtraWeightForArabic(fontWeight); + final actualWeight = fontWeight; + + return Text( + text, + maxLines: maxLines, + overflow: TextOverflow.ellipsis, + textAlign: textAlign, + style: GetTextStyle( + fontSize: fontSize.sp, + color: color == null ? null : context.getColor(color), + fontWeight: actualWeight, + fontStyle: fontStyle, + decoration: decoration, + decorationThickness: decoration == TextDecoration.none ? null : 3.h, + shadows: shadows, + letterSpacing: letterSpacing, + ), + ); + } +} + +class AdaptiveText extends StatelessWidget { + const AdaptiveText( + this.text, { + this.style, + this.maxLines = 2, + this.textAlign, + super.key, + }); + + final String text; + final int maxLines; + final TextAlign? textAlign; + final TextStyle? style; + @override + Widget build(BuildContext context) { + final style = this.style; + + final TextStyle newStyle = style == null + ? const GetRegularStyle() + : style.copyWith( + fontSize: (style.fontSize ?? 16).sp, + ); + + /// todo: tr + + return Text( + text + // .tr + , + maxLines: maxLines, + textAlign: textAlign, + style: newStyle, + ); + } +} From b7e765a099ed11f534a14621db095e1735aacf3b Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:13:04 +0300 Subject: [PATCH 04/54] create AllPadding --- lib/core/widgets/adaptive/padding/all_padding.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/all_padding.dart diff --git a/lib/core/widgets/adaptive/padding/all_padding.dart b/lib/core/widgets/adaptive/padding/all_padding.dart new file mode 100644 index 0000000..b2015c3 --- /dev/null +++ b/lib/core/widgets/adaptive/padding/all_padding.dart @@ -0,0 +1,12 @@ +part of 'adaptive_padding.dart'; + +class AllPadding extends StatelessWidget { + const AllPadding({required this.padding, required this.child, super.key}); + final double padding; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: REdgeInsetsDirectional.all(padding), child: child); + } +} From 69fe52d762a25cca900432b19651d80c1779bd2b Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:13:25 +0300 Subject: [PATCH 05/54] create CustomAppBar, GlobalAppBar --- lib/core/helpers/app_bar/app_bar.dart | 144 ++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 lib/core/helpers/app_bar/app_bar.dart diff --git a/lib/core/helpers/app_bar/app_bar.dart b/lib/core/helpers/app_bar/app_bar.dart new file mode 100644 index 0000000..9bbc944 --- /dev/null +++ b/lib/core/helpers/app_bar/app_bar.dart @@ -0,0 +1,144 @@ +import 'package:algorithm_visualizer/core/extensions/navigators.dart'; +import 'package:algorithm_visualizer/core/helpers/app_bar/back_button.dart'; +import 'package:algorithm_visualizer/core/helpers/svg_picture.dart'; +import 'package:algorithm_visualizer/core/resources/assets_manager.dart'; +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.dart'; +import 'package:flutter/material.dart'; + +class CustomAppBar { + static AppBar iconAppBar( + {bool isShadowTransparent = true, bool withBackButton = true}) { + return GlobalAppBar( + centerTitle: true, + // title: const AppLogo(), + leading: withBackButton ? null : const SizedBox(), + shadowColor: isShadowTransparent ? ColorManager.transparent : null, + ); + } +} + +class GlobalAppBar extends AppBar { + GlobalAppBar({ + super.key, + Widget? leading, + super.automaticallyImplyLeading = true, + Widget? title, + super.actions, + super.flexibleSpace, + super.bottom, + super.elevation, + super.scrolledUnderElevation, + super.notificationPredicate, + super.shadowColor, + super.surfaceTintColor, + super.shape, + super.backgroundColor, + super.foregroundColor, + super.iconTheme, + super.actionsIconTheme, + super.primary = true, + super.centerTitle, + super.excludeHeaderSemantics = false, + // super.titleSpacing, + super.toolbarOpacity = 1.0, + super.bottomOpacity = 1.0, + super.toolbarHeight, + super.leadingWidth, + super.toolbarTextStyle, + super.titleTextStyle, + super.systemOverlayStyle, + super.forceMaterialTransparency = false, + super.clipBehavior, + }) : super( + title: getTitle(title), + titleSpacing: 15, + leading: leading ?? const CustomAppBarBackButton(), + ); + + static Widget? getTitle(Widget? title) { + final text = getText(title); + + if (text != null) return GlobalAppBarText(text: text); + + return title; + } + + static String? getText(Widget? title) { + if (title is LightText) return title.text; + if (title is RegularText) return title.text; + if (title is MediumText) return title.text; + if (title is SemiBoldText) return title.text; + if (title is BoldText) return title.text; + if (title is AdaptiveText) return title.text; + if (title is Text) return title.data; + return null; + } +} + +const double secondAppBarIconSize = 28; + +class AppBarCloseButton extends StatelessWidget { + const AppBarCloseButton({this.onTap, this.withPopup = true, super.key}); + final VoidCallback? onTap; + final bool withPopup; + @override + Widget build(BuildContext context) { + return IconButton( + onPressed: () { + final onTap = this.onTap; + if (onTap != null) onTap(); + if (withPopup) { + Navigator.maybePop(context); // will be helpful for PopScope + } + }, + icon: const CustomAssetsSvg(IconsAssets.closeIcon, + size: secondAppBarIconSize), + ); + } +} + +class AppBarCheckButton extends StatelessWidget { + const AppBarCheckButton({ + this.onTap, + this.withPopup = true, + this.enableTap = true, + super.key, + }); + final VoidCallback? onTap; + final bool withPopup; + final bool enableTap; + @override + Widget build(BuildContext context) { + return IconButton( + icon: enableTap + ? const Icon(Icons.check_rounded, + size: secondAppBarIconSize, color: ColorManager.blue) + : const Icon(Icons.check_rounded, + size: secondAppBarIconSize, color: ColorManager.lightBlue), + onPressed: () { + final onTap = this.onTap; + if (onTap != null) onTap(); + if (withPopup) context.back(); + }, + ); + } +} + +class GlobalAppBarText extends StatelessWidget { + const GlobalAppBarText({super.key, required this.text}); + + final String text; + + @override + Widget build(BuildContext context) { + return MediumText( + text, + color: ThemeEnum.focusColor, + fontSize: 20, + maxLines: 1, + letterSpacing: 0.5, + ); + } +} From 1c3b6a482bfed4ab53a0a8cee5c0af64d51c23d4 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:13:50 +0300 Subject: [PATCH 06/54] create AppSettingsNotifier --- .../app_settings/app_settings_cubit.dart | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 lib/core/helpers/storage/app_settings/app_settings_cubit.dart diff --git a/lib/core/helpers/storage/app_settings/app_settings_cubit.dart b/lib/core/helpers/storage/app_settings/app_settings_cubit.dart new file mode 100644 index 0000000..3fd137d --- /dev/null +++ b/lib/core/helpers/storage/app_settings/app_settings_cubit.dart @@ -0,0 +1,92 @@ +import 'package:algorithm_visualizer/core/enums/app_settings_enum.dart'; +import 'package:algorithm_visualizer/core/extensions/language.dart'; +import 'package:flutter/material.dart'; +import 'package:riverpod/riverpod.dart'; +import 'package:get_storage/get_storage.dart'; + +part 'app_settings_state.dart'; + +// Define your StateNotifierProvider +final appSettingsProvider = + StateNotifierProvider( + (ref) => AppSettingsNotifier()); + +class AppSettingsNotifier extends StateNotifier { + AppSettingsNotifier() : super(AppSettingsState.initial()); + + static String getStorageKey = "AppSettings"; + final String _langSveKey = "lang"; + final String _modeSveKey = "mode"; + String? _languageSelectedChar; + ThemeMode? _selectedMode; + + // Use GetStorage instance + final GetStorage _storage = GetStorage(getStorageKey); + + LanguagesEnum get languageSelected => languageSelectedChar.language; + + String get languageSelectedChar => + _languageSelectedChar ?? _getLanguageSelectedChar; + String get _getLanguageSelectedChar => _storage.read(_langSveKey) ?? "en"; + + bool get isLangEnglish => languageSelected == LanguagesEnum.english; + + Future _saveLanguageToDisk(String lang) async { + await _storage.write(_langSveKey, lang); + if (_getLanguageSelectedChar != lang) throw "unable to change language"; + } + + Future changeLanguage(LanguagesEnum lang) async { + if (lang == languageSelected) return false; + + try { + await Future.wait([ + _saveLanguageToDisk(lang.shortKey), + // initializeDateFormatting(lang.shortKey, null), + ]); + + state = state.copyWith(language: lang); + + _languageSelectedChar = lang.shortKey; + + return true; + } catch (e) { + _languageSelectedChar = null; + + rethrow; + } + } + + Future _saveModeToDisk(String mode) async { + await _storage.write(_modeSveKey, mode); + if (_getModeSelected.name != mode) throw "unable to change the mode"; + _selectedMode = _getModeSelected; + } + + Future changeTheme(ThemeMode mode) async { + if (mode == modeSelected) return; + try { + await _saveModeToDisk(mode.name); + // final isLight = mode.name == 'light'; + // + // if (isLight) { + // Get.changeThemeMode(ThemeMode.light); + // } else { + // Get.changeThemeMode(ThemeMode.dark); + // } + state = state.copyWith(themeMode: mode); + } catch (e) { + _selectedMode = null; + rethrow; + } + } + + ThemeMode get modeSelected => _selectedMode ?? _getModeSelected; + + ThemeMode get _getModeSelected => + (_storage.read(_modeSveKey) ?? "light") == "light" + ? ThemeMode.light + : ThemeMode.dark; + + bool get isThemeLight => modeSelected == ThemeMode.light; +} From f067f88d24be4500ffae820816a9b8fab425c0f6 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:14:02 +0300 Subject: [PATCH 07/54] create LanguagesEnum --- lib/core/enums/app_settings_enum.dart | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 lib/core/enums/app_settings_enum.dart diff --git a/lib/core/enums/app_settings_enum.dart b/lib/core/enums/app_settings_enum.dart new file mode 100644 index 0000000..4dc6195 --- /dev/null +++ b/lib/core/enums/app_settings_enum.dart @@ -0,0 +1,2 @@ + +enum LanguagesEnum { english, arabic } From ade0a346105f5018503eb9a25a799af675a40adb Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:14:08 +0300 Subject: [PATCH 08/54] create AppSettingsState --- .../app_settings/app_settings_state.dart | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 lib/core/helpers/storage/app_settings/app_settings_state.dart diff --git a/lib/core/helpers/storage/app_settings/app_settings_state.dart b/lib/core/helpers/storage/app_settings/app_settings_state.dart new file mode 100644 index 0000000..8a9cf0b --- /dev/null +++ b/lib/core/helpers/storage/app_settings/app_settings_state.dart @@ -0,0 +1,22 @@ +part of 'app_settings_cubit.dart'; + +class AppSettingsState { + final LanguagesEnum language; + final ThemeMode themeMode; + + AppSettingsState({required this.language, required this.themeMode}); + + factory AppSettingsState.initial() { + return AppSettingsState( + language: LanguagesEnum.english, + themeMode: ThemeMode.light, + ); + } + + AppSettingsState copyWith({LanguagesEnum? language, ThemeMode? themeMode}) { + return AppSettingsState( + language: language ?? this.language, + themeMode: themeMode ?? this.themeMode, + ); + } +} From 6559eb67423b812f575ad65e41acbf5ce1eeee24 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:14:16 +0300 Subject: [PATCH 09/54] create AppTheme --- lib/config/themes/app_theme.dart | 277 +++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 lib/config/themes/app_theme.dart diff --git a/lib/config/themes/app_theme.dart b/lib/config/themes/app_theme.dart new file mode 100644 index 0000000..d4af138 --- /dev/null +++ b/lib/config/themes/app_theme.dart @@ -0,0 +1,277 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:algorithm_visualizer/core/resources/font_manager.dart'; +import 'package:algorithm_visualizer/core/resources/styles_manager.dart'; + +class AppTheme { + static ThemeData get light { + return ThemeData( + useMaterial3: true, + fontFamily: FontConstants.fontFamily, + visualDensity: VisualDensity.adaptivePlatformDensity, + primaryColor: ColorManager.white, + primaryColorLight: ColorManager.whiteD2, + hintColor: ColorManager.greyD4, + shadowColor: ColorManager.blackOp10, + focusColor: ColorManager.black, + disabledColor: ColorManager.blackOp50, + switchTheme: const SwitchThemeData(), + dialogBackgroundColor: ColorManager.whiteD1, + hoverColor: ColorManager.blackOp50, + indicatorColor: ColorManager.blackOp40, + highlightColor: ColorManager.whiteD3, + bottomSheetTheme: const BottomSheetThemeData( + backgroundColor: ColorManager.white, + surfaceTintColor: ColorManager.white, + shadowColor: ColorManager.white, + ), + dialogTheme: const DialogTheme(surfaceTintColor: ColorManager.whiteD5), + dividerColor: ColorManager.blackOp10, + scaffoldBackgroundColor: ColorManager.white, + iconTheme: const IconThemeData(color: ColorManager.black), + outlinedButtonTheme: _outlinedButtonTheme(), + elevatedButtonTheme: _elevatedButtonThemeData(), + textButtonTheme: const TextButtonThemeData( + style: ButtonStyle( + overlayColor: WidgetStatePropertyAll( + ColorManager.whiteD3, + ), + )), + chipTheme: const ChipThemeData(backgroundColor: ColorManager.blackOp10), + canvasColor: ColorManager.transparent, + splashColor: ColorManager.white, + appBarTheme: _appBarTheme(), + tabBarTheme: _tabBarTheme(), + textTheme: _textTheme(), + dividerTheme: const DividerThemeData(color: ColorManager.whiteD5), + bottomAppBarTheme: const BottomAppBarTheme(color: ColorManager.blackOp30), + textSelectionTheme: const TextSelectionThemeData( + cursorColor: ColorManager.teal, + selectionColor: ColorManager.blackOp10, + selectionHandleColor: ColorManager.black, + ), + listTileTheme: const ListTileThemeData(), + colorScheme: const ColorScheme.highContrastLight( + // circle avatar color + primaryContainer: ColorManager.whiteD4, + surface: ColorManager.whiteD3, + ) + .copyWith(surface: ColorManager.whiteD5) + .copyWith(error: ColorManager.black), + ); + } + + static ElevatedButtonThemeData _elevatedButtonThemeData() { + return ElevatedButtonThemeData( + style: ButtonStyle( + fixedSize: WidgetStateProperty.all(Size(double.maxFinite, 45.r)), + backgroundColor: WidgetStateProperty.resolveWith( + (_) => ColorManager.whiteD2), + overlayColor: WidgetStateProperty.resolveWith( + (_) => ColorManager.whiteOp20), + shape: WidgetStateProperty.all( + const RoundedRectangleBorder(borderRadius: BorderRadius.zero), + ), + ), + ); + } + + static OutlinedButtonThemeData _outlinedButtonTheme() { + return OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + fixedSize: Size(double.maxFinite, 45.r), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.r)), + side: BorderSide(width: 1.r, color: ColorManager.whiteD5), + ), + ); + } + + static TabBarTheme _tabBarTheme() { + return TabBarTheme( + indicatorSize: TabBarIndicatorSize.label, + labelPadding: EdgeInsets.zero, + indicator: BoxDecoration( + border: Border( + bottom: BorderSide(color: ColorManager.black, width: 1.5.r), + ), + ), + labelColor: ColorManager.black, + unselectedLabelColor: ColorManager.grey, + ); + } + + static TextTheme _textTheme() { + return TextTheme( + bodyLarge: _getStyle(const GetRegularStyle(color: ColorManager.greyD4)), + bodyMedium: _getStyle( + const GetRegularStyle(color: ColorManager.greyD5, fontSize: 12)), + bodySmall: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + titleSmall: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + labelSmall: _getStyle(const GetMediumStyle(color: ColorManager.greyD2)), + displaySmall: _getStyle(const GetMediumStyle(color: ColorManager.greyD2)), + displayLarge: _getStyle(const GetMediumStyle(color: ColorManager.grey)), + displayMedium: _getStyle(const GetMediumStyle(color: ColorManager.grey)), + headlineLarge: + _getStyle(const GetRegularStyle(color: ColorManager.whiteD3)), + headlineMedium: + _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + headlineSmall: + _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + labelLarge: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + labelMedium: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + titleLarge: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + titleMedium: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + ); + } + + static TextStyle _getStyle(TextStyle style) { + return style; + } + + static AppBarTheme _appBarTheme() { + return AppBarTheme( + elevation: 0, + titleSpacing: 5.w, + surfaceTintColor: ColorManager.white, + color: ColorManager.white, + shadowColor: ColorManager.blackOp20, + scrolledUnderElevation: 1.5.r, + iconTheme: const IconThemeData(color: ColorManager.black), + titleTextStyle: const GetRegularStyle( + fontSize: 16, color: ColorManager.black), + ); + } + + static ThemeData get dark { + return ThemeData( + useMaterial3: true, + fontFamily: FontConstants.fontFamily, + visualDensity: VisualDensity.adaptivePlatformDensity, + primaryColor: ColorManager.blackBlue, + primaryColorLight: ColorManager.blackL2, + hintColor: ColorManager.greyD4, + shadowColor: ColorManager.whiteOp10, + focusColor: ColorManager.white, + disabledColor: ColorManager.whiteOp50, + dialogBackgroundColor: ColorManager.blackL1, + hoverColor: ColorManager.whiteOp50, + indicatorColor: ColorManager.whiteOp40, + highlightColor: ColorManager.blackL3Blue, + bottomSheetTheme: const BottomSheetThemeData( + backgroundColor: ColorManager.blackL5, + surfaceTintColor: ColorManager.blackL5, + shadowColor: ColorManager.blackL5, + ), + dialogTheme: const DialogTheme(surfaceTintColor: ColorManager.blackL5), + dividerColor: ColorManager.whiteOp10, + scaffoldBackgroundColor: ColorManager.blackBlue, + iconTheme: const IconThemeData(color: ColorManager.white), + outlinedButtonTheme: _outlinedButtonDarkTheme(), + elevatedButtonTheme: _elevatedButtonDarkThemeData(), + textButtonTheme: const TextButtonThemeData( + style: ButtonStyle( + overlayColor: WidgetStatePropertyAll(ColorManager.blackL3Blue), + ), + ), + chipTheme: const ChipThemeData(backgroundColor: ColorManager.whiteOp10), + canvasColor: ColorManager.transparent, + splashColor: ColorManager.blackBlue, + appBarTheme: _appBarDarkTheme(), + tabBarTheme: _tabBarDarkTheme(), + textTheme: _textDarkTheme(), + dividerTheme: const DividerThemeData(color: ColorManager.blackL5), + bottomAppBarTheme: const BottomAppBarTheme(color: ColorManager.whiteOp30), + textSelectionTheme: const TextSelectionThemeData( + cursorColor: ColorManager.teal, + selectionColor: ColorManager.greyD6, + selectionHandleColor: ColorManager.white, + ), + colorScheme: const ColorScheme.highContrastDark( + primaryContainer: ColorManager.blackL4, + surface: ColorManager.blackL6, + ) + .copyWith(surface: ColorManager.blackL6) + .copyWith(error: ColorManager.white), + ); + } + + static ElevatedButtonThemeData _elevatedButtonDarkThemeData() { + return ElevatedButtonThemeData( + style: ButtonStyle( + fixedSize: WidgetStateProperty.all(Size(double.maxFinite, 45.r)), + backgroundColor: WidgetStateProperty.resolveWith( + (_) => ColorManager.blackL2), + overlayColor: WidgetStateProperty.resolveWith( + (_) => ColorManager.blackOp20), + shape: WidgetStateProperty.all( + const RoundedRectangleBorder(borderRadius: BorderRadius.zero), + ), + ), + ); + } + + static OutlinedButtonThemeData _outlinedButtonDarkTheme() { + return OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + fixedSize: Size(double.maxFinite, 45.r), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.r)), + side: BorderSide(width: 1.r, color: ColorManager.whiteD5), + ), + ); + } + + static TabBarTheme _tabBarDarkTheme() { + return TabBarTheme( + indicatorSize: TabBarIndicatorSize.label, + labelPadding: EdgeInsets.zero, + indicator: BoxDecoration( + border: Border( + bottom: BorderSide(color: ColorManager.white, width: 1.5.r), + ), + ), + labelColor: ColorManager.white, + unselectedLabelColor: ColorManager.grey, + ); + } + + static TextTheme _textDarkTheme() { + return TextTheme( + bodyLarge: _getStyle(const GetRegularStyle(color: ColorManager.greyD1)), + bodyMedium: _getStyle( + const GetRegularStyle(color: ColorManager.grey, fontSize: 12)), + bodySmall: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + titleSmall: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + labelSmall: _getStyle(const GetMediumStyle(color: ColorManager.greyD2)), + displaySmall: _getStyle(const GetMediumStyle(color: ColorManager.greyD2)), + displayLarge: _getStyle(const GetMediumStyle(color: ColorManager.grey)), + displayMedium: _getStyle(const GetMediumStyle(color: ColorManager.grey)), + headlineLarge: + _getStyle(const GetRegularStyle(color: ColorManager.blackL3Blue)), + headlineMedium: + _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + headlineSmall: + _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + labelLarge: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + labelMedium: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + titleLarge: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + titleMedium: _getStyle(const GetRegularStyle(color: ColorManager.greyD2)), + ); + } + + static AppBarTheme _appBarDarkTheme() { + return AppBarTheme( + elevation: 0, + titleSpacing: 5.w, + surfaceTintColor: ColorManager.blackBlue, + color: ColorManager.blackBlue, + shadowColor: ColorManager.greyD8, + scrolledUnderElevation: 1.5.r, + iconTheme: const IconThemeData(color: ColorManager.white), + titleTextStyle: const GetRegularStyle( + fontSize:16, color: ColorManager.white), + ); + } +} From 6a75174c0e901a843353c4a7b4b418716c361dc9 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:14:39 +0300 Subject: [PATCH 10/54] create CustomAppBarBackButton --- lib/core/helpers/app_bar/back_button.dart | 47 +++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 lib/core/helpers/app_bar/back_button.dart diff --git a/lib/core/helpers/app_bar/back_button.dart b/lib/core/helpers/app_bar/back_button.dart new file mode 100644 index 0000000..ae1ff85 --- /dev/null +++ b/lib/core/helpers/app_bar/back_button.dart @@ -0,0 +1,47 @@ +import 'package:algorithm_visualizer/core/enums/app_settings_enum.dart'; +import 'package:algorithm_visualizer/core/helpers/storage/app_settings/app_settings_cubit.dart'; +import 'package:algorithm_visualizer/core/helpers/svg_picture.dart'; +import 'package:algorithm_visualizer/core/resources/assets_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class CustomAppBarBackButton extends StatelessWidget { + const CustomAppBarBackButton({super.key}); + + @override + Widget build(BuildContext context) { + return IconButton( + icon: const CustomBackButtonIcon(), + + onPressed: () { + Navigator.maybePop(context); + }, + ); + } +} + +class CustomBackButtonIcon extends ConsumerWidget { + const CustomBackButtonIcon({super.key}); + + @override + Widget build(BuildContext context, ref) { + final isLangEnglish = + ref.watch(appSettingsProvider).language == LanguagesEnum.english; + + final String icon; + switch (Theme.of(context).platform) { + case TargetPlatform.android: + case TargetPlatform.fuchsia: + case TargetPlatform.linux: + case TargetPlatform.windows: + icon = + isLangEnglish ? IconsAssets.backButton : IconsAssets.backButtonRTL; + case TargetPlatform.iOS: + case TargetPlatform.macOS: + icon = isLangEnglish + ? IconsAssets.iosBackButton + : IconsAssets.iosBackButtonRTL; + } + return CustomAssetsSvg(icon, size: 30); + } +} From 739740480026b84a50dccbaa4eadbe68559dad29 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:14:50 +0300 Subject: [PATCH 11/54] create BoldText --- lib/core/widgets/adaptive/text/bold_text.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lib/core/widgets/adaptive/text/bold_text.dart diff --git a/lib/core/widgets/adaptive/text/bold_text.dart b/lib/core/widgets/adaptive/text/bold_text.dart new file mode 100644 index 0000000..7a8aaf9 --- /dev/null +++ b/lib/core/widgets/adaptive/text/bold_text.dart @@ -0,0 +1,16 @@ +part of 'adaptive_text.dart'; + +class BoldText extends _AdaptiveText { + const BoldText( + super.text, { + super.fontSize = 16, + super.decoration = TextDecoration.none, + super.fontStyle = FontStyle.normal, + super.color = ThemeEnum.focusColor, + super.shadows, + super.fontWeight= FontWeightManager.bold, + super.textAlign, + super.maxLines = 2, + super.key, + }) ; +} From 112aaf0038562413ee0972063d30d4d79df7ed1c Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:14:54 +0300 Subject: [PATCH 12/54] create BottomPadding --- .../widgets/adaptive/padding/bottom_padding.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/bottom_padding.dart diff --git a/lib/core/widgets/adaptive/padding/bottom_padding.dart b/lib/core/widgets/adaptive/padding/bottom_padding.dart new file mode 100644 index 0000000..6b70b89 --- /dev/null +++ b/lib/core/widgets/adaptive/padding/bottom_padding.dart @@ -0,0 +1,13 @@ +part of 'adaptive_padding.dart'; + + +class BottomPadding extends StatelessWidget { + const BottomPadding({required this.padding, required this.child, super.key}); + final double padding; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: REdgeInsetsDirectional.only(bottom: padding), child: child); + } +} From 712e6301813d242dbfbde02127d7b9343f2c2ff6 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:14:58 +0300 Subject: [PATCH 13/54] create CustomCheckBox --- .../widgets/custom_widgets/check_box.dart | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/check_box.dart diff --git a/lib/core/widgets/custom_widgets/check_box.dart b/lib/core/widgets/custom_widgets/check_box.dart new file mode 100644 index 0000000..c2e9bd3 --- /dev/null +++ b/lib/core/widgets/custom_widgets/check_box.dart @@ -0,0 +1,52 @@ +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:algorithm_visualizer/core/widgets/custom_widgets/custom_icon.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class CustomCheckBox extends StatelessWidget { + const CustomCheckBox({ + required this.isSelected, + this.size = 26, + this.isCircle = true, + this.withCheckIcon = false, + super.key, + }); + final bool isSelected; + final bool isCircle; + final bool withCheckIcon; + final double size; + @override + Widget build(BuildContext context) { + return Container( + height: size, + width: size, + decoration: BoxDecoration( + shape: isCircle ? BoxShape.circle : BoxShape.rectangle, + color: ColorManager.transparent, + border: Border.all( + width: 1.5.r, + color: isSelected + ? context.getColor(ThemeEnum.focusColor) + : context.getColor(ThemeEnum.whiteD5Color)), + ), + child: Padding( + padding: const EdgeInsets.all(3), + child: AnimatedContainer( + duration: const Duration(milliseconds: 300), + curve: Curves.easeInOut, + height: isSelected ? 20 : 0, + width: isSelected ? 20 : 0, + decoration: BoxDecoration( + color: isSelected ? context.getColor(ThemeEnum.focusColor) : null, + shape: isCircle ? BoxShape.circle : BoxShape.rectangle, + ), + child: isSelected && withCheckIcon + ? const CustomIcon(Icons.check_rounded, + color: ThemeEnum.whiteColor, size: 18) + : null, + ), + ), + ); + } +} From eb6f79c953bdde3c8b5339cd0ddac6444ce8e194 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:03 +0300 Subject: [PATCH 14/54] create ColorManager --- lib/core/resources/color_manager.dart | 103 ++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 lib/core/resources/color_manager.dart diff --git a/lib/core/resources/color_manager.dart b/lib/core/resources/color_manager.dart new file mode 100644 index 0000000..43b5297 --- /dev/null +++ b/lib/core/resources/color_manager.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; + +/// [ColorManager] +/// colorD means that get dark version from the color for example: +/// greyD2 means that get version 2 darker from grey. +/// "less darker D1 < D2 < D4 < D7 < D9 more darker" +/// ------------------------> +/// colorL means that get light version from the color for example: +/// blackL4 means that get version 4 lighter from dark. +/// "less lighter L1 < L2 < L3 < L5 < L8 more lighter" +/// ------------------------> +/// colorOp means that get less opacity version from the main color for example: +/// blackT1 means that get the same main color "black" but with less opacity. +/// opacity for main black: +/// black => 100% +/// blackOp90 => 90% +/// blackOp80 => 80% +/// blackOp70 => 70% +/// blackOp60 => 60% +/// blackOp50 => 50% +/// blackOp40 => 40% +/// blackOp30 => 30% +/// blackOp20 => 20% +/// blackOp10 => 10% + +abstract final class ColorManager { + static const Color transparent = Colors.transparent; + static const Color transparentWhite = + Color.fromRGBO(255, 255, 255, 0.48627450980392156); + static const Color whiteOp10 = Color.fromRGBO(255, 255, 255, .1); + static const Color whiteOp20 = Color.fromRGBO(255, 255, 255, .2); + static const Color whiteOp30 = Color.fromRGBO(255, 255, 255, .3); + static const Color whiteOp40 = Color.fromRGBO(255, 255, 255, .4); + static const Color whiteOp50 = Color.fromRGBO(255, 255, 255, .5); + static const Color whiteOp60 = Color.fromRGBO(255, 255, 255, .6); + static const Color whiteOp70 = Color.fromRGBO(255, 255, 255, .7); + static const Color whiteOp80 = Color.fromRGBO(255, 255, 255, .8); + static const Color whiteOp90 = Color.fromRGBO(255, 255, 255, .9); + static const Color white = Color.fromRGBO(255, 255, 255, 1); + static const Color whiteD1 = Color.fromRGBO(245, 245, 245, 1); + static const Color whiteD2 = Color.fromRGBO(240, 240, 240, 1); + static const Color whiteD3 = Color.fromRGBO(235, 235, 235, 1); + static const Color whiteD4 = Color.fromRGBO(225, 225, 225, 1); + static const Color whiteD5 = Color.fromRGBO(215, 215, 215, 1); + static const Color whiteD6 = Color.fromRGBO(205, 205, 205, 1); + static const Color whiteD7 = Color.fromRGBO(195, 195, 195, 1); + static const Color whiteD8 = Color.fromRGBO(185, 185, 185, 1); + static const Color whiteD9 = Color.fromRGBO(175, 175, 175, 1); + static const Color whiteD10 = Color.fromRGBO(165, 165, 165, 1); + + static const Color grey = Color.fromRGBO(155, 155, 155, 1); + static const Color greyOp70 = Color.fromRGBO(155, 155, 155, 0.84); + static const Color greyD1 = Color.fromRGBO(145, 145, 145, 1); + static const Color greyD2 = Color.fromRGBO(135, 135, 135, 1); + static const Color greyD3 = Color.fromRGBO(125, 125, 125, 1); + static const Color greyD4 = Color.fromRGBO(115, 115, 115, 1); + static const Color greyD5 = Color.fromRGBO(105, 105, 105, 1); + static const Color greyD6 = Color.fromRGBO(95, 95, 95, 1); + static const Color greyD7 = Color.fromRGBO(85, 85, 85, 1); + static const Color greyD8 = Color.fromRGBO(75, 75, 75, 1); + static const Color greyD9 = Color.fromRGBO(65, 65, 65, 1); + + static const Color blackL6 = Color.fromRGBO(55, 55, 55, 1); + static const Color blackL5 = Color.fromRGBO(45, 45, 45, 1); + static const Color blackL4 = Color.fromRGBO(35, 35, 35, 1); + static const Color blackL3 = Color.fromRGBO(25, 25, 25, 1); + static const Color blackL2 = Color.fromRGBO(15, 15, 15, 1); + static const Color blackL1 = Color.fromRGBO(05, 05, 05, 1); + static const Color black = Color.fromRGBO(00, 00, 00, 1); + static const Color blackOp90 = Color.fromRGBO(00, 00, 00, 0.9); + static const Color blackOp80 = Color.fromRGBO(00, 00, 00, 0.8); + static const Color blackOp70 = Color.fromRGBO(00, 00, 00, 0.7); + static const Color blackOp60 = Color.fromRGBO(00, 00, 00, 0.6); + static const Color blackOp50 = Color.fromRGBO(00, 00, 00, 0.5); + static const Color blackOp40 = Color.fromRGBO(00, 00, 00, 0.4); + static const Color blackOp30 = Color.fromRGBO(00, 00, 00, 0.3); + static const Color blackOp20 = Color.fromRGBO(00, 00, 00, 0.2); + static const Color blackOp10 = Color.fromRGBO(00, 00, 00, 0.1); + static const Color rankingGrey = Color.fromRGBO(153, 156, 159, 1.0); + + /// ------------------------------------------> + + static const Color blue = Color.fromRGBO(41, 157, 250, 1.0); + static const Color darkBlue1 = Color.fromRGBO(23, 154, 255, 1.0); + static const Color darkBlue = Color.fromRGBO(7, 114, 199, 1.0); + static const Color lightBlue = Color.fromRGBO(177, 221, 255, 1.0); + static const Color lightBlueM2 = Color.fromRGBO(209, 234, 255, 1.0); + static const Color lightBlueWhiteD1 = Color.fromRGBO(243, 243, 246, 1.0); + static const Color blackL3Blue = Color.fromRGBO(14, 14, 19, 1.0); + static const Color blackBlue = Color.fromRGBO(0, 0, 5, 1.0); + static const Color green = Color.fromRGBO(25, 189, 98, 1.0); + static const Color purple = Color.fromRGBO(160, 4, 238, 1); + static const Color purple2 = Color.fromRGBO(198, 0, 229, 1.0); + static const Color red = Color.fromRGBO(224, 60, 31, 1.0); + static const Color red2 = Color.fromRGBO(241, 83, 47, 1.0); + static const Color blackRed = Color.fromARGB(255, 182, 14, 14); + static const Color orange = Color.fromRGBO(253, 160, 7, 1.0); + static const Color teal = Color.fromRGBO(35, 133, 100, 1); + static const Color redAccent = Color.fromRGBO(236, 91, 98, 1); + static const Color yellow = Color.fromRGBO(246, 209, 11, 1.0); + static const Color lightYellow = Color.fromARGB(219, 255, 240, 27); + static const Color light2Yellow = Color.fromARGB(255, 255, 217, 27); +} From 05f76ebb14155c70b7f72f6a59433fab23bf537b Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:14 +0300 Subject: [PATCH 15/54] create CurrentDevice --- lib/core/helpers/current_device.dart | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 lib/core/helpers/current_device.dart diff --git a/lib/core/helpers/current_device.dart b/lib/core/helpers/current_device.dart new file mode 100644 index 0000000..1fc7f3c --- /dev/null +++ b/lib/core/helpers/current_device.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +extension CurrentDevice on BuildContext { + bool get isAndroid { + final ThemeData theme = Theme.of(this); + return theme.platform == TargetPlatform.android; + } +} From bc63c43ae05c3dc375e5f979797c70244e7049b5 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:23 +0300 Subject: [PATCH 16/54] create DialogParameters --- lib/core/helpers/custom_alert_dialog.dart | 130 ++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 lib/core/helpers/custom_alert_dialog.dart diff --git a/lib/core/helpers/custom_alert_dialog.dart b/lib/core/helpers/custom_alert_dialog.dart new file mode 100644 index 0000000..2979d85 --- /dev/null +++ b/lib/core/helpers/custom_alert_dialog.dart @@ -0,0 +1,130 @@ +import 'package:algorithm_visualizer/core/extensions/navigators.dart'; +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.dart'; +import 'package:algorithm_visualizer/core/widgets/custom_widgets/custom_divider.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +const double _borderRadius = 15; + +class DialogParameters { + final String title; + final String content; + final VoidCallback? onTapCancel; + final bool allowCancelPopup; + final String cancelText; + final String actionText; + final VoidCallback onTapAction; + + DialogParameters({ + required this.title, + required this.content, + this.allowCancelPopup = false, + this.onTapCancel, + this.cancelText = StringsManager.cancel, + required this.actionText, + required this.onTapAction, + }); +} + +class CustomAlertDialog { + final BuildContext context; + CustomAlertDialog(this.context); + + Future openDialog(DialogParameters parameters, + {bool barrierDismissible = true}) { + return showDialog( + context: context, + barrierDismissible: barrierDismissible, + builder: (context) { + return AlertDialog( + contentPadding: const EdgeInsetsDirectional.all(0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(_borderRadius.r), + ), + content: _Content(parameters), + ); + }, + ); + } +} + +class _Content extends StatelessWidget { + const _Content(this.parameters); + final DialogParameters parameters; + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + width: double.infinity, + child: Padding( + padding: REdgeInsets.symmetric(horizontal: 25, vertical: 25), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SemiBoldText( + parameters.title, + fontSize: 20, + textAlign: TextAlign.center, + ), + const RSizedBox(height: 5), + RegularText( + parameters.content, + maxLines: 15, + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + const CustomDivider(withHeight: false), + InkWell( + onTap: parameters.onTapAction, + child: SizedBox( + width: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: REdgeInsets.symmetric(vertical: 10), + child: BoldText(parameters.actionText, + color: ThemeEnum.redColor), + ), + ], + ), + ), + ), + const CustomDivider(withHeight: false), + InkWell( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(_borderRadius.r), + bottomRight: Radius.circular(_borderRadius.r)), + onTap: () { + final onTapCancel = parameters.onTapCancel; + if (onTapCancel != null) onTapCancel(); + + if (parameters.allowCancelPopup || onTapCancel == null) { + context.pop(); + } + }, + child: SizedBox( + width: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: REdgeInsets.symmetric(vertical: 10), + child: RegularText(parameters.cancelText, + color: ThemeEnum.focusColor), + ), + ], + ), + ), + ), + ], + ); + } +} From 7f51ee60db58ed795d23ba48a6123cb5a9f334af Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:27 +0300 Subject: [PATCH 17/54] create CustomBottomSheet --- .../custom_widgets/custom_bottom_sheet.dart | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/custom_bottom_sheet.dart diff --git a/lib/core/widgets/custom_widgets/custom_bottom_sheet.dart b/lib/core/widgets/custom_widgets/custom_bottom_sheet.dart new file mode 100644 index 0000000..be9fa5f --- /dev/null +++ b/lib/core/widgets/custom_widgets/custom_bottom_sheet.dart @@ -0,0 +1,204 @@ +import 'package:algorithm_visualizer/core/extensions/navigators.dart'; +import 'package:algorithm_visualizer/core/helpers/svg_picture.dart'; +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/padding/adaptive_padding.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.dart'; +import 'package:algorithm_visualizer/core/widgets/custom_widgets/custom_divider.dart'; +import 'package:flutter/material.dart'; + +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class CustomBottomSheet { + static BuildContext? context; + static initializeContextForPost(BuildContext ctx) { + context = ctx; + } + + static Future bottomSheet( + BuildContext ctx, { + required Widget child, + bool isScrollControlled = false, + }) async { + final tempContext = context ?? ctx; + if (isScrollControlled) { + return scrollableBottomSheet( + tempContext, + withDivider: false, + scrollable: true, + child: [child], + ); + } + return showModalBottomSheet( + context: tempContext, + useSafeArea: true, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: const Radius.circular(15).r), + ), + builder: (BuildContext context) { + return RSizedBox( + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + const Align( + alignment: AlignmentDirectional.center, + child: _BottomSheetDash(), + ), + child, + const RSizedBox(height: 10), + ], + ), + ); + }, + ); + } + + static Future _showBottomSheet( + BuildContext context, Widget child) async { + return showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + isDismissible: false, + useSafeArea: true, + builder: (context) { + return GestureDetector( + onTap: () { + context.back(); + }, + child: Container( + color: ColorManager.transparent, + child: GestureDetector( + onTap: () {}, + child: DraggableScrollableSheet( + initialChildSize: 0.8, + minChildSize: 0.8, + maxChildSize: 0.8, + builder: (_, controller) { + return Container( + decoration: BoxDecoration( + color: context.getColor(ThemeEnum.bottomSheetColor), + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10), + topRight: Radius.circular(10), + ), + ), + child: child, + ); + }, + ), + ), + ), + ); + }, + ); + } + + static Future scrollableBottomSheet( + BuildContext ctx, { + required List child, + Widget? title, + bool withDivider = true, + bool scrollable = true, + double childHorizontalPadding = 0, + }) async { + final tempContext = context ?? ctx; + return _showBottomSheet( + tempContext, + Padding( + padding: REdgeInsets.symmetric(vertical: 5), + child: Padding( + padding: REdgeInsets.symmetric(horizontal: childHorizontalPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + const Align( + alignment: AlignmentDirectional.center, + child: _BottomSheetDash(withLittleBottomPadding: true), + ), + title ?? const SizedBox(), + if (withDivider) const CustomDivider(color: ThemeEnum.greyColor), + Flexible( + child: scrollable + ? SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: child, + ), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: child, + ), + ), + const RSizedBox(height: 10), + ], + ), + ), + ), + ); + } +} + +class _BottomSheetDash extends StatelessWidget { + const _BottomSheetDash({this.withLittleBottomPadding = false}); + final bool withLittleBottomPadding; + @override + Widget build(BuildContext context) { + return Padding( + padding: REdgeInsetsDirectional.only( + start: 10, + end: 10, + top: 10, + bottom: withLittleBottomPadding ? 5 : 10), + child: Container( + width: 40.w, + height: 3.5.h, + decoration: BoxDecoration( + color: context.getColor(ThemeEnum.hoverColor), + borderRadius: BorderRadius.circular(5)), + ), + ); + } +} + +class BottomSheetText extends StatelessWidget { + const BottomSheetText( + this.text, { + this.color = ThemeEnum.focusColor, + this.icon, + this.iconSize, + super.key, + }); + final String text; + final String? icon; + final double? iconSize; + final ThemeEnum color; + @override + Widget build(BuildContext context) { + final icon = this.icon; + return RSizedBox( + width: double.infinity, + child: SymmetricPadding( + horizontal: 25, + vertical: 10, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (icon != null) ...[ + CustomAssetsSvg(icon, size: iconSize, color: color), + const RSizedBox(width: 25), + ], + Flexible(child: RegularText(text, color: color)), + ], + ), + ), + ); + } +} From a5534fc372b33d247521274de867ccea3378ad53 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:31 +0300 Subject: [PATCH 18/54] create CustomCircularProgress --- .../custom_circulars_progress.dart | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/custom_circulars_progress.dart diff --git a/lib/core/widgets/custom_widgets/custom_circulars_progress.dart b/lib/core/widgets/custom_widgets/custom_circulars_progress.dart new file mode 100644 index 0000000..6121fa9 --- /dev/null +++ b/lib/core/widgets/custom_widgets/custom_circulars_progress.dart @@ -0,0 +1,238 @@ +import 'package:algorithm_visualizer/core/helpers/current_device.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart' + show TargetPlatform, defaultTargetPlatform; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class CustomCircularProgress extends StatelessWidget { + final ThemeEnum? color; + const CustomCircularProgress({this.color, super.key}); + + @override + Widget build(BuildContext context) { + bool isThatAndroid = defaultTargetPlatform == TargetPlatform.android; + final color = this.color; + final tColor = + color == null ? Theme.of(context).focusColor : context.getColor(color); + + return isThatAndroid + ? Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Transform.scale( + scale: 0.75, + child: SizedBox( + width: 20.r, + height: 20.r, + child: CircularProgressIndicator( + strokeWidth: 3.r, color: tColor), + ), + ), + ], + ) + : CupertinoActivityIndicator( + color: tColor, radius: 9.r, animating: true); + } +} + +class SmallCircularProgress extends StatelessWidget { + final ThemeEnum? color; + const SmallCircularProgress({this.color, super.key}); + + @override + Widget build(BuildContext context) { + bool isThatAndroid = defaultTargetPlatform == TargetPlatform.android; + final color = this.color; + final tColor = + color == null ? Theme.of(context).focusColor : context.getColor(color); + + return isThatAndroid + ? SizedBox( + width: 15.r, + height: 15.r, + child: ClipOval( + child: + CircularProgressIndicator(strokeWidth: 3.5.r, color: tColor), + ), + ) + : CupertinoActivityIndicator( + color: tColor, radius: 9.r, animating: true); + } +} + +class ThineCircularProgress extends StatelessWidget { + final ThemeEnum? color; + final ThemeEnum? backgroundColor; + final double strokeWidth; + const ThineCircularProgress( + {super.key, this.color, this.backgroundColor, this.strokeWidth = 2}); + + @override + Widget build(BuildContext context) { + final color = this.color; + final tColor = + color == null ? Theme.of(context).focusColor : context.getColor(color); + final backgroundColor = this.backgroundColor; + + return Center( + child: CircularProgressIndicator.adaptive( + strokeWidth: strokeWidth.r, + valueColor: AlwaysStoppedAnimation(tColor), + backgroundColor: + backgroundColor != null ? context.getColor(backgroundColor) : null, + ), + ); + } +} + +class ThineCircularProgressWithValue extends StatelessWidget { + final ThemeEnum? color; + final ThemeEnum? backgroundColor; + final double strokeWidth; + final double value; + const ThineCircularProgressWithValue({ + super.key, + this.color, + this.backgroundColor, + this.strokeWidth = 2, + this.value = 0, + }); + + @override + Widget build(BuildContext context) { + final color = this.color; + final tColor = + color == null ? Theme.of(context).focusColor : context.getColor(color); + final backgroundColor = this.backgroundColor; + + return Center( + child: CircularProgressIndicator.adaptive( + strokeWidth: strokeWidth.r, + valueColor: AlwaysStoppedAnimation(tColor), + backgroundColor: + backgroundColor != null ? context.getColor(backgroundColor) : null, + value: value, + ), + ); + } +} + +class CustomLinearProgress extends StatelessWidget { + final ThemeEnum color; + final ThemeEnum backgroundColor; + final double strokeWidth; + const CustomLinearProgress({ + super.key, + this.color = ThemeEnum.focusColor, + this.backgroundColor = ThemeEnum.whiteD2Color, + this.strokeWidth = 1.5, + }); + + @override + Widget build(BuildContext context) { + return Center( + child: LinearProgressIndicator( + minHeight: strokeWidth.r, + color: context.getColor(color), + backgroundColor: context.getColor(backgroundColor), + ), + ); + } +} + +class CustomThineCircularProgress extends StatelessWidget { + final ThemeEnum? color; + final ThemeEnum? backgroundColor; + final double strokeWidth; + const CustomThineCircularProgress( + {super.key, this.color, this.backgroundColor, this.strokeWidth = 2}); + + @override + Widget build(BuildContext context) { + final color = this.color; + final tColor = + color == null ? Theme.of(context).focusColor : context.getColor(color); + final backgroundColor = this.backgroundColor; + + return Center( + child: context.isAndroid + ? CircularProgressIndicator( + strokeWidth: strokeWidth.r, + valueColor: AlwaysStoppedAnimation(tColor), + backgroundColor: backgroundColor != null + ? context.getColor(backgroundColor) + : null, + ) + : CupertinoActivityIndicator( + color: tColor, radius: strokeWidth.r, animating: true), + ); + } +} + +class CustomThineCircularProgressWithValue extends StatelessWidget { + final ThemeEnum? color; + final ThemeEnum? backgroundColor; + final double strokeWidth; + final double value; + const CustomThineCircularProgressWithValue({ + super.key, + this.color, + this.backgroundColor, + this.strokeWidth = 2, + this.value = 0, + }); + + @override + Widget build(BuildContext context) { + final color = this.color; + final tColor = + color == null ? Theme.of(context).focusColor : context.getColor(color); + final backgroundColor = this.backgroundColor; + + return Center( + child: context.isAndroid + ? CircularProgressIndicator( + strokeWidth: strokeWidth.r, + valueColor: AlwaysStoppedAnimation(tColor), + backgroundColor: backgroundColor != null + ? context.getColor(backgroundColor) + : null, + value: value, + ) + : CupertinoActivityIndicator( + color: tColor, radius: strokeWidth.r, animating: false), + ); + } +} + +class BaseCircularProgress extends StatelessWidget { + final ThemeEnum? color; + final ThemeEnum? backgroundColor; + final double strokeWidth; + const BaseCircularProgress({ + super.key, + this.color, + this.backgroundColor, + this.strokeWidth = 2, + }); + + @override + Widget build(BuildContext context) { + final color = this.color; + final tColor = + color == null ? Theme.of(context).focusColor : context.getColor(color); + final backgroundColor = this.backgroundColor; + + return Center( + child: CircularProgressIndicator( + strokeWidth: strokeWidth.r, + valueColor: AlwaysStoppedAnimation(tColor), + backgroundColor: + backgroundColor != null ? context.getColor(backgroundColor) : null, + ), + ); + } +} From 390982623a12049e148a9c2f0b539e9686bd12ce Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:36 +0300 Subject: [PATCH 19/54] create CustomDivider --- .../custom_widgets/custom_divider.dart | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/custom_divider.dart diff --git a/lib/core/widgets/custom_widgets/custom_divider.dart b/lib/core/widgets/custom_widgets/custom_divider.dart new file mode 100644 index 0000000..6fe568b --- /dev/null +++ b/lib/core/widgets/custom_widgets/custom_divider.dart @@ -0,0 +1,32 @@ +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class CustomDivider extends StatelessWidget { + const CustomDivider({ + this.color = ThemeEnum.whiteD4Color, + this.withHeight = true, + this.thickness, + super.key, + }); + final ThemeEnum color; + final bool withHeight; + final double? thickness; + @override + Widget build(BuildContext context) { + return Divider( + color: context.getColor(color), + height: withHeight ? 4.r : 0, + thickness: thickness, + ); + } +} + +class WideCustomDivider extends StatelessWidget { + const WideCustomDivider({super.key}); + + @override + Widget build(BuildContext context) { + return const CustomDivider(color: ThemeEnum.whiteD1Color, thickness: 5); + } +} From 3c99244083bf05cfb18faaf9792e9af0f0d6a0ec Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:40 +0300 Subject: [PATCH 20/54] create CustomIcon --- .../widgets/custom_widgets/custom_icon.dart | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/custom_icon.dart diff --git a/lib/core/widgets/custom_widgets/custom_icon.dart b/lib/core/widgets/custom_widgets/custom_icon.dart new file mode 100644 index 0000000..7fa374b --- /dev/null +++ b/lib/core/widgets/custom_widgets/custom_icon.dart @@ -0,0 +1,26 @@ +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class CustomIcon extends StatelessWidget { + const CustomIcon( + this.icon, { + this.size = 22, + this.color = ThemeEnum.focusColor, + this.shadows, + super.key, + }); + final IconData icon; + final ThemeEnum color; + final double size; + final List? shadows; + @override + Widget build(BuildContext context) { + return Icon( + icon, + color: context.getColor(color), + size: size.r, + shadows: shadows, + ); + } +} From 02ba0fba2ed1bedcd03abcd1303b7575c4d2ce45 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:15:56 +0300 Subject: [PATCH 21/54] create CustomRoundedElevatedButton --- .../custom_rounded_elevated_button.dart | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart diff --git a/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart b/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart new file mode 100644 index 0000000..9e7fecd --- /dev/null +++ b/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart @@ -0,0 +1,48 @@ +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class CustomRoundedElevatedButton extends StatelessWidget { + final ThemeEnum? backgroundColor; + final ThemeEnum? shadowColor; + final Widget child; + final VoidCallback onPressed; + final bool fitToContent; + final bool smallRounded; + final double fixedSize; + const CustomRoundedElevatedButton({ + super.key, + this.backgroundColor = ThemeEnum.focusColor, + this.shadowColor = ThemeEnum.transparentColor, + this.fitToContent = true, + this.smallRounded = false, + this.fixedSize = 35, + required this.child, + required this.onPressed, + }); + + @override + Widget build(BuildContext context) { + final backgroundColor = this.backgroundColor; + final shadowColor = this.shadowColor; + final background = + backgroundColor == null ? null : context.getColor(backgroundColor); + final shadow = shadowColor == null ? null : context.getColor(shadowColor); + + return ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: background, + shadowColor: shadow ?? ColorManager.transparent, + fixedSize: fitToContent ? Size.fromHeight(fixedSize.r) : null, + padding: EdgeInsets.symmetric(horizontal: 15.r), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(smallRounded ? 10 : 50).r), + surfaceTintColor: background, + foregroundColor: context.getColor(ThemeEnum.hintColor), + ), + onPressed: onPressed, + child: child, + ); + } +} From 33492e9ceb081d57258871625efec7441f7ae845 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:16:00 +0300 Subject: [PATCH 22/54] create CustomSwitch --- .../widgets/custom_widgets/custom_switch.dart | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/custom_switch.dart diff --git a/lib/core/widgets/custom_widgets/custom_switch.dart b/lib/core/widgets/custom_widgets/custom_switch.dart new file mode 100644 index 0000000..902dd7b --- /dev/null +++ b/lib/core/widgets/custom_widgets/custom_switch.dart @@ -0,0 +1,40 @@ +import 'package:algorithm_visualizer/config/themes/app_theme.dart'; +import 'package:algorithm_visualizer/core/helpers/storage/app_settings/app_settings_cubit.dart'; +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +/// [Theme] sometimes switch came from material 2 randomly, +/// so this to make sure for it (not enough if you right useMaterial3 in app theme) + +class CustomSwitch extends ConsumerWidget { + const CustomSwitch({required this.value, required this.onChanged, super.key}); + final bool value; + + final void Function(bool value) onChanged; + @override + Widget build(BuildContext context, WidgetRef ref) { + final isLight = ref.watch(appSettingsProvider).themeMode == ThemeMode.light; + return Theme( + data: isLight ? AppTheme.light : AppTheme.dark, + child: Switch.adaptive( + value: value, + onChanged: onChanged, + activeTrackColor: context.getColor(ThemeEnum.focusColor), + activeColor: context.getColor(ThemeEnum.whiteD1Color), + inactiveThumbColor: context.getColor(ThemeEnum.whiteColor), + thumbIcon: WidgetStatePropertyAll( + Icon( + Icons.add, + color: context.getColor(ThemeEnum.transparentColor), + ), + ), + inactiveTrackColor: + isLight ? ColorManager.whiteD5 : ColorManager.blackL3, + trackOutlineColor: + const WidgetStatePropertyAll(ColorManager.transparent), + ), + ); + } +} From 695843a358d47f64ecc0777dbc2a29065eb7234d Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:16:11 +0300 Subject: [PATCH 23/54] create EndPadding --- lib/core/widgets/adaptive/padding/end_padding.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/end_padding.dart diff --git a/lib/core/widgets/adaptive/padding/end_padding.dart b/lib/core/widgets/adaptive/padding/end_padding.dart new file mode 100644 index 0000000..ca4bdbc --- /dev/null +++ b/lib/core/widgets/adaptive/padding/end_padding.dart @@ -0,0 +1,12 @@ +part of 'adaptive_padding.dart'; + +class EndPadding extends StatelessWidget { + const EndPadding({required this.padding, required this.child, super.key}); + final double padding; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: REdgeInsetsDirectional.only(end: padding), child: child); + } +} From d54225f2870293fb97c6d57724e102ef72f2a440 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:16:19 +0300 Subject: [PATCH 24/54] create ErrorScreen --- .../widgets/custom_widgets/error_screen.dart | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/error_screen.dart diff --git a/lib/core/widgets/custom_widgets/error_screen.dart b/lib/core/widgets/custom_widgets/error_screen.dart new file mode 100644 index 0000000..a7cb014 --- /dev/null +++ b/lib/core/widgets/custom_widgets/error_screen.dart @@ -0,0 +1,27 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/padding/adaptive_padding.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.dart'; +import 'package:flutter/foundation.dart' as foundation; +import 'package:flutter/material.dart'; + +class ErrorScreen extends StatelessWidget { + const ErrorScreen(this.detailsException, {super.key}); + final dynamic detailsException; + @override + Widget build(BuildContext context) { + return Material( + child: AllPadding( + padding: 20, + child: foundation.kReleaseMode + ? const Center( + child: RegularText(StringsManager.sorryForInconvenience, + fontSize: 18), + ) + : Center( + child: RegularText('Exception Details: $detailsException', + maxLines: 5), + ), + ), + ); + } +} From 16be839144fc3be6db4d7635f26eaa39b04fe09d Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:16:25 +0300 Subject: [PATCH 25/54] create FontWeightManager --- lib/core/resources/font_manager.dart | 40 ++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 lib/core/resources/font_manager.dart diff --git a/lib/core/resources/font_manager.dart b/lib/core/resources/font_manager.dart new file mode 100644 index 0000000..8a4e452 --- /dev/null +++ b/lib/core/resources/font_manager.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +// import 'package:google_fonts/google_fonts.dart'; +// +// class CustomGoogleFont { +// static TextStyle getFontStyle({required TextStyle textStyle}) { +// return textStyle.copyWith(fontWeight: FontWeight.w100); +// } +// +// static TextTheme getFontTextTheme(TextTheme textTheme) { +// return textTheme; +// } +// } + +class FontConstants { + static const String fontFamily = "Sf_UI_Display"; +} + +class FontWeightManager { + static const FontWeight light100 = FontWeight.w100; + static const FontWeight light200 = FontWeight.w200; + static const FontWeight light = FontWeight.w300; + static const FontWeight regular = FontWeight.w400; + static const FontWeight medium = FontWeight.w500; + static const FontWeight semiBold = FontWeight.w600; + static const FontWeight bold = FontWeight.w700; + static const FontWeight bold800 = FontWeight.w800; + static const FontWeight bold900 = FontWeight.w900; + + static FontWeight getAdaptiveFontWeight(FontWeight oldWeight) { + if (oldWeight == light100) return light200; + if (oldWeight == light200) return light; + if (oldWeight == light) return regular; + if (oldWeight == regular) return medium; + if (oldWeight == medium) return semiBold; + if (oldWeight == semiBold) return bold; + if (oldWeight == bold) return bold800; + if (oldWeight == bold800) return bold900; + return oldWeight; + } +} From 00d5f0304d58ab83b826713fddb19f2631c9f27e Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:16:38 +0300 Subject: [PATCH 26/54] create GridPage --- lib/features/grid/view/grid_page.dart | 168 ++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 lib/features/grid/view/grid_page.dart diff --git a/lib/features/grid/view/grid_page.dart b/lib/features/grid/view/grid_page.dart new file mode 100644 index 0000000..7d1d19a --- /dev/null +++ b/lib/features/grid/view/grid_page.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final appSettingsProvider = Provider>((ref) => []); + +class GridPage extends StatelessWidget { + const GridPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Grid Page'), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + const int numSquares = 20; + + // it's square, so the height is the same of width. Size(value,value) => value + final double gridSize = + (constraints.maxWidth < constraints.maxHeight) + ? constraints.maxWidth / numSquares + : constraints.maxHeight / numSquares; + + final crossAxisCount = (constraints.maxWidth / gridSize).floor(); + final mainAxisCount = (constraints.maxHeight / gridSize).floor(); + + final count = crossAxisCount * mainAxisCount; + return Listener( + onPointerDown: (event) { + // _toggleColor(!isBlack); + }, + onPointerMove: (event) { + // print( + // "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL ${event.localPosition},,,,$gridSize,,, ${crossAxisCount},,$mainAxisCount,,$count"); + // _toggleColor(!isBlack); + }, + child: GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: crossAxisCount, + childAspectRatio: 1.0, // Ensures squares + ), + itemBuilder: (context, index) { + return _Square(size: gridSize); + }, + itemCount: count, + ), + ); + }, + ), + ), + ); + } +} + +class _Square extends StatefulWidget { + final double size; + + const _Square({required this.size}); + + @override + _SquareState createState() => _SquareState(); +} + +class _SquareState extends State<_Square> { + bool isBlack = false; + + void _toggleColor(bool value) { + setState(() { + isBlack = value; + }); + } + + @override + Widget build(BuildContext context) { + return Listener( + onPointerDown: (event) { + _toggleColor(!isBlack); + }, + // onPointerMove: (event) { + // _toggleColor(!isBlack); + // }, + child: Container( + decoration: BoxDecoration( + border: isBlack + ? null + : Border.all(color: Colors.grey.withOpacity(0.5), width: 0.5), + ), + child: AnimatedScale( + scale: isBlack ? 1.0 : 0.1, + duration: const Duration(milliseconds: 700), + curve: Curves.elasticOut, + child: Container( + width: widget.size, + height: widget.size, + color: isBlack ? Colors.black : Colors.transparent, + ), + ), + ), + ); + } +} + +// class _GridPage extends StatelessWidget { +// const _GridPage(); +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// appBar: AppBar( +// title: Text('Grid Page'), +// ), +// body: SafeArea( +// child: LayoutBuilder( +// builder: (BuildContext context, BoxConstraints constraints) { +// const int numSquares = 25; +// +// // Calculate grid size based on the smaller dimension +// final gridSize = Size(constraints.maxWidth / numSquares, +// constraints.maxHeight / numSquares*0.5); +// +// return CustomPaint( +// size: Size.infinite, // Takes up all available space +// painter: GridPainter( +// gridSize: gridSize, // Use the calculated grid size +// gridColor: +// Colors.grey.withOpacity(0.3), // Adjust grid color and opacity +// ), +// child: Container(), +// ); +// }, +// ), +// ), +// ); +// } +// } +// +// class GridPainter extends CustomPainter { +// final Size gridSize; +// final Color gridColor; +// +// GridPainter({required this.gridSize, this.gridColor = Colors.grey}); +// +// @override +// void paint(Canvas canvas, Size size) { +// final paint = Paint() +// ..color = gridColor +// ..strokeWidth = 1; +// final squarePanting= Paint()..color=Colors.purple.withOpacity(0.6); +// // Draw vertical lines +// for (double x = 0; x <= size.width; x += gridSize.width) { +// canvas.drawLine(Offset(x, 0), Offset(x, size.height), paint); +// } +// +// // Draw horizontal lines +// for (double y = 0; y <= size.height; y += gridSize.height) { +// canvas.drawLine(Offset(0, y), Offset(size.width, y), paint); +// } canvas.drawPaint(squarePanting); +// +// } +// +// @override +// bool shouldRepaint(covariant CustomPainter oldDelegate) { +// return false; +// } +// } From 2ed184612d963ec4b5d17da416d1c10d39115d4a Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:16:44 +0300 Subject: [PATCH 27/54] create HeroWidget --- .../widgets/custom_widgets/hero_widget.dart | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/hero_widget.dart diff --git a/lib/core/widgets/custom_widgets/hero_widget.dart b/lib/core/widgets/custom_widgets/hero_widget.dart new file mode 100644 index 0000000..51d66e5 --- /dev/null +++ b/lib/core/widgets/custom_widgets/hero_widget.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class HeroWidget extends StatelessWidget { + const HeroWidget({super.key, required this.tag, required this.child}); + final String tag; + final Widget child; + @override + Widget build(BuildContext context) { + try { + if (tag.isEmpty) return child; + + return Hero(tag: tag, child: child); + } catch (e) { + return child; + } + } +} From 515d89a0b5654eee9bee2ba650f0423c82c88497 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:16:49 +0300 Subject: [PATCH 28/54] create HorizontalPadding --- .../adaptive/padding/horizontal_padding.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/horizontal_padding.dart diff --git a/lib/core/widgets/adaptive/padding/horizontal_padding.dart b/lib/core/widgets/adaptive/padding/horizontal_padding.dart new file mode 100644 index 0000000..7de2415 --- /dev/null +++ b/lib/core/widgets/adaptive/padding/horizontal_padding.dart @@ -0,0 +1,13 @@ +part of '../../../../core/widgets/adaptive/padding/adaptive_padding.dart'; + +class HorizontalPadding extends StatelessWidget { + const HorizontalPadding( + {required this.padding, required this.child, super.key}); + final double padding; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: REdgeInsets.symmetric(horizontal: padding), child: child); + } +} From 57efde2889f8a315249d1c1ec23be9987f27cbf4 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:17:02 +0300 Subject: [PATCH 29/54] create KeyboardVisibilityBuilder --- .../custom_widgets/keyboard_detected.dart | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/keyboard_detected.dart diff --git a/lib/core/widgets/custom_widgets/keyboard_detected.dart b/lib/core/widgets/custom_widgets/keyboard_detected.dart new file mode 100644 index 0000000..abd2e71 --- /dev/null +++ b/lib/core/widgets/custom_widgets/keyboard_detected.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +class KeyboardVisibilityBuilder extends StatefulWidget { + final Widget? child; + final Widget Function( + BuildContext context, + Widget? child, + bool isKeyboardVisible, + ) builder; + + const KeyboardVisibilityBuilder({ + super.key, + this.child, + required this.builder, + }); + + @override + KeyboardVisibilityBuilderState createState() => + KeyboardVisibilityBuilderState(); +} + +class KeyboardVisibilityBuilderState extends State + with WidgetsBindingObserver { + var _isKeyboardVisible = false; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeMetrics() { + final bottomInset = View.of(context).viewInsets.bottom; + final newValue = bottomInset > 0.0; + if (newValue != _isKeyboardVisible) { + setState(() { + _isKeyboardVisible = newValue; + }); + } + } + + @override + Widget build(BuildContext context) => widget.builder( + context, + widget.child, + _isKeyboardVisible, + ); +} From 8c4f1c7a8f49ac851bb604e5a36f484a8c490e5e Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:17:10 +0300 Subject: [PATCH 30/54] create LanguagesKeys --- lib/core/extensions/language.dart | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 lib/core/extensions/language.dart diff --git a/lib/core/extensions/language.dart b/lib/core/extensions/language.dart new file mode 100644 index 0000000..a2304fd --- /dev/null +++ b/lib/core/extensions/language.dart @@ -0,0 +1,24 @@ +import 'package:algorithm_visualizer/core/enums/app_settings_enum.dart'; + +extension LanguagesKeys on LanguagesEnum { + String get shortKey => _keys[this] ?? "en"; + String get shortKeyWithCounty => _keysWithCountry[this] ?? "en_us"; + + Map get _keys => { + LanguagesEnum.english: "en", + LanguagesEnum.arabic: "ar", + }; + Map get _keysWithCountry => { + LanguagesEnum.english: "en_us", + LanguagesEnum.arabic: "ar_sa", + }; +} + +extension LanguagesString on String { + LanguagesEnum get language => _keys[this] ?? LanguagesEnum.english; + + Map get _keys => { + "en": LanguagesEnum.english, + "ar": LanguagesEnum.arabic, + }; +} From 22e01f437913e8d9c478d0150fe18b76f21912b8 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:17:14 +0300 Subject: [PATCH 31/54] create LightText --- lib/core/widgets/adaptive/text/light_text.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/core/widgets/adaptive/text/light_text.dart diff --git a/lib/core/widgets/adaptive/text/light_text.dart b/lib/core/widgets/adaptive/text/light_text.dart new file mode 100644 index 0000000..3d9a0dd --- /dev/null +++ b/lib/core/widgets/adaptive/text/light_text.dart @@ -0,0 +1,15 @@ +part of 'adaptive_text.dart'; + +class LightText extends _AdaptiveText { + const LightText( + super.text, { + super.fontSize = 16, + super.decoration = TextDecoration.none, + super.fontStyle = FontStyle.normal, + super.color = ThemeEnum.focusColor, + super.maxLines = 2, + super.textAlign, + super.shadows, + super.key, + }) : super(fontWeight: FontWeightManager.light); +} From e1511377947548b988714ba59e3bd7fef9f090a6 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:17:37 +0300 Subject: [PATCH 32/54] handle main --- lib/main.dart | 124 ++------------------------------------------------ 1 file changed, 3 insertions(+), 121 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8e94089..ba7dd3e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,125 +1,7 @@ +import 'package:algorithm_visualizer/core/material_app/my_app.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - 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: ColorScheme.fromSeed(seedColor: Colors.deepPurple), - useMaterial3: true, - ), - 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: 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), - ), // This trailing comma makes auto-formatting nicer for build methods. - ); - } + runApp(const ProviderScope(child: MyApp())); } From 098c48d9cab44a530122fde833595374d0f5843b Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:17:45 +0300 Subject: [PATCH 33/54] create MediumText --- lib/core/widgets/adaptive/text/medium_text.dart | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lib/core/widgets/adaptive/text/medium_text.dart diff --git a/lib/core/widgets/adaptive/text/medium_text.dart b/lib/core/widgets/adaptive/text/medium_text.dart new file mode 100644 index 0000000..d552cea --- /dev/null +++ b/lib/core/widgets/adaptive/text/medium_text.dart @@ -0,0 +1,17 @@ +part of 'adaptive_text.dart'; + +class MediumText extends _AdaptiveText { + const MediumText( + super.text, { + super.fontSize = 16, + super.decoration = TextDecoration.none, + super.fontStyle = FontStyle.normal, + super.color = ThemeEnum.focusColor, + super.textAlign, + super.maxLines, + super.translate, + super.shadows, + super.letterSpacing, + super.key, + }) : super(fontWeight: FontWeightManager.medium); +} From c16d9d9fbe4eb298e70dcfd8584617eb819a49be Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:17:54 +0300 Subject: [PATCH 34/54] create MediumText --- lib/core/material_app/my_app.dart | 87 +++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 lib/core/material_app/my_app.dart diff --git a/lib/core/material_app/my_app.dart b/lib/core/material_app/my_app.dart new file mode 100644 index 0000000..3cc4aad --- /dev/null +++ b/lib/core/material_app/my_app.dart @@ -0,0 +1,87 @@ +import 'package:algorithm_visualizer/config/routes/route_app.dart'; +import 'package:algorithm_visualizer/core/extensions/language.dart'; +import 'package:algorithm_visualizer/core/helpers/storage/app_settings/app_settings_cubit.dart'; +import 'package:algorithm_visualizer/core/helpers/system_overlay_style.dart'; +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:algorithm_visualizer/config/themes/app_theme.dart'; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + const defaultSize = Size(360, 690); + + return ScreenUtilInit( + designSize: defaultSize, + minTextAdapt: true, + splitScreenMode: true, + fontSizeResolver: (fontSize, instance) { + final size = fontSize; + final width = MediaQuery.of(context).size.width; + // Size(501.7, 669.0) + + if (width <= 450) return size.toDouble() * (instance.scaleText); + + return size.toDouble() * (instance.scaleText / 1.35); + }, + builder: (context, child) { + return Consumer( + builder: (context, ref, child) { + final controller = ref.watch(appSettingsProvider); + bool isDarkMode = controller.themeMode != ThemeMode.light; + final theme = isDarkMode ? AppTheme.dark : AppTheme.light; + final themeMode = isDarkMode ? ThemeMode.dark : ThemeMode.light; + + return LayoutBuilder( + builder: (context, constraints) { + final padding = constraints.maxWidth < 450 + ? 0.0 + : ((constraints.maxWidth - defaultSize.width) / 2.3); + + return SystemOverlay( + isBlackTheme: isDarkMode, + child: Container( + color: isDarkMode ? ColorManager.black : ColorManager.white, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: padding), + child: MaterialApp.router( + title: StringsManager.appName, + // defaultTransition: Transition.noTransition, + // translations: TranslationHandler(), + locale: Locale(controller.language.shortKey), + // fallbackLocale: + // Locale(LanguagesEnum.english.shortKey), + localeResolutionCallback: dynamicTranslate, + theme: theme, + darkTheme: AppTheme.dark, + themeMode: themeMode, + debugShowCheckedModeBanner: false, + routerDelegate: AppRoutes.router.routerDelegate, + backButtonDispatcher: + AppRoutes.router.backButtonDispatcher, + routeInformationParser: + AppRoutes.router.routeInformationParser, + routeInformationProvider: + AppRoutes.router.routeInformationProvider, + ), + ), + ), + ); + }, + ); + }, + ); + }, + ); + } + + Locale? dynamicTranslate(Locale? locale, Iterable supportedLocales) { + if (locale != null && supportedLocales.contains(locale)) return locale; + return supportedLocales.first; + } +} From 14d8bd01dbe78f3b4201ea278453a5734c2a6f4a Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:17:58 +0300 Subject: [PATCH 35/54] create Navigators --- lib/core/extensions/navigators.dart | 144 ++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 lib/core/extensions/navigators.dart diff --git a/lib/core/extensions/navigators.dart b/lib/core/extensions/navigators.dart new file mode 100644 index 0000000..62bf92a --- /dev/null +++ b/lib/core/extensions/navigators.dart @@ -0,0 +1,144 @@ +import 'package:algorithm_visualizer/config/routes/route_app.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +extension Navigators on BuildContext { + String? get currentRoute => ModalRoute.of(this)?.settings.name; + (String?, Object?) get currentRouteSettings => ( + ModalRoute.of(this)?.settings.name, + ModalRoute.of(this)?.settings.arguments + ); + void unFocusKeyboard() { + try { + if (mounted) FocusScope.of(this).unfocus(); + } catch (e) { + // + } + } + + void back({dynamic result}) { + try { + unFocusKeyboard(); + + GoRouter.of(this).canPop() ? GoRouter.of(this).pop(result) : null; + } catch (e) { + // + } + } + + void pop({dynamic result}) { + try { + unFocusKeyboard(); + + if (Navigator.of(this).canPop()) { + return Navigator.of(this, rootNavigator: true).pop(result); + } + } catch (e) { + // + } + } + + Future pushTo( + RouteConfig path, { + Object? arguments, + String pathParameters = "", + Map? pathParametersRaw, + String queryParameters = "", + bool pauseVideo = true, + }) async { + unFocusKeyboard(); + + if (pathParameters.isNotEmpty && arguments == null) { + arguments = pathParameters; + + final currentValue = currentRouteSettings.$2; + + if (currentValue is Map && + currentRoute == path.name && + arguments == currentValue[path.pathParamsName]) { + return; + } + } + + return await GoRouter.of(this) + .pushNamed( + path.name, + extra: arguments, + pathParameters: pathParametersRaw ?? + (pathParameters.isNotEmpty + ? {path.pathParamsName: pathParameters} + : {}), + queryParameters: queryParameters.isNotEmpty + ? {path.queryParamsName: queryParameters} + : {}, + ) + .then((value) { + unFocusKeyboard(); + return value; + }); + } + + Future pushAndRemoveCurrent( + RouteConfig path, { + Object? arguments, + String pathParameters = "", + }) async { + return await GoRouter.of(this) + .pushReplacementNamed( + path.name, + extra: arguments, + pathParameters: + pathParameters.isEmpty ? {} : {path.pathParamsName: pathParameters}, + ) + .then((value) { + unFocusKeyboard(); + return value; + }); + } + + Future pushAndRemoveAll( + RouteConfig path, { + String pathParameters = "", + Object? arguments, + }) async { + unFocusKeyboard(); + + while (GoRouter.of(this).canPop()) { + GoRouter.of(this).pop(); + } + await GoRouter.of(this) + .pushReplacementNamed( + path.name, + extra: arguments, + pathParameters: + pathParameters.isEmpty ? {} : {path.pathParamsName: pathParameters}, + ) + .then((value) { + unFocusKeyboard(); + return value; + }); + } + + Future pushAndRemoveAllUntilBase( + RouteConfig path, { + String pathParameters = "", + Object? arguments, + }) async { + unFocusKeyboard(); + + while (GoRouter.of(this).canPop()) { + GoRouter.of(this).pop(); + } + await GoRouter.of(this) + .pushNamed( + path.name, + extra: arguments, + pathParameters: + pathParameters.isEmpty ? {} : {path.pathParamsName: pathParameters}, + ) + .then((value) { + unFocusKeyboard(); + return value; + }); + } +} From 54ecbf232d7e91ecc923c138e4ac302590bde76f Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:18:24 +0300 Subject: [PATCH 36/54] create OnlyPadding --- .../adaptive/padding/only_padding.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/only_padding.dart diff --git a/lib/core/widgets/adaptive/padding/only_padding.dart b/lib/core/widgets/adaptive/padding/only_padding.dart new file mode 100644 index 0000000..5bce7ea --- /dev/null +++ b/lib/core/widgets/adaptive/padding/only_padding.dart @@ -0,0 +1,30 @@ +part of '../../../../core/widgets/adaptive/padding/adaptive_padding.dart'; + +class OnlyPadding extends StatelessWidget { + const OnlyPadding({ + this.startPadding = 0, + this.endPadding = 0, + this.topPadding = 0, + this.bottomPadding = 0, + required this.child, + super.key, + }); + final double startPadding; + final double endPadding; + final double topPadding; + final double bottomPadding; + final Widget child; + @override + Widget build(BuildContext context) { + + return _RPadding( + padding: REdgeInsetsDirectional.only( + start: startPadding, + end: endPadding, + top: topPadding, + bottom: bottomPadding, + ), + child: child, + ); + } +} From ae7d0327ddf1124fd7cd052ea5bf8feec02f608e Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:18:55 +0300 Subject: [PATCH 37/54] create HashCode --- lib/core/helpers/random_text.dart | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 lib/core/helpers/random_text.dart diff --git a/lib/core/helpers/random_text.dart b/lib/core/helpers/random_text.dart new file mode 100644 index 0000000..df9b8b6 --- /dev/null +++ b/lib/core/helpers/random_text.dart @@ -0,0 +1,19 @@ + +class HashCode { + static String generateIdentifier(List userIds) { + userIds.sort(); + + String concatenatedIds = userIds.join(','); + + int checksum = 0; + for (int i = 0; i < concatenatedIds.length; i++) { + checksum += concatenatedIds.codeUnitAt(i) * (i + 1); + } + + String hexString = checksum.toRadixString(16); + + String uniqueString = hexString.substring(0, hexString.length.clamp(0, 32)); + + return uniqueString; + } +} From 8ddb942996edd23191eaf6766a820526f531ef20 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:19:13 +0300 Subject: [PATCH 38/54] create RegularText --- lib/core/widgets/adaptive/text/regular_text.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/core/widgets/adaptive/text/regular_text.dart diff --git a/lib/core/widgets/adaptive/text/regular_text.dart b/lib/core/widgets/adaptive/text/regular_text.dart new file mode 100644 index 0000000..dbf6ab4 --- /dev/null +++ b/lib/core/widgets/adaptive/text/regular_text.dart @@ -0,0 +1,15 @@ +part of '../../adaptive/text/adaptive_text.dart'; + +class RegularText extends _AdaptiveText { + const RegularText( + super.text, { + super.fontSize = 16, + super.decoration = TextDecoration.none, + super.fontStyle = FontStyle.normal, + super.color, + super.shadows, + super.maxLines = 2, + super.textAlign, + super.key, + }) : super(fontWeight: FontWeightManager.regular); +} From cfc59b4b2ce8c3a037dcf7ef20cf4015127815ea Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:19:17 +0300 Subject: [PATCH 39/54] create RoundedOutlinedButton --- .../rounded_outlined_button.dart | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/rounded_outlined_button.dart diff --git a/lib/core/widgets/custom_widgets/rounded_outlined_button.dart b/lib/core/widgets/custom_widgets/rounded_outlined_button.dart new file mode 100644 index 0000000..8bc4769 --- /dev/null +++ b/lib/core/widgets/custom_widgets/rounded_outlined_button.dart @@ -0,0 +1,47 @@ +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +enum OutlineEnumFixedSize { small, non } + +class RoundedOutlinedButton extends StatelessWidget { + final ThemeEnum? backgroundColor; + final Widget child; + final VoidCallback? onPressed; + final OutlineEnumFixedSize size; + final ThemeEnum borderColor; + final bool smallRounded; + const RoundedOutlinedButton({ + super.key, + this.smallRounded = false, + this.backgroundColor, + this.size = OutlineEnumFixedSize.small, + this.borderColor = ThemeEnum.hintColor, + required this.child, + required this.onPressed, + }); + @override + Widget build(BuildContext context) { + final backgroundColor = this.backgroundColor; + final background = + backgroundColor == null ? null : context.getColor(backgroundColor); + + return OutlinedButton( + style: OutlinedButton.styleFrom( + backgroundColor: + backgroundColor == null ? null : context.getColor(backgroundColor), + fixedSize: size == OutlineEnumFixedSize.small + ? Size.fromHeight(smallRounded ? 30.h : 35.h) + : null, + padding: REdgeInsets.symmetric(horizontal: 15), + surfaceTintColor: background, + foregroundColor: context.getColor(ThemeEnum.hintColor), + side: BorderSide(color: context.getColor(borderColor), width: 1.5.r), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(smallRounded ? 5 : 50)), + ), + onPressed: onPressed, + child: child, + ); + } +} From 06fa14384d0c42b6d92aa35fc0319db0ddcb9fdb Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:19:25 +0300 Subject: [PATCH 40/54] create RouteConfig --- lib/config/routes/route_app.dart | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 lib/config/routes/route_app.dart diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart new file mode 100644 index 0000000..2e17fdc --- /dev/null +++ b/lib/config/routes/route_app.dart @@ -0,0 +1,68 @@ +import 'package:algorithm_visualizer/core/helpers/app_bar/app_bar.dart'; +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.dart'; +import 'package:algorithm_visualizer/features/grid/view/grid_page.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +class Routes { + static const RouteConfig grid = RouteConfig( + name: 'grid', + path: '/', + ); + + // name: 'hashtag', + // path: '/hashtag/:hashtagId', + // pathParamsName: "hashtagId", + // queryParamsName: 'mid', +} + +class RouteConfig { + final String name; + final String path; + final String pathParamsName; + final String queryParamsName; + + const RouteConfig({ + required this.name, + required this.path, + this.pathParamsName = "", + this.queryParamsName = "", + }); +} + +class AppRoutes { + static final router = GoRouter( + debugLogDiagnostics: true, + initialLocation: Routes.grid.path, + errorBuilder: (context, state) => const _UnknownPage(), + routes: [ + ShellRoute( + builder: (context, state, child) { + return child; + }, + routes: [ + GoRoute( + path: Routes.grid.path, + name: Routes.grid.name, + builder: (context, state) => const GridPage(), + ), + ], + ), + + ///------------------------------------------------------------> + ], + ); +} + +class _UnknownPage extends StatelessWidget { + const _UnknownPage(); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: GlobalAppBar(), + body: const Center(child: RegularText(StringsManager.unknownPage)), + ); + } +} From d70689f752cd72fe01c98aac9c82fd1ff7e55b47 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:19:30 +0300 Subject: [PATCH 41/54] create CustomScaleTransition --- .../custom_widgets/scale_transition.dart | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/scale_transition.dart diff --git a/lib/core/widgets/custom_widgets/scale_transition.dart b/lib/core/widgets/custom_widgets/scale_transition.dart new file mode 100644 index 0000000..227b2f1 --- /dev/null +++ b/lib/core/widgets/custom_widgets/scale_transition.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; + +class CustomScaleTransition extends StatefulWidget { + const CustomScaleTransition({ + required this.remove, + required this.child, + super.key, + }); + final Widget child; + final bool remove; + @override + State createState() => _CustomScaleTransitionState(); +} + +class _CustomScaleTransitionState extends State + with TickerProviderStateMixin { + bool remove = false; + + @override + void didUpdateWidget(covariant CustomScaleTransition oldWidget) { + if (oldWidget == widget || remove == widget.remove) return; + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + remove = widget.remove; + }); + }); + + super.didUpdateWidget(oldWidget); + } + + @override + Widget build(BuildContext context) { + return AnimatedScale( + scale: remove ? 0 : 1, + duration: const Duration(milliseconds: 300), + child: widget.child, + ); + } +} From 4a56205e4f95a41e69daa43cc8823e234e2fa58e Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:19:35 +0300 Subject: [PATCH 42/54] create SemiBoldText --- .../widgets/adaptive/text/semi_bold_text.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lib/core/widgets/adaptive/text/semi_bold_text.dart diff --git a/lib/core/widgets/adaptive/text/semi_bold_text.dart b/lib/core/widgets/adaptive/text/semi_bold_text.dart new file mode 100644 index 0000000..1b3d345 --- /dev/null +++ b/lib/core/widgets/adaptive/text/semi_bold_text.dart @@ -0,0 +1,16 @@ +part of 'adaptive_text.dart'; + +class SemiBoldText extends _AdaptiveText { + const SemiBoldText( + super.text, { + super.fontSize = 16, + super.decoration = TextDecoration.none, + super.fontStyle = FontStyle.normal, + super.color = ThemeEnum.focusColor, + super.maxLines = 2, + super.shadows, + super.textAlign, + super.letterSpacing, + super.key, + }) : super(fontWeight: FontWeightManager.semiBold); +} From 859e073f7f6eda4e1b98b5ea191f07c738bc9c8c Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:19:39 +0300 Subject: [PATCH 43/54] create StartPadding --- lib/core/widgets/adaptive/padding/start_padding.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/start_padding.dart diff --git a/lib/core/widgets/adaptive/padding/start_padding.dart b/lib/core/widgets/adaptive/padding/start_padding.dart new file mode 100644 index 0000000..ea313c5 --- /dev/null +++ b/lib/core/widgets/adaptive/padding/start_padding.dart @@ -0,0 +1,12 @@ +part of'../../../../core/widgets/adaptive/padding/adaptive_padding.dart'; +class StartPadding extends StatelessWidget { + const StartPadding( + {required this.padding, required this.child, super.key}); + final double padding; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: REdgeInsetsDirectional.only(start: padding), child: child); + } +} From 3ba5b210677af3ddf2ce0f72376df026cf2c568a Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:20:15 +0300 Subject: [PATCH 44/54] create StringsManager --- lib/core/resources/strings_manager.dart | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 lib/core/resources/strings_manager.dart diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart new file mode 100644 index 0000000..b5662ba --- /dev/null +++ b/lib/core/resources/strings_manager.dart @@ -0,0 +1,23 @@ +/// [StringsManager] text in english is the same key for translation map +library; + +class StringsManager { + static const String english = "English"; + static const String arabic = "Arabic"; + static const String turkish = "Turkish"; + static const String spanish = "Spanish"; + static const String germany = "Germany"; + static const String french = "French"; + static const String italian = "Italian"; + static const String russian = "Russian"; + static const String hindi = "Hindi"; + static const String chinese = "Chinese"; + static const String japanese = "Japanese"; + static const String korean = "Korean"; + + /// -----------------------------------------------------------------------> + + static const String appName = "Algorithm Visualizer"; + static const String welcomeToApp = "Welcome to $appName"; + +} From ac3fa274e829d31c8c67e5bed8ac998ccaa278a1 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:20:19 +0300 Subject: [PATCH 45/54] create GetTextStyle --- lib/core/resources/styles_manager.dart | 83 ++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 lib/core/resources/styles_manager.dart diff --git a/lib/core/resources/styles_manager.dart b/lib/core/resources/styles_manager.dart new file mode 100644 index 0000000..547e4c7 --- /dev/null +++ b/lib/core/resources/styles_manager.dart @@ -0,0 +1,83 @@ +import 'package:algorithm_visualizer/core/resources/font_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; + +class GetTextStyle extends TextStyle { + const GetTextStyle({ + required double fontSize, + super.height, + required super.fontWeight, + super.color, + required FontStyle super.fontStyle, + required TextDecoration super.decoration, + super.decorationThickness, + super.letterSpacing = 0, + super.shadows, + super.wordSpacing = 1, + }) : super(fontSize: fontSize, fontFamily: FontConstants.fontFamily); +} + +class GetLightStyle extends GetTextStyle { + const GetLightStyle({ + super.fontSize = 16, + super.height, + super.color = ColorManager.black, + super.fontStyle = FontStyle.normal, + super.decoration = TextDecoration.none, + super.decorationThickness, + super.letterSpacing, + super.shadows, + }) : super(fontWeight: FontWeightManager.light); +} + +class GetRegularStyle extends GetTextStyle { + const GetRegularStyle({ + super.fontSize = 16, + super.height, + super.color = ColorManager.black, + super.fontStyle = FontStyle.normal, + super.decoration = TextDecoration.none, + super.decorationThickness, + super.letterSpacing, + super.shadows, + }) : super(fontWeight: FontWeightManager.regular); +} + +class GetMediumStyle extends GetTextStyle { + const GetMediumStyle({ + super.fontSize = 16, + super.height, + super.color = ColorManager.black, + super.fontStyle = FontStyle.normal, + super.decoration = TextDecoration.none, + super.decorationThickness, + super.letterSpacing, + super.shadows, + }) : super(fontWeight: FontWeightManager.medium); +} + +class GetSemiBoldStyle extends GetTextStyle { + const GetSemiBoldStyle({ + super.fontSize = 16, + super.height, + super.color = ColorManager.black, + super.fontStyle = FontStyle.normal, + super.decoration = TextDecoration.none, + super.decorationThickness, + super.letterSpacing, + super.shadows, + }) : super(fontWeight: FontWeightManager.semiBold); +} + +class GetBoldStyle extends GetTextStyle { + const GetBoldStyle({ + super.fontSize = 16, + super.height, + super.color = ColorManager.black, + super.fontStyle = FontStyle.normal, + super.decoration = TextDecoration.none, + super.decorationThickness, + super.letterSpacing, + super.shadows, + }) : super(fontWeight: FontWeightManager.bold); +} From eb853874018da5ded2c28f45f13443d193956c0c Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:20:24 +0300 Subject: [PATCH 46/54] create CustomAssetsSvg --- lib/core/helpers/svg_picture.dart | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 lib/core/helpers/svg_picture.dart diff --git a/lib/core/helpers/svg_picture.dart b/lib/core/helpers/svg_picture.dart new file mode 100644 index 0000000..7a6874a --- /dev/null +++ b/lib/core/helpers/svg_picture.dart @@ -0,0 +1,33 @@ +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class CustomAssetsSvg extends StatelessWidget { + const CustomAssetsSvg( + this.path, { + this.size, + this.semanticLabel, + this.color = ThemeEnum.focusColor, + super.key, + }); + final String path; + final String? semanticLabel; + final double? size; + final ThemeEnum? color; + @override + Widget build(BuildContext context) { + final color = this.color; + final size = this.size; + if (path.isEmpty) return const RSizedBox(); + + return SvgPicture.asset( + path, + height: size?.r, + semanticsLabel: semanticLabel, + colorFilter: color == null + ? null + : ColorFilter.mode(context.getColor(color), BlendMode.srcIn), + ); + } +} From c792469fee52addef840216ab70374369c023497 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:20:29 +0300 Subject: [PATCH 47/54] create SymmetricPadding --- .../adaptive/padding/symmetric_padding.dart | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/symmetric_padding.dart diff --git a/lib/core/widgets/adaptive/padding/symmetric_padding.dart b/lib/core/widgets/adaptive/padding/symmetric_padding.dart new file mode 100644 index 0000000..785a0d4 --- /dev/null +++ b/lib/core/widgets/adaptive/padding/symmetric_padding.dart @@ -0,0 +1,20 @@ +part of '../../../../core/widgets/adaptive/padding/adaptive_padding.dart'; + +class SymmetricPadding extends StatelessWidget { + const SymmetricPadding({ + required this.horizontal, + required this.vertical, + required this.child, + super.key, + }); + final double horizontal; + final double vertical; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: + REdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), + child: child); + } +} From 8c42c3118dd294f0a3cab6e312625d4edbb097b7 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:20:32 +0300 Subject: [PATCH 48/54] create SystemOverlay --- lib/core/helpers/system_overlay_style.dart | 56 ++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 lib/core/helpers/system_overlay_style.dart diff --git a/lib/core/helpers/system_overlay_style.dart b/lib/core/helpers/system_overlay_style.dart new file mode 100644 index 0000000..6401eea --- /dev/null +++ b/lib/core/helpers/system_overlay_style.dart @@ -0,0 +1,56 @@ +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class SystemOverlay extends StatelessWidget { + const SystemOverlay({ + required this.child, + this.isBlackTheme = true, + super.key, + }); + final Widget child; + final bool isBlackTheme; + @override + Widget build(BuildContext context) { + return AnnotatedRegion( + value: isBlackTheme ? blackTheme() : whiteTheme(), + child: child, + ); + } + + SystemUiOverlayStyle blackTheme() { + return const SystemUiOverlayStyle( + statusBarColor: ColorManager.black, + statusBarIconBrightness: Brightness.light, + systemNavigationBarColor: ColorManager.blackL2, + systemNavigationBarIconBrightness: Brightness.light); + } + + SystemUiOverlayStyle whiteTheme() { + return const SystemUiOverlayStyle( + statusBarColor: ColorManager.white, + statusBarIconBrightness: Brightness.dark, + systemNavigationBarColor: ColorManager.white, + systemNavigationBarIconBrightness: Brightness.dark); + } +} + +class TransparentSystemOverlay extends StatelessWidget { + const TransparentSystemOverlay({required this.child, super.key}); + final Widget child; + @override + Widget build(BuildContext context) { + return AnnotatedRegion( + value: transparentTheme(), + child: child, + ); + } + + SystemUiOverlayStyle transparentTheme() { + return const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + systemNavigationBarColor: Colors.transparent, + systemNavigationBarDividerColor: ColorManager.transparent + ); + } +} From a439521cbc9439424946ff9b45af639e5f7c4767 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:20:39 +0300 Subject: [PATCH 49/54] create ThemeEnum --- lib/core/resources/theme_manager.dart | 143 ++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 lib/core/resources/theme_manager.dart diff --git a/lib/core/resources/theme_manager.dart b/lib/core/resources/theme_manager.dart new file mode 100644 index 0000000..aa4d1f1 --- /dev/null +++ b/lib/core/resources/theme_manager.dart @@ -0,0 +1,143 @@ +import 'package:algorithm_visualizer/core/resources/color_manager.dart'; +import 'package:flutter/material.dart'; + +enum ThemeEnum { + primaryColor, + focusColor, + hintColor, + + whiteD1Color, + whiteD2Color, + whiteD3Color, + whiteD4Color, + whiteD5Color, + whiteD7Color, + whiteColor, + transparentWhiteColor, + transparentColor, + blackColor, + whiteOp60Color, + solidWhiteOp60Color, + whiteOp50Color, + whiteOp20Color, + greyColor, + grey5Color, + darkGreyColor, + trendsRankingColor, + hoverColor, + blackOp80, + blackOp50, + blackOp20, + blackOp10, + bottomSheetColor, + + blueColor, + darkBlueColor, + lightBlueColor, + greenColor, + redColor, + orangeColor, +} +// +// abstract class BaseGetColor extends Color { +// const BaseGetColor(this.color, super.value); +// final ThemeEnum color; +// +// getColor(BuildContext context) => context._getColor(color); +// } + +// class GetColor extends Color { +// const GetColor(this.color) +// : super(AppSettingsViewModel.getInstance().isThemeLight ? 0 : 1); +// final ThemeEnum color; +// +// getColor(BuildContext context) => context._getColor(color); +// +// static Map get _colors { +// final isLight = AppSettingsViewModel.getInstance().isThemeLight; +// return { +// ThemeEnum.whiteD5Color: +// isLight ? ColorManager.whiteD5 : ColorManager.blackL5, +// ThemeEnum.whiteD7Color: +// isLight ? ColorManager.whiteD7 : ColorManager.blackL6, +// ThemeEnum.transparentColor: ColorManager.transparent, +// ThemeEnum.transparentWhiteColor: ColorManager.whiteOp20, +// ThemeEnum.blackOp20: ColorManager.blackOp20, +// ThemeEnum.trendsRankingColor: ColorManager.rankingGrey, +// ThemeEnum.whiteColor: ColorManager.white, +// ThemeEnum.blackColor: ColorManager.black, +// ThemeEnum.whiteOp60Color: +// isLight ? ColorManager.whiteOp60 : ColorManager.blackOp60, +// ThemeEnum.whiteOp50Color: +// isLight ? ColorManager.whiteOp50 : ColorManager.blackOp50, +// ThemeEnum.whiteOp20Color: +// isLight ? ColorManager.whiteOp20 : ColorManager.blackOp20, +// ThemeEnum.blackOp80: ColorManager.blackOp80, +// ThemeEnum.blackOp50: +// isLight ? ColorManager.blackOp50 : ColorManager.whiteOp50, +// ThemeEnum.greyColor: ColorManager.grey, +// ThemeEnum.grey5Color: +// isLight ? ColorManager.greyD9 : ColorManager.whiteD4, +// ThemeEnum.blueColor: ColorManager.blue, +// ThemeEnum.darkBlueColor: ColorManager.darkBlue, +// ThemeEnum.lightBlueColor: ColorManager.lightBlue, +// ThemeEnum.greenColor: ColorManager.green, +// ThemeEnum.redColor: ColorManager.red, +// ThemeEnum.orangeColor: ColorManager.orange, +// }; +// } +// } + +extension ThemeExtension on BuildContext { + Map get _colors { + // final isLight = AppSettingsViewModel.getInstance().isThemeLight; + + return { + ThemeEnum.primaryColor: Theme.of(this).primaryColor, + ThemeEnum.focusColor: Theme.of(this).focusColor, + ThemeEnum.hintColor: Theme.of(this).hintColor, + + /// what ever dark or light. Maybe if we have multiple themes, it will save a lot of time. + ThemeEnum.whiteD1Color: Theme.of(this).dialogBackgroundColor, + ThemeEnum.whiteD2Color: Theme.of(this).primaryColorLight, + ThemeEnum.bottomSheetColor: + Theme.of(this).bottomSheetTheme.backgroundColor ?? + Theme.of(this).primaryColorLight, + ThemeEnum.whiteD3Color: + Theme.of(this).textTheme.headlineLarge?.color ?? ColorManager.grey, + ThemeEnum.whiteD4Color: Theme.of(this).colorScheme.primaryContainer, + ThemeEnum.whiteD5Color: ColorManager.whiteD5, + ThemeEnum.whiteD7Color: ColorManager.whiteD7, + ThemeEnum.transparentColor: ColorManager.transparent, + ThemeEnum.transparentWhiteColor: ColorManager.whiteOp20, + ThemeEnum.blackOp20: ColorManager.blackOp20, + ThemeEnum.trendsRankingColor: ColorManager.rankingGrey, + + ThemeEnum.blackOp10: Theme.of(this).dividerColor, + + ThemeEnum.whiteColor: ColorManager.white, + ThemeEnum.blackColor: ColorManager.black, + ThemeEnum.whiteOp60Color: ColorManager.whiteOp60, + ThemeEnum.solidWhiteOp60Color: ColorManager.whiteOp60, + ThemeEnum.whiteOp50Color: ColorManager.whiteOp50, + ThemeEnum.whiteOp20Color: ColorManager.whiteOp20, + ThemeEnum.blackOp80: ColorManager.blackOp80, + ThemeEnum.blackOp50: ColorManager.blackOp50, + ThemeEnum.hoverColor: Theme.of(this).hoverColor, + + ThemeEnum.greyColor: ColorManager.grey, + ThemeEnum.grey5Color: ColorManager.greyD9, + ThemeEnum.darkGreyColor: + Theme.of(this).textTheme.bodyLarge?.color ?? ColorManager.greyD3, + ThemeEnum.blueColor: ColorManager.blue, + ThemeEnum.darkBlueColor: ColorManager.darkBlue, + ThemeEnum.lightBlueColor: ColorManager.lightBlue, + ThemeEnum.greenColor: ColorManager.green, + ThemeEnum.redColor: ColorManager.red, + ThemeEnum.orangeColor: ColorManager.orange, + }; + } + + Color getColor(ThemeEnum color) => + _colors[color] ?? Theme.of(this).primaryColor; +} From 1c207418078096d1d80c2d3f41edb533a2b86d11 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:20:47 +0300 Subject: [PATCH 50/54] create TopPadding --- lib/core/widgets/adaptive/padding/top_padding.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/top_padding.dart diff --git a/lib/core/widgets/adaptive/padding/top_padding.dart b/lib/core/widgets/adaptive/padding/top_padding.dart new file mode 100644 index 0000000..2ec83b5 --- /dev/null +++ b/lib/core/widgets/adaptive/padding/top_padding.dart @@ -0,0 +1,12 @@ +part of'../../../../core/widgets/adaptive/padding/adaptive_padding.dart'; +class TopPadding extends StatelessWidget { + const TopPadding( + {required this.padding, required this.child, super.key}); + final double padding; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: REdgeInsetsDirectional.only(top: padding), child: child); + } +} From 3cf84155a10a928b5c73b5ed5eabc0f1edc7d59f Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:21:06 +0300 Subject: [PATCH 51/54] create VerticalAnimationHeroPage --- .../vertical_animation_hero_page.dart | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart diff --git a/lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart b/lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart new file mode 100644 index 0000000..9e77dc7 --- /dev/null +++ b/lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +class VerticalAnimationHeroPage extends StatefulWidget { + const VerticalAnimationHeroPage({ + required this.onSwipe, + required this.child, + super.key, + }); + final VoidCallback onSwipe; + final Widget child; + @override + State createState() => + _VerticalAnimationHeroPageState(); +} + +class _VerticalAnimationHeroPageState extends State { + final ScrollController controller = ScrollController(); + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Listener( + onPointerUp: (event) { + double offset = controller.offset; + if (offset < 0) offset = offset * -1; + if (offset > 50) widget.onSwipe(); + }, + child: CustomScrollView( + physics: const BouncingScrollPhysics(), + controller: controller, + slivers: [ + SliverFillRemaining(child: widget.child), + const SliverToBoxAdapter(child: SizedBox(height: 1)), + ], + ), + ); + } +} From 3a0836c4e1440f77354cfea3ae10c1c1e609619f Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:21:10 +0300 Subject: [PATCH 52/54] create VerticalPadding --- .../widgets/adaptive/padding/vertical_padding.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/core/widgets/adaptive/padding/vertical_padding.dart diff --git a/lib/core/widgets/adaptive/padding/vertical_padding.dart b/lib/core/widgets/adaptive/padding/vertical_padding.dart new file mode 100644 index 0000000..bd7369d --- /dev/null +++ b/lib/core/widgets/adaptive/padding/vertical_padding.dart @@ -0,0 +1,13 @@ +part of '../../../../core/widgets/adaptive/padding/adaptive_padding.dart'; + +class VerticalPadding extends StatelessWidget { + const VerticalPadding( + {required this.padding, required this.child, super.key}); + final double padding; + final Widget child; + @override + Widget build(BuildContext context) { + return _RPadding( + padding: REdgeInsets.symmetric(vertical: padding), child: child); + } +} From 0a796b10d488c29f023abe430ce82e58bd336eed Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:21:27 +0300 Subject: [PATCH 53/54] handle dependencies --- pubspec.yaml | 76 +++++++--------------------------------------------- 1 file changed, 9 insertions(+), 67 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index a890761..7769dcc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,91 +1,33 @@ name: algorithm_visualizer description: "This will be something great" -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +publish_to: 'none' # Remove this line if you wish to publish to pub.dev -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. version: 1.0.0+1 environment: sdk: '>=3.4.1 <4.0.0' -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter + go_router: ^14.2.1 + get_it: ^7.6.7 + flutter_screenutil: ^5.9.1 + flutter_svg: ^2.0.10+1 + riverpod: ^2.5.1 + flutter_riverpod: ^2.5.1 + get_storage: ^2.1.1 - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.6 dev_dependencies: flutter_test: sdk: flutter - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. flutter_lints: ^3.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages + uses-material-design: true From 42f2aeb03e20797d5b22573582c5ed1582098716 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 8 Aug 2024 20:21:31 +0300 Subject: [PATCH 54/54] handle dependencies --- pubspec.lock | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 254 insertions(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index 5a8354a..ae26b44 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" async: dependency: transitive description: @@ -57,6 +65,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" flutter: dependency: "direct main" description: flutter @@ -70,11 +86,88 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_riverpod: + dependency: "direct main" + description: + name: flutter_riverpod + sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d" + url: "https://pub.dev" + source: hosted + version: "2.5.1" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" + url: "https://pub.dev" + source: hosted + version: "5.9.3" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + get: + dependency: transitive + description: + name: get + sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e + url: "https://pub.dev" + source: hosted + version: "4.6.6" + get_it: + dependency: "direct main" + description: + name: get_it + sha256: d85128a5dae4ea777324730dc65edd9c9f43155c109d5cc0a69cab74139fbac1 + url: "https://pub.dev" + source: hosted + version: "7.7.0" + get_storage: + dependency: "direct main" + description: + name: get_storage + sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + go_router: + dependency: "direct main" + description: + name: go_router + sha256: d380de0355788c5c784fe9f81b43fc833b903991c25ecc4e2a416a67faefa722 + url: "https://pub.dev" + source: hosted + version: "14.2.2" + http: + dependency: transitive + description: + name: http + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + url: "https://pub.dev" + source: hosted + version: "1.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" leak_tracker: dependency: transitive description: @@ -107,6 +200,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" matcher: dependency: transitive description: @@ -139,6 +240,94 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + url: "https://pub.dev" + source: hosted + version: "2.1.4" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "490539678396d4c3c0b06efdaab75ae60675c3e0c66f72bc04c2e2c1e0e2abeb" + url: "https://pub.dev" + source: hosted + version: "2.2.9" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + riverpod: + dependency: "direct main" + description: + name: riverpod + sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d + url: "https://pub.dev" + source: hosted + version: "2.5.1" sky_engine: dependency: transitive description: flutter @@ -160,6 +349,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.11.1" + state_notifier: + dependency: transitive + description: + name: state_notifier + sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb + url: "https://pub.dev" + source: hosted + version: "1.0.0" stream_channel: dependency: transitive description: @@ -192,6 +389,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -208,6 +437,30 @@ packages: url: "https://pub.dev" source: hosted version: "14.2.1" + web: + dependency: transitive + description: + name: web + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" sdks: dart: ">=3.4.1 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + flutter: ">=3.22.0"