From 9c55404131402b017c579f897ae5814ce7c8b9e8 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:58:23 +0300 Subject: [PATCH 001/107] handle DraggableProgressBar --- lib/core/draggable_progress.dart | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/core/draggable_progress.dart b/lib/core/draggable_progress.dart index 00629fe..e13a5c7 100644 --- a/lib/core/draggable_progress.dart +++ b/lib/core/draggable_progress.dart @@ -2,19 +2,37 @@ import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; import 'package:flutter/material.dart'; class DraggableProgressBar extends StatefulWidget { - const DraggableProgressBar({required this.onChanged, super.key}); + const DraggableProgressBar({ + this.runOnChangedInitially = false, + required this.onChanged, + this.sliderValue = 0.3, + this.isActive = true, + super.key, + }); final void Function(double persent) onChanged; + final bool runOnChangedInitially; + final double sliderValue; + final bool isActive; @override LinearSliderState createState() => LinearSliderState(); } class LinearSliderState extends State { - double sliderValue = 0.3; + late double sliderValue = widget.sliderValue; + @override + void initState() { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (widget.runOnChangedInitially) widget.onChanged(sliderValue); + }); + super.initState(); + } @override Widget build(BuildContext context) { return Slider( - activeColor: context.getColor(ThemeEnum.blueColor), + activeColor: widget.isActive + ? context.getColor(ThemeEnum.mediumBlueColor) + : context.getColor(ThemeEnum.whiteD7Color), value: sliderValue, onChanged: (v) { setState(() { From 30633306bf8dc38dd9e691e2abe6dc3b4da528e4 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:58:46 +0300 Subject: [PATCH 002/107] handle color of sorting --- .../base/view_model/sorting_notifier.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index f518d92..a51b64f 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -15,11 +15,11 @@ abstract class SortingNotifier extends StateNotifier { _initializePositions(); } - static double maxListItemHeight = 250.h; + static double maxListItemHeight = 250.r; static double itemsPadding = 1.w; static const ThemeEnum swappingColor = ThemeEnum.redColor; - static const ThemeEnum comparedColor = ThemeEnum.comparedColor; - static const ThemeEnum itemColor = ThemeEnum.blueColor; + static const ThemeEnum comparedColor = ThemeEnum.lightBlueColor; + static const ThemeEnum itemColor = ThemeEnum.darkBlueColor; static const ThemeEnum doneSortingColor = ThemeEnum.greenColor; static const int _defaultSize = 20; @@ -30,7 +30,7 @@ abstract class SortingNotifier extends StateNotifier { // static const Duration _maxSpeedDuration = Duration(milliseconds: 3000); // static const Duration _minSpeedDuration = Duration(milliseconds: 20); - SortingEnum operation = SortingEnum.none; + SortingEnum _operation = SortingEnum.none; CancelableOperation? cancelableSort; int i = 0; @@ -56,6 +56,13 @@ abstract class SortingNotifier extends StateNotifier { Duration get speedDuration => state.swipeDuration; int get _size => state.size; + SortingEnum get operation => _operation; + + set operation(SortingEnum value) { + state = state.copyWith(operationStatus: value); + _operation = value; + } + void _initializePositions() { final positions = {}; final itemWidth = calculateItemWidth(ScreenSize.context!, _size); @@ -83,7 +90,7 @@ abstract class SortingNotifier extends StateNotifier { void stopSorting() { cancelableSort?.cancel(); - operation = SortingEnum.stopped; + if (operation == SortingEnum.played) operation = SortingEnum.stopped; } Future playSorting() async { From 87fb75512e0a9987ddbef8ad20442b1319b6a0c9 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:59:12 +0300 Subject: [PATCH 003/107] refactoring and handle size changing while running --- .../sorting/base/view/sorting_page.dart | 112 ++++++++++++++---- 1 file changed, 90 insertions(+), 22 deletions(-) diff --git a/lib/features/sorting/base/view/sorting_page.dart b/lib/features/sorting/base/view/sorting_page.dart index 7f7588b..7844f32 100644 --- a/lib/features/sorting/base/view/sorting_page.dart +++ b/lib/features/sorting/base/view/sorting_page.dart @@ -1,6 +1,8 @@ import 'package:algorithm_visualizer/core/draggable_progress.dart' show DraggableProgressBar; +import 'package:algorithm_visualizer/core/resources/color_manager.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/padding/adaptive_padding.dart'; import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.dart'; import 'package:algorithm_visualizer/core/widgets/custom_widgets/custom_rounded_elevated_button.dart'; import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; @@ -10,12 +12,12 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; part '../widgets/sorting_app_bar.dart'; part '../widgets/control_buttons.dart'; -class SortingPage extends ConsumerWidget { +class SortingPage extends StatelessWidget { const SortingPage({required this.instance, required this.title, super.key}); final StateNotifierProvider instance; final String title; @override - Widget build(BuildContext context, ref) { + Widget build(BuildContext context) { return Scaffold( appBar: appBar(), body: SafeArea( @@ -33,19 +35,15 @@ class SortingPage extends ConsumerWidget { spacing: 10, children: [ _ControlButtons(instance), - Row( - children: [ - DraggableProgressBar( - onChanged: (persent) { - ref.read(instance.notifier).changeSpeed(persent); - }, - ), - DraggableProgressBar( - onChanged: (persent) { - ref.read(instance.notifier).changeSize(persent); - }, - ), - ], + SymmetricPadding( + horizontal: 15, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SpeedDraggable(instance: instance), + SizeDraggable(instance: instance), + ], + ), ), ], ), @@ -69,6 +67,75 @@ class SortingPage extends ConsumerWidget { } } +class SpeedDraggable extends ConsumerWidget { + const SpeedDraggable({super.key, required this.instance}); + + final StateNotifierProvider instance; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Flexible( + child: Row( + children: [ + const MediumText(StringsManager.speed, fontSize: 12), + Flexible( + child: DraggableProgressBar( + runOnChangedInitially: true, + onChanged: (persent) { + ref.read(instance.notifier).changeSpeed(persent); + }, + ), + ), + ], + ), + ); + } +} + +class SizeDraggable extends ConsumerWidget { + const SizeDraggable({super.key, required this.instance}); + + final StateNotifierProvider instance; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final operationStatus = ref.watch(instance.select((state) => state.operationStatus)); + final isRunning = operationStatus == SortingEnum.played || operationStatus == SortingEnum.stopped; + return Flexible( + child: Row( + children: [ + MediumText( + StringsManager.size, + fontSize: 12, + color: isRunning ? ThemeEnum.whiteD7Color : null, + ), + Flexible( + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + DraggableProgressBar( + isActive: !isRunning, + runOnChangedInitially: true, + sliderValue: 0.15, + onChanged: (persent) { + ref.read(instance.notifier).changeSize(persent); + }, + ), + if (isRunning) + Container( + color: ColorManager.transparent, + height: 20.r, + width: double.infinity, + ) + ], + ), + ), + ], + ), + ); + } +} + class Item extends StatelessWidget { final String text; @@ -95,8 +162,8 @@ class _BuildList extends ConsumerWidget { return Padding( padding: const EdgeInsets.only(top: 5), - child: SizedBox( - height: SortingNotifier.maxListItemHeight * 1.3, + child: RSizedBox( + height: SortingNotifier.maxListItemHeight * 1.05, width: double.infinity, child: Stack( alignment: AlignmentDirectional.bottomCenter, @@ -104,11 +171,11 @@ class _BuildList extends ConsumerWidget { items.length, (index) { final item = items[index]; - final position = ref.watch(instance.select((state) => state.positions[item.id]!)); + final position = ref.watch(instance.select((state) => state.positions[item.id])); return AnimatedPositioned( key: ValueKey(item.id), - left: position.dx, - bottom: position.dy, + left: position?.dx, + bottom: position?.dy, duration: speedDuration, child: _BuildItem( item: item, index: index, speedDuration: speedDuration * 0.5, instance: instance), @@ -138,7 +205,8 @@ class _BuildItem extends ConsumerWidget { Widget build(BuildContext context, ref) { final size = ref.watch(instance.select((state) => state.size)); final itemWidth = SortingNotifier.calculateItemWidth(context, size); - final currentItem = ref.watch(instance.select((state) => state.list[index])); + final currentItem = + ref.watch(instance.select((state) => index < state.list.length ? state.list[index] : null)); return Padding( padding: EdgeInsets.symmetric(horizontal: SortingNotifier.itemsPadding / 2), @@ -147,7 +215,7 @@ class _BuildItem extends ConsumerWidget { height: SortingNotifier.calculateItemHeight(item.value, size), width: itemWidth, decoration: BoxDecoration( - color: context.getColor(currentItem.getColor), + color: context.getColor(currentItem?.getColor ?? SortingNotifier.itemColor), borderRadius: const BorderRadius.vertical(top: Radius.circular(1)), ), ), From 29bda61cf4b33129bc7e4e75b2113b204b184d13 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:59:20 +0300 Subject: [PATCH 004/107] refactoring and handle size changing while running --- lib/features/sorting/base/view_model/sorting_state.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/features/sorting/base/view_model/sorting_state.dart b/lib/features/sorting/base/view_model/sorting_state.dart index ec1917b..f6bf73d 100644 --- a/lib/features/sorting/base/view_model/sorting_state.dart +++ b/lib/features/sorting/base/view_model/sorting_state.dart @@ -5,7 +5,9 @@ class SortingNotifierState { final Map positions; final Duration swipeDuration; final int size; + final SortingEnum operationStatus; SortingNotifierState({ + this.operationStatus = SortingEnum.none, this.size = SortingNotifier._defaultSize, this.swipeDuration = SortingNotifier._defaultSpeedDuration, required this.list, @@ -18,8 +20,10 @@ class SortingNotifierState { List? list, Map? positions, List? selectedAlgorithms, + SortingEnum? operationStatus, }) { return SortingNotifierState( + operationStatus: operationStatus ?? this.operationStatus, size: size ?? this.size, swipeDuration: swipeDuration ?? this.swipeDuration, list: list ?? this.list, From 305a2858b2da2fe231fb499c15075a3ed58e0f3f Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:59:30 +0300 Subject: [PATCH 005/107] add some strings --- lib/core/resources/strings_manager.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index e6cfad1..0b5f4d9 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -38,4 +38,6 @@ class StringsManager { static const String play = "Play"; static const String reset = "Reset"; static const String sort = "Sort"; + static const String speed = "Speed"; + static const String size = "Size"; } From 62539010e55eddecb549847de45ecd69f250b27f Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:59:42 +0300 Subject: [PATCH 006/107] reformat the code --- lib/core/widgets/adaptive/padding/symmetric_padding.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/core/widgets/adaptive/padding/symmetric_padding.dart b/lib/core/widgets/adaptive/padding/symmetric_padding.dart index 785a0d4..133deb5 100644 --- a/lib/core/widgets/adaptive/padding/symmetric_padding.dart +++ b/lib/core/widgets/adaptive/padding/symmetric_padding.dart @@ -2,8 +2,8 @@ part of '../../../../core/widgets/adaptive/padding/adaptive_padding.dart'; class SymmetricPadding extends StatelessWidget { const SymmetricPadding({ - required this.horizontal, - required this.vertical, + this.horizontal = 0, + this.vertical = 0, required this.child, super.key, }); @@ -13,8 +13,6 @@ class SymmetricPadding extends StatelessWidget { @override Widget build(BuildContext context) { return _RPadding( - padding: - REdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), - child: child); + padding: REdgeInsets.symmetric(horizontal: horizontal, vertical: vertical), child: child); } } From f7178c7c18913c5a7b234bb04bc13cf6807ae570 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 20:59:53 +0300 Subject: [PATCH 007/107] add some colors --- lib/core/resources/theme_manager.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/core/resources/theme_manager.dart b/lib/core/resources/theme_manager.dart index 4d7d443..0bfab25 100644 --- a/lib/core/resources/theme_manager.dart +++ b/lib/core/resources/theme_manager.dart @@ -33,6 +33,7 @@ enum ThemeEnum { blueColor, darkBlueColor, + mediumBlueColor, lightBlueColor, greenColor, redColor, @@ -82,7 +83,8 @@ extension ThemeExtension on BuildContext { Theme.of(this).textTheme.bodyLarge?.color ?? ColorManager.greyD3, ThemeEnum.blueColor: ColorManager.blue, ThemeEnum.darkBlueColor: ColorManager.darkBlue, - ThemeEnum.lightBlueColor: ColorManager.lightBlue, + ThemeEnum.mediumBlueColor: ColorManager.mediumBlue, + ThemeEnum.lightBlueColor: ColorManager.finishedSearcherBlue, ThemeEnum.greenColor: ColorManager.green, ThemeEnum.redColor: ColorManager.red, ThemeEnum.orangeColor: ColorManager.orange, From 7e3e1d679dd20d470d8dd292d8e5ddc00bf6ab12 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sat, 23 Aug 2025 21:35:45 +0300 Subject: [PATCH 008/107] handle generate maze --- .../searching/view_model/grid_notifier.dart | 84 +++++++++++++++---- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index 1498ea5..589024b 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -20,7 +20,7 @@ class MazeDirection { class SearchingNotifier extends StateNotifier { SearchingNotifier() : super(GridNotifierState()); - final int columnSquares = 25; + final int columnSquares = 26; // make it odd always static const Duration scaleAppearDurationForWall = Duration(milliseconds: 700); static const Duration clearDuration = Duration(microseconds: 1); static const Duration drawFindingPathDuration = Duration(milliseconds: 2); @@ -341,17 +341,62 @@ class SearchingNotifier extends StateNotifier { } } - // Random starting point + // 🔹 Draw outer border walls + await _drawBorders(gridData); + + // 🔹 Force the second border inside as a corridor (always empty) + _makeSafeCorridor(gridData); + final random = Random(); - int startRow = (random.nextInt(state.rowMainAxisCount - 2) ~/ 2) * 2 + 1; - int startCol = (random.nextInt(state.columnCrossAxisCount - 2) ~/ 2) * 2 + 1; + int startRow = (random.nextInt((state.rowMainAxisCount - 3) ~/ 2) * 2) + 2; // >= 2 + int startCol = (random.nextInt((state.columnCrossAxisCount - 3) ~/ 2) * 2) + 2; // >= 2 - await _cravePassage(startRow, startCol, gridData); + await _drawWalls(startRow, startCol, gridData); state = state.copyWith(gridData: gridData); } - Future _cravePassage(int row, int col, List gridData) async { + Future _drawBorders(List gridData) async { + // Top & bottom rows + for (int c = 0; c < state.columnCrossAxisCount; c++) { + for (final r in [0, state.rowMainAxisCount - 1]) { + final idx = r * state.columnCrossAxisCount + c; + if (gridData[idx] != GridStatus.startPoint && gridData[idx] != GridStatus.targetPoint) { + gridData[idx] = GridStatus.wall; + state = state.copyWith(gridData: List.from(gridData)); + await Future.delayed(mazeDuration); + } + } + } + + // Left & right columns + for (int r = 1; r < state.rowMainAxisCount - 1; r++) { + for (final c in [0, state.columnCrossAxisCount - 1]) { + final idx = r * state.columnCrossAxisCount + c; + if (gridData[idx] != GridStatus.startPoint && gridData[idx] != GridStatus.targetPoint) { + gridData[idx] = GridStatus.wall; + state = state.copyWith(gridData: List.from(gridData)); + await Future.delayed(mazeDuration); + } + } + } + } + + /// Make the second layer inside the borders always a safe corridor (roads). + void _makeSafeCorridor(List gridData) { + for (int r = 1; r < state.rowMainAxisCount - 1; r++) { + for (int c = 1; c < state.columnCrossAxisCount - 1; c++) { + if (r == 1 || r == state.rowMainAxisCount - 2 || c == 1 || c == state.columnCrossAxisCount - 2) { + final idx = r * state.columnCrossAxisCount + c; + if (gridData[idx] != GridStatus.startPoint && gridData[idx] != GridStatus.targetPoint) { + gridData[idx] = GridStatus.empty; // always keep clear + } + } + } + } + } + + Future _drawWalls(int row, int col, List gridData) async { final directions = [MazeDirection.up, MazeDirection.down, MazeDirection.left, MazeDirection.right]; directions.shuffle(); @@ -359,25 +404,32 @@ class SearchingNotifier extends StateNotifier { final newRow = row + direction.rowDelta * 2; final newCol = col + direction.colDelta * 2; - final currentGrid = gridData[newRow * state.columnCrossAxisCount + newCol]; if (_isValidCell(newRow, newCol) && - currentGrid == GridStatus.empty && - currentGrid != GridStatus.startPoint && - currentGrid != GridStatus.targetPoint) { - gridData[(row + direction.rowDelta) * state.columnCrossAxisCount + (col + direction.colDelta)] = - GridStatus.wall; - gridData[newRow * state.columnCrossAxisCount + newCol] = GridStatus.wall; + gridData[newRow * state.columnCrossAxisCount + newCol] == GridStatus.empty) { + final betweenRow = row + direction.rowDelta; + final betweenCol = col + direction.colDelta; - state = state.copyWith(gridData: List.from(gridData)); + final betweenIdx = betweenRow * state.columnCrossAxisCount + betweenCol; + final newIdx = newRow * state.columnCrossAxisCount + newCol; + if (gridData[betweenIdx] != GridStatus.startPoint && gridData[betweenIdx] != GridStatus.targetPoint) { + gridData[betweenIdx] = GridStatus.wall; + } + + if (gridData[newIdx] != GridStatus.startPoint && gridData[newIdx] != GridStatus.targetPoint) { + gridData[newIdx] = GridStatus.wall; + } + + state = state.copyWith(gridData: List.from(gridData)); await Future.delayed(mazeDuration); - await _cravePassage(newRow, newCol, gridData); + await _drawWalls(newRow, newCol, gridData); } } } bool _isValidCell(int row, int col) { - return row > 0 && col > 0 && row < state.rowMainAxisCount && col < state.columnCrossAxisCount; + // must be inside the "safe corridor" + return row > 1 && col > 1 && row < state.rowMainAxisCount - 2 && col < state.columnCrossAxisCount - 2; } } From e95c4fdc203a07ac2afbd261d95d45fe88a9257d Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 00:59:02 +0300 Subject: [PATCH 009/107] add some other mazes --- .../searching/view_model/grid_notifier.dart | 77 ++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index 589024b..694357e 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -331,7 +331,7 @@ class SearchingNotifier extends StateNotifier { } } - void generateMaze() async { + void generateRecursiveBacktrackerMaze() async { final gridData = List.from(state.gridData); // Clear the maze but keep start and target points @@ -432,4 +432,79 @@ class SearchingNotifier extends StateNotifier { // must be inside the "safe corridor" return row > 1 && col > 1 && row < state.rowMainAxisCount - 2 && col < state.columnCrossAxisCount - 2; } + + // Recursive Division Maze Generation + Future generateRecursiveDivisionMaze() async { + final gridData = List.from(state.gridData); + + // Step 1: Start with all empty + for (int i = 0; i < gridData.length; i++) { + if (gridData[i] != GridStatus.startPoint && gridData[i] != GridStatus.targetPoint) { + gridData[i] = GridStatus.empty; + } + } + + // Step 2: Add outer borders as walls + for (int r = 0; r < state.rowMainAxisCount; r++) { + for (int c = 0; c < state.columnCrossAxisCount; c++) { + if (r == 0 || c == 0 || r == state.rowMainAxisCount - 1 || c == state.columnCrossAxisCount - 1) { + if (gridData[r * state.columnCrossAxisCount + c] != GridStatus.startPoint && + gridData[r * state.columnCrossAxisCount + c] != GridStatus.targetPoint) { + gridData[r * state.columnCrossAxisCount + c] = GridStatus.wall; + state = state.copyWith(gridData: List.from(gridData)); + await Future.delayed(mazeDuration); + } + } + } + } + + state = state.copyWith(gridData: List.from(gridData)); + + await _divide(1, 1, state.rowMainAxisCount - 2, state.columnCrossAxisCount - 2, gridData); + + state = state.copyWith(gridData: gridData); + } + + Future _divide(int row, int col, int height, int width, List gridData) async { + if (height < 2 || width < 2) return; + + final random = Random(); + final horizontal = random.nextBool(); + + if (horizontal) { + // Horizontal wall + int wallRow = row + (random.nextInt(height ~/ 2)) * 2 + 1; + int passageCol = col + (random.nextInt(width ~/ 2)) * 2; + + for (int c = col; c < col + width; c++) { + if (c == passageCol) continue; + if (gridData[wallRow * state.columnCrossAxisCount + c] != GridStatus.startPoint && + gridData[wallRow * state.columnCrossAxisCount + c] != GridStatus.targetPoint) { + gridData[wallRow * state.columnCrossAxisCount + c] = GridStatus.wall; + state = state.copyWith(gridData: List.from(gridData)); + await Future.delayed(mazeDuration); // 🔹 Delay for each cell + } + } + + await _divide(row, col, wallRow - row, width, gridData); + await _divide(wallRow + 1, col, row + height - wallRow - 1, width, gridData); + } else { + // Vertical wall + int wallCol = col + (random.nextInt(width ~/ 2)) * 2 + 1; + int passageRow = row + (random.nextInt(height ~/ 2)) * 2; + + for (int r = row; r < row + height; r++) { + if (r == passageRow) continue; + if (gridData[r * state.columnCrossAxisCount + wallCol] != GridStatus.startPoint && + gridData[r * state.columnCrossAxisCount + wallCol] != GridStatus.targetPoint) { + gridData[r * state.columnCrossAxisCount + wallCol] = GridStatus.wall; + state = state.copyWith(gridData: List.from(gridData)); + await Future.delayed(mazeDuration); // 🔹 Delay for each cell + } + } + + await _divide(row, col, height, wallCol - col, gridData); + await _divide(row, wallCol + 1, height, col + width - wallCol - 1, gridData); + } + } } From 2241cd95a47f252cb2839e74aee69e43b2a3fc32 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 00:59:13 +0300 Subject: [PATCH 010/107] handle maze functions --- lib/features/searching/view/grid_page.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index 37e9ad6..d4e90e6 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -41,9 +41,15 @@ class SearchingPage extends StatelessWidget { CustomAlertDialog(context).solidDialog( parameters: [ ListDialogParameters( - text: StringsManager.generateMaze, + text: StringsManager.recursiveBacktrackerMaze, onTap: () { - ref.read(_gridNotifierProvider.notifier).generateMaze(); + ref.read(_gridNotifierProvider.notifier).generateRecursiveBacktrackerMaze(); + }, + ), + ListDialogParameters( + text: StringsManager.recursiveDivisionMaze, + onTap: () { + ref.read(_gridNotifierProvider.notifier).generateRecursiveDivisionMaze(); }, ), ListDialogParameters( From b15fb5ca2b1eda865191eb8565e753596062f07f Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 00:59:23 +0300 Subject: [PATCH 011/107] add some text --- lib/core/resources/strings_manager.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index 0b5f4d9..86b5c71 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -26,7 +26,8 @@ class StringsManager { static const String clear = "Clear"; static const String clearAll = "Clear all"; static const String clearPath = "Clear path"; - static const String generateMaze = "Generate maze"; + static const String recursiveBacktrackerMaze = "Recursive Backtracker Maze"; + static const String recursiveDivisionMaze = "Recursive Division Maze"; static const String searching = "Searching"; static const String sorting = "Sorting"; static const String bubbleSort = "Bubble sort"; From ca096ddfbafa3d011c229fd3b3817e20b4752302 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 01:13:55 +0300 Subject: [PATCH 012/107] add some text --- lib/core/resources/strings_manager.dart | 3 +++ lib/features/searching/view/grid_page.dart | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index 86b5c71..263cfde 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -24,6 +24,9 @@ class StringsManager { static const String unknownPage = "Unknown page"; static const String notInitializeGridYet = "Not initialize grid yet."; static const String clear = "Clear"; + static const String dijkstra = "Dijkstra"; + static const String bFS = "BFS"; + static const String dFS = "DFS"; static const String clearAll = "Clear all"; static const String clearPath = "Clear path"; static const String recursiveBacktrackerMaze = "Recursive Backtracker Maze"; diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index d4e90e6..8c3bccf 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -53,13 +53,13 @@ class SearchingPage extends StatelessWidget { }, ), ListDialogParameters( - text: "Dijkstra", + text: StringsManager.dijkstra, onTap: () { ref.read(_gridNotifierProvider.notifier).performDijkstra(); }, ), ListDialogParameters( - text: "BFS", + text: StringsManager.bFS, onTap: () { ref.read(_gridNotifierProvider.notifier).performBFS(); }, From e366af1669cd1116f7aef14d5192efbeb4b60d1d Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:09:12 +0300 Subject: [PATCH 013/107] add performAStar --- .../searching/view_model/grid_notifier.dart | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index 694357e..1c4241f 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -331,6 +331,86 @@ class SearchingNotifier extends StateNotifier { } } + Future performAStar() async { + final gridData = List.from(state.gridData); + final startPointIndex = gridData.indexOf(GridStatus.startPoint); + final targetPointIndex = gridData.indexOf(GridStatus.targetPoint); + + if (startPointIndex == -1 || targetPointIndex == -1) return; + + final cross = state.columnCrossAxisCount; + + final gScore = List.filled(gridData.length, double.infinity); + final fScore = List.filled(gridData.length, double.infinity); + final previous = List.filled(gridData.length, null); + final visited = {}; + + gScore[startPointIndex] = 0; + fScore[startPointIndex] = _heuristic(startPointIndex, targetPointIndex, cross); + + // priority queue based on fScore (g + h) + final pq = PriorityQueue((a, b) => fScore[a].compareTo(fScore[b])); + pq.add(startPointIndex); + + final directions = [ + -cross, // up + cross, // down + -1, // left + 1, // right + ]; + + while (pq.isNotEmpty) { + final currentIndex = pq.removeFirst(); + + if (currentIndex == targetPointIndex) { + await _tracePath(previous, currentIndex); + return; + } + + visited.add(currentIndex); + + for (final direction in directions) { + final neighborIndex = currentIndex + direction; + + if (!_isValidNeighbor(currentIndex, neighborIndex, direction, cross, gridData)) { + continue; + } + + if (visited.contains(neighborIndex)) continue; + + final tentativeG = gScore[currentIndex] + 1; // weight = 1 + + if (tentativeG < gScore[neighborIndex]) { + gScore[neighborIndex] = tentativeG; + fScore[neighborIndex] = tentativeG + _heuristic(neighborIndex, targetPointIndex, cross); + previous[neighborIndex] = currentIndex; + + if (!pq.contains(neighborIndex)) { + pq.add(neighborIndex); + } + + // visualize + if (gridData[neighborIndex] != GridStatus.startPoint && + gridData[neighborIndex] != GridStatus.targetPoint) { + gridData[neighborIndex] = GridStatus.searcher; + state = state.copyWith(gridData: List.from(gridData)); + await Future.delayed(drawSearcherDuration); + } + } + } + } + } + + double _heuristic(int index, int targetIndex, int cross) { + // Manhattan distance + final x1 = index % cross; + final y1 = index ~/ cross; + final x2 = targetIndex % cross; + final y2 = targetIndex ~/ cross; + + return ((x1 - x2).abs() + (y1 - y2).abs()).toDouble(); + } + void generateRecursiveBacktrackerMaze() async { final gridData = List.from(state.gridData); From 5e3a79c9ac245ee4eb915b8372a70b4a2f4d6471 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:09:16 +0300 Subject: [PATCH 014/107] add performAStar --- lib/core/resources/strings_manager.dart | 1 + lib/features/searching/view/grid_page.dart | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index 263cfde..e70717e 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -25,6 +25,7 @@ class StringsManager { static const String notInitializeGridYet = "Not initialize grid yet."; static const String clear = "Clear"; static const String dijkstra = "Dijkstra"; + static const String aStarSearch = "A* Search"; static const String bFS = "BFS"; static const String dFS = "DFS"; static const String clearAll = "Clear all"; diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index 8c3bccf..cb03249 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -58,6 +58,12 @@ class SearchingPage extends StatelessWidget { ref.read(_gridNotifierProvider.notifier).performDijkstra(); }, ), + ListDialogParameters( + text: StringsManager.aStarSearch, + onTap: () { + ref.read(_gridNotifierProvider.notifier).performAStar(); + }, + ), ListDialogParameters( text: StringsManager.bFS, onTap: () { From 82d516deecff5434ad8c32c63ca9a61fdd7901d0 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:48:38 +0300 Subject: [PATCH 015/107] add heapSort in SortingListPage --- lib/features/sorting/base/view/sorting_list_page.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index fa420f5..8696e45 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -53,6 +53,15 @@ class SortingListPage extends StatelessWidget { context.pushTo(Routes.mergeSort); }, ), + CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.heapSort), + onPressed: () { + context.pushTo(Routes.heapSort); + }, + ), + ], ), ), From 8e2d93227369a1077b3a61634f44b65f08fa2956 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:48:52 +0300 Subject: [PATCH 016/107] add quickSort in SortingListPage --- lib/features/sorting/base/view/sorting_list_page.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index 8696e45..a64bdd4 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -61,7 +61,14 @@ class SortingListPage extends StatelessWidget { context.pushTo(Routes.heapSort); }, ), - + CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.quickSort), + onPressed: () { + context.pushTo(Routes.quickSort); + }, + ), ], ), ), From 06d591081181f9be7e211068bcc418daf921cff7 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:49:52 +0300 Subject: [PATCH 017/107] add radixSort in SortingListPage --- lib/features/sorting/base/view/sorting_list_page.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index a64bdd4..46a1949 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -69,6 +69,15 @@ class SortingListPage extends StatelessWidget { context.pushTo(Routes.quickSort); }, ), + CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.radixSort), + onPressed: () { + context.pushTo(Routes.radixSort); + }, + ), + ], ), ), From 12b89693b3ae831852b96cd87f5d5910f2363629 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:50:04 +0300 Subject: [PATCH 018/107] add shellSort in SortingListPage --- lib/features/sorting/base/view/sorting_list_page.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index 46a1949..65ee522 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -77,6 +77,14 @@ class SortingListPage extends StatelessWidget { context.pushTo(Routes.radixSort); }, ), + CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.shellSort), + onPressed: () { + context.pushTo(Routes.shellSort); + }, + ), ], ), From c8deb0a896df0206cf46a842958e9cdd0f2d248d Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:50:14 +0300 Subject: [PATCH 019/107] add countingSort in SortingListPage --- lib/features/sorting/base/view/sorting_list_page.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index 65ee522..d394a4d 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -85,6 +85,14 @@ class SortingListPage extends StatelessWidget { context.pushTo(Routes.shellSort); }, ), + CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.countingSort), + onPressed: () { + context.pushTo(Routes.countingSort); + }, + ), ], ), From 6b2fea25ee250f0b0c3e78850f2a08f882dc39b9 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:50:22 +0300 Subject: [PATCH 020/107] add bucketSort in SortingListPage --- lib/features/sorting/base/view/sorting_list_page.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index d394a4d..a8ce4e4 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -93,7 +93,14 @@ class SortingListPage extends StatelessWidget { context.pushTo(Routes.countingSort); }, ), - + CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.bucketSort), + onPressed: () { + context.pushTo(Routes.bucketSort); + }, + ), ], ), ), From cc950fbd5bdc6fc4f381aef17021cebe85e11c0a Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:51:10 +0300 Subject: [PATCH 021/107] add heapSort in Routes --- lib/config/routes/route_app.dart | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index 5978d35..0df25b5 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -5,8 +5,11 @@ import 'package:algorithm_visualizer/features/base/view/base_page.dart'; import 'package:algorithm_visualizer/features/searching/view/grid_page.dart'; import 'package:algorithm_visualizer/features/sorting/base/view/sorting_list_page.dart'; import 'package:algorithm_visualizer/features/sorting/bubble/view/bubble_sort_page.dart'; +import 'package:algorithm_visualizer/features/sorting/heap/view/heap_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/insertion/view/insertion_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/merge/view/merge_sort_page.dart'; +import 'package:algorithm_visualizer/features/sorting/quick/view/quick_sort_page.dart'; +import 'package:algorithm_visualizer/features/sorting/radix/view/radix_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/selection/view/selection_sort_page.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -41,6 +44,10 @@ class Routes { name: 'mergeSort', path: 'mergeSort', ); + static const RouteConfig heapSort = RouteConfig( + name: 'heapSort', + path: 'heapSort', + ); } class RouteConfig { @@ -111,6 +118,14 @@ class AppRoutes { return const MergeSortPage(); }, ), + GoRoute( + path: Routes.heapSort.path, + name: Routes.heapSort.name, + builder: (context, state) { + return const HeapSortPage(); + }, + ), + ], ), ], From a2f52e1f10e3a8e1817ffde2839399608894639c Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:51:44 +0300 Subject: [PATCH 022/107] add quickSort in Routes --- lib/config/routes/route_app.dart | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index 0df25b5..f22c982 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -48,6 +48,10 @@ class Routes { name: 'heapSort', path: 'heapSort', ); + static const RouteConfig quickSort = RouteConfig( + name: 'quickSort', + path: 'quickSort', + ); } class RouteConfig { @@ -125,7 +129,13 @@ class AppRoutes { return const HeapSortPage(); }, ), - + GoRoute( + path: Routes.quickSort.path, + name: Routes.quickSort.name, + builder: (context, state) { + return const QuickSortPage(); + }, + ), ], ), ], From 44e065b45e3551b54493eff6035f2da95221c445 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:52:03 +0300 Subject: [PATCH 023/107] add radixSort in Routes --- lib/config/routes/route_app.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index f22c982..5a72468 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -52,6 +52,10 @@ class Routes { name: 'quickSort', path: 'quickSort', ); + static const RouteConfig radixSort = RouteConfig( + name: 'radixSort', + path: 'radixSort', + ); } class RouteConfig { @@ -136,6 +140,13 @@ class AppRoutes { return const QuickSortPage(); }, ), + GoRoute( + path: Routes.radixSort.path, + name: Routes.radixSort.name, + builder: (context, state) { + return const RadixSortPage(); + }, + ), ], ), ], From 0cfcaedb812d0bd0eec0c434d64d7ea4de1fa651 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:52:42 +0300 Subject: [PATCH 024/107] add shellSort in Routes --- lib/config/routes/route_app.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index 5a72468..f6ba5c7 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -56,6 +56,10 @@ class Routes { name: 'radixSort', path: 'radixSort', ); + static const RouteConfig shellSort = RouteConfig( + name: 'shellSort', + path: 'shellSort', + ); } class RouteConfig { @@ -147,6 +151,13 @@ class AppRoutes { return const RadixSortPage(); }, ), + GoRoute( + path: Routes.shellSort.path, + name: Routes.shellSort.name, + builder: (context, state) { + return const ShellSortPage(); + }, + ), ], ), ], From 0936fed5034eedafb25ab4cfb25cedb66c675024 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:53:14 +0300 Subject: [PATCH 025/107] add countingSort in Routes --- lib/config/routes/route_app.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index f6ba5c7..4b596cc 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -60,6 +60,10 @@ class Routes { name: 'shellSort', path: 'shellSort', ); + static const RouteConfig countingSort = RouteConfig( + name: 'countingSort', + path: 'countingSort', + ); } class RouteConfig { @@ -158,6 +162,13 @@ class AppRoutes { return const ShellSortPage(); }, ), + GoRoute( + path: Routes.countingSort.path, + name: Routes.countingSort.name, + builder: (context, state) { + return const CountingSortPage(); + }, + ), ], ), ], From 8616b8d2ffae6ffb84cc86b2383f0cccb8361cc2 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 13:55:36 +0300 Subject: [PATCH 026/107] add bucketSort in Routes --- lib/config/routes/route_app.dart | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index 4b596cc..9aac71a 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -64,6 +64,10 @@ class Routes { name: 'countingSort', path: 'countingSort', ); + static const RouteConfig bucketSort = RouteConfig( + name: 'bucketSort', + path: 'bucketSort', + ); } class RouteConfig { @@ -169,6 +173,13 @@ class AppRoutes { return const CountingSortPage(); }, ), + GoRoute( + path: Routes.bucketSort.path, + name: Routes.bucketSort.name, + builder: (context, state) { + return const BucketSortPage(); + }, + ), ], ), ], From 168c86e1fc9af39a1265cadf21d54ba1bf10b541 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:20:48 +0300 Subject: [PATCH 027/107] add some sorting text --- lib/core/resources/strings_manager.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index e70717e..318b44c 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -38,6 +38,12 @@ class StringsManager { static const String insertionSort = "Insertion sort"; static const String selectionSort = "Selection sort"; static const String mergeSort = "Merge sort"; + static const String heapSort = "Heap sort"; + static const String quickSort = "Quick sort"; + static const String radixSort = "Radix sort"; + static const String shellSort = "Shell sort"; + static const String countingSort = "Counting sort"; + static const String bucketSort = "Bucket sort"; static const String stop = "Stop"; static const String play = "Play"; From 041717e24a9caa7383667b0be8d1282069d3b4dd Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:09 +0300 Subject: [PATCH 028/107] impl MergeSortNotifier --- lib/config/routes/route_app.dart | 3 ++ .../merge/view_model/merge_sort_notifier.dart | 51 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index 9aac71a..4bb6116 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -5,12 +5,15 @@ import 'package:algorithm_visualizer/features/base/view/base_page.dart'; import 'package:algorithm_visualizer/features/searching/view/grid_page.dart'; import 'package:algorithm_visualizer/features/sorting/base/view/sorting_list_page.dart'; import 'package:algorithm_visualizer/features/sorting/bubble/view/bubble_sort_page.dart'; +import 'package:algorithm_visualizer/features/sorting/bucket/view/bucket_sort_page.dart'; +import 'package:algorithm_visualizer/features/sorting/counting/view/counting_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/heap/view/heap_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/insertion/view/insertion_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/merge/view/merge_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/quick/view/quick_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/radix/view/radix_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/selection/view/selection_sort_page.dart'; +import 'package:algorithm_visualizer/features/sorting/shell/view/shell_sort_page.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; diff --git a/lib/features/sorting/merge/view_model/merge_sort_notifier.dart b/lib/features/sorting/merge/view_model/merge_sort_notifier.dart index 1787a71..29246a6 100644 --- a/lib/features/sorting/merge/view_model/merge_sort_notifier.dart +++ b/lib/features/sorting/merge/view_model/merge_sort_notifier.dart @@ -1,9 +1,56 @@ import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:collection/collection.dart'; class MergeSortNotifier extends SortingNotifier { @override SortingResult buildSorting(List values) { - // TODO: implement buildSorting - throw UnimplementedError(); + final steps = []; + final arr = List.from(values); + + // In-place merge using adjacent swaps so it matches your 'swapping' handler. + void mergeInPlace(int left, int mid, int right) { + int i = left; + int j = mid + 1; + + while (i <= mid && j <= right) { + // Show comparison between current heads + steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.compared)); + // Clear highlight + steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.unSorted)); + + if (arr[i] <= arr[j]) { + i++; + } else { + // arr[j] should be inserted before arr[i]. + // Bubble arr[j] leftwards via adjacent swaps until it reaches i. + int k = j; + while (k > i) { + steps.add(SortingStep(index1: k, index2: k - 1, action: SortingStatus.swapping)); + arr.swap(k, k - 1); + + // your handler clears to unSorted + steps.add(SortingStep(index1: k, index2: k - 1, action: SortingStatus.swapped)); + k--; + } + // Now the element originally at j is at position i. + i++; + mid++; // left segment grew by one + j++; // next element in right segment + } + } + } + + void mergeSort(int left, int right) { + if (left >= right) return; + final mid = (left + right) >> 1; + mergeSort(left, mid); + mergeSort(mid + 1, right); + mergeInPlace(left, mid, right); + } + + if (arr.isNotEmpty) mergeSort(0, arr.length - 1); + + // No "sorted" marks during the run; your base class greens everything at the end. + return SortingResult(sortedValues: arr, steps: steps); } } From 9d216af778d99d4fd9ff8857599b6a1dbf11d0ab Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:17 +0300 Subject: [PATCH 029/107] create BucketSortNotifier --- .../view_model/bucket_sort_notifier.dart | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart diff --git a/lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart b/lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart new file mode 100644 index 0000000..38a5bc7 --- /dev/null +++ b/lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart @@ -0,0 +1,67 @@ +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:collection/collection.dart'; + +class BucketSortNotifier extends SortingNotifier { + @override + SortingResult buildSorting(List values) { + final steps = []; + final arr = List.from(values); + + if (arr.isEmpty) { + return SortingResult(sortedValues: arr, steps: steps); + } + + int n = arr.length; + int maxVal = arr.reduce((a, b) => a > b ? a : b); + int minVal = arr.reduce((a, b) => a < b ? a : b); + + // Decide number of buckets (basic choice = n) + int bucketCount = n; + double bucketRange = (maxVal - minVal + 1) / bucketCount; + + // 1. Create buckets + final buckets = List.generate(bucketCount, (_) => []); + + // 2. Scatter: put array elements into buckets + for (int value in arr) { + int bucketIndex = ((value - minVal) / bucketRange).floor(); + if (bucketIndex >= bucketCount) bucketIndex = bucketCount - 1; + buckets[bucketIndex].add(value); + } + + // 3. Sort each bucket (Insertion Sort) + for (var bucket in buckets) { + for (int i = 1; i < bucket.length; i++) { + int key = bucket[i]; + int j = i - 1; + while (j >= 0 && bucket[j] > key) { + bucket[j + 1] = bucket[j]; + j--; + } + bucket[j + 1] = key; + } + } + + // 4. Gather: merge buckets back into arr + int index = 0; + for (var bucket in buckets) { + for (int value in bucket) { + if (arr[index] != value) { + // Find where the value currently is + int targetIndex = arr.indexOf(value, index); + + // Swap for visualization + steps.add(SortingStep(index1: index, index2: targetIndex, action: SortingStatus.swapping)); + arr.swap(index, targetIndex); + steps.add(SortingStep(index1: index, index2: targetIndex, action: SortingStatus.swapped)); + } + index++; + } + } + + // Mark all sorted at the end + steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); + + return SortingResult(sortedValues: arr, steps: steps); + } +} From e33c94a1db70c951bcc4b802dc5f18ba424a73fc Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:23 +0300 Subject: [PATCH 030/107] create BucketSortPage --- .../sorting/bucket/view/bucket_sort_page.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/features/sorting/bucket/view/bucket_sort_page.dart diff --git a/lib/features/sorting/bucket/view/bucket_sort_page.dart b/lib/features/sorting/bucket/view/bucket_sort_page.dart new file mode 100644 index 0000000..65141ce --- /dev/null +++ b/lib/features/sorting/bucket/view/bucket_sort_page.dart @@ -0,0 +1,30 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view/sorting_page.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/bucket/view_model/bucket_sort_notifier.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final _notifierProvider = StateNotifierProvider( + (ref) => BucketSortNotifier(), +); + +class BucketSortPage extends ConsumerStatefulWidget { + const BucketSortPage({super.key}); + + @override + ConsumerState createState() => _BucketSortPageState(); +} + +class _BucketSortPageState extends ConsumerState { + @override + void deactivate() { + ref.invalidate(_notifierProvider); // deletes current instance and resets + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return SortingPage(instance: _notifierProvider, title: StringsManager.bucketSort); + } +} From 11ff2c66e0790c726d1b1713371383017ce181f4 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:29 +0300 Subject: [PATCH 031/107] create CountingSortNotifier --- .../view_model/counting_sort_notifier.dart | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 lib/features/sorting/counting/view_model/counting_sort_notifier.dart diff --git a/lib/features/sorting/counting/view_model/counting_sort_notifier.dart b/lib/features/sorting/counting/view_model/counting_sort_notifier.dart new file mode 100644 index 0000000..b7210d9 --- /dev/null +++ b/lib/features/sorting/counting/view_model/counting_sort_notifier.dart @@ -0,0 +1,51 @@ +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:collection/collection.dart'; + +class CountingSortNotifier extends SortingNotifier { + @override + SortingResult buildSorting(List values) { + final steps = []; + final arr = List.from(values); + + if (arr.isEmpty) { + return SortingResult(sortedValues: arr, steps: steps); + } + + // 1. Find range of input values + int maxVal = arr.reduce((a, b) => a > b ? a : b); + int minVal = arr.reduce((a, b) => a < b ? a : b); + int range = maxVal - minVal + 1; + + // 2. Frequency array + final count = List.filled(range, 0); + for (int i = 0; i < arr.length; i++) { + count[arr[i] - minVal]++; + } + + // 3. Build the sorted array + int index = 0; + for (int i = 0; i < range; i++) { + while (count[i] > 0) { + int correctValue = i + minVal; + + if (arr[index] != correctValue) { + // Find where the correctValue currently is + int targetIndex = arr.indexOf(correctValue, index); + + // Log swap + steps.add(SortingStep(index1: index, index2: targetIndex, action: SortingStatus.swapping)); + arr.swap(index, targetIndex); + steps.add(SortingStep(index1: index, index2: targetIndex, action: SortingStatus.swapped)); + } + + index++; + count[i]--; + } + } + + // Mark all sorted at the end + steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); + + return SortingResult(sortedValues: arr, steps: steps); + } +} From 66c24021da282282567e109dd5c8e61cd224d9e4 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:34 +0300 Subject: [PATCH 032/107] create CountingSortPage --- .../counting/view/counting_sort_page.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/features/sorting/counting/view/counting_sort_page.dart diff --git a/lib/features/sorting/counting/view/counting_sort_page.dart b/lib/features/sorting/counting/view/counting_sort_page.dart new file mode 100644 index 0000000..0e75822 --- /dev/null +++ b/lib/features/sorting/counting/view/counting_sort_page.dart @@ -0,0 +1,30 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view/sorting_page.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/counting/view_model/counting_sort_notifier.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final _notifierProvider = StateNotifierProvider( + (ref) => CountingSortNotifier(), +); + +class CountingSortPage extends ConsumerStatefulWidget { + const CountingSortPage({super.key}); + + @override + ConsumerState createState() => _CountingSortPageState(); +} + +class _CountingSortPageState extends ConsumerState { + @override + void deactivate() { + ref.invalidate(_notifierProvider); // deletes current instance and resets + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return SortingPage(instance: _notifierProvider, title: StringsManager.countingSort); + } +} From 15ab58d9cf98315a7d58b4ebed46349a85bfdb9b Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:40 +0300 Subject: [PATCH 033/107] create HeapSortNotifier --- .../heap/view_model/heap_sort_notifier.dart | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 lib/features/sorting/heap/view_model/heap_sort_notifier.dart diff --git a/lib/features/sorting/heap/view_model/heap_sort_notifier.dart b/lib/features/sorting/heap/view_model/heap_sort_notifier.dart new file mode 100644 index 0000000..f3b11e0 --- /dev/null +++ b/lib/features/sorting/heap/view_model/heap_sort_notifier.dart @@ -0,0 +1,71 @@ +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:collection/collection.dart'; + +class HeapSortNotifier extends SortingNotifier { + @override + SortingResult buildSorting(List values) { + final steps = []; + final arr = List.from(values); + + void heapify(int n, int i) { + int largest = i; + int left = 2 * i + 1; + int right = 2 * i + 2; + + // Compare left child + if (left < n) { + steps.add(SortingStep(index1: largest, index2: left, action: SortingStatus.compared)); + if (arr[left] > arr[largest]) { + largest = left; + } + steps.add(SortingStep(index1: i, index2: left, action: SortingStatus.unSorted)); + } + + // Compare right child + if (right < n) { + steps.add(SortingStep(index1: largest, index2: right, action: SortingStatus.compared)); + if (arr[right] > arr[largest]) { + largest = right; + } + steps.add(SortingStep(index1: i, index2: right, action: SortingStatus.unSorted)); + } + + // If largest is not root + if (largest != i) { + steps.add(SortingStep(index1: i, index2: largest, action: SortingStatus.swapping)); + + arr.swap(i, largest); + + steps.add(SortingStep(index1: i, index2: largest, action: SortingStatus.swapped)); + + heapify(n, largest); + } + } + + int n = arr.length; + + // Build max heap + for (int i = n ~/ 2 - 1; i >= 0; i--) { + heapify(n, i); + } + + // Extract elements one by one + for (int i = n - 1; i > 0; i--) { + steps.add(SortingStep(index1: 0, index2: i, action: SortingStatus.swapping)); + + arr.swap(0, i); + + steps.add(SortingStep(index1: 0, index2: i, action: SortingStatus.swapped)); + + // Mark last element as sorted + steps.add(SortingStep(index1: i, index2: i, action: SortingStatus.sorted)); + + heapify(i, 0); + } + + // Mark the first element sorted + steps.add(SortingStep(index1: 0, index2: 0, action: SortingStatus.sorted)); + + return SortingResult(sortedValues: arr, steps: steps); + } +} From a42d2bff90c50d3a55c3ccccdec1349604dd531f Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:45 +0300 Subject: [PATCH 034/107] create HeapSortPage --- .../sorting/heap/view/heap_sort_page.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/features/sorting/heap/view/heap_sort_page.dart diff --git a/lib/features/sorting/heap/view/heap_sort_page.dart b/lib/features/sorting/heap/view/heap_sort_page.dart new file mode 100644 index 0000000..cefabaf --- /dev/null +++ b/lib/features/sorting/heap/view/heap_sort_page.dart @@ -0,0 +1,30 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view/sorting_page.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/heap/view_model/heap_sort_notifier.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final _notifierProvider = StateNotifierProvider( + (ref) => HeapSortNotifier(), +); + +class HeapSortPage extends ConsumerStatefulWidget { + const HeapSortPage({super.key}); + + @override + ConsumerState createState() => _HeapSortPageState(); +} + +class _HeapSortPageState extends ConsumerState { + @override + void deactivate() { + ref.invalidate(_notifierProvider); // deletes current instance and resets + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return SortingPage(instance: _notifierProvider, title: StringsManager.heapSort); + } +} From a12bd8d760cfb6adf8706835f092e79edbe5d4c2 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:50 +0300 Subject: [PATCH 035/107] create QuickSortNotifier --- .../quick/view_model/quick_sort_notifier.dart | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 lib/features/sorting/quick/view_model/quick_sort_notifier.dart diff --git a/lib/features/sorting/quick/view_model/quick_sort_notifier.dart b/lib/features/sorting/quick/view_model/quick_sort_notifier.dart new file mode 100644 index 0000000..d9f634a --- /dev/null +++ b/lib/features/sorting/quick/view_model/quick_sort_notifier.dart @@ -0,0 +1,53 @@ +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:collection/collection.dart'; + +class QuickSortNotifier extends SortingNotifier { + @override + SortingResult buildSorting(List values) { + final steps = []; + final arr = List.from(values); + + int partition(int low, int high) { + final pivot = arr[high]; + int i = low - 1; + + for (int j = low; j < high; j++) { + // Compare arr[j] with pivot + steps.add(SortingStep(index1: j, index2: high, action: SortingStatus.compared)); + steps.add(SortingStep(index1: j, index2: high, action: SortingStatus.unSorted)); + + if (arr[j] <= pivot) { + i++; + if (i != j) { + steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.swapping)); + arr.swap(i, j); + steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.swapped)); + } + } + } + + // Place pivot in correct position + if (i + 1 != high) { + steps.add(SortingStep(index1: i + 1, index2: high, action: SortingStatus.swapping)); + arr.swap(i + 1, high); + steps.add(SortingStep(index1: i + 1, index2: high, action: SortingStatus.swapped)); + } + + return i + 1; + } + + void quickSort(int low, int high) { + if (low < high) { + int pi = partition(low, high); + + quickSort(low, pi - 1); + quickSort(pi + 1, high); + } + } + + if (arr.isNotEmpty) quickSort(0, arr.length - 1); + + // Final marking of all sorted items (UI will green them at end anyway) + return SortingResult(sortedValues: arr, steps: steps); + } +} From c2358009f49d7584911b17a74fe21bb42529c829 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:21:55 +0300 Subject: [PATCH 036/107] create QuickSortPage --- .../sorting/quick/view/quick_sort_page.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/features/sorting/quick/view/quick_sort_page.dart diff --git a/lib/features/sorting/quick/view/quick_sort_page.dart b/lib/features/sorting/quick/view/quick_sort_page.dart new file mode 100644 index 0000000..45663c7 --- /dev/null +++ b/lib/features/sorting/quick/view/quick_sort_page.dart @@ -0,0 +1,30 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view/sorting_page.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/quick/view_model/quick_sort_notifier.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final _notifierProvider = StateNotifierProvider( + (ref) => QuickSortNotifier(), +); + +class QuickSortPage extends ConsumerStatefulWidget { + const QuickSortPage({super.key}); + + @override + ConsumerState createState() => _QuickSortPageState(); +} + +class _QuickSortPageState extends ConsumerState { + @override + void deactivate() { + ref.invalidate(_notifierProvider); // deletes current instance and resets + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return SortingPage(instance: _notifierProvider, title: StringsManager.quickSort); + } +} From a83adc27b88a6cc92303e1d3eecd7727563067fc Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:22:00 +0300 Subject: [PATCH 037/107] create RadixSortNotifier --- .../radix/view_model/radix_sort_notifier.dart | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 lib/features/sorting/radix/view_model/radix_sort_notifier.dart diff --git a/lib/features/sorting/radix/view_model/radix_sort_notifier.dart b/lib/features/sorting/radix/view_model/radix_sort_notifier.dart new file mode 100644 index 0000000..5faa797 --- /dev/null +++ b/lib/features/sorting/radix/view_model/radix_sort_notifier.dart @@ -0,0 +1,67 @@ +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:collection/collection.dart'; + +class RadixSortNotifier extends SortingNotifier { + @override + SortingResult buildSorting(List values) { + final steps = []; + final arr = List.from(values); + + int getMax(List arr) { + int maxVal = arr[0]; + for (int i = 1; i < arr.length; i++) { + if (arr[i] > maxVal) maxVal = arr[i]; + } + return maxVal; + } + + void countSort(int exp) { + final n = arr.length; + final output = List.filled(n, 0); + final count = List.filled(10, 0); + + // Count occurrences of digits + for (int i = 0; i < n; i++) { + int digit = (arr[i] ~/ exp) % 10; + count[digit]++; + } + + // Accumulate counts + for (int i = 1; i < 10; i++) { + count[i] += count[i - 1]; + } + + // Build output array (stable order) + for (int i = n - 1; i >= 0; i--) { + int digit = (arr[i] ~/ exp) % 10; + output[count[digit] - 1] = arr[i]; + count[digit]--; + } + + // Copy output back into arr with steps + for (int i = 0; i < n; i++) { + if (arr[i] != output[i]) { + // Find where arr[i] should go + int newVal = output[i]; + int oldIndex = arr.indexOf(newVal, i); // find next occurrence + + steps.add(SortingStep(index1: i, index2: oldIndex, action: SortingStatus.swapping)); + arr.swap(i, oldIndex); + steps.add(SortingStep(index1: i, index2: oldIndex, action: SortingStatus.swapped)); + } + } + } + + final maxVal = getMax(arr); + + // Do counting sort for every digit + for (int exp = 1; maxVal ~/ exp > 0; exp *= 10) { + countSort(exp); + } + + // Mark all sorted at the end + steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); + + return SortingResult(sortedValues: arr, steps: steps); + } +} From 520514c83d0a6baaa32ac09e1478bceac15ad9be Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:22:07 +0300 Subject: [PATCH 038/107] create RadixSortPage --- .../sorting/radix/view/radix_sort_page.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/features/sorting/radix/view/radix_sort_page.dart diff --git a/lib/features/sorting/radix/view/radix_sort_page.dart b/lib/features/sorting/radix/view/radix_sort_page.dart new file mode 100644 index 0000000..7ed816a --- /dev/null +++ b/lib/features/sorting/radix/view/radix_sort_page.dart @@ -0,0 +1,30 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view/sorting_page.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/radix/view_model/radix_sort_notifier.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final _notifierProvider = StateNotifierProvider( + (ref) => RadixSortNotifier(), +); + +class RadixSortPage extends ConsumerStatefulWidget { + const RadixSortPage({super.key}); + + @override + ConsumerState createState() => _RadixSortPageState(); +} + +class _RadixSortPageState extends ConsumerState { + @override + void deactivate() { + ref.invalidate(_notifierProvider); // deletes current instance and resets + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return SortingPage(instance: _notifierProvider, title: StringsManager.radixSort); + } +} From 5feceebcfd6e7cea14f519e9804cc66afec0dac5 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:22:25 +0300 Subject: [PATCH 039/107] create ShellSortNotifier --- .../shell/view_model/shell_sort_notifier.dart | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 lib/features/sorting/shell/view_model/shell_sort_notifier.dart diff --git a/lib/features/sorting/shell/view_model/shell_sort_notifier.dart b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart new file mode 100644 index 0000000..c2138fd --- /dev/null +++ b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart @@ -0,0 +1,37 @@ +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:collection/collection.dart'; + +class ShellSortNotifier extends SortingNotifier { + @override + SortingResult buildSorting(List values) { + final steps = []; + final arr = List.from(values); + int n = arr.length; + + // Start with a big gap, then reduce + for (int gap = n ~/ 2; gap > 0; gap ~/= 2) { + // Do a gapped insertion sort + for (int i = gap; i < n; i++) { + int j = i; + + while (j >= gap && arr[j - gap] > arr[j]) { + // Compare + steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.compared)); + steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.unSorted)); + + // Swap + steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapping)); + arr.swap(j, j - gap); + steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapped)); + + j -= gap; + } + } + } + + // Mark all sorted at the end + steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); + + return SortingResult(sortedValues: arr, steps: steps); + } +} From cccc3037b1d56dd4fe2e1cd0878abbdae546dcc4 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:22:32 +0300 Subject: [PATCH 040/107] create ShellSortPage --- .../sorting/shell/view/shell_sort_page.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lib/features/sorting/shell/view/shell_sort_page.dart diff --git a/lib/features/sorting/shell/view/shell_sort_page.dart b/lib/features/sorting/shell/view/shell_sort_page.dart new file mode 100644 index 0000000..5f41375 --- /dev/null +++ b/lib/features/sorting/shell/view/shell_sort_page.dart @@ -0,0 +1,30 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view/sorting_page.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/shell/view_model/shell_sort_notifier.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final _notifierProvider = StateNotifierProvider( + (ref) => ShellSortNotifier(), +); + +class ShellSortPage extends ConsumerStatefulWidget { + const ShellSortPage({super.key}); + + @override + ConsumerState createState() => _ShellSortPageState(); +} + +class _ShellSortPageState extends ConsumerState { + @override + void deactivate() { + ref.invalidate(_notifierProvider); // deletes current instance and resets + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return SortingPage(instance: _notifierProvider, title: StringsManager.shellSort); + } +} From 538470df653a8cc20d58b45cf6b11b69559a1838 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 15:54:16 +0300 Subject: [PATCH 041/107] handle sorting notifier public functions --- .../base/view_model/sorting_notifier.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index a51b64f..4d3e412 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -11,7 +11,7 @@ part '../helper/sorting_enums.dart'; part '../helper/sortable_item.dart'; abstract class SortingNotifier extends StateNotifier { - SortingNotifier() : super(SortingNotifierState(list: generateList(_defaultSize))) { + SortingNotifier() : super(SortingNotifierState(list: _generateList(_defaultSize))) { _initializePositions(); } @@ -36,7 +36,7 @@ abstract class SortingNotifier extends StateNotifier { int i = 0; int j = 0; - static List generateList(int size) { + static List _generateList(int size) { return List.generate(size, (index) => SortableItem(id: index, value: index + 1))..shuffle(); } @@ -97,7 +97,7 @@ abstract class SortingNotifier extends StateNotifier { if (operation == SortingEnum.played) return; operation = SortingEnum.played; - await startSelectedSorting(); + await _startSelectedSorting(); operation = SortingEnum.none; } @@ -109,11 +109,11 @@ abstract class SortingNotifier extends StateNotifier { i = 0; j = 0; - state = state.copyWith(list: generateList(_size)); + state = state.copyWith(list: _generateList(_size)); _initializePositions(); } - Future greenSortedItemsAsDone() async { + Future _greenSortedItemsAsDone() async { final list = List.from(state.list); for (int i = 0; i < list.length; i++) { @@ -123,8 +123,8 @@ abstract class SortingNotifier extends StateNotifier { } } - Future startSelectedSorting() async { - cancelableSort = CancelableOperation.fromFuture(buildSort()); + Future _startSelectedSorting() async { + cancelableSort = CancelableOperation.fromFuture(_buildSort()); try { await cancelableSort?.value; @@ -133,7 +133,7 @@ abstract class SortingNotifier extends StateNotifier { } } - Future buildSort() async { + Future _buildSort() async { final list = List.from(state.list); final values = list.map((e) => e.value).toList(); @@ -187,7 +187,7 @@ abstract class SortingNotifier extends StateNotifier { await Future.delayed(speedDuration); } - await greenSortedItemsAsDone(); + await _greenSortedItemsAsDone(); } SortingResult buildSorting(List values); From 68c2b3d1331e976083d02d1804a022845f374a41 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:41:09 +0300 Subject: [PATCH 042/107] create ComparisonSortNotifier --- .../view_model/comparison_sort_notifier.dart | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart diff --git a/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart new file mode 100644 index 0000000..1412262 --- /dev/null +++ b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart @@ -0,0 +1,137 @@ +import 'package:algorithm_visualizer/core/resources/strings_manager.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/bubble/view_model/bubble_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/bucket/view_model/bucket_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/counting/view_model/counting_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/heap/view_model/heap_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/insertion/view_model/insertion_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/merge/view_model/merge_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/quick/view_model/quick_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/radix/view_model/radix_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/selection/view_model/selection_sort_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/shell/view_model/shell_sort_notifier.dart'; +import 'package:collection/collection.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +part 'comparison_sort_state.dart'; + +class SortingAlgorithm { + final String name; + final StateNotifierProvider provider; + SortingAlgorithm({required this.name, required this.provider}); +} + +class ComparisonSortNotifier extends StateNotifier { + ComparisonSortNotifier() : super(ComparisonSortingNotifierState(selectedAlgorithms: [])); + + final Map sortingAlgorithms = { + StringsManager.bubbleSort: SortingAlgorithm( + name: StringsManager.bubbleSort, + provider: StateNotifierProvider( + (ref) => BubbleSortNotifier(), + ), + ), + StringsManager.insertionSort: SortingAlgorithm( + name: StringsManager.insertionSort, + provider: StateNotifierProvider( + (ref) => InsertionSortNotifier(), + ), + ), + StringsManager.selectionSort: SortingAlgorithm( + name: StringsManager.selectionSort, + provider: StateNotifierProvider( + (ref) => SelectionSortNotifier(), + ), + ), + StringsManager.mergeSort: SortingAlgorithm( + name: StringsManager.mergeSort, + provider: StateNotifierProvider( + (ref) => MergeSortNotifier(), + ), + ), + StringsManager.heapSort: SortingAlgorithm( + name: StringsManager.heapSort, + provider: StateNotifierProvider( + (ref) => HeapSortNotifier(), + ), + ), + StringsManager.quickSort: SortingAlgorithm( + name: StringsManager.quickSort, + provider: StateNotifierProvider( + (ref) => QuickSortNotifier(), + ), + ), + StringsManager.radixSort: SortingAlgorithm( + name: StringsManager.radixSort, + provider: StateNotifierProvider( + (ref) => RadixSortNotifier(), + ), + ), + StringsManager.shellSort: SortingAlgorithm( + name: StringsManager.shellSort, + provider: StateNotifierProvider( + (ref) => ShellSortNotifier(), + ), + ), + StringsManager.countingSort: SortingAlgorithm( + name: StringsManager.countingSort, + provider: StateNotifierProvider( + (ref) => CountingSortNotifier(), + ), + ), + StringsManager.bucketSort: SortingAlgorithm( + name: StringsManager.bucketSort, + provider: StateNotifierProvider( + (ref) => BucketSortNotifier(), + ), + ), + }; + + void selectAlgorithm(String algo) { + final isExist = state.selectedAlgorithms.firstWhereOrNull((element) => element.name == algo) != null; + if (isExist) { + state = state.copyWith( + selectedAlgorithms: state.selectedAlgorithms.where((element) => element.name != algo).toList()); + return; + } + + final value = sortingAlgorithms[algo]; + if (value != null) { + state = state.copyWith( + selectedAlgorithms: [ + ...state.selectedAlgorithms, + value, + ], + ); + } + } + + void changeSize(double size, WidgetRef ref) { + for (var element in state.selectedAlgorithms) { + ref.read(element.provider.notifier).changeSize(size); + } + } + + void changeSpeed(double percent, WidgetRef ref) { + for (var element in state.selectedAlgorithms) { + ref.read(element.provider.notifier).changeSpeed(percent); + } + } + + Future generateAgain(WidgetRef ref) async { + for (var element in state.selectedAlgorithms) { + ref.read(element.provider.notifier).generateAgain(); + } + } + + Future playSorting(WidgetRef ref) async { + for (var element in state.selectedAlgorithms) { + ref.read(element.provider.notifier).playSorting(); + } + } + + void stopSorting(WidgetRef ref) { + for (var element in state.selectedAlgorithms) { + ref.read(element.provider.notifier).stopSorting(); + } + } +} From 6d58de1f053a9c1078f7512938641cee2786e471 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:41:14 +0300 Subject: [PATCH 043/107] create ComparisonSortPage --- .../comparison/view/comparison_sort_page.dart | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 lib/features/sorting/comparison/view/comparison_sort_page.dart diff --git a/lib/features/sorting/comparison/view/comparison_sort_page.dart b/lib/features/sorting/comparison/view/comparison_sort_page.dart new file mode 100644 index 0000000..4a689b4 --- /dev/null +++ b/lib/features/sorting/comparison/view/comparison_sort_page.dart @@ -0,0 +1,171 @@ +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/padding/adaptive_padding.dart'; +import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.dart'; +import 'package:algorithm_visualizer/core/widgets/custom_widgets/custom_icon.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view/sorting_page.dart'; +import 'package:algorithm_visualizer/features/sorting/base/view_model/sorting_notifier.dart'; +import 'package:algorithm_visualizer/features/sorting/comparison/view_model/comparison_sort_notifier.dart'; +import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +final _notifierProvider = StateNotifierProvider( + (ref) => ComparisonSortNotifier(), +); + +class ComparisonSortPage extends ConsumerStatefulWidget { + const ComparisonSortPage({super.key}); + + @override + ConsumerState createState() => _ComparisonSortPageState(); +} + +class _ComparisonSortPageState extends ConsumerState { + @override + void deactivate() { + ref.invalidate(_notifierProvider); // deletes current instance and resets + super.deactivate(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: appBar(), + drawer: const _DrawerMenu(), + body: SafeArea( + child: Column( + children: [ + const Flexible(child: _BuildComparisonLists()), + const RSizedBox(height: 15), + Padding( + padding: REdgeInsets.symmetric(horizontal: 0), + child: Align( + alignment: AlignmentDirectional.bottomCenter, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + spacing: 10, + children: [ + SortingControlButtons( + playSorting: () => ref.read(_notifierProvider.notifier).playSorting(ref), + stopSorting: () => ref.read(_notifierProvider.notifier).stopSorting(ref), + generateAgain: () => ref.read(_notifierProvider.notifier).generateAgain(ref), + ), + SymmetricPadding( + horizontal: 15, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SpeedDraggable( + onChanged: (persent) { + ref.read(_notifierProvider.notifier).changeSpeed(persent,ref); + }, + ), + _SizeDraggable(ref: ref), + ], + ), + ), + ], + ), + ), + ), + ], + ), + ), + ); + } + + AppBar appBar() { + return AppBar( + elevation: 1, + title: const SortingAppBar(title: StringsManager.comparisonSort), + ); + } +} + +class _SizeDraggable extends StatelessWidget { + const _SizeDraggable({required this.ref}); + + final WidgetRef ref; + + @override + Widget build(BuildContext context) { + final operationStatus = ref.watch(_notifierProvider.select((state) => state.operationStatus)); + final isRunning = operationStatus == SortingEnum.played || operationStatus == SortingEnum.stopped; + + return SizeDraggable( + isRunning: isRunning, + onChanged: (persent) { + ref.read(_notifierProvider.notifier).changeSize(persent,ref); + }, + ); + } +} + +class _DrawerMenu extends ConsumerWidget { + const _DrawerMenu(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final selectedAlgorithms = ref.watch(_notifierProvider.select((state) => state.selectedAlgorithms)); + final algorithms = ref.read(_notifierProvider.notifier).sortingAlgorithms.keys.toList(); + return Drawer( + child: SafeArea( + child: ListView( + padding: EdgeInsets.zero, + children: [ + const ListTile( + title: SemiBoldText(StringsManager.comparisonAlgorithms, color: ThemeEnum.focusColor), + ), + ...List.generate( + algorithms.length, + (index) => ListTile( + trailing: + selectedAlgorithms.firstWhereOrNull((element) => element.name == algorithms[index]) != + null + ? const CustomIcon(Icons.check) + : null, + title: RegularText(algorithms[index]), + onTap: () { + ref.read(_notifierProvider.notifier).selectAlgorithm(algorithms[index]); + }, + ), + ), + ], + ), + ), + ); + } +} + +class _BuildComparisonLists extends ConsumerWidget { + const _BuildComparisonLists(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final selectedAlgorithms = ref.watch(_notifierProvider.select((state) => state.selectedAlgorithms)); + + return Align( + alignment: AlignmentDirectional.topCenter, + child: Column( + children: List.generate( + selectedAlgorithms.length, + (index) => Flexible( + child: Column( + children: [ + Flexible( + child: ShowUpSortingList( + selectedAlgorithms[index].provider, + selectedAlgorithmLength: selectedAlgorithms.length, + ), + ), + RegularText(selectedAlgorithms[index].name, fontSize: 12), + ], + ), + ), + ), + ), + ); + } +} From 4e6b9e0cb9492ebfccaab4c457387c9347b4b0ba Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:41:40 +0300 Subject: [PATCH 044/107] create ComparisonSortingNotifierState --- .../view_model/comparison_sort_state.dart | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 lib/features/sorting/comparison/view_model/comparison_sort_state.dart diff --git a/lib/features/sorting/comparison/view_model/comparison_sort_state.dart b/lib/features/sorting/comparison/view_model/comparison_sort_state.dart new file mode 100644 index 0000000..de54e24 --- /dev/null +++ b/lib/features/sorting/comparison/view_model/comparison_sort_state.dart @@ -0,0 +1,21 @@ +part of 'comparison_sort_notifier.dart'; + +class ComparisonSortingNotifierState { + final List selectedAlgorithms; + final SortingEnum operationStatus; + + ComparisonSortingNotifierState({ + required this.selectedAlgorithms, + this.operationStatus = SortingEnum.none, + }); + + ComparisonSortingNotifierState copyWith({ + SortingEnum? operationStatus, + List? selectedAlgorithms, + }) { + return ComparisonSortingNotifierState( + operationStatus: operationStatus ?? this.operationStatus, + selectedAlgorithms: selectedAlgorithms ?? this.selectedAlgorithms, + ); + } +} From 855fd0eff72a3cf3e9bada2f614d063f8ab79988 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:41:52 +0300 Subject: [PATCH 045/107] change _ControlButtons to _SortingControlButtons --- .../sorting/base/widgets/control_buttons.dart | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/features/sorting/base/widgets/control_buttons.dart b/lib/features/sorting/base/widgets/control_buttons.dart index 221a801..0543bd8 100644 --- a/lib/features/sorting/base/widgets/control_buttons.dart +++ b/lib/features/sorting/base/widgets/control_buttons.dart @@ -1,9 +1,29 @@ part of '../view/sorting_page.dart'; -class _ControlButtons extends ConsumerWidget { - const _ControlButtons(this.instance); +class _SortingControlButtons extends ConsumerWidget { + const _SortingControlButtons(this.instance); final StateNotifierProvider instance; + @override + Widget build(BuildContext context, ref) { + return SortingControlButtons( + playSorting: () => ref.read(instance.notifier).playSorting(), + stopSorting: () => ref.read(instance.notifier).stopSorting(), + generateAgain: () => ref.read(instance.notifier).generateAgain(), + ); + } +} + +class SortingControlButtons extends ConsumerWidget { + const SortingControlButtons({ + required this.playSorting, + required this.stopSorting, + required this.generateAgain, + super.key, + }); + final VoidCallback playSorting; + final VoidCallback stopSorting; + final VoidCallback generateAgain; @override Widget build(BuildContext context, ref) { return Row( @@ -12,36 +32,30 @@ class _ControlButtons extends ConsumerWidget { CustomRoundedElevatedButton( roundedRadius: 3, backgroundColor: ThemeEnum.blackOp10, + onPressed: playSorting, child: const RegularText( StringsManager.play, fontSize: 14, ), - onPressed: () { - ref.read(instance.notifier).playSorting(); - }, ), CustomRoundedElevatedButton( roundedRadius: 3, backgroundColor: ThemeEnum.blackOp10, + onPressed: stopSorting, child: const RegularText( StringsManager.stop, fontSize: 14, ), - onPressed: () { - ref.read(instance.notifier).stopSorting(); - }, ), CustomRoundedElevatedButton( roundedRadius: 3, backgroundColor: ThemeEnum.redColor, + onPressed: generateAgain, child: const RegularText( StringsManager.reset, color: ThemeEnum.whiteColor, fontSize: 14, ), - onPressed: () { - ref.read(instance.notifier).generateAgain(); - }, ), ], ); From 44356fa309a2fe75e9215d2f0e00c0743bccb43a Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:42:05 +0300 Subject: [PATCH 046/107] redesign HeapSortNotifier --- .../heap/view_model/heap_sort_notifier.dart | 43 ++++++++----------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/lib/features/sorting/heap/view_model/heap_sort_notifier.dart b/lib/features/sorting/heap/view_model/heap_sort_notifier.dart index f3b11e0..fede98e 100644 --- a/lib/features/sorting/heap/view_model/heap_sort_notifier.dart +++ b/lib/features/sorting/heap/view_model/heap_sort_notifier.dart @@ -12,57 +12,50 @@ class HeapSortNotifier extends SortingNotifier { int left = 2 * i + 1; int right = 2 * i + 2; - // Compare left child if (left < n) { - steps.add(SortingStep(index1: largest, index2: left, action: SortingStatus.compared)); + steps.add(SortingStep(index1: i, index2: left, action: SortingStatus.compared)); + steps.add(SortingStep(index1: i, index2: left, action: SortingStatus.unSorted)); if (arr[left] > arr[largest]) { largest = left; } - steps.add(SortingStep(index1: i, index2: left, action: SortingStatus.unSorted)); } - // Compare right child if (right < n) { - steps.add(SortingStep(index1: largest, index2: right, action: SortingStatus.compared)); + steps.add(SortingStep(index1: i, index2: right, action: SortingStatus.compared)); + steps.add(SortingStep(index1: i, index2: right, action: SortingStatus.unSorted)); if (arr[right] > arr[largest]) { largest = right; } - steps.add(SortingStep(index1: i, index2: right, action: SortingStatus.unSorted)); } - // If largest is not root if (largest != i) { steps.add(SortingStep(index1: i, index2: largest, action: SortingStatus.swapping)); - arr.swap(i, largest); - steps.add(SortingStep(index1: i, index2: largest, action: SortingStatus.swapped)); heapify(n, largest); } } - int n = arr.length; + void heapSort() { + int n = arr.length; - // Build max heap - for (int i = n ~/ 2 - 1; i >= 0; i--) { - heapify(n, i); - } - - // Extract elements one by one - for (int i = n - 1; i > 0; i--) { - steps.add(SortingStep(index1: 0, index2: i, action: SortingStatus.swapping)); - - arr.swap(0, i); - - steps.add(SortingStep(index1: 0, index2: i, action: SortingStatus.swapped)); + // Build max heap + for (int i = (n ~/ 2) - 1; i >= 0; i--) { + heapify(n, i); + } - // Mark last element as sorted - steps.add(SortingStep(index1: i, index2: i, action: SortingStatus.sorted)); + // Extract elements one by one + for (int i = n - 1; i > 0; i--) { + steps.add(SortingStep(index1: 0, index2: i, action: SortingStatus.swapping)); + arr.swap(0, i); + steps.add(SortingStep(index1: 0, index2: i, action: SortingStatus.swapped)); - heapify(i, 0); + heapify(i, 0); + } } + if (arr.isNotEmpty) heapSort(); // Mark the first element sorted steps.add(SortingStep(index1: 0, index2: 0, action: SortingStatus.sorted)); From 947bf0559482b95d8d9fc899b7c99457c519ae3f Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:42:11 +0300 Subject: [PATCH 047/107] redesign MergeSortNotifier --- .../merge/view_model/merge_sort_notifier.dart | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/lib/features/sorting/merge/view_model/merge_sort_notifier.dart b/lib/features/sorting/merge/view_model/merge_sort_notifier.dart index 29246a6..3c6e8bf 100644 --- a/lib/features/sorting/merge/view_model/merge_sort_notifier.dart +++ b/lib/features/sorting/merge/view_model/merge_sort_notifier.dart @@ -7,50 +7,44 @@ class MergeSortNotifier extends SortingNotifier { final steps = []; final arr = List.from(values); - // In-place merge using adjacent swaps so it matches your 'swapping' handler. void mergeInPlace(int left, int mid, int right) { int i = left; int j = mid + 1; while (i <= mid && j <= right) { - // Show comparison between current heads + // Compare current elements steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.compared)); - // Clear highlight steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.unSorted)); if (arr[i] <= arr[j]) { i++; } else { - // arr[j] should be inserted before arr[i]. - // Bubble arr[j] leftwards via adjacent swaps until it reaches i. + // Bubble arr[j] left until it reaches position i int k = j; while (k > i) { steps.add(SortingStep(index1: k, index2: k - 1, action: SortingStatus.swapping)); arr.swap(k, k - 1); - - // your handler clears to unSorted steps.add(SortingStep(index1: k, index2: k - 1, action: SortingStatus.swapped)); k--; } - // Now the element originally at j is at position i. i++; - mid++; // left segment grew by one - j++; // next element in right segment + mid++; + j++; } } } void mergeSort(int left, int right) { - if (left >= right) return; - final mid = (left + right) >> 1; - mergeSort(left, mid); - mergeSort(mid + 1, right); - mergeInPlace(left, mid, right); + if (left < right) { + final mid = (left + right) >> 1; + mergeSort(left, mid); + mergeSort(mid + 1, right); + mergeInPlace(left, mid, right); + } } if (arr.isNotEmpty) mergeSort(0, arr.length - 1); - // No "sorted" marks during the run; your base class greens everything at the end. return SortingResult(sortedValues: arr, steps: steps); } } From fe7bd432411232c6c7d69a76a86ec66476f2f713 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:42:17 +0300 Subject: [PATCH 048/107] redesign QuickSortNotifier --- .../sorting/quick/view_model/quick_sort_notifier.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/features/sorting/quick/view_model/quick_sort_notifier.dart b/lib/features/sorting/quick/view_model/quick_sort_notifier.dart index d9f634a..529b0cd 100644 --- a/lib/features/sorting/quick/view_model/quick_sort_notifier.dart +++ b/lib/features/sorting/quick/view_model/quick_sort_notifier.dart @@ -38,8 +38,7 @@ class QuickSortNotifier extends SortingNotifier { void quickSort(int low, int high) { if (low < high) { - int pi = partition(low, high); - + final pi = partition(low, high); quickSort(low, pi - 1); quickSort(pi + 1, high); } @@ -47,7 +46,6 @@ class QuickSortNotifier extends SortingNotifier { if (arr.isNotEmpty) quickSort(0, arr.length - 1); - // Final marking of all sorted items (UI will green them at end anyway) return SortingResult(sortedValues: arr, steps: steps); } } From 3f710b620141e25e37a37ce6df69a9372ab5da8c Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:42:22 +0300 Subject: [PATCH 049/107] redesign RadixSortNotifier --- .../radix/view_model/radix_sort_notifier.dart | 81 +++++++++---------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/lib/features/sorting/radix/view_model/radix_sort_notifier.dart b/lib/features/sorting/radix/view_model/radix_sort_notifier.dart index 5faa797..c80ab0e 100644 --- a/lib/features/sorting/radix/view_model/radix_sort_notifier.dart +++ b/lib/features/sorting/radix/view_model/radix_sort_notifier.dart @@ -7,61 +7,54 @@ class RadixSortNotifier extends SortingNotifier { final steps = []; final arr = List.from(values); - int getMax(List arr) { - int maxVal = arr[0]; - for (int i = 1; i < arr.length; i++) { - if (arr[i] > maxVal) maxVal = arr[i]; - } - return maxVal; + if (arr.isEmpty) { + return SortingResult(sortedValues: arr, steps: steps); } - void countSort(int exp) { - final n = arr.length; - final output = List.filled(n, 0); - final count = List.filled(10, 0); + int maxVal = arr.reduce((a, b) => a > b ? a : b); - // Count occurrences of digits - for (int i = 0; i < n; i++) { - int digit = (arr[i] ~/ exp) % 10; - count[digit]++; - } + // Perform counting sort for every digit + for (int exp = 1; maxVal ~/ exp > 0; exp *= 10) { + _countingSortByDigit(arr, exp, steps); + } - // Accumulate counts - for (int i = 1; i < 10; i++) { - count[i] += count[i - 1]; - } + // Mark all as sorted + steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); - // Build output array (stable order) - for (int i = n - 1; i >= 0; i--) { - int digit = (arr[i] ~/ exp) % 10; - output[count[digit] - 1] = arr[i]; - count[digit]--; - } + return SortingResult(sortedValues: arr, steps: steps); + } - // Copy output back into arr with steps - for (int i = 0; i < n; i++) { - if (arr[i] != output[i]) { - // Find where arr[i] should go - int newVal = output[i]; - int oldIndex = arr.indexOf(newVal, i); // find next occurrence + void _countingSortByDigit(List arr, int exp, List steps) { + int n = arr.length; + List output = List.filled(n, 0); + List count = List.filled(10, 0); - steps.add(SortingStep(index1: i, index2: oldIndex, action: SortingStatus.swapping)); - arr.swap(i, oldIndex); - steps.add(SortingStep(index1: i, index2: oldIndex, action: SortingStatus.swapped)); - } - } + // 1. Count occurrences of digits + for (int i = 0; i < n; i++) { + int digit = (arr[i] ~/ exp) % 10; + count[digit]++; } - final maxVal = getMax(arr); - - // Do counting sort for every digit - for (int exp = 1; maxVal ~/ exp > 0; exp *= 10) { - countSort(exp); + // 2. Compute prefix sums + for (int i = 1; i < 10; i++) { + count[i] += count[i - 1]; } - // Mark all sorted at the end - steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); + // 3. Build output array (stable order, so go from right to left) + for (int i = n - 1; i >= 0; i--) { + int digit = (arr[i] ~/ exp) % 10; + output[count[digit] - 1] = arr[i]; + count[digit]--; + } - return SortingResult(sortedValues: arr, steps: steps); + // 4. Copy back to arr + log steps + for (int i = 0; i < n; i++) { + if (arr[i] != output[i]) { + int oldIndex = arr.indexOf(output[i], i); + steps.add(SortingStep(index1: i, index2: oldIndex, action: SortingStatus.swapping)); + arr.swap(i, oldIndex); + steps.add(SortingStep(index1: i, index2: oldIndex, action: SortingStatus.swapped)); + } + } } } From b7e3677c59bbb297e9fab2db602492c4b28085e1 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:42:36 +0300 Subject: [PATCH 050/107] redesign ShellSortNotifier --- .../view_model/selection_sort_notifier.dart | 3 +- .../shell/view_model/shell_sort_notifier.dart | 34 ++++++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/features/sorting/selection/view_model/selection_sort_notifier.dart b/lib/features/sorting/selection/view_model/selection_sort_notifier.dart index a0d99db..ee7d69a 100644 --- a/lib/features/sorting/selection/view_model/selection_sort_notifier.dart +++ b/lib/features/sorting/selection/view_model/selection_sort_notifier.dart @@ -29,7 +29,8 @@ class SelectionSortNotifier extends SortingNotifier { steps.add(SortingStep(index1: i, index2: minIndex, action: SortingStatus.swapping)); arr.swap(minIndex, i); - steps.add(SortingStep(index1: minIndex, index2: j, action: SortingStatus.swapped)); + + steps.add(SortingStep(index1: minIndex, index2: i, action: SortingStatus.swapped)); } steps.add(SortingStep(index1: i, index2: i, action: SortingStatus.sorted)); diff --git a/lib/features/sorting/shell/view_model/shell_sort_notifier.dart b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart index c2138fd..1f435f2 100644 --- a/lib/features/sorting/shell/view_model/shell_sort_notifier.dart +++ b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart @@ -6,32 +6,34 @@ class ShellSortNotifier extends SortingNotifier { SortingResult buildSorting(List values) { final steps = []; final arr = List.from(values); - int n = arr.length; + final n = arr.length; - // Start with a big gap, then reduce - for (int gap = n ~/ 2; gap > 0; gap ~/= 2) { - // Do a gapped insertion sort + // Knuth gap sequence: 1, 4, 13, 40, ... + int gap = 1; + while (gap < n ~/ 3) { + gap = 3 * gap + 1; + } + + for (; gap >= 1; gap = (gap - 1) ~/ 3) { for (int i = gap; i < n; i++) { int j = i; - - while (j >= gap && arr[j - gap] > arr[j]) { - // Compare + // Gapped insertion via adjacent swaps (with step logs) + while (j >= gap) { steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.compared)); steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.unSorted)); - // Swap - steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapping)); - arr.swap(j, j - gap); - steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapped)); - - j -= gap; + if (arr[j] < arr[j - gap]) { + steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapping)); + arr.swap(j, j - gap); + steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapped)); + j -= gap; + } else { + break; + } } } } - // Mark all sorted at the end - steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); - return SortingResult(sortedValues: arr, steps: steps); } } From 31cb8214a60022259c7c6491330c761549085a79 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:43:00 +0300 Subject: [PATCH 051/107] redesign ShellSortNotifier --- .../shell/view_model/shell_sort_notifier.dart | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/features/sorting/shell/view_model/shell_sort_notifier.dart b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart index 1f435f2..2ba99e9 100644 --- a/lib/features/sorting/shell/view_model/shell_sort_notifier.dart +++ b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart @@ -6,18 +6,11 @@ class ShellSortNotifier extends SortingNotifier { SortingResult buildSorting(List values) { final steps = []; final arr = List.from(values); - final n = arr.length; + int n = arr.length; - // Knuth gap sequence: 1, 4, 13, 40, ... - int gap = 1; - while (gap < n ~/ 3) { - gap = 3 * gap + 1; - } - - for (; gap >= 1; gap = (gap - 1) ~/ 3) { + for (int gap = n ~/ 2; gap > 0; gap ~/= 2) { for (int i = gap; i < n; i++) { int j = i; - // Gapped insertion via adjacent swaps (with step logs) while (j >= gap) { steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.compared)); steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.unSorted)); @@ -26,14 +19,17 @@ class ShellSortNotifier extends SortingNotifier { steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapping)); arr.swap(j, j - gap); steps.add(SortingStep(index1: j, index2: j - gap, action: SortingStatus.swapped)); - j -= gap; } else { break; } + j -= gap; } } } + // Mark all sorted at the end + steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); + return SortingResult(sortedValues: arr, steps: steps); } } From 97f6eba4d2853408eed03c8f1fc4782392b3c459 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:43:18 +0300 Subject: [PATCH 052/107] refactoring SortingListPage --- .../sorting/base/view/sorting_list_page.dart | 112 +++++------------- 1 file changed, 31 insertions(+), 81 deletions(-) diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index a8ce4e4..75502c4 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -16,91 +16,22 @@ class SortingListPage extends StatelessWidget { elevation: 1, title: const InkWell(child: RegularText(StringsManager.sorting)), ), - body: SafeArea( + body: const SafeArea( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.bubbleSort), - onPressed: () { - context.pushTo(Routes.bubbleSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.insertionSort), - onPressed: () { - context.pushTo(Routes.insertionSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.selectionSort), - onPressed: () { - context.pushTo(Routes.selectionSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.mergeSort), - onPressed: () { - context.pushTo(Routes.mergeSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.heapSort), - onPressed: () { - context.pushTo(Routes.heapSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.quickSort), - onPressed: () { - context.pushTo(Routes.quickSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.radixSort), - onPressed: () { - context.pushTo(Routes.radixSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.shellSort), - onPressed: () { - context.pushTo(Routes.shellSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.countingSort), - onPressed: () { - context.pushTo(Routes.countingSort); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.bucketSort), - onPressed: () { - context.pushTo(Routes.bucketSort); - }, - ), + _CustomButton(text: StringsManager.bubbleSort, route: Routes.bubbleSort), + _CustomButton(text: StringsManager.insertionSort, route: Routes.insertionSort), + _CustomButton(text: StringsManager.selectionSort, route: Routes.selectionSort), + _CustomButton(text: StringsManager.mergeSort, route: Routes.mergeSort), + _CustomButton(text: StringsManager.heapSort, route: Routes.heapSort), + _CustomButton(text: StringsManager.quickSort, route: Routes.quickSort), + _CustomButton(text: StringsManager.radixSort, route: Routes.radixSort), + _CustomButton(text: StringsManager.shellSort, route: Routes.shellSort), + _CustomButton(text: StringsManager.countingSort, route: Routes.countingSort), + _CustomButton(text: StringsManager.bucketSort, route: Routes.bucketSort), + _CustomButton(text: StringsManager.comparisonSort, route: Routes.comparisonSort), ], ), ), @@ -108,3 +39,22 @@ class SortingListPage extends StatelessWidget { ); } } + +class _CustomButton extends StatelessWidget { + const _CustomButton({required this.text, required this.route}); + final String text; + final RouteConfig route; + @override + Widget build(BuildContext context) { + return CustomRoundedElevatedButton( + fixedSize: 160, + fitToContent: false, + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: FittedBox(child: RegularText(text)), + onPressed: () { + context.pushTo(route); + }, + ); + } +} From eba83f8762ed79934f30927494b3493339edb412 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:43:44 +0300 Subject: [PATCH 053/107] reformat the code --- lib/config/routes/route_app.dart | 12 +++++++ .../custom_rounded_elevated_button.dart | 2 +- .../base/view_model/sorting_notifier.dart | 34 ++++++++----------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/lib/config/routes/route_app.dart b/lib/config/routes/route_app.dart index 4bb6116..7679ee7 100644 --- a/lib/config/routes/route_app.dart +++ b/lib/config/routes/route_app.dart @@ -6,6 +6,7 @@ import 'package:algorithm_visualizer/features/searching/view/grid_page.dart'; import 'package:algorithm_visualizer/features/sorting/base/view/sorting_list_page.dart'; import 'package:algorithm_visualizer/features/sorting/bubble/view/bubble_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/bucket/view/bucket_sort_page.dart'; +import 'package:algorithm_visualizer/features/sorting/comparison/view/comparison_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/counting/view/counting_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/heap/view/heap_sort_page.dart'; import 'package:algorithm_visualizer/features/sorting/insertion/view/insertion_sort_page.dart'; @@ -71,6 +72,10 @@ class Routes { name: 'bucketSort', path: 'bucketSort', ); + static const RouteConfig comparisonSort = RouteConfig( + name: 'comparisonSort', + path: 'comparisonSort', + ); } class RouteConfig { @@ -183,6 +188,13 @@ class AppRoutes { return const BucketSortPage(); }, ), + GoRoute( + path: Routes.comparisonSort.path, + name: Routes.comparisonSort.name, + builder: (context, state) { + return const ComparisonSortPage(); + }, + ), ], ), ], diff --git a/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart b/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart index 2dbb418..ccdbb5e 100644 --- a/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart +++ b/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart @@ -34,7 +34,7 @@ class CustomRoundedElevatedButton extends StatelessWidget { style: ElevatedButton.styleFrom( backgroundColor: background, shadowColor: shadow ?? ColorManager.transparent, - fixedSize: fitToContent ? Size.fromHeight(fixedSize.r) : null, + fixedSize: fitToContent ? Size.fromHeight(fixedSize.r) : Size.fromWidth(fixedSize.r), padding: EdgeInsets.symmetric(horizontal: 15.r), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(roundedRadius).r), diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index 4d3e412..a7e6031 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -31,10 +31,7 @@ abstract class SortingNotifier extends StateNotifier { // static const Duration _minSpeedDuration = Duration(milliseconds: 20); SortingEnum _operation = SortingEnum.none; - CancelableOperation? cancelableSort; - - int i = 0; - int j = 0; + CancelableOperation? _cancelableSort; static List _generateList(int size) { return List.generate(size, (index) => SortableItem(id: index, value: index + 1))..shuffle(); @@ -56,9 +53,9 @@ abstract class SortingNotifier extends StateNotifier { Duration get speedDuration => state.swipeDuration; int get _size => state.size; - SortingEnum get operation => _operation; + SortingEnum get _getOperation => _operation; - set operation(SortingEnum value) { + set _setOperation(SortingEnum value) { state = state.copyWith(operationStatus: value); _operation = value; } @@ -81,7 +78,7 @@ abstract class SortingNotifier extends StateNotifier { } void changeSize(double size) { - if (operation == SortingEnum.played) return; + if (_getOperation == SortingEnum.played) return; final newSize = _minSize + (_maxSize - _minSize) * size; state = state.copyWith(size: newSize.toInt()); @@ -89,25 +86,22 @@ abstract class SortingNotifier extends StateNotifier { } void stopSorting() { - cancelableSort?.cancel(); - if (operation == SortingEnum.played) operation = SortingEnum.stopped; + _cancelableSort?.cancel(); + if (_getOperation == SortingEnum.played) _setOperation = SortingEnum.stopped; } Future playSorting() async { - if (operation == SortingEnum.played) return; - operation = SortingEnum.played; + if (_getOperation == SortingEnum.played) return; + _setOperation = SortingEnum.played; await _startSelectedSorting(); - operation = SortingEnum.none; + _setOperation = SortingEnum.none; } Future generateAgain() async { - await cancelableSort?.cancel(); - operation = SortingEnum.none; - - i = 0; - j = 0; + await _cancelableSort?.cancel(); + _setOperation = SortingEnum.none; state = state.copyWith(list: _generateList(_size)); _initializePositions(); @@ -124,10 +118,10 @@ abstract class SortingNotifier extends StateNotifier { } Future _startSelectedSorting() async { - cancelableSort = CancelableOperation.fromFuture(_buildSort()); + _cancelableSort = CancelableOperation.fromFuture(_buildSort()); try { - await cancelableSort?.value; + await _cancelableSort?.value; } catch (e) { debugPrint("something wrong with bubbleSort: $e"); } @@ -140,7 +134,7 @@ abstract class SortingNotifier extends StateNotifier { final steps = buildSorting(values).steps; for (final step in steps) { - if (operation != SortingEnum.played) return; + if (_getOperation != SortingEnum.played) return; switch (step.action) { case SortingStatus.compared: From 6a57fe04ca50bb28f0491b64f53a459b828dde22 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:43:52 +0300 Subject: [PATCH 054/107] refactoring SortingPage --- .../sorting/base/view/sorting_page.dart | 152 ++++++------------ 1 file changed, 48 insertions(+), 104 deletions(-) diff --git a/lib/features/sorting/base/view/sorting_page.dart b/lib/features/sorting/base/view/sorting_page.dart index 7844f32..ef25d7f 100644 --- a/lib/features/sorting/base/view/sorting_page.dart +++ b/lib/features/sorting/base/view/sorting_page.dart @@ -11,122 +11,74 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; part '../widgets/sorting_app_bar.dart'; part '../widgets/control_buttons.dart'; +part '../widgets/size_draggable.dart'; +part '../widgets/speed_draggable.dart'; class SortingPage extends StatelessWidget { const SortingPage({required this.instance, required this.title, super.key}); final StateNotifierProvider instance; final String title; + @override Widget build(BuildContext context) { return Scaffold( appBar: appBar(), - body: SafeArea( - child: Stack( - alignment: AlignmentDirectional.bottomCenter, - children: [ - Align(alignment: AlignmentDirectional.topCenter, child: _BuildList(instance)), - // _ControlButtons(), - Padding( - padding: REdgeInsets.symmetric(horizontal: 0), - child: Align( - alignment: AlignmentDirectional.bottomCenter, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - spacing: 10, - children: [ - _ControlButtons(instance), - SymmetricPadding( - horizontal: 15, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SpeedDraggable(instance: instance), - SizeDraggable(instance: instance), - ], - ), - ), - ], - ), - ), - ), - ], - ), - ), + body: _BuildBody(instance: instance), ); } AppBar appBar() { return AppBar( elevation: 1, - title: Consumer( - builder: (context, ref, _) { - return InkWell(child: RegularText(title)); - }, - ), + title: SortingAppBar(title: title), ); } } -class SpeedDraggable extends ConsumerWidget { - const SpeedDraggable({super.key, required this.instance}); +class SortingAppBar extends StatelessWidget { + const SortingAppBar({super.key, required this.title}); - final StateNotifierProvider instance; + final String title; @override - Widget build(BuildContext context, WidgetRef ref) { - return Flexible( - child: Row( - children: [ - const MediumText(StringsManager.speed, fontSize: 12), - Flexible( - child: DraggableProgressBar( - runOnChangedInitially: true, - onChanged: (persent) { - ref.read(instance.notifier).changeSpeed(persent); - }, - ), - ), - ], - ), + Widget build(BuildContext context) { + return Consumer( + builder: (context, ref, _) { + return InkWell(child: RegularText(title)); + }, ); } } -class SizeDraggable extends ConsumerWidget { - const SizeDraggable({super.key, required this.instance}); +class _BuildBody extends StatelessWidget { + const _BuildBody({required this.instance}); final StateNotifierProvider instance; @override - Widget build(BuildContext context, WidgetRef ref) { - final operationStatus = ref.watch(instance.select((state) => state.operationStatus)); - final isRunning = operationStatus == SortingEnum.played || operationStatus == SortingEnum.stopped; - return Flexible( - child: Row( + Widget build(BuildContext context) { + return SafeArea( + child: Stack( + alignment: AlignmentDirectional.bottomCenter, children: [ - MediumText( - StringsManager.size, - fontSize: 12, - color: isRunning ? ThemeEnum.whiteD7Color : null, - ), - Flexible( - child: Stack( - alignment: AlignmentDirectional.center, + Align(alignment: AlignmentDirectional.topCenter, child: ShowUpSortingList(instance)), + Align( + alignment: AlignmentDirectional.bottomCenter, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + spacing: 10, children: [ - DraggableProgressBar( - isActive: !isRunning, - runOnChangedInitially: true, - sliderValue: 0.15, - onChanged: (persent) { - ref.read(instance.notifier).changeSize(persent); - }, + _SortingControlButtons(instance), + SymmetricPadding( + horizontal: 15, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _SpeedDraggable(instance: instance), + _SizeDraggable(instance: instance), + ], + ), ), - if (isRunning) - Container( - color: ColorManager.transparent, - height: 20.r, - width: double.infinity, - ) ], ), ), @@ -136,25 +88,10 @@ class SizeDraggable extends ConsumerWidget { } } -class Item extends StatelessWidget { - final String text; - - const Item({super.key, required this.text}); - - @override - Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(10), - color: context.getColor(ThemeEnum.whiteD7Color), - child: RegularText(text, color: ThemeEnum.primaryColor), - ); - } -} - -class _BuildList extends ConsumerWidget { - const _BuildList(this.instance); +class ShowUpSortingList extends ConsumerWidget { + const ShowUpSortingList(this.instance, {this.selectedAlgorithmLength = 1, super.key}); final StateNotifierProvider instance; - + final int selectedAlgorithmLength; @override Widget build(BuildContext context, ref) { final items = ref.watch(instance.select((state) => state.list)); @@ -163,7 +100,7 @@ class _BuildList extends ConsumerWidget { return Padding( padding: const EdgeInsets.only(top: 5), child: RSizedBox( - height: SortingNotifier.maxListItemHeight * 1.05, + height: selectedAlgorithmLength == 1 ? SortingNotifier.maxListItemHeight * 1.05 : null, width: double.infinity, child: Stack( alignment: AlignmentDirectional.bottomCenter, @@ -178,7 +115,12 @@ class _BuildList extends ConsumerWidget { bottom: position?.dy, duration: speedDuration, child: _BuildItem( - item: item, index: index, speedDuration: speedDuration * 0.5, instance: instance), + item: item, + index: index, + instance: instance, + speedDuration: speedDuration * 0.5, + selectedAlgorithmLength: selectedAlgorithmLength, + ), ); }, ), @@ -194,12 +136,14 @@ class _BuildItem extends ConsumerWidget { required this.index, required this.speedDuration, required this.instance, + required this.selectedAlgorithmLength, }); final int index; final SortableItem item; final Duration speedDuration; final StateNotifierProvider instance; + final int selectedAlgorithmLength; @override Widget build(BuildContext context, ref) { @@ -212,7 +156,7 @@ class _BuildItem extends ConsumerWidget { padding: EdgeInsets.symmetric(horizontal: SortingNotifier.itemsPadding / 2), child: AnimatedContainer( duration: speedDuration, - height: SortingNotifier.calculateItemHeight(item.value, size), + height: SortingNotifier.calculateItemHeight(item.value, size) / selectedAlgorithmLength, width: itemWidth, decoration: BoxDecoration( color: context.getColor(currentItem?.getColor ?? SortingNotifier.itemColor), From 8f915af0d87a14c61a4edb651513ebba9a3df03a Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:43:59 +0300 Subject: [PATCH 055/107] add some text --- lib/core/resources/strings_manager.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index 318b44c..78ebc83 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -44,6 +44,8 @@ class StringsManager { static const String shellSort = "Shell sort"; static const String countingSort = "Counting sort"; static const String bucketSort = "Bucket sort"; + static const String comparisonSort = "Comparison sort"; + static const String comparisonAlgorithms = "Comparison algorithms"; static const String stop = "Stop"; static const String play = "Play"; From cd98ecf225d1dd4ef6dfc64129df05d2d1659113 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:44:19 +0300 Subject: [PATCH 056/107] create SizeDraggable --- .../sorting/base/widgets/size_draggable.dart | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 lib/features/sorting/base/widgets/size_draggable.dart diff --git a/lib/features/sorting/base/widgets/size_draggable.dart b/lib/features/sorting/base/widgets/size_draggable.dart new file mode 100644 index 0000000..49cbc3f --- /dev/null +++ b/lib/features/sorting/base/widgets/size_draggable.dart @@ -0,0 +1,59 @@ +part of '../view/sorting_page.dart'; + +class _SizeDraggable extends ConsumerWidget { + const _SizeDraggable({ required this.instance}); + + final StateNotifierProvider instance; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final operationStatus = ref.watch(instance.select((state) => state.operationStatus)); + final isRunning = operationStatus == SortingEnum.played || operationStatus == SortingEnum.stopped; + return SizeDraggable( + isRunning: isRunning, + onChanged: (persent) { + ref.read(instance.notifier).changeSize(persent); + }, + ); + } +} + +class SizeDraggable extends ConsumerWidget { + const SizeDraggable({super.key, required this.onChanged, required this.isRunning}); + + final ValueChanged onChanged; + final bool isRunning; + @override + Widget build(BuildContext context, WidgetRef ref) { + return Flexible( + child: Row( + children: [ + MediumText( + StringsManager.size, + fontSize: 12, + color: isRunning ? ThemeEnum.whiteD7Color : null, + ), + Flexible( + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + DraggableProgressBar( + isActive: !isRunning, + runOnChangedInitially: true, + sliderValue: 0.15, + onChanged: onChanged, + ), + if (isRunning) + Container( + color: ColorManager.transparent, + height: 20.r, + width: double.infinity, + ) + ], + ), + ), + ], + ), + ); + } +} From 66fbf46caecdfea35e45afb319015e28546b4ece Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:44:24 +0300 Subject: [PATCH 057/107] create SpeedDraggable --- .../sorting/base/widgets/speed_draggable.dart | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 lib/features/sorting/base/widgets/speed_draggable.dart diff --git a/lib/features/sorting/base/widgets/speed_draggable.dart b/lib/features/sorting/base/widgets/speed_draggable.dart new file mode 100644 index 0000000..6159dba --- /dev/null +++ b/lib/features/sorting/base/widgets/speed_draggable.dart @@ -0,0 +1,38 @@ +part of '../view/sorting_page.dart'; + +class _SpeedDraggable extends ConsumerWidget { + const _SpeedDraggable({required this.instance}); + + final StateNotifierProvider instance; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return SpeedDraggable( + onChanged: (persent) { + ref.read(instance.notifier).changeSpeed(persent); + }, + ); + } +} + +class SpeedDraggable extends ConsumerWidget { + const SpeedDraggable({super.key, required this.onChanged}); + + final ValueChanged onChanged; + @override + Widget build(BuildContext context, WidgetRef ref) { + return Flexible( + child: Row( + children: [ + const MediumText(StringsManager.speed, fontSize: 12), + Flexible( + child: DraggableProgressBar( + runOnChangedInitially: true, + onChanged: onChanged, + ), + ), + ], + ), + ); + } +} From fa3cd703ecbde782ac3949a7e17ddbed0201e8af Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Sun, 24 Aug 2025 23:52:27 +0300 Subject: [PATCH 058/107] handle operation status for comparison algorithms --- .../base/view_model/sorting_notifier.dart | 4 +-- .../comparison/view/comparison_sort_page.dart | 4 +-- .../view_model/comparison_sort_notifier.dart | 25 ++++++++++++++----- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index a7e6031..5ba865e 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -30,7 +30,6 @@ abstract class SortingNotifier extends StateNotifier { // static const Duration _maxSpeedDuration = Duration(milliseconds: 3000); // static const Duration _minSpeedDuration = Duration(milliseconds: 20); - SortingEnum _operation = SortingEnum.none; CancelableOperation? _cancelableSort; static List _generateList(int size) { @@ -53,11 +52,10 @@ abstract class SortingNotifier extends StateNotifier { Duration get speedDuration => state.swipeDuration; int get _size => state.size; - SortingEnum get _getOperation => _operation; + SortingEnum get _getOperation => state.operationStatus; set _setOperation(SortingEnum value) { state = state.copyWith(operationStatus: value); - _operation = value; } void _initializePositions() { diff --git a/lib/features/sorting/comparison/view/comparison_sort_page.dart b/lib/features/sorting/comparison/view/comparison_sort_page.dart index 4a689b4..903339c 100644 --- a/lib/features/sorting/comparison/view/comparison_sort_page.dart +++ b/lib/features/sorting/comparison/view/comparison_sort_page.dart @@ -59,7 +59,7 @@ class _ComparisonSortPageState extends ConsumerState { children: [ SpeedDraggable( onChanged: (persent) { - ref.read(_notifierProvider.notifier).changeSpeed(persent,ref); + ref.read(_notifierProvider.notifier).changeSpeed(persent, ref); }, ), _SizeDraggable(ref: ref), @@ -97,7 +97,7 @@ class _SizeDraggable extends StatelessWidget { return SizeDraggable( isRunning: isRunning, onChanged: (persent) { - ref.read(_notifierProvider.notifier).changeSize(persent,ref); + ref.read(_notifierProvider.notifier).changeSize(persent, ref); }, ); } diff --git a/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart index 1412262..72ca7d0 100644 --- a/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart +++ b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart @@ -86,6 +86,12 @@ class ComparisonSortNotifier extends StateNotifier state.operationStatus; + + set _setOperation(SortingEnum value) { + state = state.copyWith(operationStatus: value); + } + void selectAlgorithm(String algo) { final isExist = state.selectedAlgorithms.firstWhereOrNull((element) => element.name == algo) != null; if (isExist) { @@ -106,6 +112,8 @@ class ComparisonSortNotifier extends StateNotifier generateAgain(WidgetRef ref) async { - for (var element in state.selectedAlgorithms) { - ref.read(element.provider.notifier).generateAgain(); - } + final generateAgain = state.selectedAlgorithms.map((e) => ref.read(e.provider.notifier).generateAgain()); + await Future.wait(generateAgain.toList()); + _setOperation = SortingEnum.none; } Future playSorting(WidgetRef ref) async { - for (var element in state.selectedAlgorithms) { - ref.read(element.provider.notifier).playSorting(); - } + if (_getOperation == SortingEnum.played) return; + + final playSorting = state.selectedAlgorithms.map((e) => ref.read(e.provider.notifier).playSorting()); + _setOperation = SortingEnum.played; + + await Future.wait(playSorting.toList()); + _setOperation = SortingEnum.none; } void stopSorting(WidgetRef ref) { for (var element in state.selectedAlgorithms) { ref.read(element.provider.notifier).stopSorting(); } + if (_getOperation == SortingEnum.played) _setOperation = SortingEnum.stopped; } } From df9c3ddbe8e261b4e02b6294df8f1b90fced2a16 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 00:00:26 +0300 Subject: [PATCH 059/107] handle deleting instances --- .../comparison/view/comparison_sort_page.dart | 12 +++++++++++- .../view_model/comparison_sort_notifier.dart | 11 +++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/features/sorting/comparison/view/comparison_sort_page.dart b/lib/features/sorting/comparison/view/comparison_sort_page.dart index 903339c..a8bdd2c 100644 --- a/lib/features/sorting/comparison/view/comparison_sort_page.dart +++ b/lib/features/sorting/comparison/view/comparison_sort_page.dart @@ -26,6 +26,16 @@ class _ComparisonSortPageState extends ConsumerState { @override void deactivate() { ref.invalidate(_notifierProvider); // deletes current instance and resets + + ComparisonSortNotifier.sortingAlgorithms.values.toList().forEach( + (element) { + try { + ref.invalidate(element.provider); + } catch (e) { + // + } + }, + ); super.deactivate(); } @@ -109,7 +119,7 @@ class _DrawerMenu extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final selectedAlgorithms = ref.watch(_notifierProvider.select((state) => state.selectedAlgorithms)); - final algorithms = ref.read(_notifierProvider.notifier).sortingAlgorithms.keys.toList(); + final algorithms = ComparisonSortNotifier.sortingAlgorithms.keys.toList(); return Drawer( child: SafeArea( child: ListView( diff --git a/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart index 72ca7d0..c1b4fcd 100644 --- a/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart +++ b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart @@ -21,9 +21,14 @@ class SortingAlgorithm { } class ComparisonSortNotifier extends StateNotifier { - ComparisonSortNotifier() : super(ComparisonSortingNotifierState(selectedAlgorithms: [])); + ComparisonSortNotifier() + : super( + ComparisonSortingNotifierState( + selectedAlgorithms: [sortingAlgorithms[StringsManager.bubbleSort]!], + ), + ); - final Map sortingAlgorithms = { + static final Map sortingAlgorithms = { StringsManager.bubbleSort: SortingAlgorithm( name: StringsManager.bubbleSort, provider: StateNotifierProvider( @@ -94,6 +99,8 @@ class ComparisonSortNotifier extends StateNotifier element.name == algo) != null; + if (isExist && state.selectedAlgorithms.length == 1) return; + if (isExist) { state = state.copyWith( selectedAlgorithms: state.selectedAlgorithms.where((element) => element.name != algo).toList()); From a89446d688ba96f728f09cbed1240d3db091e48c Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 00:20:21 +0300 Subject: [PATCH 060/107] add close icon for comparison --- lib/features/sorting/comparison/view/comparison_sort_page.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/features/sorting/comparison/view/comparison_sort_page.dart b/lib/features/sorting/comparison/view/comparison_sort_page.dart index a8bdd2c..c44840d 100644 --- a/lib/features/sorting/comparison/view/comparison_sort_page.dart +++ b/lib/features/sorting/comparison/view/comparison_sort_page.dart @@ -90,6 +90,9 @@ class _ComparisonSortPageState extends ConsumerState { return AppBar( elevation: 1, title: const SortingAppBar(title: StringsManager.comparisonSort), + actions: [ + CloseButton(), + ], ); } } From b333af3699ede3c1cce4e730a5612315e18bd730 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 12:33:59 +0300 Subject: [PATCH 061/107] reformat the code --- .../sorting/comparison/view/comparison_sort_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/features/sorting/comparison/view/comparison_sort_page.dart b/lib/features/sorting/comparison/view/comparison_sort_page.dart index c44840d..306895c 100644 --- a/lib/features/sorting/comparison/view/comparison_sort_page.dart +++ b/lib/features/sorting/comparison/view/comparison_sort_page.dart @@ -90,8 +90,8 @@ class _ComparisonSortPageState extends ConsumerState { return AppBar( elevation: 1, title: const SortingAppBar(title: StringsManager.comparisonSort), - actions: [ - CloseButton(), + actions: const [ + CloseButton(), ], ); } From 25a9c869c3dcb7b0ac61e5de45e2f79b3214c800 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:53:53 +0300 Subject: [PATCH 062/107] handle edge cases for searching --- .../searching/view_model/grid_notifier.dart | 86 +++++++++++++++++-- 1 file changed, 80 insertions(+), 6 deletions(-) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index 1c4241f..6c8292e 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -30,6 +30,9 @@ class SearchingNotifier extends StateNotifier { int tapDownIndex = -1; GridStatus tapDownGridStatus = GridStatus.empty; + /// [_isBuildingGrid] if build maze or search or even clear grid + bool _isBuildingGrid = false; + bool _isSearched = false; void updateGridLayout(Size size) { final screenWidth = size.width; final screenHeight = size.height; @@ -123,25 +126,47 @@ class SearchingNotifier extends StateNotifier { } } - void clearTheGrid({bool keepWall = false}) { - _clearTheGrid(addState: state, keepWall: keepWall); + Future clearTheGrid({bool keepWall = false, bool clearAnyway = false}) async { + if (!clearAnyway && _isBuildingGrid) return; + _isBuildingGrid = true; + + await _clearTheGrid(addState: state, keepWall: keepWall); state = state.copyWith(currentTappedIndex: -1); + + _isSearched = false; + _isBuildingGrid = false; } void onPointerDownOnGrid(PointerDownEvent event) { + if (_isBuildingGrid) return; + _isBuildingGrid = true; + tapDownIndex = _getIndex(addState: state, localPosition: event.localPosition); + _isBuildingGrid = false; } void onPointerUpOnGrid(PointerUpEvent event) { + if (_isBuildingGrid) return; + _isBuildingGrid = true; + tapDownIndex = -1; + + _isBuildingGrid = false; } void onFingerMoveOnGrid(PointerMoveEvent event) { + if (_isBuildingGrid) return; + _isBuildingGrid = true; + final index = _getIndex(addState: state, localPosition: event.localPosition); /// to handle multi calls from listener widget - if (index == state.currentTappedIndex) return; + if (index == state.currentTappedIndex) { + _isBuildingGrid = false; + + return; + } if (index >= 0 && index < state.gridData.length) { final updatedGridData = List.from(state.gridData); @@ -165,6 +190,8 @@ class SearchingNotifier extends StateNotifier { state = state.copyWith(gridData: updatedGridData, currentTappedIndex: index); } + + _isBuildingGrid = false; } int _getIndex({ @@ -183,11 +210,20 @@ class SearchingNotifier extends StateNotifier { } Future performBFS() async { + if (_isBuildingGrid) return; + _isBuildingGrid = true; + + if (_isSearched) await clearTheGrid(keepWall: true,clearAnyway: true); + final gridData = List.from(state.gridData); final startPointIndex = gridData.indexOf(GridStatus.startPoint); final targetPointIndex = gridData.indexOf(GridStatus.targetPoint); - if (startPointIndex == -1 || targetPointIndex == -1) return; + if (startPointIndex == -1 || targetPointIndex == -1) { + _isBuildingGrid = false; + return; + } + final queue = Queue(); final Set visited = {}; @@ -215,6 +251,9 @@ class SearchingNotifier extends StateNotifier { if (currentIndex == targetPointIndex) { _tracePath(previous, currentIndex); + _isBuildingGrid = false; + _isSearched = true; + return; } @@ -239,14 +278,24 @@ class SearchingNotifier extends StateNotifier { await Future.delayed(drawSearcherDuration); } } + + _isBuildingGrid = false; + _isSearched = true; } Future performDijkstra() async { + if (_isBuildingGrid) return; + _isBuildingGrid = true; + if (_isSearched) await clearTheGrid(keepWall: true,clearAnyway: true); + final gridData = List.from(state.gridData); final startPointIndex = gridData.indexOf(GridStatus.startPoint); final targetPointIndex = gridData.indexOf(GridStatus.targetPoint); - if (startPointIndex == -1 || targetPointIndex == -1) return; + if (startPointIndex == -1 || targetPointIndex == -1) { + _isBuildingGrid = false; + return; + } final distance = List.filled(gridData.length, double.infinity); final previous = List.filled(gridData.length, null); @@ -275,6 +324,8 @@ class SearchingNotifier extends StateNotifier { // If we reached the target, we trace back the path if (currentIndex == targetPointIndex) { _tracePath(previous, currentIndex); + _isBuildingGrid = false; + _isSearched = true; return; } @@ -302,6 +353,8 @@ class SearchingNotifier extends StateNotifier { } } } + _isBuildingGrid = false; + _isSearched = true; } bool _isValidNeighbor( @@ -332,11 +385,19 @@ class SearchingNotifier extends StateNotifier { } Future performAStar() async { + if (_isBuildingGrid) return; + _isBuildingGrid = true; + if (_isSearched) await clearTheGrid(keepWall: true,clearAnyway: true); + final gridData = List.from(state.gridData); final startPointIndex = gridData.indexOf(GridStatus.startPoint); final targetPointIndex = gridData.indexOf(GridStatus.targetPoint); - if (startPointIndex == -1 || targetPointIndex == -1) return; + if (startPointIndex == -1 || targetPointIndex == -1) { + _isBuildingGrid = false; + + return; + } final cross = state.columnCrossAxisCount; @@ -364,6 +425,9 @@ class SearchingNotifier extends StateNotifier { if (currentIndex == targetPointIndex) { await _tracePath(previous, currentIndex); + _isBuildingGrid = false; + _isSearched = true; + return; } @@ -399,6 +463,8 @@ class SearchingNotifier extends StateNotifier { } } } + _isBuildingGrid = false; + _isSearched = true; } double _heuristic(int index, int targetIndex, int cross) { @@ -412,6 +478,8 @@ class SearchingNotifier extends StateNotifier { } void generateRecursiveBacktrackerMaze() async { + if (_isBuildingGrid) return; + _isBuildingGrid = true; final gridData = List.from(state.gridData); // Clear the maze but keep start and target points @@ -434,6 +502,8 @@ class SearchingNotifier extends StateNotifier { await _drawWalls(startRow, startCol, gridData); state = state.copyWith(gridData: gridData); + _isBuildingGrid = false; + _isSearched = false; } Future _drawBorders(List gridData) async { @@ -515,6 +585,8 @@ class SearchingNotifier extends StateNotifier { // Recursive Division Maze Generation Future generateRecursiveDivisionMaze() async { + if (_isBuildingGrid) return; + _isBuildingGrid = true; final gridData = List.from(state.gridData); // Step 1: Start with all empty @@ -543,6 +615,8 @@ class SearchingNotifier extends StateNotifier { await _divide(1, 1, state.rowMainAxisCount - 2, state.columnCrossAxisCount - 2, gridData); state = state.copyWith(gridData: gridData); + _isBuildingGrid = false; + _isSearched = false; } Future _divide(int row, int col, int height, int width, List gridData) async { From a52a2dd496efc3be5458635cd6097db6717804c7 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:54:17 +0300 Subject: [PATCH 063/107] change the buttons places --- lib/features/searching/view/grid_page.dart | 166 ++++++++++++++------- 1 file changed, 112 insertions(+), 54 deletions(-) diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index cb03249..6990eeb 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -2,7 +2,6 @@ import 'package:algorithm_visualizer/core/resources/color_manager.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_dialog.dart'; import 'package:algorithm_visualizer/core/widgets/custom_widgets/custom_icon.dart'; import 'package:algorithm_visualizer/features/searching/view_model/grid_notifier.dart'; import 'package:flutter/material.dart'; @@ -33,65 +32,120 @@ class SearchingPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - actions: [ - Consumer( - builder: (context, ref, _) { - return TextButton( - onPressed: () { - CustomAlertDialog(context).solidDialog( - parameters: [ - ListDialogParameters( - text: StringsManager.recursiveBacktrackerMaze, - onTap: () { - ref.read(_gridNotifierProvider.notifier).generateRecursiveBacktrackerMaze(); + title: Consumer(builder: (context, ref, _) { + return Row( + children: [ + Expanded( + flex: 4, + child: SizedBox( + width: double.infinity, + height: 40.r, + child: Center( + child: FittedBox( + fit: BoxFit.scaleDown, + child: PopupMenuButton( + position: PopupMenuPosition.under, + onSelected: (value) { + if (value == StringsManager.recursiveBacktrackerMaze) { + ref.read(_gridNotifierProvider.notifier).generateRecursiveBacktrackerMaze(); + } else if (value == StringsManager.recursiveDivisionMaze) { + ref.read(_gridNotifierProvider.notifier).generateRecursiveDivisionMaze(); + } }, + itemBuilder: (context) => [ + buildPopupMenuItem(StringsManager.recursiveBacktrackerMaze), + buildPopupMenuItem(StringsManager.recursiveDivisionMaze), + ], + icon: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + MediumText(StringsManager.generateMaze, fontSize: 12), + CustomIcon( + Icons.keyboard_arrow_down_rounded, + size: 16, + ), + ], + ), // 3-dot menu ), - ListDialogParameters( - text: StringsManager.recursiveDivisionMaze, - onTap: () { - ref.read(_gridNotifierProvider.notifier).generateRecursiveDivisionMaze(); + ), + ), + ), + ), + Expanded( + flex: 3, + child: SizedBox( + width: double.infinity, + height: 40.r, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Center( + child: PopupMenuButton( + position: PopupMenuPosition.under, + style: const ButtonStyle( + backgroundColor: WidgetStatePropertyAll(ColorManager.finishedSearcherBlue)), + onSelected: (value) { + if (value == StringsManager.dijkstra) { + ref.read(_gridNotifierProvider.notifier).performDijkstra(); + } else if (value == StringsManager.aStarSearch) { + ref.read(_gridNotifierProvider.notifier).performAStar(); + } else if (value == StringsManager.bFS) { + ref.read(_gridNotifierProvider.notifier).performBFS(); + } }, + itemBuilder: (context) => [ + buildPopupMenuItem(StringsManager.dijkstra), + buildPopupMenuItem(StringsManager.aStarSearch), + buildPopupMenuItem(StringsManager.bFS), + ], + icon: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + MediumText(StringsManager.visualize, fontSize: 12), + CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16), + ], + ), // 3-dot menu ), - ListDialogParameters( - text: StringsManager.dijkstra, - onTap: () { - ref.read(_gridNotifierProvider.notifier).performDijkstra(); + ), + ), + ), + ), + Expanded( + flex: 3, + child: SizedBox( + width: double.infinity, + height: 40.r, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Center( + child: PopupMenuButton( + position: PopupMenuPosition.under, + onSelected: (value) { + if (value == StringsManager.clearPath) { + ref.read(_gridNotifierProvider.notifier).clearTheGrid(keepWall: true); + } else if (value == StringsManager.clearAll) { + ref.read(_gridNotifierProvider.notifier).clearTheGrid(); + } }, + itemBuilder: (context) => [ + buildPopupMenuItem(StringsManager.clearPath, ThemeEnum.redColor), + buildPopupMenuItem(StringsManager.clearAll, ThemeEnum.redColor), + ], + icon: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + MediumText(StringsManager.clear, fontSize: 12, color: ThemeEnum.redColor), + CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16, color: ColorManager.red), + ], + ), // 3-dot menu ), - ListDialogParameters( - text: StringsManager.aStarSearch, - onTap: () { - ref.read(_gridNotifierProvider.notifier).performAStar(); - }, - ), - ListDialogParameters( - text: StringsManager.bFS, - onTap: () { - ref.read(_gridNotifierProvider.notifier).performBFS(); - }, - ), - ListDialogParameters( - text: StringsManager.clearPath, - color: ThemeEnum.redColor, - onTap: () { - ref.read(_gridNotifierProvider.notifier).clearTheGrid(keepWall: true); - }, - ), - ListDialogParameters( - text: StringsManager.clearAll, - color: ThemeEnum.redColor, - onTap: () { - ref.read(_gridNotifierProvider.notifier).clearTheGrid(); - }, - ), - ], - ); - }, - child: const CustomIcon(Icons.menu_rounded), - ); - }, - ), - ], + ), + ), + ), + ), + ], + ); + }), + centerTitle: true, ), body: SafeArea( child: LayoutBuilder( @@ -102,6 +156,10 @@ class SearchingPage extends StatelessWidget { ), ); } + + PopupMenuItem buildPopupMenuItem(String value, [ThemeEnum? color]) { + return PopupMenuItem(value: value, child: RegularText(value, fontSize: 12, color: color)); + } } class _BuildLayout extends ConsumerStatefulWidget { From 070c1758b18e0be2422c46ddec2bedf4027af593 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 14:54:24 +0300 Subject: [PATCH 064/107] add some texts --- lib/core/resources/strings_manager.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index 78ebc83..a40051c 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -46,6 +46,8 @@ class StringsManager { static const String bucketSort = "Bucket sort"; static const String comparisonSort = "Comparison sort"; static const String comparisonAlgorithms = "Comparison algorithms"; + static const String generateMaze = "Generate Maze"; + static const String visualize = "Visualize"; static const String stop = "Stop"; static const String play = "Play"; From dc1eca11b2954cee0f3bfcc40bde74d20e46abd0 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 16:16:58 +0300 Subject: [PATCH 065/107] handle some space for searching --- lib/core/resources/strings_manager.dart | 1 + lib/features/searching/view/grid_page.dart | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/core/resources/strings_manager.dart b/lib/core/resources/strings_manager.dart index a40051c..ffcea1e 100644 --- a/lib/core/resources/strings_manager.dart +++ b/lib/core/resources/strings_manager.dart @@ -48,6 +48,7 @@ class StringsManager { static const String comparisonAlgorithms = "Comparison algorithms"; static const String generateMaze = "Generate Maze"; static const String visualize = "Visualize"; + static const String maze = "Maze"; static const String stop = "Stop"; static const String play = "Play"; diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index 6990eeb..af664d1 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -59,7 +59,7 @@ class SearchingPage extends StatelessWidget { icon: const Row( mainAxisSize: MainAxisSize.min, children: [ - MediumText(StringsManager.generateMaze, fontSize: 12), + MediumText(StringsManager.maze, fontSize: 12), CustomIcon( Icons.keyboard_arrow_down_rounded, size: 16, @@ -72,7 +72,7 @@ class SearchingPage extends StatelessWidget { ), ), Expanded( - flex: 3, + flex: 7, child: SizedBox( width: double.infinity, height: 40.r, @@ -110,7 +110,7 @@ class SearchingPage extends StatelessWidget { ), ), Expanded( - flex: 3, + flex: 7, child: SizedBox( width: double.infinity, height: 40.r, From 98b46abc80e9971e6108e5d2fec436f8cc510692 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 16:18:57 +0300 Subject: [PATCH 066/107] extract control buttons --- lib/features/searching/view/grid_page.dart | 233 +++++++++++---------- 1 file changed, 122 insertions(+), 111 deletions(-) diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index af664d1..fed380a 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -32,134 +32,145 @@ class SearchingPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Consumer(builder: (context, ref, _) { - return Row( - children: [ - Expanded( - flex: 4, - child: SizedBox( - width: double.infinity, - height: 40.r, - child: Center( - child: FittedBox( - fit: BoxFit.scaleDown, - child: PopupMenuButton( - position: PopupMenuPosition.under, - onSelected: (value) { - if (value == StringsManager.recursiveBacktrackerMaze) { - ref.read(_gridNotifierProvider.notifier).generateRecursiveBacktrackerMaze(); - } else if (value == StringsManager.recursiveDivisionMaze) { - ref.read(_gridNotifierProvider.notifier).generateRecursiveDivisionMaze(); - } - }, - itemBuilder: (context) => [ - buildPopupMenuItem(StringsManager.recursiveBacktrackerMaze), - buildPopupMenuItem(StringsManager.recursiveDivisionMaze), + title: _ControlButtons(), + centerTitle: true, + ), + body: SafeArea( + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return _BuildLayout(constraints.biggest); + }, + ), + ), + ); + } +} + +class _ControlButtons extends StatelessWidget { + const _ControlButtons(); + + PopupMenuItem buildPopupMenuItem(String value, [ThemeEnum? color]) { + return PopupMenuItem(value: value, child: RegularText(value, fontSize: 12, color: color)); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, ref, _) { + return Row( + children: [ + Expanded( + flex: 4, + child: SizedBox( + width: double.infinity, + height: 40.r, + child: Center( + child: FittedBox( + fit: BoxFit.scaleDown, + child: PopupMenuButton( + position: PopupMenuPosition.under, + onSelected: (value) { + if (value == StringsManager.recursiveBacktrackerMaze) { + ref.read(_gridNotifierProvider.notifier).generateRecursiveBacktrackerMaze(); + } else if (value == StringsManager.recursiveDivisionMaze) { + ref.read(_gridNotifierProvider.notifier).generateRecursiveDivisionMaze(); + } + }, + itemBuilder: (context) => [ + buildPopupMenuItem(StringsManager.recursiveBacktrackerMaze), + buildPopupMenuItem(StringsManager.recursiveDivisionMaze), + ], + icon: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + MediumText(StringsManager.maze, fontSize: 12), + CustomIcon( + Icons.keyboard_arrow_down_rounded, + size: 16, + ), ], - icon: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - MediumText(StringsManager.maze, fontSize: 12), - CustomIcon( - Icons.keyboard_arrow_down_rounded, - size: 16, - ), - ], - ), // 3-dot menu - ), + ), // 3-dot menu ), ), ), ), - Expanded( - flex: 7, - child: SizedBox( - width: double.infinity, - height: 40.r, - child: FittedBox( - fit: BoxFit.scaleDown, - child: Center( - child: PopupMenuButton( - position: PopupMenuPosition.under, - style: const ButtonStyle( - backgroundColor: WidgetStatePropertyAll(ColorManager.finishedSearcherBlue)), - onSelected: (value) { - if (value == StringsManager.dijkstra) { - ref.read(_gridNotifierProvider.notifier).performDijkstra(); - } else if (value == StringsManager.aStarSearch) { - ref.read(_gridNotifierProvider.notifier).performAStar(); - } else if (value == StringsManager.bFS) { - ref.read(_gridNotifierProvider.notifier).performBFS(); - } - }, - itemBuilder: (context) => [ - buildPopupMenuItem(StringsManager.dijkstra), - buildPopupMenuItem(StringsManager.aStarSearch), - buildPopupMenuItem(StringsManager.bFS), + ), + Expanded( + flex: 7, + child: SizedBox( + width: double.infinity, + height: 40.r, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Center( + child: PopupMenuButton( + position: PopupMenuPosition.under, + style: const ButtonStyle( + backgroundColor: WidgetStatePropertyAll(ColorManager.finishedSearcherBlue)), + onSelected: (value) { + if (value == StringsManager.dijkstra) { + ref.read(_gridNotifierProvider.notifier).performDijkstra(); + } else if (value == StringsManager.aStarSearch) { + ref.read(_gridNotifierProvider.notifier).performAStar(); + } else if (value == StringsManager.bFS) { + ref.read(_gridNotifierProvider.notifier).performBFS(); + } + }, + itemBuilder: (context) => [ + buildPopupMenuItem(StringsManager.dijkstra), + buildPopupMenuItem(StringsManager.aStarSearch), + buildPopupMenuItem(StringsManager.bFS), + ], + icon: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + MediumText(StringsManager.visualize, fontSize: 12), + CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16), ], - icon: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - MediumText(StringsManager.visualize, fontSize: 12), - CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16), - ], - ), // 3-dot menu - ), + ), // 3-dot menu ), ), ), ), - Expanded( - flex: 7, - child: SizedBox( - width: double.infinity, - height: 40.r, - child: FittedBox( - fit: BoxFit.scaleDown, - child: Center( - child: PopupMenuButton( - position: PopupMenuPosition.under, - onSelected: (value) { - if (value == StringsManager.clearPath) { - ref.read(_gridNotifierProvider.notifier).clearTheGrid(keepWall: true); - } else if (value == StringsManager.clearAll) { - ref.read(_gridNotifierProvider.notifier).clearTheGrid(); - } - }, - itemBuilder: (context) => [ - buildPopupMenuItem(StringsManager.clearPath, ThemeEnum.redColor), - buildPopupMenuItem(StringsManager.clearAll, ThemeEnum.redColor), + ), + Expanded( + flex: 7, + child: SizedBox( + width: double.infinity, + height: 40.r, + child: FittedBox( + fit: BoxFit.scaleDown, + child: Center( + child: PopupMenuButton( + position: PopupMenuPosition.under, + onSelected: (value) { + if (value == StringsManager.clearPath) { + ref.read(_gridNotifierProvider.notifier).clearTheGrid(keepWall: true); + } else if (value == StringsManager.clearAll) { + ref.read(_gridNotifierProvider.notifier).clearTheGrid(); + } + }, + itemBuilder: (context) => [ + buildPopupMenuItem(StringsManager.clearPath, ThemeEnum.redColor), + buildPopupMenuItem(StringsManager.clearAll, ThemeEnum.redColor), + ], + icon: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + MediumText(StringsManager.clear, fontSize: 12, color: ThemeEnum.redColor), + CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16, color: ColorManager.red), ], - icon: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - MediumText(StringsManager.clear, fontSize: 12, color: ThemeEnum.redColor), - CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16, color: ColorManager.red), - ], - ), // 3-dot menu - ), + ), // 3-dot menu ), ), ), ), - ], - ); - }), - centerTitle: true, - ), - body: SafeArea( - child: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return _BuildLayout(constraints.biggest); - }, - ), - ), + ), + ], + ); + }, ); } - - PopupMenuItem buildPopupMenuItem(String value, [ThemeEnum? color]) { - return PopupMenuItem(value: value, child: RegularText(value, fontSize: 12, color: color)); - } } class _BuildLayout extends ConsumerStatefulWidget { From 502f129c22f2c902af6ae31932e0a2f9a482e9e6 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:46:20 +0300 Subject: [PATCH 067/107] handle generate maze and columns of grid --- .../searching/view_model/grid_notifier.dart | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index 6c8292e..286d789 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -20,7 +20,9 @@ class MazeDirection { class SearchingNotifier extends StateNotifier { SearchingNotifier() : super(GridNotifierState()); - final int columnSquares = 26; // make it odd always + + /// [_gridSquareSize] + final double _gridSquareSize = 24; static const Duration scaleAppearDurationForWall = Duration(milliseconds: 700); static const Duration clearDuration = Duration(microseconds: 1); static const Duration drawFindingPathDuration = Duration(milliseconds: 2); @@ -37,11 +39,8 @@ class SearchingNotifier extends StateNotifier { final screenWidth = size.width; final screenHeight = size.height; - final double gridSize = - (screenWidth < screenHeight) ? screenWidth / columnSquares : screenHeight / columnSquares; - - final columnCrossAxisCount = (screenWidth / gridSize).floor(); - final rowMainAxisCount = (screenHeight / gridSize).floor(); + final columnCrossAxisCount = (screenWidth / _gridSquareSize).floor(); + final rowMainAxisCount = (screenHeight / _gridSquareSize).floor(); final count = columnCrossAxisCount * rowMainAxisCount; @@ -49,7 +48,7 @@ class SearchingNotifier extends StateNotifier { columnCrossAxisCount: columnCrossAxisCount, rowMainAxisCount: rowMainAxisCount, gridCount: count, - gridSize: gridSize, + gridSize: _gridSquareSize, screenWidth: screenWidth, screenHeight: screenHeight, ); @@ -213,7 +212,7 @@ class SearchingNotifier extends StateNotifier { if (_isBuildingGrid) return; _isBuildingGrid = true; - if (_isSearched) await clearTheGrid(keepWall: true,clearAnyway: true); + if (_isSearched) await clearTheGrid(keepWall: true, clearAnyway: true); final gridData = List.from(state.gridData); final startPointIndex = gridData.indexOf(GridStatus.startPoint); @@ -224,7 +223,6 @@ class SearchingNotifier extends StateNotifier { return; } - final queue = Queue(); final Set visited = {}; final previous = List.filled(gridData.length, null); @@ -286,7 +284,7 @@ class SearchingNotifier extends StateNotifier { Future performDijkstra() async { if (_isBuildingGrid) return; _isBuildingGrid = true; - if (_isSearched) await clearTheGrid(keepWall: true,clearAnyway: true); + if (_isSearched) await clearTheGrid(keepWall: true, clearAnyway: true); final gridData = List.from(state.gridData); final startPointIndex = gridData.indexOf(GridStatus.startPoint); @@ -387,7 +385,7 @@ class SearchingNotifier extends StateNotifier { Future performAStar() async { if (_isBuildingGrid) return; _isBuildingGrid = true; - if (_isSearched) await clearTheGrid(keepWall: true,clearAnyway: true); + if (_isSearched) await clearTheGrid(keepWall: true, clearAnyway: true); final gridData = List.from(state.gridData); final startPointIndex = gridData.indexOf(GridStatus.startPoint); @@ -480,6 +478,8 @@ class SearchingNotifier extends StateNotifier { void generateRecursiveBacktrackerMaze() async { if (_isBuildingGrid) return; _isBuildingGrid = true; + if (_isSearched) await clearTheGrid(clearAnyway: true); + final gridData = List.from(state.gridData); // Clear the maze but keep start and target points @@ -503,7 +503,7 @@ class SearchingNotifier extends StateNotifier { state = state.copyWith(gridData: gridData); _isBuildingGrid = false; - _isSearched = false; + _isSearched = true; } Future _drawBorders(List gridData) async { @@ -587,6 +587,8 @@ class SearchingNotifier extends StateNotifier { Future generateRecursiveDivisionMaze() async { if (_isBuildingGrid) return; _isBuildingGrid = true; + if (_isSearched) await clearTheGrid(clearAnyway: true); + final gridData = List.from(state.gridData); // Step 1: Start with all empty @@ -616,7 +618,7 @@ class SearchingNotifier extends StateNotifier { state = state.copyWith(gridData: gridData); _isBuildingGrid = false; - _isSearched = false; + _isSearched = true; } Future _divide(int row, int col, int height, int width, List gridData) async { From 0f5d9e252c8c669c199c7140ce48620a9e8dabf9 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:46:35 +0300 Subject: [PATCH 068/107] handle grid on large screen --- lib/core/material_app/my_app.dart | 3 ++- lib/features/searching/view/grid_page.dart | 17 +++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/core/material_app/my_app.dart b/lib/core/material_app/my_app.dart index 3cc4aad..8571a8f 100644 --- a/lib/core/material_app/my_app.dart +++ b/lib/core/material_app/my_app.dart @@ -14,7 +14,8 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - const defaultSize = Size(360, 690); + + final defaultSize = MediaQuery.sizeOf(context); return ScreenUtilInit( designSize: defaultSize, diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index fed380a..9003573 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -32,7 +32,7 @@ class SearchingPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: _ControlButtons(), + title: const _ControlButtons(), centerTitle: true, ), body: SafeArea( @@ -83,10 +83,10 @@ class _ControlButtons extends StatelessWidget { icon: const Row( mainAxisSize: MainAxisSize.min, children: [ - MediumText(StringsManager.maze, fontSize: 12), + MediumText(StringsManager.maze, fontSize: 16), CustomIcon( Icons.keyboard_arrow_down_rounded, - size: 16, + size: 20, ), ], ), // 3-dot menu @@ -124,8 +124,8 @@ class _ControlButtons extends StatelessWidget { icon: const Row( mainAxisSize: MainAxisSize.min, children: [ - MediumText(StringsManager.visualize, fontSize: 12), - CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16), + MediumText(StringsManager.visualize, fontSize: 16), + CustomIcon(Icons.keyboard_arrow_down_rounded, size: 22), ], ), // 3-dot menu ), @@ -157,8 +157,8 @@ class _ControlButtons extends StatelessWidget { icon: const Row( mainAxisSize: MainAxisSize.min, children: [ - MediumText(StringsManager.clear, fontSize: 12, color: ThemeEnum.redColor), - CustomIcon(Icons.keyboard_arrow_down_rounded, size: 16, color: ColorManager.red), + MediumText(StringsManager.clear, fontSize: 16, color: ThemeEnum.redColor), + CustomIcon(Icons.keyboard_arrow_down_rounded, size: 20, color: ColorManager.red), ], ), // 3-dot menu ), @@ -250,7 +250,8 @@ class _Square extends ConsumerStatefulWidget { class _SquareState extends ConsumerState<_Square> { @override Widget build(BuildContext context) { - final isSelected = ref.watch(_gridNotifierProvider.select((it) => it.gridData[widget.index])); + final isSelected = ref.watch(_gridNotifierProvider + .select((it) => it.gridData.length > widget.index ? it.gridData[widget.index] : GridStatus.empty)); final isColored = isSelected != GridStatus.empty; final showBorder = isSelected != GridStatus.empty && From b0a488fd42b5fecbba77a6df5d8e2550a4e751d7 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:46:56 +0300 Subject: [PATCH 069/107] add some low level macos files --- macos/Runner.xcodeproj/project.pbxproj | 98 ++++++++++++++++++- .../xcshareddata/xcschemes/Runner.xcscheme | 1 + .../contents.xcworkspacedata | 3 + macos/Runner/AppDelegate.swift | 6 +- 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index a6f9901..05ed00a 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -27,6 +27,8 @@ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + BC0695BE8BA6DC7C18097C19 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EFF8E0EB3563FC8B93AB509 /* Pods_RunnerTests.framework */; }; + FD5A63B08DF895FB684A09FE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0FBA750DA18DC593C98ECBE /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -60,11 +62,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0EFF8E0EB3563FC8B93AB509 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 23A4DBC67A1A6A65723262E9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* algorithm_visualizer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "algorithm_visualizer.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* algorithm_visualizer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = algorithm_visualizer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -76,8 +80,14 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 560AC72BC0C18017F5A9626B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 8411ABA32E67EC1D74FB3B96 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + B8EB7DF779F1EFC007352DCF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + C22B857E797CFF10C241D852 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + D0FBA750DA18DC593C98ECBE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DC777C9E959E5C0BFB9580AF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + BC0695BE8BA6DC7C18097C19 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +103,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + FD5A63B08DF895FB684A09FE /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -125,6 +137,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + D5E1AE4133BFDC95E9F8843F /* Pods */, ); sourceTree = ""; }; @@ -172,9 +185,25 @@ path = Runner; sourceTree = ""; }; + D5E1AE4133BFDC95E9F8843F /* Pods */ = { + isa = PBXGroup; + children = ( + 560AC72BC0C18017F5A9626B /* Pods-Runner.debug.xcconfig */, + 23A4DBC67A1A6A65723262E9 /* Pods-Runner.release.xcconfig */, + 8411ABA32E67EC1D74FB3B96 /* Pods-Runner.profile.xcconfig */, + C22B857E797CFF10C241D852 /* Pods-RunnerTests.debug.xcconfig */, + DC777C9E959E5C0BFB9580AF /* Pods-RunnerTests.release.xcconfig */, + B8EB7DF779F1EFC007352DCF /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + D0FBA750DA18DC593C98ECBE /* Pods_Runner.framework */, + 0EFF8E0EB3563FC8B93AB509 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -186,6 +215,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 0D13C9B613943B381077B388 /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -204,11 +234,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + CE18D4BD866962CCF82166CC /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 7A625F1AF1C52229A9606F09 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -291,6 +323,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 0D13C9B613943B381077B388 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -329,6 +383,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 7A625F1AF1C52229A9606F09 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + CE18D4BD866962CCF82166CC /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -380,6 +473,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = C22B857E797CFF10C241D852 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -394,6 +488,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DC777C9E959E5C0BFB9580AF /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -408,6 +503,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = B8EB7DF779F1EFC007352DCF /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 7e4fd8b..06f7eef 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -59,6 +59,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index d53ef64..b3c1761 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } From e0ee474d91af9f921a8b657d5c78364d512e33ea Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:52:39 +0300 Subject: [PATCH 070/107] center visualize button --- lib/features/searching/view/grid_page.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index 9003573..4dcd931 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -60,7 +60,7 @@ class _ControlButtons extends StatelessWidget { return Row( children: [ Expanded( - flex: 4, + flex: 8, child: SizedBox( width: double.infinity, height: 40.r, @@ -96,7 +96,7 @@ class _ControlButtons extends StatelessWidget { ), ), Expanded( - flex: 7, + flex: 10, child: SizedBox( width: double.infinity, height: 40.r, @@ -134,7 +134,7 @@ class _ControlButtons extends StatelessWidget { ), ), Expanded( - flex: 7, + flex: 10, child: SizedBox( width: double.infinity, height: 40.r, From 1758dd309eccc0f1abc29444ac10cb195f1ef73e Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 18:24:26 +0300 Subject: [PATCH 071/107] handle view with large screen --- lib/core/helpers/current_device.dart | 5 ++ lib/features/searching/view/grid_page.dart | 11 ++++- .../sorting/base/view/sorting_list_page.dart | 2 +- .../sorting/base/view/sorting_page.dart | 47 ++++++++++--------- .../base/view_model/sorting_notifier.dart | 13 +++-- 5 files changed, 51 insertions(+), 27 deletions(-) diff --git a/lib/core/helpers/current_device.dart b/lib/core/helpers/current_device.dart index 1fc7f3c..bb75fe6 100644 --- a/lib/core/helpers/current_device.dart +++ b/lib/core/helpers/current_device.dart @@ -5,4 +5,9 @@ extension CurrentDevice on BuildContext { final ThemeData theme = Theme.of(this); return theme.platform == TargetPlatform.android; } + + bool get isIOS { + final ThemeData theme = Theme.of(this); + return theme.platform == TargetPlatform.iOS; + } } diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index 4dcd931..7e233be 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -46,11 +46,18 @@ class SearchingPage extends StatelessWidget { } } -class _ControlButtons extends StatelessWidget { +class _ControlButtons extends StatefulWidget { const _ControlButtons(); + @override + State<_ControlButtons> createState() => _ControlButtonsState(); +} + +class _ControlButtonsState extends State<_ControlButtons> { PopupMenuItem buildPopupMenuItem(String value, [ThemeEnum? color]) { - return PopupMenuItem(value: value, child: RegularText(value, fontSize: 12, color: color)); + final isLargeScreen = MediaQuery.sizeOf(context).width > 500; + return PopupMenuItem( + value: value, child: RegularText(value, fontSize: isLargeScreen ? 16 : 14, color: color)); } @override diff --git a/lib/features/sorting/base/view/sorting_list_page.dart b/lib/features/sorting/base/view/sorting_list_page.dart index 75502c4..b9c8d38 100644 --- a/lib/features/sorting/base/view/sorting_list_page.dart +++ b/lib/features/sorting/base/view/sorting_list_page.dart @@ -19,7 +19,7 @@ class SortingListPage extends StatelessWidget { body: const SafeArea( child: Center( child: Column( - mainAxisAlignment: MainAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _CustomButton(text: StringsManager.bubbleSort, route: Routes.bubbleSort), _CustomButton(text: StringsManager.insertionSort, route: Routes.insertionSort), diff --git a/lib/features/sorting/base/view/sorting_page.dart b/lib/features/sorting/base/view/sorting_page.dart index ef25d7f..5deb6ad 100644 --- a/lib/features/sorting/base/view/sorting_page.dart +++ b/lib/features/sorting/base/view/sorting_page.dart @@ -58,28 +58,32 @@ class _BuildBody extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( - child: Stack( - alignment: AlignmentDirectional.bottomCenter, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Align(alignment: AlignmentDirectional.topCenter, child: ShowUpSortingList(instance)), - Align( - alignment: AlignmentDirectional.bottomCenter, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - spacing: 10, - children: [ - _SortingControlButtons(instance), - SymmetricPadding( - horizontal: 15, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _SpeedDraggable(instance: instance), - _SizeDraggable(instance: instance), - ], + Flexible( + child: Align( + alignment: AlignmentDirectional.bottomCenter, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + spacing: 10, + children: [ + Flexible(child: _SortingControlButtons(instance)), + Flexible( + child: SymmetricPadding( + horizontal: 15, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _SpeedDraggable(instance: instance), + _SizeDraggable(instance: instance), + ], + ), + ), ), - ), - ], + ], + ), ), ), ], @@ -96,11 +100,12 @@ class ShowUpSortingList extends ConsumerWidget { Widget build(BuildContext context, ref) { final items = ref.watch(instance.select((state) => state.list)); final speedDuration = ref.watch(instance.select((state) => state.swipeDuration)); + final maxHeight = SortingNotifier.calculateMaxListItemHeight(context); return Padding( padding: const EdgeInsets.only(top: 5), child: RSizedBox( - height: selectedAlgorithmLength == 1 ? SortingNotifier.maxListItemHeight * 1.05 : null, + height: selectedAlgorithmLength == 1 ? maxHeight*1.01 : null, width: double.infinity, child: Stack( alignment: AlignmentDirectional.bottomCenter, @@ -156,7 +161,7 @@ class _BuildItem extends ConsumerWidget { padding: EdgeInsets.symmetric(horizontal: SortingNotifier.itemsPadding / 2), child: AnimatedContainer( duration: speedDuration, - height: SortingNotifier.calculateItemHeight(item.value, size) / selectedAlgorithmLength, + height: SortingNotifier.calculateItemHeight(context, item.value, size) / selectedAlgorithmLength, width: itemWidth, decoration: BoxDecoration( color: context.getColor(currentItem?.getColor ?? SortingNotifier.itemColor), diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index 5ba865e..288ca8e 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -15,7 +15,7 @@ abstract class SortingNotifier extends StateNotifier { _initializePositions(); } - static double maxListItemHeight = 250.r; + // static double maxListItemHeight = 250.r; static double itemsPadding = 1.w; static const ThemeEnum swappingColor = ThemeEnum.redColor; static const ThemeEnum comparedColor = ThemeEnum.lightBlueColor; @@ -44,8 +44,15 @@ abstract class SortingNotifier extends StateNotifier { return availableWidth / size > 0 ? availableWidth / size : 1.0; } - static double calculateItemHeight(int itemIndex, int size) { - final value = (maxListItemHeight / size) * (itemIndex + 1); + static double calculateMaxListItemHeight(BuildContext context) { + final screenHeight = MediaQuery.of(context).size.height * 0.65; + + // Ensure a positive width + return screenHeight > 0 ? screenHeight : 1.0; + } + + static double calculateItemHeight(BuildContext context, int itemIndex, int size) { + final value = (calculateMaxListItemHeight(context) / size) * (itemIndex + 1); return value.h; } From 31baebf89015e48c2084e3d4192dee43d53e2353 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 19:26:33 +0300 Subject: [PATCH 072/107] handle sorting view --- .../sorting/base/view/sorting_page.dart | 4 ++-- .../base/view_model/sorting_notifier.dart | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/features/sorting/base/view/sorting_page.dart b/lib/features/sorting/base/view/sorting_page.dart index 5deb6ad..c59f54c 100644 --- a/lib/features/sorting/base/view/sorting_page.dart +++ b/lib/features/sorting/base/view/sorting_page.dart @@ -105,7 +105,7 @@ class ShowUpSortingList extends ConsumerWidget { return Padding( padding: const EdgeInsets.only(top: 5), child: RSizedBox( - height: selectedAlgorithmLength == 1 ? maxHeight*1.01 : null, + height: selectedAlgorithmLength == 1 ? maxHeight * 1.01 : null, width: double.infinity, child: Stack( alignment: AlignmentDirectional.bottomCenter, @@ -161,7 +161,7 @@ class _BuildItem extends ConsumerWidget { padding: EdgeInsets.symmetric(horizontal: SortingNotifier.itemsPadding / 2), child: AnimatedContainer( duration: speedDuration, - height: SortingNotifier.calculateItemHeight(context, item.value, size) / selectedAlgorithmLength, + height: SortingNotifier.calculateItemHeight(context, item.value, size, selectedAlgorithmLength), width: itemWidth, decoration: BoxDecoration( color: context.getColor(currentItem?.getColor ?? SortingNotifier.itemColor), diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index 288ca8e..0732ef4 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -51,9 +51,23 @@ abstract class SortingNotifier extends StateNotifier { return screenHeight > 0 ? screenHeight : 1.0; } - static double calculateItemHeight(BuildContext context, int itemIndex, int size) { + static double calculateItemHeight( + BuildContext context, + int itemIndex, + int size, + int selectedAlgorithmsLength, + ) { final value = (calculateMaxListItemHeight(context) / size) * (itemIndex + 1); - return value.h; + final perc = selectedAlgorithmsLength == 1 + ? 1 + : selectedAlgorithmsLength <= 3 + ? 0.9 + : selectedAlgorithmsLength <= 6 + ? 0.8 + : selectedAlgorithmsLength <= 9 + ? 0.7 + : 0.6; + return value.h / selectedAlgorithmsLength * perc; } Duration get speedDuration => state.swipeDuration; From e92196b3c4a645e5823d9e540dbab8613155eaa8 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Mon, 25 Aug 2025 19:26:51 +0300 Subject: [PATCH 073/107] change grid square to 25 --- lib/features/searching/view_model/grid_notifier.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index 286d789..bcd1171 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -22,7 +22,7 @@ class SearchingNotifier extends StateNotifier { SearchingNotifier() : super(GridNotifierState()); /// [_gridSquareSize] - final double _gridSquareSize = 24; + final double _gridSquareSize = 25; static const Duration scaleAppearDurationForWall = Duration(milliseconds: 700); static const Duration clearDuration = Duration(microseconds: 1); static const Duration drawFindingPathDuration = Duration(milliseconds: 2); From c4e70f5cc018f76e3ddf7ed171af1dcadbf2a637 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:45:20 +0300 Subject: [PATCH 074/107] handle deleting instances --- .../sorting/base/view/sorting_page.dart | 18 ++- .../base/view_model/sorting_notifier.dart | 13 ++- .../sorting/base/widgets/control_buttons.dart | 2 +- .../comparison/view/comparison_sort_page.dart | 106 +++++++++--------- .../view_model/comparison_sort_notifier.dart | 22 ++-- 5 files changed, 92 insertions(+), 69 deletions(-) diff --git a/lib/features/sorting/base/view/sorting_page.dart b/lib/features/sorting/base/view/sorting_page.dart index c59f54c..57a32c8 100644 --- a/lib/features/sorting/base/view/sorting_page.dart +++ b/lib/features/sorting/base/view/sorting_page.dart @@ -14,16 +14,24 @@ part '../widgets/control_buttons.dart'; part '../widgets/size_draggable.dart'; part '../widgets/speed_draggable.dart'; -class SortingPage extends StatelessWidget { +class SortingPage extends ConsumerWidget { const SortingPage({required this.instance, required this.title, super.key}); final StateNotifierProvider instance; final String title; @override - Widget build(BuildContext context) { - return Scaffold( - appBar: appBar(), - body: _BuildBody(instance: instance), + Widget build(BuildContext context, WidgetRef ref) { + return PopScope( + onPopInvokedWithResult: (didPop, result) async { + if (didPop) { + await ref.read(instance.notifier).cancelSorting(); + ref.invalidate(instance); // deletes current instance and resets + } + }, + child: Scaffold( + appBar: appBar(), + body: _BuildBody(instance: instance), + ), ); } diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index 0732ef4..d2d769f 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -104,18 +104,23 @@ abstract class SortingNotifier extends StateNotifier { generateAgain(); } - void stopSorting() { - _cancelableSort?.cancel(); + Future cancelSorting() async { + await _cancelableSort?.cancel(); + } + + Future stopSorting() async { + await _cancelableSort?.cancel(); if (_getOperation == SortingEnum.played) _setOperation = SortingEnum.stopped; } - Future playSorting() async { + Future playSorting(BuildContext context) async { if (_getOperation == SortingEnum.played) return; _setOperation = SortingEnum.played; await _startSelectedSorting(); - _setOperation = SortingEnum.none; +// to avoid error of mounted when popup while the sorting algorithm still running + if (context.mounted) _setOperation = SortingEnum.none; } Future generateAgain() async { diff --git a/lib/features/sorting/base/widgets/control_buttons.dart b/lib/features/sorting/base/widgets/control_buttons.dart index 0543bd8..c9eb1a5 100644 --- a/lib/features/sorting/base/widgets/control_buttons.dart +++ b/lib/features/sorting/base/widgets/control_buttons.dart @@ -7,7 +7,7 @@ class _SortingControlButtons extends ConsumerWidget { @override Widget build(BuildContext context, ref) { return SortingControlButtons( - playSorting: () => ref.read(instance.notifier).playSorting(), + playSorting: () => ref.read(instance.notifier).playSorting(context), stopSorting: () => ref.read(instance.notifier).stopSorting(), generateAgain: () => ref.read(instance.notifier).generateAgain(), ); diff --git a/lib/features/sorting/comparison/view/comparison_sort_page.dart b/lib/features/sorting/comparison/view/comparison_sort_page.dart index 306895c..ea16486 100644 --- a/lib/features/sorting/comparison/view/comparison_sort_page.dart +++ b/lib/features/sorting/comparison/view/comparison_sort_page.dart @@ -24,63 +24,65 @@ class ComparisonSortPage extends ConsumerStatefulWidget { class _ComparisonSortPageState extends ConsumerState { @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - - ComparisonSortNotifier.sortingAlgorithms.values.toList().forEach( - (element) { - try { - ref.invalidate(element.provider); - } catch (e) { - // + Widget build(BuildContext context) { + return PopScope( + onPopInvokedWithResult: (didPop, result) async { + if (didPop) { + await ref.read(_notifierProvider.notifier).cancelSorting(ref); + + ComparisonSortNotifier.sortingAlgorithms.values.toList().forEach( + (element) { + try { + ref.invalidate(element.provider); + } catch (e) { + // + } + }, + ); + ref.invalidate(_notifierProvider); // deletes current instance and resets } }, - ); - super.deactivate(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: appBar(), - drawer: const _DrawerMenu(), - body: SafeArea( - child: Column( - children: [ - const Flexible(child: _BuildComparisonLists()), - const RSizedBox(height: 15), - Padding( - padding: REdgeInsets.symmetric(horizontal: 0), - child: Align( - alignment: AlignmentDirectional.bottomCenter, - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - spacing: 10, - children: [ - SortingControlButtons( - playSorting: () => ref.read(_notifierProvider.notifier).playSorting(ref), - stopSorting: () => ref.read(_notifierProvider.notifier).stopSorting(ref), - generateAgain: () => ref.read(_notifierProvider.notifier).generateAgain(ref), - ), - SymmetricPadding( - horizontal: 15, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SpeedDraggable( - onChanged: (persent) { - ref.read(_notifierProvider.notifier).changeSpeed(persent, ref); - }, - ), - _SizeDraggable(ref: ref), - ], + child: Scaffold( + appBar: appBar(), + drawer: const _DrawerMenu(), + body: SafeArea( + child: Column( + children: [ + const Flexible(child: _BuildComparisonLists()), + const RSizedBox(height: 15), + Padding( + padding: REdgeInsets.symmetric(horizontal: 0), + child: Align( + alignment: AlignmentDirectional.bottomCenter, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + spacing: 10, + children: [ + SortingControlButtons( + playSorting: () => ref.read(_notifierProvider.notifier).playSorting(context, ref), + stopSorting: () => ref.read(_notifierProvider.notifier).stopSorting(ref), + generateAgain: () => ref.read(_notifierProvider.notifier).generateAgain(ref), + ), + SymmetricPadding( + horizontal: 15, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SpeedDraggable( + onChanged: (persent) { + ref.read(_notifierProvider.notifier).changeSpeed(persent, ref); + }, + ), + _SizeDraggable(ref: ref), + ], + ), ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart index c1b4fcd..fef9d0d 100644 --- a/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart +++ b/lib/features/sorting/comparison/view_model/comparison_sort_notifier.dart @@ -11,6 +11,7 @@ import 'package:algorithm_visualizer/features/sorting/radix/view_model/radix_sor import 'package:algorithm_visualizer/features/sorting/selection/view_model/selection_sort_notifier.dart'; import 'package:algorithm_visualizer/features/sorting/shell/view_model/shell_sort_notifier.dart'; import 'package:collection/collection.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; part 'comparison_sort_state.dart'; @@ -138,20 +139,27 @@ class ComparisonSortNotifier extends StateNotifier playSorting(WidgetRef ref) async { + Future playSorting(BuildContext context, WidgetRef ref) async { if (_getOperation == SortingEnum.played) return; - final playSorting = state.selectedAlgorithms.map((e) => ref.read(e.provider.notifier).playSorting()); + final playSorting = + state.selectedAlgorithms.map((e) => ref.read(e.provider.notifier).playSorting(context)); _setOperation = SortingEnum.played; await Future.wait(playSorting.toList()); - _setOperation = SortingEnum.none; + if (context.mounted) _setOperation = SortingEnum.none; } - void stopSorting(WidgetRef ref) { - for (var element in state.selectedAlgorithms) { - ref.read(element.provider.notifier).stopSorting(); - } + Future stopSorting(WidgetRef ref) async { + final stopSorting = state.selectedAlgorithms.map((e) => ref.read(e.provider.notifier).stopSorting()); + _setOperation = SortingEnum.played; + + await Future.wait(stopSorting.toList()); + if (_getOperation == SortingEnum.played) _setOperation = SortingEnum.stopped; } + Future cancelSorting(WidgetRef ref) async { + final cancelSorting = state.selectedAlgorithms.map((e) => ref.read(e.provider.notifier).cancelSorting()); + await Future.wait(cancelSorting.toList()); + } } From 5a94d4060b7b9864761e4f6c99070b58c77f8045 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:45:43 +0300 Subject: [PATCH 075/107] handle deleting instances --- lib/features/sorting/bubble/view/bubble_sort_page.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/features/sorting/bubble/view/bubble_sort_page.dart b/lib/features/sorting/bubble/view/bubble_sort_page.dart index c88f7fa..338d9d8 100644 --- a/lib/features/sorting/bubble/view/bubble_sort_page.dart +++ b/lib/features/sorting/bubble/view/bubble_sort_page.dart @@ -17,12 +17,6 @@ class BubbleSortPage extends ConsumerStatefulWidget { } class _BubbleSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } - @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.bubbleSort); From f4e52b9b63f70b919cddbd0ba222152ba96cd6df Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:49:08 +0300 Subject: [PATCH 076/107] handle deleting instances --- .../sorting/bubble/view/bubble_sort_page.dart | 6 +++--- .../sorting/bucket/view/bucket_sort_page.dart | 12 +++--------- .../sorting/counting/view/counting_sort_page.dart | 11 +++-------- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/lib/features/sorting/bubble/view/bubble_sort_page.dart b/lib/features/sorting/bubble/view/bubble_sort_page.dart index 338d9d8..5e036e3 100644 --- a/lib/features/sorting/bubble/view/bubble_sort_page.dart +++ b/lib/features/sorting/bubble/view/bubble_sort_page.dart @@ -9,14 +9,14 @@ final _notifierProvider = StateNotifierProvider BubbleSortNotifier(), ); -class BubbleSortPage extends ConsumerStatefulWidget { +class BubbleSortPage extends StatefulWidget { const BubbleSortPage({super.key}); @override - ConsumerState createState() => _BubbleSortPageState(); + State createState() => _BubbleSortPageState(); } -class _BubbleSortPageState extends ConsumerState { +class _BubbleSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.bubbleSort); diff --git a/lib/features/sorting/bucket/view/bucket_sort_page.dart b/lib/features/sorting/bucket/view/bucket_sort_page.dart index 65141ce..d7ff110 100644 --- a/lib/features/sorting/bucket/view/bucket_sort_page.dart +++ b/lib/features/sorting/bucket/view/bucket_sort_page.dart @@ -9,20 +9,14 @@ final _notifierProvider = StateNotifierProvider BucketSortNotifier(), ); -class BucketSortPage extends ConsumerStatefulWidget { +class BucketSortPage extends StatefulWidget { const BucketSortPage({super.key}); @override - ConsumerState createState() => _BucketSortPageState(); + State createState() => _BucketSortPageState(); } -class _BucketSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } - +class _BucketSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.bucketSort); diff --git a/lib/features/sorting/counting/view/counting_sort_page.dart b/lib/features/sorting/counting/view/counting_sort_page.dart index 0e75822..2fc7574 100644 --- a/lib/features/sorting/counting/view/counting_sort_page.dart +++ b/lib/features/sorting/counting/view/counting_sort_page.dart @@ -9,19 +9,14 @@ final _notifierProvider = StateNotifierProvider CountingSortNotifier(), ); -class CountingSortPage extends ConsumerStatefulWidget { +class CountingSortPage extends StatefulWidget { const CountingSortPage({super.key}); @override - ConsumerState createState() => _CountingSortPageState(); + State createState() => _CountingSortPageState(); } -class _CountingSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } +class _CountingSortPageState extends State { @override Widget build(BuildContext context) { From d55c5834068a1617b414dc9e07d6232eca96a0bb Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:49:11 +0300 Subject: [PATCH 077/107] handle deleting instances --- lib/features/sorting/heap/view/heap_sort_page.dart | 11 +++-------- .../sorting/insertion/view/insertion_sort_page.dart | 12 +++--------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/lib/features/sorting/heap/view/heap_sort_page.dart b/lib/features/sorting/heap/view/heap_sort_page.dart index cefabaf..3743911 100644 --- a/lib/features/sorting/heap/view/heap_sort_page.dart +++ b/lib/features/sorting/heap/view/heap_sort_page.dart @@ -9,19 +9,14 @@ final _notifierProvider = StateNotifierProvider HeapSortNotifier(), ); -class HeapSortPage extends ConsumerStatefulWidget { +class HeapSortPage extends StatefulWidget { const HeapSortPage({super.key}); @override - ConsumerState createState() => _HeapSortPageState(); + State createState() => _HeapSortPageState(); } -class _HeapSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } +class _HeapSortPageState extends State { @override Widget build(BuildContext context) { diff --git a/lib/features/sorting/insertion/view/insertion_sort_page.dart b/lib/features/sorting/insertion/view/insertion_sort_page.dart index 992213c..712bc59 100644 --- a/lib/features/sorting/insertion/view/insertion_sort_page.dart +++ b/lib/features/sorting/insertion/view/insertion_sort_page.dart @@ -9,20 +9,14 @@ final _notifierProvider = StateNotifierProvider InsertionSortNotifier(), ); -class InsertionSortPage extends ConsumerStatefulWidget { +class InsertionSortPage extends StatefulWidget { const InsertionSortPage({super.key}); @override - ConsumerState createState() => _InsertionSortPageState(); + State createState() => _InsertionSortPageState(); } -class _InsertionSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } - +class _InsertionSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.insertionSort); From b857100cdd96645b9db7173f9bb230c35e99512a Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:49:14 +0300 Subject: [PATCH 078/107] handle deleting instances --- lib/features/sorting/merge/view/merge_sort_page.dart | 11 +++-------- lib/features/sorting/quick/view/quick_sort_page.dart | 12 +++--------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/lib/features/sorting/merge/view/merge_sort_page.dart b/lib/features/sorting/merge/view/merge_sort_page.dart index 79ed2a7..1b1f5c6 100644 --- a/lib/features/sorting/merge/view/merge_sort_page.dart +++ b/lib/features/sorting/merge/view/merge_sort_page.dart @@ -9,19 +9,14 @@ final _notifierProvider = StateNotifierProvider MergeSortNotifier(), ); -class MergeSortPage extends ConsumerStatefulWidget { +class MergeSortPage extends StatefulWidget { const MergeSortPage({super.key}); @override - ConsumerState createState() => _MergeSortPageState(); + State createState() => _MergeSortPageState(); } -class _MergeSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } +class _MergeSortPageState extends State { @override Widget build(BuildContext context) { diff --git a/lib/features/sorting/quick/view/quick_sort_page.dart b/lib/features/sorting/quick/view/quick_sort_page.dart index 45663c7..d59d807 100644 --- a/lib/features/sorting/quick/view/quick_sort_page.dart +++ b/lib/features/sorting/quick/view/quick_sort_page.dart @@ -9,20 +9,14 @@ final _notifierProvider = StateNotifierProvider QuickSortNotifier(), ); -class QuickSortPage extends ConsumerStatefulWidget { +class QuickSortPage extends StatefulWidget { const QuickSortPage({super.key}); @override - ConsumerState createState() => _QuickSortPageState(); + State createState() => _QuickSortPageState(); } -class _QuickSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } - +class _QuickSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.quickSort); From 31ca44ea24458985d7ca2f0e77e2e43872d242b2 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:49:16 +0300 Subject: [PATCH 079/107] handle deleting instances --- lib/features/sorting/radix/view/radix_sort_page.dart | 12 +++--------- .../sorting/selection/view/selection_sort_page.dart | 12 +++--------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/lib/features/sorting/radix/view/radix_sort_page.dart b/lib/features/sorting/radix/view/radix_sort_page.dart index 7ed816a..dc1978a 100644 --- a/lib/features/sorting/radix/view/radix_sort_page.dart +++ b/lib/features/sorting/radix/view/radix_sort_page.dart @@ -9,20 +9,14 @@ final _notifierProvider = StateNotifierProvider RadixSortNotifier(), ); -class RadixSortPage extends ConsumerStatefulWidget { +class RadixSortPage extends StatefulWidget { const RadixSortPage({super.key}); @override - ConsumerState createState() => _RadixSortPageState(); + State createState() => _RadixSortPageState(); } -class _RadixSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } - +class _RadixSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.radixSort); diff --git a/lib/features/sorting/selection/view/selection_sort_page.dart b/lib/features/sorting/selection/view/selection_sort_page.dart index dd2f321..7be7254 100644 --- a/lib/features/sorting/selection/view/selection_sort_page.dart +++ b/lib/features/sorting/selection/view/selection_sort_page.dart @@ -9,20 +9,14 @@ final _notifierProvider = StateNotifierProvider SelectionSortNotifier(), ); -class SelectionSortPage extends ConsumerStatefulWidget { +class SelectionSortPage extends StatefulWidget { const SelectionSortPage({super.key}); @override - ConsumerState createState() => _SelectionSortPageState(); + State createState() => _SelectionSortPageState(); } -class _SelectionSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } - +class _SelectionSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider,title: StringsManager.selectionSort); From 7e2d392a4431540bb803ad10f0d6a9c0d647ea31 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:49:19 +0300 Subject: [PATCH 080/107] handle deleting instances --- lib/features/sorting/shell/view/shell_sort_page.dart | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/features/sorting/shell/view/shell_sort_page.dart b/lib/features/sorting/shell/view/shell_sort_page.dart index 5f41375..46a887e 100644 --- a/lib/features/sorting/shell/view/shell_sort_page.dart +++ b/lib/features/sorting/shell/view/shell_sort_page.dart @@ -9,20 +9,14 @@ final _notifierProvider = StateNotifierProvider ShellSortNotifier(), ); -class ShellSortPage extends ConsumerStatefulWidget { +class ShellSortPage extends StatefulWidget { const ShellSortPage({super.key}); @override - ConsumerState createState() => _ShellSortPageState(); + State createState() => _ShellSortPageState(); } -class _ShellSortPageState extends ConsumerState { - @override - void deactivate() { - ref.invalidate(_notifierProvider); // deletes current instance and resets - super.deactivate(); - } - +class _ShellSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.shellSort); From 726bc3ea384df27c80beca038be8d5b64d687b51 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:51:21 +0300 Subject: [PATCH 081/107] convert StatefulWidget to StatelessWidget --- lib/features/sorting/bubble/view/bubble_sort_page.dart | 7 +------ lib/features/sorting/bucket/view/bucket_sort_page.dart | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/features/sorting/bubble/view/bubble_sort_page.dart b/lib/features/sorting/bubble/view/bubble_sort_page.dart index 5e036e3..89f36c6 100644 --- a/lib/features/sorting/bubble/view/bubble_sort_page.dart +++ b/lib/features/sorting/bubble/view/bubble_sort_page.dart @@ -9,14 +9,9 @@ final _notifierProvider = StateNotifierProvider BubbleSortNotifier(), ); -class BubbleSortPage extends StatefulWidget { +class BubbleSortPage extends StatelessWidget { const BubbleSortPage({super.key}); - @override - State createState() => _BubbleSortPageState(); -} - -class _BubbleSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.bubbleSort); diff --git a/lib/features/sorting/bucket/view/bucket_sort_page.dart b/lib/features/sorting/bucket/view/bucket_sort_page.dart index d7ff110..4d283e4 100644 --- a/lib/features/sorting/bucket/view/bucket_sort_page.dart +++ b/lib/features/sorting/bucket/view/bucket_sort_page.dart @@ -9,14 +9,9 @@ final _notifierProvider = StateNotifierProvider BucketSortNotifier(), ); -class BucketSortPage extends StatefulWidget { +class BucketSortPage extends StatelessWidget { const BucketSortPage({super.key}); - @override - State createState() => _BucketSortPageState(); -} - -class _BucketSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.bucketSort); From a562d54bd48a1bc96f4e79041287fa870ef2d5f8 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:51:26 +0300 Subject: [PATCH 082/107] convert StatefulWidget to StatelessWidget --- .../sorting/counting/view/counting_sort_page.dart | 8 +------- lib/features/sorting/heap/view/heap_sort_page.dart | 8 +------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/lib/features/sorting/counting/view/counting_sort_page.dart b/lib/features/sorting/counting/view/counting_sort_page.dart index 2fc7574..14879fd 100644 --- a/lib/features/sorting/counting/view/counting_sort_page.dart +++ b/lib/features/sorting/counting/view/counting_sort_page.dart @@ -9,15 +9,9 @@ final _notifierProvider = StateNotifierProvider CountingSortNotifier(), ); -class CountingSortPage extends StatefulWidget { +class CountingSortPage extends StatelessWidget { const CountingSortPage({super.key}); - @override - State createState() => _CountingSortPageState(); -} - -class _CountingSortPageState extends State { - @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.countingSort); diff --git a/lib/features/sorting/heap/view/heap_sort_page.dart b/lib/features/sorting/heap/view/heap_sort_page.dart index 3743911..cc7de2d 100644 --- a/lib/features/sorting/heap/view/heap_sort_page.dart +++ b/lib/features/sorting/heap/view/heap_sort_page.dart @@ -9,15 +9,9 @@ final _notifierProvider = StateNotifierProvider HeapSortNotifier(), ); -class HeapSortPage extends StatefulWidget { +class HeapSortPage extends StatelessWidget { const HeapSortPage({super.key}); - @override - State createState() => _HeapSortPageState(); -} - -class _HeapSortPageState extends State { - @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.heapSort); From cdf4692ff956d791923706c7be2fdb2db4a6fb3f Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:51:30 +0300 Subject: [PATCH 083/107] convert StatefulWidget to StatelessWidget --- .../sorting/insertion/view/insertion_sort_page.dart | 7 +------ lib/features/sorting/merge/view/merge_sort_page.dart | 8 +------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/lib/features/sorting/insertion/view/insertion_sort_page.dart b/lib/features/sorting/insertion/view/insertion_sort_page.dart index 712bc59..b0fd495 100644 --- a/lib/features/sorting/insertion/view/insertion_sort_page.dart +++ b/lib/features/sorting/insertion/view/insertion_sort_page.dart @@ -9,14 +9,9 @@ final _notifierProvider = StateNotifierProvider InsertionSortNotifier(), ); -class InsertionSortPage extends StatefulWidget { +class InsertionSortPage extends StatelessWidget { const InsertionSortPage({super.key}); - @override - State createState() => _InsertionSortPageState(); -} - -class _InsertionSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.insertionSort); diff --git a/lib/features/sorting/merge/view/merge_sort_page.dart b/lib/features/sorting/merge/view/merge_sort_page.dart index 1b1f5c6..bb11e68 100644 --- a/lib/features/sorting/merge/view/merge_sort_page.dart +++ b/lib/features/sorting/merge/view/merge_sort_page.dart @@ -9,15 +9,9 @@ final _notifierProvider = StateNotifierProvider MergeSortNotifier(), ); -class MergeSortPage extends StatefulWidget { +class MergeSortPage extends StatelessWidget { const MergeSortPage({super.key}); - @override - State createState() => _MergeSortPageState(); -} - -class _MergeSortPageState extends State { - @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.mergeSort); From 7a218ae43de1dfc7854c2b3027e83da5585a5bb7 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:51:33 +0300 Subject: [PATCH 084/107] convert StatefulWidget to StatelessWidget --- lib/features/sorting/quick/view/quick_sort_page.dart | 7 +------ lib/features/sorting/radix/view/radix_sort_page.dart | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/features/sorting/quick/view/quick_sort_page.dart b/lib/features/sorting/quick/view/quick_sort_page.dart index d59d807..511876e 100644 --- a/lib/features/sorting/quick/view/quick_sort_page.dart +++ b/lib/features/sorting/quick/view/quick_sort_page.dart @@ -9,14 +9,9 @@ final _notifierProvider = StateNotifierProvider QuickSortNotifier(), ); -class QuickSortPage extends StatefulWidget { +class QuickSortPage extends StatelessWidget { const QuickSortPage({super.key}); - @override - State createState() => _QuickSortPageState(); -} - -class _QuickSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.quickSort); diff --git a/lib/features/sorting/radix/view/radix_sort_page.dart b/lib/features/sorting/radix/view/radix_sort_page.dart index dc1978a..39fa6db 100644 --- a/lib/features/sorting/radix/view/radix_sort_page.dart +++ b/lib/features/sorting/radix/view/radix_sort_page.dart @@ -9,14 +9,9 @@ final _notifierProvider = StateNotifierProvider RadixSortNotifier(), ); -class RadixSortPage extends StatefulWidget { +class RadixSortPage extends StatelessWidget { const RadixSortPage({super.key}); - @override - State createState() => _RadixSortPageState(); -} - -class _RadixSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.radixSort); From bd3d5f32dc8948f2627048b31bf58effbb80c04c Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:51:42 +0300 Subject: [PATCH 085/107] convert StatefulWidget to StatelessWidget --- .../sorting/selection/view/selection_sort_page.dart | 7 +------ lib/features/sorting/shell/view/shell_sort_page.dart | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/lib/features/sorting/selection/view/selection_sort_page.dart b/lib/features/sorting/selection/view/selection_sort_page.dart index 7be7254..d4b27af 100644 --- a/lib/features/sorting/selection/view/selection_sort_page.dart +++ b/lib/features/sorting/selection/view/selection_sort_page.dart @@ -9,14 +9,9 @@ final _notifierProvider = StateNotifierProvider SelectionSortNotifier(), ); -class SelectionSortPage extends StatefulWidget { +class SelectionSortPage extends StatelessWidget { const SelectionSortPage({super.key}); - @override - State createState() => _SelectionSortPageState(); -} - -class _SelectionSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider,title: StringsManager.selectionSort); diff --git a/lib/features/sorting/shell/view/shell_sort_page.dart b/lib/features/sorting/shell/view/shell_sort_page.dart index 46a887e..298e394 100644 --- a/lib/features/sorting/shell/view/shell_sort_page.dart +++ b/lib/features/sorting/shell/view/shell_sort_page.dart @@ -9,14 +9,9 @@ final _notifierProvider = StateNotifierProvider ShellSortNotifier(), ); -class ShellSortPage extends StatefulWidget { +class ShellSortPage extends StatelessWidget { const ShellSortPage({super.key}); - @override - State createState() => _ShellSortPageState(); -} - -class _ShellSortPageState extends State { @override Widget build(BuildContext context) { return SortingPage(instance: _notifierProvider, title: StringsManager.shellSort); From c1a53ef4e3b74de4fc117ecdc91bbb0c673c2170 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:52:10 +0300 Subject: [PATCH 086/107] add some low level files for android --- android/.gitignore | 3 ++- android/app/src/main/AndroidManifest.xml | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/android/.gitignore b/android/.gitignore index 6f56801..be3943c 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,9 +5,10 @@ gradle-wrapper.jar /gradlew.bat /local.properties GeneratedPluginRegistrant.java +.cxx/ # Remember to never publicly share your keystore. -# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +# See https://flutter.dev/to/reference-keystore key.properties **/*.keystore **/*.jks diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f6cc2c8..b0a2f84 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ Date: Tue, 26 Aug 2025 18:52:12 +0300 Subject: [PATCH 087/107] add some low level files for android --- android/app/build.gradle | 58 ---------------------------------------- android/build.gradle | 18 ------------- 2 files changed, 76 deletions(-) delete mode 100644 android/app/build.gradle delete mode 100644 android/build.gradle diff --git a/android/app/build.gradle b/android/app/build.gradle deleted file mode 100644 index f1cb206..0000000 --- a/android/app/build.gradle +++ /dev/null @@ -1,58 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file("local.properties") -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader("UTF-8") { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty("flutter.versionCode") -if (flutterVersionCode == null) { - flutterVersionCode = "1" -} - -def flutterVersionName = localProperties.getProperty("flutter.versionName") -if (flutterVersionName == null) { - flutterVersionName = "1.0" -} - -android { - namespace = "com.example.algorithm_visualizer" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.algorithm_visualizer" - // You can update the following values to match your application needs. - // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutterVersionCode.toInteger() - versionName = flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.debug - } - } -} - -flutter { - source = "../.." -} diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index d2ffbff..0000000 --- a/android/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = "../build" -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} From 2e59bb57a6b4fa636ea6824d0e6df08a0abc9adf Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:52:13 +0300 Subject: [PATCH 088/107] add some low level files for android --- android/app/build.gradle.kts | 44 ++++++++++++++++++++++++++++++++++++ android/build.gradle.kts | 21 +++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 android/app/build.gradle.kts create mode 100644 android/build.gradle.kts diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 0000000..84922bf --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.example.algorithm_visualizer" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.algorithm_visualizer" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 0000000..89176ef --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,21 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} From 4781e7c7f65ca03798bbcf30261df35edea316d7 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:52:15 +0300 Subject: [PATCH 089/107] add some low level files for android --- android/gradle.properties | 2 +- android/gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index 3b5b324..f018a61 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,3 +1,3 @@ -org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 7bb2df6..ac3b479 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip From 0b57adc3f29e10688aebfc279d5100b488b3c73a Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:52:17 +0300 Subject: [PATCH 090/107] add some low level files for android --- .../algorithm_visualizer/MainActivity.kt | 2 +- android/settings.gradle | 25 ------------------- 2 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 android/settings.gradle diff --git a/android/app/src/main/kotlin/com/example/algorithm_visualizer/MainActivity.kt b/android/app/src/main/kotlin/com/example/algorithm_visualizer/MainActivity.kt index ab74996..1ee9bf9 100644 --- a/android/app/src/main/kotlin/com/example/algorithm_visualizer/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/algorithm_visualizer/MainActivity.kt @@ -2,4 +2,4 @@ package com.example.algorithm_visualizer import io.flutter.embedding.android.FlutterActivity -class MainActivity: FlutterActivity() +class MainActivity : FlutterActivity() diff --git a/android/settings.gradle b/android/settings.gradle deleted file mode 100644 index 536165d..0000000 --- a/android/settings.gradle +++ /dev/null @@ -1,25 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.3.0" apply false - id "org.jetbrains.kotlin.android" version "1.7.10" apply false -} - -include ":app" From e0a994260db6522f92cd861b988988405c344a0f Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 18:52:18 +0300 Subject: [PATCH 091/107] add some low level files for android --- android/settings.gradle.kts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 android/settings.gradle.kts diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 0000000..ab39a10 --- /dev/null +++ b/android/settings.gradle.kts @@ -0,0 +1,25 @@ +pluginManagement { + val flutterSdkPath = run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.7.3" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false +} + +include(":app") From 351261b572e54df152c0a523b8500a13e72f582e Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 19:08:41 +0300 Subject: [PATCH 092/107] handle the height of sorting item --- .../sorting/base/view_model/sorting_notifier.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index d2d769f..eecce75 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -59,12 +59,12 @@ abstract class SortingNotifier extends StateNotifier { ) { final value = (calculateMaxListItemHeight(context) / size) * (itemIndex + 1); final perc = selectedAlgorithmsLength == 1 - ? 1 - : selectedAlgorithmsLength <= 3 + ? 0.95 + : selectedAlgorithmsLength <= 2 ? 0.9 - : selectedAlgorithmsLength <= 6 + : selectedAlgorithmsLength <= 4 ? 0.8 - : selectedAlgorithmsLength <= 9 + : selectedAlgorithmsLength <= 6 ? 0.7 : 0.6; return value.h / selectedAlgorithmsLength * perc; @@ -105,11 +105,11 @@ abstract class SortingNotifier extends StateNotifier { } Future cancelSorting() async { - await _cancelableSort?.cancel(); + await _cancelableSort?.cancel(); } Future stopSorting() async { - await _cancelableSort?.cancel(); + await _cancelableSort?.cancel(); if (_getOperation == SortingEnum.played) _setOperation = SortingEnum.stopped; } From a8744743f4ed20a3538ca707997003a789262f52 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 20:02:29 +0300 Subject: [PATCH 093/107] handle popup while search running --- lib/features/searching/view/grid_page.dart | 32 ++++--- .../searching/view_model/grid_notifier.dart | 96 ++++++++++++++++--- 2 files changed, 103 insertions(+), 25 deletions(-) diff --git a/lib/features/searching/view/grid_page.dart b/lib/features/searching/view/grid_page.dart index 7e233be..2e21d1b 100644 --- a/lib/features/searching/view/grid_page.dart +++ b/lib/features/searching/view/grid_page.dart @@ -25,21 +25,29 @@ BorderDirectional _thineVerticalBorder() => BorderDirectional( bottom: _borderSide(true), ); -class SearchingPage extends StatelessWidget { +class SearchingPage extends ConsumerWidget { const SearchingPage({super.key}); @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const _ControlButtons(), - centerTitle: true, - ), - body: SafeArea( - child: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return _BuildLayout(constraints.biggest); - }, + Widget build(BuildContext context, WidgetRef ref) { + return PopScope( + onPopInvokedWithResult: (didPop, result) async { + if (didPop) { + await ref.read(_gridNotifierProvider.notifier).cancelSearching(); + ref.invalidate(_gridNotifierProvider); + } + }, + child: Scaffold( + appBar: AppBar( + title: const _ControlButtons(), + centerTitle: true, + ), + body: SafeArea( + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return _BuildLayout(constraints.biggest); + }, + ), ), ), ); diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index bcd1171..b89d3d6 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -1,5 +1,6 @@ import 'dart:collection'; import 'dart:math'; +import 'package:async/async.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -25,16 +26,22 @@ class SearchingNotifier extends StateNotifier { final double _gridSquareSize = 25; static const Duration scaleAppearDurationForWall = Duration(milliseconds: 700); static const Duration clearDuration = Duration(microseconds: 1); - static const Duration drawFindingPathDuration = Duration(milliseconds: 2); - static const Duration drawSearcherDuration = Duration(milliseconds: 5); + static const Duration drawSearcherDuration = Duration(milliseconds: 25); static const Duration mazeDuration = Duration(milliseconds: 10); int tapDownIndex = -1; GridStatus tapDownGridStatus = GridStatus.empty; + CancelableOperation? _cancelableSearch; /// [_isBuildingGrid] if build maze or search or even clear grid bool _isBuildingGrid = false; bool _isSearched = false; + + Future cancelSearching() async { + await _cancelableSearch?.cancel(); + // _cancelableSearch=null; + } + void updateGridLayout(Size size) { final screenWidth = size.width; final screenHeight = size.height; @@ -129,6 +136,19 @@ class SearchingNotifier extends StateNotifier { if (!clearAnyway && _isBuildingGrid) return; _isBuildingGrid = true; + await cancelSearching(); + + _cancelableSearch = + CancelableOperation.fromFuture(_clearTheGridFun(clearAnyway: clearAnyway, keepWall: keepWall)); + + try { + await _cancelableSearch?.value; + } catch (e) { + debugPrint("something wrong with clearTheGrid: $e"); + } + } + + Future _clearTheGridFun({bool keepWall = false, bool clearAnyway = false}) async { await _clearTheGrid(addState: state, keepWall: keepWall); state = state.copyWith(currentTappedIndex: -1); @@ -138,20 +158,11 @@ class SearchingNotifier extends StateNotifier { } void onPointerDownOnGrid(PointerDownEvent event) { - if (_isBuildingGrid) return; - _isBuildingGrid = true; - tapDownIndex = _getIndex(addState: state, localPosition: event.localPosition); - _isBuildingGrid = false; } void onPointerUpOnGrid(PointerUpEvent event) { - if (_isBuildingGrid) return; - _isBuildingGrid = true; - tapDownIndex = -1; - - _isBuildingGrid = false; } void onFingerMoveOnGrid(PointerMoveEvent event) { @@ -211,7 +222,18 @@ class SearchingNotifier extends StateNotifier { Future performBFS() async { if (_isBuildingGrid) return; _isBuildingGrid = true; + await cancelSearching(); + _cancelableSearch = CancelableOperation.fromFuture(_performBFSFun()); + + try { + await _cancelableSearch?.value; + } catch (e) { + debugPrint("something wrong with performBFS: $e"); + } + } + + Future _performBFSFun() async { if (_isSearched) await clearTheGrid(keepWall: true, clearAnyway: true); final gridData = List.from(state.gridData); @@ -284,6 +306,18 @@ class SearchingNotifier extends StateNotifier { Future performDijkstra() async { if (_isBuildingGrid) return; _isBuildingGrid = true; + await cancelSearching(); + + _cancelableSearch = CancelableOperation.fromFuture(_performDijkstraFun()); + + try { + await _cancelableSearch?.value; + } catch (e) { + debugPrint("something wrong with performDijkstra: $e"); + } + } + + Future _performDijkstraFun() async { if (_isSearched) await clearTheGrid(keepWall: true, clearAnyway: true); final gridData = List.from(state.gridData); @@ -385,6 +419,18 @@ class SearchingNotifier extends StateNotifier { Future performAStar() async { if (_isBuildingGrid) return; _isBuildingGrid = true; + await cancelSearching(); + + _cancelableSearch = CancelableOperation.fromFuture(_performAStarFun()); + + try { + await _cancelableSearch?.value; + } catch (e) { + debugPrint("something wrong with performAStar: $e"); + } + } + + Future _performAStarFun() async { if (_isSearched) await clearTheGrid(keepWall: true, clearAnyway: true); final gridData = List.from(state.gridData); @@ -475,9 +521,21 @@ class SearchingNotifier extends StateNotifier { return ((x1 - x2).abs() + (y1 - y2).abs()).toDouble(); } - void generateRecursiveBacktrackerMaze() async { + Future generateRecursiveBacktrackerMaze() async { if (_isBuildingGrid) return; _isBuildingGrid = true; + await cancelSearching(); + + _cancelableSearch = CancelableOperation.fromFuture(_generateRecursiveBacktrackerMazeFun()); + + try { + await _cancelableSearch?.value; + } catch (e) { + debugPrint("something wrong with generateRecursiveBacktrackerMaze: $e"); + } + } + + Future _generateRecursiveBacktrackerMazeFun() async { if (_isSearched) await clearTheGrid(clearAnyway: true); final gridData = List.from(state.gridData); @@ -583,10 +641,22 @@ class SearchingNotifier extends StateNotifier { return row > 1 && col > 1 && row < state.rowMainAxisCount - 2 && col < state.columnCrossAxisCount - 2; } - // Recursive Division Maze Generation Future generateRecursiveDivisionMaze() async { if (_isBuildingGrid) return; _isBuildingGrid = true; + await cancelSearching(); + + _cancelableSearch = CancelableOperation.fromFuture(_generateRecursiveDivisionMazeFun()); + + try { + await _cancelableSearch?.value; + } catch (e) { + debugPrint("something wrong with generateRecursiveDivisionMaze: $e"); + } + } + + // Recursive Division Maze Generation + Future _generateRecursiveDivisionMazeFun() async { if (_isSearched) await clearTheGrid(clearAnyway: true); final gridData = List.from(state.gridData); From 2b05f02833b131d0d21378d557c0e2f498f20306 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 21:09:01 +0300 Subject: [PATCH 094/107] fix right border glitch --- lib/features/searching/view_model/grid_notifier.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index b89d3d6..8f95773 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -169,7 +169,16 @@ class SearchingNotifier extends StateNotifier { if (_isBuildingGrid) return; _isBuildingGrid = true; - final index = _getIndex(addState: state, localPosition: event.localPosition); + int index = _getIndex(addState: state, localPosition: event.localPosition); + + /// when you try to draw on the right border if you make the arrow closly to the border it will draw the wall in the left side (the next index) + /// those two lines to prevent that + final calcIndex = (event.localPosition.dx / _gridSquareSize).floor(); + if (calcIndex != 0 && + calcIndex % state.columnCrossAxisCount == 0 && + index % state.columnCrossAxisCount == 0) { + index--; + } /// to handle multi calls from listener widget if (index == state.currentTappedIndex) { From 61aae5102a7eabe050ac393d2f61e3058c17dba6 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Tue, 26 Aug 2025 21:13:26 +0300 Subject: [PATCH 095/107] remove adapt font size --- lib/core/material_app/my_app.dart | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/lib/core/material_app/my_app.dart b/lib/core/material_app/my_app.dart index 8571a8f..0fba7c5 100644 --- a/lib/core/material_app/my_app.dart +++ b/lib/core/material_app/my_app.dart @@ -14,22 +14,12 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - final defaultSize = MediaQuery.sizeOf(context); 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) { @@ -40,9 +30,8 @@ class MyApp extends StatelessWidget { return LayoutBuilder( builder: (context, constraints) { - final padding = constraints.maxWidth < 450 - ? 0.0 - : ((constraints.maxWidth - defaultSize.width) / 2.3); + final padding = + constraints.maxWidth < 450 ? 0.0 : ((constraints.maxWidth - defaultSize.width) / 2.3); return SystemOverlay( isBlackTheme: isDarkMode, @@ -63,12 +52,9 @@ class MyApp extends StatelessWidget { themeMode: themeMode, debugShowCheckedModeBanner: false, routerDelegate: AppRoutes.router.routerDelegate, - backButtonDispatcher: - AppRoutes.router.backButtonDispatcher, - routeInformationParser: - AppRoutes.router.routeInformationParser, - routeInformationProvider: - AppRoutes.router.routeInformationProvider, + backButtonDispatcher: AppRoutes.router.backButtonDispatcher, + routeInformationParser: AppRoutes.router.routeInformationParser, + routeInformationProvider: AppRoutes.router.routeInformationProvider, ), ), ), From 516814a5c59eb57f502195e13736c2f1678e1e97 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:39:38 +0300 Subject: [PATCH 096/107] reformat the code --- .../sorting/bucket/view_model/bucket_sort_notifier.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart b/lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart index 38a5bc7..b184e72 100644 --- a/lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart +++ b/lib/features/sorting/bucket/view_model/bucket_sort_notifier.dart @@ -15,21 +15,17 @@ class BucketSortNotifier extends SortingNotifier { int maxVal = arr.reduce((a, b) => a > b ? a : b); int minVal = arr.reduce((a, b) => a < b ? a : b); - // Decide number of buckets (basic choice = n) int bucketCount = n; double bucketRange = (maxVal - minVal + 1) / bucketCount; - // 1. Create buckets final buckets = List.generate(bucketCount, (_) => []); - // 2. Scatter: put array elements into buckets for (int value in arr) { int bucketIndex = ((value - minVal) / bucketRange).floor(); if (bucketIndex >= bucketCount) bucketIndex = bucketCount - 1; buckets[bucketIndex].add(value); } - // 3. Sort each bucket (Insertion Sort) for (var bucket in buckets) { for (int i = 1; i < bucket.length; i++) { int key = bucket[i]; @@ -42,7 +38,6 @@ class BucketSortNotifier extends SortingNotifier { } } - // 4. Gather: merge buckets back into arr int index = 0; for (var bucket in buckets) { for (int value in bucket) { @@ -59,7 +54,6 @@ class BucketSortNotifier extends SortingNotifier { } } - // Mark all sorted at the end steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); return SortingResult(sortedValues: arr, steps: steps); From b85b01fed2e52b2812dfccb2484218be7d8d4f67 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:39:42 +0300 Subject: [PATCH 097/107] reformat the code --- .../searching/view_model/grid_notifier.dart | 40 ++++++++----------- .../view_model/counting_sort_notifier.dart | 10 +---- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/lib/features/searching/view_model/grid_notifier.dart b/lib/features/searching/view_model/grid_notifier.dart index 8f95773..5c63c64 100644 --- a/lib/features/searching/view_model/grid_notifier.dart +++ b/lib/features/searching/view_model/grid_notifier.dart @@ -269,10 +269,10 @@ class SearchingNotifier extends StateNotifier { const right = 1; final directions = [ - up, // up - down, // down - left, // left - right, // right + up, + down, + left, + right, ]; while (queue.isNotEmpty) { @@ -299,7 +299,7 @@ class SearchingNotifier extends StateNotifier { } } - // for marking the current grid as visited + /// for marking the current grid as visited if (gridData[currentIndex] != GridStatus.startPoint && gridData[currentIndex] != GridStatus.targetPoint) { gridData[currentIndex] = GridStatus.searcher; @@ -345,7 +345,6 @@ class SearchingNotifier extends StateNotifier { distance[startPointIndex] = 0; - // priority queue to get the minimum distance vertex final pq = PriorityQueue((a, b) => distance[a].compareTo(distance[b])); pq.add(startPointIndex); @@ -359,10 +358,9 @@ class SearchingNotifier extends StateNotifier { while (pq.isNotEmpty) { final currentIndex = pq.removeFirst(); - // Mark the current node as visited + /// mark the current node as visited visited[currentIndex] = true; - // If we reached the target, we trace back the path if (currentIndex == targetPointIndex) { _tracePath(previous, currentIndex); _isBuildingGrid = false; @@ -377,14 +375,15 @@ class SearchingNotifier extends StateNotifier { continue; } - final tentativeDistance = distance[currentIndex] + 1; // Assume weight of 1 for each move + final tentativeDistance = distance[currentIndex] + 1; + + /// assume weight of 1 for each move if (tentativeDistance < distance[neighborIndex]) { distance[neighborIndex] = tentativeDistance; previous[neighborIndex] = currentIndex; pq.add(neighborIndex); - // Visualize the search process if (gridData[neighborIndex] != GridStatus.startPoint && gridData[neighborIndex] != GridStatus.targetPoint) { gridData[neighborIndex] = GridStatus.searcher; @@ -403,8 +402,8 @@ class SearchingNotifier extends StateNotifier { final isFirstLeftInRowIndex = neighborIndex % cross == 0; final isEndRightInRowIndex = (neighborIndex + 1) % cross == 0; - if (direction == 1 && isFirstLeftInRowIndex) return false; // avoid exiting the boundaries - if (direction == -1 && isEndRightInRowIndex) return false; // avoid exiting the boundaries + if (direction == 1 && isFirstLeftInRowIndex) return false; + if (direction == -1 && isEndRightInRowIndex) return false; return neighborIndex >= 0 && neighborIndex < gridData.length && @@ -506,7 +505,6 @@ class SearchingNotifier extends StateNotifier { pq.add(neighborIndex); } - // visualize if (gridData[neighborIndex] != GridStatus.startPoint && gridData[neighborIndex] != GridStatus.targetPoint) { gridData[neighborIndex] = GridStatus.searcher; @@ -521,7 +519,6 @@ class SearchingNotifier extends StateNotifier { } double _heuristic(int index, int targetIndex, int cross) { - // Manhattan distance final x1 = index % cross; final y1 = index ~/ cross; final x2 = targetIndex % cross; @@ -549,17 +546,15 @@ class SearchingNotifier extends StateNotifier { final gridData = List.from(state.gridData); - // Clear the maze but keep start and target points + /// clear the maze but keep start and target points for (int i = 0; i < gridData.length; i++) { if (gridData[i] != GridStatus.startPoint && gridData[i] != GridStatus.targetPoint) { gridData[i] = GridStatus.empty; } } - // 🔹 Draw outer border walls await _drawBorders(gridData); - // 🔹 Force the second border inside as a corridor (always empty) _makeSafeCorridor(gridData); final random = Random(); @@ -574,7 +569,6 @@ class SearchingNotifier extends StateNotifier { } Future _drawBorders(List gridData) async { - // Top & bottom rows for (int c = 0; c < state.columnCrossAxisCount; c++) { for (final r in [0, state.rowMainAxisCount - 1]) { final idx = r * state.columnCrossAxisCount + c; @@ -586,7 +580,6 @@ class SearchingNotifier extends StateNotifier { } } - // Left & right columns for (int r = 1; r < state.rowMainAxisCount - 1; r++) { for (final c in [0, state.columnCrossAxisCount - 1]) { final idx = r * state.columnCrossAxisCount + c; @@ -664,7 +657,6 @@ class SearchingNotifier extends StateNotifier { } } - // Recursive Division Maze Generation Future _generateRecursiveDivisionMazeFun() async { if (_isSearched) await clearTheGrid(clearAnyway: true); @@ -707,7 +699,7 @@ class SearchingNotifier extends StateNotifier { final horizontal = random.nextBool(); if (horizontal) { - // Horizontal wall + /// horizontal wall int wallRow = row + (random.nextInt(height ~/ 2)) * 2 + 1; int passageCol = col + (random.nextInt(width ~/ 2)) * 2; @@ -717,14 +709,14 @@ class SearchingNotifier extends StateNotifier { gridData[wallRow * state.columnCrossAxisCount + c] != GridStatus.targetPoint) { gridData[wallRow * state.columnCrossAxisCount + c] = GridStatus.wall; state = state.copyWith(gridData: List.from(gridData)); - await Future.delayed(mazeDuration); // 🔹 Delay for each cell + await Future.delayed(mazeDuration); } } await _divide(row, col, wallRow - row, width, gridData); await _divide(wallRow + 1, col, row + height - wallRow - 1, width, gridData); } else { - // Vertical wall + /// vertical wall int wallCol = col + (random.nextInt(width ~/ 2)) * 2 + 1; int passageRow = row + (random.nextInt(height ~/ 2)) * 2; @@ -734,7 +726,7 @@ class SearchingNotifier extends StateNotifier { gridData[r * state.columnCrossAxisCount + wallCol] != GridStatus.targetPoint) { gridData[r * state.columnCrossAxisCount + wallCol] = GridStatus.wall; state = state.copyWith(gridData: List.from(gridData)); - await Future.delayed(mazeDuration); // 🔹 Delay for each cell + await Future.delayed(mazeDuration); } } diff --git a/lib/features/sorting/counting/view_model/counting_sort_notifier.dart b/lib/features/sorting/counting/view_model/counting_sort_notifier.dart index b7210d9..267a0b1 100644 --- a/lib/features/sorting/counting/view_model/counting_sort_notifier.dart +++ b/lib/features/sorting/counting/view_model/counting_sort_notifier.dart @@ -7,32 +7,25 @@ class CountingSortNotifier extends SortingNotifier { final steps = []; final arr = List.from(values); - if (arr.isEmpty) { - return SortingResult(sortedValues: arr, steps: steps); - } + if (arr.isEmpty) return SortingResult(sortedValues: arr, steps: steps); - // 1. Find range of input values int maxVal = arr.reduce((a, b) => a > b ? a : b); int minVal = arr.reduce((a, b) => a < b ? a : b); int range = maxVal - minVal + 1; - // 2. Frequency array final count = List.filled(range, 0); for (int i = 0; i < arr.length; i++) { count[arr[i] - minVal]++; } - // 3. Build the sorted array int index = 0; for (int i = 0; i < range; i++) { while (count[i] > 0) { int correctValue = i + minVal; if (arr[index] != correctValue) { - // Find where the correctValue currently is int targetIndex = arr.indexOf(correctValue, index); - // Log swap steps.add(SortingStep(index1: index, index2: targetIndex, action: SortingStatus.swapping)); arr.swap(index, targetIndex); steps.add(SortingStep(index1: index, index2: targetIndex, action: SortingStatus.swapped)); @@ -43,7 +36,6 @@ class CountingSortNotifier extends SortingNotifier { } } - // Mark all sorted at the end steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); return SortingResult(sortedValues: arr, steps: steps); From faf3eb6a997ae7957f1b3da5d47637e410b4e5b2 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:39:45 +0300 Subject: [PATCH 098/107] reformat the code --- lib/features/sorting/heap/view_model/heap_sort_notifier.dart | 3 --- lib/features/sorting/merge/view_model/merge_sort_notifier.dart | 2 -- 2 files changed, 5 deletions(-) diff --git a/lib/features/sorting/heap/view_model/heap_sort_notifier.dart b/lib/features/sorting/heap/view_model/heap_sort_notifier.dart index fede98e..b533775 100644 --- a/lib/features/sorting/heap/view_model/heap_sort_notifier.dart +++ b/lib/features/sorting/heap/view_model/heap_sort_notifier.dart @@ -40,12 +40,10 @@ class HeapSortNotifier extends SortingNotifier { void heapSort() { int n = arr.length; - // Build max heap for (int i = (n ~/ 2) - 1; i >= 0; i--) { heapify(n, i); } - // Extract elements one by one for (int i = n - 1; i > 0; i--) { steps.add(SortingStep(index1: 0, index2: i, action: SortingStatus.swapping)); arr.swap(0, i); @@ -56,7 +54,6 @@ class HeapSortNotifier extends SortingNotifier { } if (arr.isNotEmpty) heapSort(); - // Mark the first element sorted steps.add(SortingStep(index1: 0, index2: 0, action: SortingStatus.sorted)); return SortingResult(sortedValues: arr, steps: steps); diff --git a/lib/features/sorting/merge/view_model/merge_sort_notifier.dart b/lib/features/sorting/merge/view_model/merge_sort_notifier.dart index 3c6e8bf..7fc2e0d 100644 --- a/lib/features/sorting/merge/view_model/merge_sort_notifier.dart +++ b/lib/features/sorting/merge/view_model/merge_sort_notifier.dart @@ -12,14 +12,12 @@ class MergeSortNotifier extends SortingNotifier { int j = mid + 1; while (i <= mid && j <= right) { - // Compare current elements steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.compared)); steps.add(SortingStep(index1: i, index2: j, action: SortingStatus.unSorted)); if (arr[i] <= arr[j]) { i++; } else { - // Bubble arr[j] left until it reaches position i int k = j; while (k > i) { steps.add(SortingStep(index1: k, index2: k - 1, action: SortingStatus.swapping)); From a34160a5ce540bccc8bca9c24044fa4c799ed776 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:39:46 +0300 Subject: [PATCH 099/107] reformat the code --- .../sorting/quick/view_model/quick_sort_notifier.dart | 2 -- .../sorting/radix/view_model/radix_sort_notifier.dart | 6 ------ 2 files changed, 8 deletions(-) diff --git a/lib/features/sorting/quick/view_model/quick_sort_notifier.dart b/lib/features/sorting/quick/view_model/quick_sort_notifier.dart index 529b0cd..761fdde 100644 --- a/lib/features/sorting/quick/view_model/quick_sort_notifier.dart +++ b/lib/features/sorting/quick/view_model/quick_sort_notifier.dart @@ -12,7 +12,6 @@ class QuickSortNotifier extends SortingNotifier { int i = low - 1; for (int j = low; j < high; j++) { - // Compare arr[j] with pivot steps.add(SortingStep(index1: j, index2: high, action: SortingStatus.compared)); steps.add(SortingStep(index1: j, index2: high, action: SortingStatus.unSorted)); @@ -26,7 +25,6 @@ class QuickSortNotifier extends SortingNotifier { } } - // Place pivot in correct position if (i + 1 != high) { steps.add(SortingStep(index1: i + 1, index2: high, action: SortingStatus.swapping)); arr.swap(i + 1, high); diff --git a/lib/features/sorting/radix/view_model/radix_sort_notifier.dart b/lib/features/sorting/radix/view_model/radix_sort_notifier.dart index c80ab0e..c038c53 100644 --- a/lib/features/sorting/radix/view_model/radix_sort_notifier.dart +++ b/lib/features/sorting/radix/view_model/radix_sort_notifier.dart @@ -13,12 +13,10 @@ class RadixSortNotifier extends SortingNotifier { int maxVal = arr.reduce((a, b) => a > b ? a : b); - // Perform counting sort for every digit for (int exp = 1; maxVal ~/ exp > 0; exp *= 10) { _countingSortByDigit(arr, exp, steps); } - // Mark all as sorted steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); return SortingResult(sortedValues: arr, steps: steps); @@ -29,25 +27,21 @@ class RadixSortNotifier extends SortingNotifier { List output = List.filled(n, 0); List count = List.filled(10, 0); - // 1. Count occurrences of digits for (int i = 0; i < n; i++) { int digit = (arr[i] ~/ exp) % 10; count[digit]++; } - // 2. Compute prefix sums for (int i = 1; i < 10; i++) { count[i] += count[i - 1]; } - // 3. Build output array (stable order, so go from right to left) for (int i = n - 1; i >= 0; i--) { int digit = (arr[i] ~/ exp) % 10; output[count[digit] - 1] = arr[i]; count[digit]--; } - // 4. Copy back to arr + log steps for (int i = 0; i < n; i++) { if (arr[i] != output[i]) { int oldIndex = arr.indexOf(output[i], i); From 01db55f270d151686080ba727e30dd5457f5e770 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:39:48 +0300 Subject: [PATCH 100/107] reformat the code --- lib/features/searching/widgets/searcher_grid.dart | 2 -- .../sorting/selection/view_model/selection_sort_notifier.dart | 1 - 2 files changed, 3 deletions(-) diff --git a/lib/features/searching/widgets/searcher_grid.dart b/lib/features/searching/widgets/searcher_grid.dart index ddda9fa..bcaf3b7 100644 --- a/lib/features/searching/widgets/searcher_grid.dart +++ b/lib/features/searching/widgets/searcher_grid.dart @@ -26,7 +26,6 @@ class _SearcherGridState extends State<_SearcherGrid> with SingleTickerProviderS vsync: this, ); - // Define the scale animation from 0.1 to 1.2 then back to 1.0 _scaleAnimation = TweenSequence([ TweenSequenceItem(tween: Tween(begin: 0.1, end: 1.4), weight: 60), TweenSequenceItem(tween: Tween(begin: 1.4, end: 1.0), weight: 40), @@ -37,7 +36,6 @@ class _SearcherGridState extends State<_SearcherGrid> with SingleTickerProviderS ), ); - // Define the color animation _colorAnimation = TweenSequence([ TweenSequenceItem(tween: ColorTween(begin: startColor, end: mediumColor), weight: 40), TweenSequenceItem(tween: ColorTween(begin: mediumColor, end: finishedSearcherColor), weight: 60), diff --git a/lib/features/sorting/selection/view_model/selection_sort_notifier.dart b/lib/features/sorting/selection/view_model/selection_sort_notifier.dart index ee7d69a..c2ceb98 100644 --- a/lib/features/sorting/selection/view_model/selection_sort_notifier.dart +++ b/lib/features/sorting/selection/view_model/selection_sort_notifier.dart @@ -15,7 +15,6 @@ class SelectionSortNotifier extends SortingNotifier { if (arr[j] < arr[minIndex]) { final previousIndex = minIndex; - // to reset action if (minIndex != i) { steps.add(SortingStep(index1: previousIndex, index2: previousIndex, action: SortingStatus.none)); } From 2d41143c838707d7b0a23e35395075be3c8d0462 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:39:49 +0300 Subject: [PATCH 101/107] reformat the code --- lib/features/sorting/base/helper/sorting_enums.dart | 13 ------------- .../shell/view_model/shell_sort_notifier.dart | 1 - 2 files changed, 14 deletions(-) diff --git a/lib/features/sorting/base/helper/sorting_enums.dart b/lib/features/sorting/base/helper/sorting_enums.dart index 4f406c1..b68aedd 100644 --- a/lib/features/sorting/base/helper/sorting_enums.dart +++ b/lib/features/sorting/base/helper/sorting_enums.dart @@ -1,18 +1,5 @@ part of '../view_model/sorting_notifier.dart'; -enum SortingAlgorithm { - bubble, - selection, - insertion, - merge, - // quick, - // shell, - // heap, - // count, - // radix, - // bucket, -} - enum SortingEnum { played, stopped, none } enum SortingStatus { unSorted, compared, swapping, swapped, sorted, none } diff --git a/lib/features/sorting/shell/view_model/shell_sort_notifier.dart b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart index 2ba99e9..44ed082 100644 --- a/lib/features/sorting/shell/view_model/shell_sort_notifier.dart +++ b/lib/features/sorting/shell/view_model/shell_sort_notifier.dart @@ -27,7 +27,6 @@ class ShellSortNotifier extends SortingNotifier { } } - // Mark all sorted at the end steps.add(SortingStep(index1: arr.length - 1, index2: arr.length - 1, action: SortingStatus.sorted)); return SortingResult(sortedValues: arr, steps: steps); From ca82ad57e9d9c0539375565864e5a13eab055c84 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:39:51 +0300 Subject: [PATCH 102/107] reformat the code --- lib/features/sorting/base/view_model/sorting_notifier.dart | 7 +------ lib/features/sorting/base/view_model/sorting_state.dart | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/features/sorting/base/view_model/sorting_notifier.dart b/lib/features/sorting/base/view_model/sorting_notifier.dart index eecce75..8802656 100644 --- a/lib/features/sorting/base/view_model/sorting_notifier.dart +++ b/lib/features/sorting/base/view_model/sorting_notifier.dart @@ -15,7 +15,6 @@ abstract class SortingNotifier extends StateNotifier { _initializePositions(); } - // static double maxListItemHeight = 250.r; static double itemsPadding = 1.w; static const ThemeEnum swappingColor = ThemeEnum.redColor; static const ThemeEnum comparedColor = ThemeEnum.lightBlueColor; @@ -27,8 +26,6 @@ abstract class SortingNotifier extends StateNotifier { static const int _minSize = 10; static const Duration _defaultSpeedDuration = Duration(milliseconds: 300); - // static const Duration _maxSpeedDuration = Duration(milliseconds: 3000); - // static const Duration _minSpeedDuration = Duration(milliseconds: 20); CancelableOperation? _cancelableSort; @@ -40,14 +37,12 @@ abstract class SortingNotifier extends StateNotifier { final screenWidth = MediaQuery.of(context).size.width; final availableWidth = screenWidth - (itemsPadding * (size - 1)); - // Ensure a positive width return availableWidth / size > 0 ? availableWidth / size : 1.0; } static double calculateMaxListItemHeight(BuildContext context) { final screenHeight = MediaQuery.of(context).size.height * 0.65; - // Ensure a positive width return screenHeight > 0 ? screenHeight : 1.0; } @@ -194,7 +189,7 @@ abstract class SortingNotifier extends StateNotifier { state = state.copyWith(list: list); break; - // i don't want to make it green while sorting and mark all of them at once as green at the end + /// i don't want to make it green while sorting and mark all of them at once as green at the end case SortingStatus.sorted: case SortingStatus.none: list[step.index1] = list[step.index1].copyWith(sortedStatus: SortingStatus.none); diff --git a/lib/features/sorting/base/view_model/sorting_state.dart b/lib/features/sorting/base/view_model/sorting_state.dart index f6bf73d..5311605 100644 --- a/lib/features/sorting/base/view_model/sorting_state.dart +++ b/lib/features/sorting/base/view_model/sorting_state.dart @@ -19,7 +19,6 @@ class SortingNotifierState { Duration? swipeDuration, List? list, Map? positions, - List? selectedAlgorithms, SortingEnum? operationStatus, }) { return SortingNotifierState( From fe9600ed1485a823d51bf03b3ed0076688deea95 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:59:03 +0300 Subject: [PATCH 103/107] create FloatingAnimatedButton --- .../base/view/movable_animated_button.dart | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 lib/features/base/view/movable_animated_button.dart diff --git a/lib/features/base/view/movable_animated_button.dart b/lib/features/base/view/movable_animated_button.dart new file mode 100644 index 0000000..eb91a49 --- /dev/null +++ b/lib/features/base/view/movable_animated_button.dart @@ -0,0 +1,91 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +class FloatingAnimatedButton extends StatefulWidget { + final Widget child; + final Duration stepDuration; + + const FloatingAnimatedButton({ + super.key, + required this.child, + this.stepDuration = const Duration(seconds: 3), + }); + + @override + State createState() => _FloatingAnimatedButtonState(); +} + +class _FloatingAnimatedButtonState extends State with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _scale; + late Animation _offset; + + final Random _random = Random(); + double _currentScale = 1.0; + Offset _currentOffset = Offset.zero; + + @override + void initState() { + super.initState(); + + _controller = AnimationController(vsync: this); + + _setNewRandomAnimation(); + + // when one random animation finishes → schedule the next one + _controller.addStatusListener((status) { + if (status == AnimationStatus.completed) { + _currentScale = _scale.value; + _currentOffset = _offset.value; + _setNewRandomAnimation(); + } + }); + } + + void _setNewRandomAnimation() { + // generate new random target scale and offset + final newScale = 0.95 + _random.nextDouble() * 0.1; + final newOffset = Offset( + (_random.nextDouble() * 40 - 35) / 100, + (_random.nextDouble() * 40 - 35) / 100, + ); + + _scale = Tween( + begin: _currentScale, + end: newScale, + ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut)); + + _offset = Tween( + begin: _currentOffset, + end: newOffset, + ).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut)); + + _controller.duration = widget.stepDuration + Duration(milliseconds: _random.nextInt(2000)); + + _controller.reset(); + _controller.forward(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _controller, + builder: (_, __) { + return Transform.translate( + offset: _offset.value * 25, + child: Transform.scale( + scale: _scale.value, + child: widget.child, + ), + ); + }, + ); + } +} From 51e0300ea827438c4e0b1638540d5351c45f5142 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:59:19 +0300 Subject: [PATCH 104/107] create MovablePinsBackground --- lib/features/base/view/movable_pins.dart | 210 +++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 lib/features/base/view/movable_pins.dart diff --git a/lib/features/base/view/movable_pins.dart b/lib/features/base/view/movable_pins.dart new file mode 100644 index 0000000..322163d --- /dev/null +++ b/lib/features/base/view/movable_pins.dart @@ -0,0 +1,210 @@ +import 'dart:math'; + +import 'package:algorithm_visualizer/core/resources/theme_manager.dart'; +import 'package:flutter/material.dart'; + +class MovablePinsBackground extends StatefulWidget { + const MovablePinsBackground({this.pinColor = ThemeEnum.whiteD5Color, required this.child, super.key}); + final ThemeEnum pinColor; + final Widget child; + @override + State createState() => _MovablePinsBackgroundState(); +} + +class _MovablePinsBackgroundState extends State with SingleTickerProviderStateMixin { + late AnimationController _controller; + final List _particles = []; + final Random _random = Random(); + + /// 🔧 Adjustable parameters + double speedFactor = 0.3; + double densityFactor = 0.45; + final int maxPins = 150; + + @override + void initState() { + super.initState(); + _controller = AnimationController( + vsync: this, + duration: const Duration(hours: 1), + )..addListener(_update); + + _controller.repeat(); + } + + void _createParticles(Size size) { + if (_particles.isNotEmpty) return; + + final baseCount = (size.width * size.height / 2500).round(); + final count = (baseCount * densityFactor).round(); + + for (int i = 0; i < count; i++) { + _particles.add(Particle.random(_random, size, speedFactor)); + } + } + + void _update() { + final size = MediaQuery.of(context).size; + + setState(() { + for (int i = _particles.length - 1; i >= 0; i--) { + final p = _particles[i]; + p.randomWalk(); + p.update(); + + // remove if outside screen + if (!p.isInside(size)) { + _particles.removeAt(i); + _particles.add(Particle.random(_random, size, speedFactor)); + } + } + }); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + _createParticles(size); + + return GestureDetector( + // set max pins limit + + onTapDown: (d) { + setState(() { + // add new pin + _particles.add(Particle( + d.localPosition, + Offset((_random.nextDouble() * 2 - 1) * 0.5, (_random.nextDouble() * 2 - 1) * 0.5), + _random, + size, + speedFactor, + )); + + // if exceeded maxPins → remove the oldest one (index 0) + if (_particles.length > maxPins) { + _particles.removeAt(0); + } + }); + }, + onPanUpdate: (d) { + setState(() { + const influenceRadius = 100.0; // 👈 adjust how far the finger affects pins + for (var p in _particles) { + final distance = (p.position - d.localPosition).distance; + if (distance < influenceRadius) { + // push away + final direction = (p.position - d.localPosition).normalize(); + p.velocity += direction * 0.5; // 👈 adjust strength + } + } + }); + }, + + child: Stack( + alignment: AlignmentDirectional.center, + children: [ + CustomPaint( + painter: ParticlePainter(_particles, context.getColor(widget.pinColor)), + child: const SizedBox.expand(), + ), + widget.child + ], + ), + ); + } +} + +class Particle { + Offset position; + Offset velocity; + final Size screenSize; + final Random random; + final double speedFactor; + + Particle(this.position, this.velocity, this.random, this.screenSize, this.speedFactor); + + factory Particle.random(Random random, Size screenSize, double speedFactor) { + return Particle( + Offset( + random.nextDouble() * screenSize.width, + random.nextDouble() * screenSize.height, + ), + Offset( + (random.nextDouble() * 2 - 1) * 0.5, + (random.nextDouble() * 2 - 1) * 0.5, + ), + random, + screenSize, + speedFactor, + ); + } + + void randomWalk() { + final dx = (random.nextDouble() * 0.2 - 0.1) * speedFactor; + final dy = (random.nextDouble() * 0.2 - 0.1) * speedFactor; + velocity += Offset(dx, dy); + + final maxSpeed = 1.5 * speedFactor; + if (velocity.distance > maxSpeed) { + velocity = (velocity / velocity.distance) * maxSpeed; + } + } + + void update() { + position += velocity; + } + + bool isInside(Size size) { + return position.dx >= -20 && + position.dx <= size.width + 20 && + position.dy >= -20 && + position.dy <= size.height + 20; + } +} + +class ParticlePainter extends CustomPainter { + final List particles; + final Color pinColor; + + ParticlePainter(this.particles, this.pinColor); + + @override + void paint(Canvas canvas, Size size) { + final circlePaint = Paint()..color = pinColor; + final linePaint = Paint() + ..color = pinColor.withOpacity(0.2) + ..strokeWidth = 0.5; + + const maxDistance = 150.0; + + for (var p in particles) { + canvas.drawCircle(p.position, 3, circlePaint); + + for (var other in particles) { + if (p == other) continue; + final dist = (p.position - other.position).distance; + if (dist < maxDistance) { + linePaint.color = pinColor.withOpacity(1 - dist / maxDistance); + canvas.drawLine(p.position, other.position, linePaint); + } + } + } + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) => true; +} + +extension OffsetX on Offset { + Offset normalize() { + final len = distance; + if (len == 0) return Offset.zero; + return this / len; + } +} From 634b898adbf541c4cba03a8b4ef737183fb620da Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 18:59:39 +0300 Subject: [PATCH 105/107] add movable and interact background for home page --- lib/features/base/view/base_page.dart | 46 +++++++++++++++------------ 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/lib/features/base/view/base_page.dart b/lib/features/base/view/base_page.dart index 077c1c7..1323f83 100644 --- a/lib/features/base/view/base_page.dart +++ b/lib/features/base/view/base_page.dart @@ -7,6 +7,9 @@ import 'package:algorithm_visualizer/core/widgets/adaptive/text/adaptive_text.da import 'package:algorithm_visualizer/core/widgets/custom_widgets/custom_rounded_elevated_button.dart'; import 'package:flutter/material.dart'; +import 'movable_animated_button.dart'; +import 'movable_pins.dart'; + class BasePage extends StatefulWidget { const BasePage({super.key}); @@ -28,26 +31,29 @@ class _BasePageState extends State { return Scaffold( body: SafeArea( child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.searching), - onPressed: () { - context.pushTo(Routes.searching); - }, - ), - CustomRoundedElevatedButton( - roundedRadius: 3, - backgroundColor: ThemeEnum.whiteD5Color, - child: const RegularText(StringsManager.sorting), - onPressed: () { - context.pushTo(Routes.sortingList); - }, - ), - ], + child: MovablePinsBackground( + pinColor: ThemeEnum.whiteD4Color, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FloatingAnimatedButton( + child: CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.searching), + onPressed: () => context.pushTo(Routes.searching), + ), + ), + FloatingAnimatedButton( + child: CustomRoundedElevatedButton( + roundedRadius: 3, + backgroundColor: ThemeEnum.whiteD5Color, + child: const RegularText(StringsManager.sorting), + onPressed: () => context.pushTo(Routes.sortingList), + ), + ), + ], + ), ), ), ), From 755d878d180fd5a59fc377e30058935b12a57e45 Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 22:31:36 +0300 Subject: [PATCH 106/107] update app them for new flutter version --- lib/config/themes/app_theme.dart | 8 ++++---- pubspec.lock | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/config/themes/app_theme.dart b/lib/config/themes/app_theme.dart index 258791c..d7e10b9 100644 --- a/lib/config/themes/app_theme.dart +++ b/lib/config/themes/app_theme.dart @@ -44,7 +44,7 @@ class AppTheme { tabBarTheme: _tabBarTheme(), textTheme: _textTheme(), dividerTheme: const DividerThemeData(color: ColorManager.whiteD5), - bottomAppBarTheme: const BottomAppBarTheme(color: ColorManager.blackOp30), + bottomAppBarTheme: const BottomAppBarThemeData(color: ColorManager.blackOp30), textSelectionTheme: const TextSelectionThemeData( cursorColor: ColorManager.teal, selectionColor: ColorManager.blackOp10, @@ -125,7 +125,7 @@ class AppTheme { elevation: 0, titleSpacing: 5.w, surfaceTintColor: ColorManager.white, - color: ColorManager.white, + backgroundColor: ColorManager.white, shadowColor: ColorManager.blackOp20, scrolledUnderElevation: 1.5.r, iconTheme: const IconThemeData(color: ColorManager.black), @@ -169,7 +169,7 @@ class AppTheme { tabBarTheme: _tabBarDarkTheme(), textTheme: _textDarkTheme(), dividerTheme: const DividerThemeData(color: ColorManager.blackL5), - bottomAppBarTheme: const BottomAppBarTheme(color: ColorManager.whiteOp30), + bottomAppBarTheme: const BottomAppBarThemeData(color: ColorManager.whiteOp30), textSelectionTheme: const TextSelectionThemeData( cursorColor: ColorManager.teal, selectionColor: ColorManager.greyD6, @@ -244,7 +244,7 @@ class AppTheme { elevation: 0, titleSpacing: 5.w, surfaceTintColor: ColorManager.blackBlue, - color: ColorManager.blackBlue, + backgroundColor: ColorManager.blackBlue, shadowColor: ColorManager.greyD8, scrolledUnderElevation: 1.5.r, iconTheme: const IconThemeData(color: ColorManager.white), diff --git a/pubspec.lock b/pubspec.lock index 2bfec98..e4330a2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -180,26 +180,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" + sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0" url: "https://pub.dev" source: hosted - version: "10.0.9" + version: "11.0.1" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" url: "https://pub.dev" source: hosted - version: "3.0.9" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: @@ -393,10 +393,10 @@ packages: dependency: transitive description: name: test_api - sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.6" typed_data: dependency: transitive description: @@ -433,10 +433,10 @@ packages: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: @@ -470,5 +470,5 @@ packages: source: hosted version: "6.5.0" sdks: - dart: ">=3.7.0-0 <4.0.0" + dart: ">=3.8.0-0 <4.0.0" flutter: ">=3.22.0" From 1ee27d68b2c790c293435f5ea7e63f55763389ee Mon Sep 17 00:00:00 2001 From: Ahmed Abdo <88978546+AhmedAbdoElhawary@users.noreply.github.com> Date: Wed, 27 Aug 2025 23:30:48 +0300 Subject: [PATCH 107/107] add some low level files --- .VSCodeCounter/2025-08-24_12-43-46/details.md | 148 ++++++++++ .../2025-08-24_12-43-46/diff-details.md | 15 + .VSCodeCounter/2025-08-24_12-43-46/diff.csv | 2 + .VSCodeCounter/2025-08-24_12-43-46/diff.md | 19 ++ .VSCodeCounter/2025-08-24_12-43-46/diff.txt | 22 ++ .../2025-08-24_12-43-46/results.csv | 135 +++++++++ .../2025-08-24_12-43-46/results.json | 1 + .VSCodeCounter/2025-08-24_12-43-46/results.md | 125 +++++++++ .../2025-08-24_12-43-46/results.txt | 261 ++++++++++++++++++ macos/Podfile.lock | 23 ++ 10 files changed, 751 insertions(+) create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/details.md create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/diff-details.md create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/diff.csv create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/diff.md create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/diff.txt create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/results.csv create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/results.json create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/results.md create mode 100644 .VSCodeCounter/2025-08-24_12-43-46/results.txt create mode 100644 macos/Podfile.lock diff --git a/.VSCodeCounter/2025-08-24_12-43-46/details.md b/.VSCodeCounter/2025-08-24_12-43-46/details.md new file mode 100644 index 0000000..9809de8 --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/details.md @@ -0,0 +1,148 @@ +# Details + +Date : 2025-08-24 12:43:46 + +Directory /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer + +Total : 133 files, 6259 codes, 411 comments, 1006 blanks, all 7676 lines + +[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md) + +## Files +| filename | language | code | comment | blank | total | +| :--- | :--- | ---: | ---: | ---: | ---: | +| [.github/workflows/script.yml](/.github/workflows/script.yml) | YAML | 24 | 0 | 7 | 31 | +| [README.md](/README.md) | Markdown | 53 | 0 | 10 | 63 | +| [analysis\_options.yaml](/analysis_options.yaml) | YAML | 3 | 22 | 4 | 29 | +| [android/app/build.gradle](/android/app/build.gradle) | Groovy | 44 | 6 | 9 | 59 | +| [android/app/src/debug/AndroidManifest.xml](/android/app/src/debug/AndroidManifest.xml) | XML | 3 | 4 | 1 | 8 | +| [android/app/src/main/AndroidManifest.xml](/android/app/src/main/AndroidManifest.xml) | XML | 34 | 11 | 1 | 46 | +| [android/app/src/main/res/drawable-v21/launch\_background.xml](/android/app/src/main/res/drawable-v21/launch_background.xml) | XML | 4 | 7 | 2 | 13 | +| [android/app/src/main/res/drawable/launch\_background.xml](/android/app/src/main/res/drawable/launch_background.xml) | XML | 4 | 7 | 2 | 13 | +| [android/app/src/main/res/values-night/styles.xml](/android/app/src/main/res/values-night/styles.xml) | XML | 9 | 9 | 1 | 19 | +| [android/app/src/main/res/values/styles.xml](/android/app/src/main/res/values/styles.xml) | XML | 9 | 9 | 1 | 19 | +| [android/app/src/profile/AndroidManifest.xml](/android/app/src/profile/AndroidManifest.xml) | XML | 3 | 4 | 1 | 8 | +| [android/build.gradle](/android/build.gradle) | Groovy | 16 | 0 | 3 | 19 | +| [android/gradle.properties](/android/gradle.properties) | Properties | 3 | 0 | 1 | 4 | +| [android/gradle/wrapper/gradle-wrapper.properties](/android/gradle/wrapper/gradle-wrapper.properties) | Properties | 5 | 0 | 1 | 6 | +| [android/settings.gradle](/android/settings.gradle) | Groovy | 21 | 0 | 5 | 26 | +| [ios/Podfile](/ios/Podfile) | Ruby | 32 | 3 | 10 | 45 | +| [ios/Runner/AppDelegate.swift](/ios/Runner/AppDelegate.swift) | Swift | 12 | 0 | 2 | 14 | +| [ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json](/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json) | JSON | 122 | 0 | 1 | 123 | +| [ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json](/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json) | JSON | 23 | 0 | 1 | 24 | +| [ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md](/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md) | Markdown | 3 | 0 | 2 | 5 | +| [ios/Runner/Base.lproj/LaunchScreen.storyboard](/ios/Runner/Base.lproj/LaunchScreen.storyboard) | XML | 36 | 1 | 1 | 38 | +| [ios/Runner/Base.lproj/Main.storyboard](/ios/Runner/Base.lproj/Main.storyboard) | XML | 25 | 1 | 1 | 27 | +| [ios/Runner/Runner-Bridging-Header.h](/ios/Runner/Runner-Bridging-Header.h) | C++ | 1 | 0 | 1 | 2 | +| [ios/RunnerTests/RunnerTests.swift](/ios/RunnerTests/RunnerTests.swift) | Swift | 7 | 2 | 4 | 13 | +| [lib/config/routes/route\_app.dart](/lib/config/routes/route_app.dart) | Dart | 125 | 1 | 9 | 135 | +| [lib/config/themes/app\_theme.dart](/lib/config/themes/app_theme.dart) | Dart | 239 | 2 | 14 | 255 | +| [lib/core/draggable\_progress.dart](/lib/core/draggable_progress.dart) | Dart | 42 | 0 | 4 | 46 | +| [lib/core/enums/app\_settings\_enum.dart](/lib/core/enums/app_settings_enum.dart) | Dart | 1 | 0 | 2 | 3 | +| [lib/core/extensions/language.dart](/lib/core/extensions/language.dart) | Dart | 20 | 0 | 5 | 25 | +| [lib/core/extensions/navigators.dart](/lib/core/extensions/navigators.dart) | Dart | 126 | 3 | 16 | 145 | +| [lib/core/helpers/app\_bar/app\_bar.dart](/lib/core/helpers/app_bar/app_bar.dart) | Dart | 127 | 2 | 13 | 142 | +| [lib/core/helpers/app\_bar/back\_button.dart](/lib/core/helpers/app_bar/back_button.dart) | Dart | 21 | 0 | 6 | 27 | +| [lib/core/helpers/current\_device.dart](/lib/core/helpers/current_device.dart) | Dart | 7 | 0 | 2 | 9 | +| [lib/core/helpers/custom\_alert\_dialog.dart](/lib/core/helpers/custom_alert_dialog.dart) | Dart | 123 | 0 | 8 | 131 | +| [lib/core/helpers/random\_int.dart](/lib/core/helpers/random_int.dart) | Dart | 9 | 0 | 4 | 13 | +| [lib/core/helpers/random\_text.dart](/lib/core/helpers/random_text.dart) | Dart | 13 | 0 | 7 | 20 | +| [lib/core/helpers/screen\_size.dart](/lib/core/helpers/screen_size.dart) | Dart | 7 | 0 | 2 | 9 | +| [lib/core/helpers/storage/app\_settings/app\_settings\_cubit.dart](/lib/core/helpers/storage/app_settings/app_settings_cubit.dart) | Dart | 62 | 10 | 21 | 93 | +| [lib/core/helpers/storage/app\_settings/app\_settings\_state.dart](/lib/core/helpers/storage/app_settings/app_settings_state.dart) | Dart | 18 | 0 | 5 | 23 | +| [lib/core/helpers/svg\_picture.dart](/lib/core/helpers/svg_picture.dart) | Dart | 31 | 0 | 3 | 34 | +| [lib/core/helpers/system\_overlay\_style.dart](/lib/core/helpers/system_overlay_style.dart) | Dart | 51 | 0 | 6 | 57 | +| [lib/core/material\_app/my\_app.dart](/lib/core/material_app/my_app.dart) | Dart | 74 | 5 | 9 | 88 | +| [lib/core/resources/color\_manager.dart](/lib/core/resources/color_manager.dart) | Dart | 79 | 23 | 8 | 110 | +| [lib/core/resources/font\_manager.dart](/lib/core/resources/font_manager.dart) | Dart | 26 | 11 | 4 | 41 | +| [lib/core/resources/strings\_manager.dart](/lib/core/resources/strings_manager.dart) | Dart | 41 | 2 | 5 | 48 | +| [lib/core/resources/styles\_manager.dart](/lib/core/resources/styles_manager.dart) | Dart | 77 | 0 | 7 | 84 | +| [lib/core/resources/theme\_manager.dart](/lib/core/resources/theme_manager.dart) | Dart | 86 | 2 | 10 | 98 | +| [lib/core/widgets/adapt\_widget\_size.dart](/lib/core/widgets/adapt_widget_size.dart) | Dart | 18 | 0 | 4 | 22 | +| [lib/core/widgets/adaptive/padding/adaptive\_padding.dart](/lib/core/widgets/adaptive/padding/adaptive_padding.dart) | Dart | 20 | 0 | 2 | 22 | +| [lib/core/widgets/adaptive/padding/all\_padding.dart](/lib/core/widgets/adaptive/padding/all_padding.dart) | Dart | 11 | 0 | 2 | 13 | +| [lib/core/widgets/adaptive/padding/bottom\_padding.dart](/lib/core/widgets/adaptive/padding/bottom_padding.dart) | Dart | 11 | 0 | 3 | 14 | +| [lib/core/widgets/adaptive/padding/end\_padding.dart](/lib/core/widgets/adaptive/padding/end_padding.dart) | Dart | 11 | 0 | 2 | 13 | +| [lib/core/widgets/adaptive/padding/horizontal\_padding.dart](/lib/core/widgets/adaptive/padding/horizontal_padding.dart) | Dart | 12 | 0 | 2 | 14 | +| [lib/core/widgets/adaptive/padding/only\_padding.dart](/lib/core/widgets/adaptive/padding/only_padding.dart) | Dart | 28 | 0 | 3 | 31 | +| [lib/core/widgets/adaptive/padding/start\_padding.dart](/lib/core/widgets/adaptive/padding/start_padding.dart) | Dart | 12 | 0 | 1 | 13 | +| [lib/core/widgets/adaptive/padding/symmetric\_padding.dart](/lib/core/widgets/adaptive/padding/symmetric_padding.dart) | Dart | 17 | 0 | 2 | 19 | +| [lib/core/widgets/adaptive/padding/top\_padding.dart](/lib/core/widgets/adaptive/padding/top_padding.dart) | Dart | 12 | 0 | 1 | 13 | +| [lib/core/widgets/adaptive/padding/vertical\_padding.dart](/lib/core/widgets/adaptive/padding/vertical_padding.dart) | Dart | 12 | 0 | 2 | 14 | +| [lib/core/widgets/adaptive/text/adaptive\_text.dart](/lib/core/widgets/adaptive/text/adaptive_text.dart) | Dart | 91 | 5 | 13 | 109 | +| [lib/core/widgets/adaptive/text/bold\_text.dart](/lib/core/widgets/adaptive/text/bold_text.dart) | Dart | 15 | 0 | 2 | 17 | +| [lib/core/widgets/adaptive/text/light\_text.dart](/lib/core/widgets/adaptive/text/light_text.dart) | Dart | 14 | 0 | 2 | 16 | +| [lib/core/widgets/adaptive/text/medium\_text.dart](/lib/core/widgets/adaptive/text/medium_text.dart) | Dart | 16 | 0 | 2 | 18 | +| [lib/core/widgets/adaptive/text/regular\_text.dart](/lib/core/widgets/adaptive/text/regular_text.dart) | Dart | 14 | 0 | 2 | 16 | +| [lib/core/widgets/adaptive/text/semi\_bold\_text.dart](/lib/core/widgets/adaptive/text/semi_bold_text.dart) | Dart | 15 | 0 | 2 | 17 | +| [lib/core/widgets/custom\_widgets/check\_box.dart](/lib/core/widgets/custom_widgets/check_box.dart) | Dart | 51 | 0 | 2 | 53 | +| [lib/core/widgets/custom\_widgets/custom\_bottom\_sheet.dart](/lib/core/widgets/custom_widgets/custom_bottom_sheet.dart) | Dart | 197 | 0 | 8 | 205 | +| [lib/core/widgets/custom\_widgets/custom\_circulars\_progress.dart](/lib/core/widgets/custom_widgets/custom_circulars_progress.dart) | Dart | 215 | 0 | 24 | 239 | +| [lib/core/widgets/custom\_widgets/custom\_dialog.dart](/lib/core/widgets/custom_widgets/custom_dialog.dart) | Dart | 91 | 0 | 6 | 97 | +| [lib/core/widgets/custom\_widgets/custom\_divider.dart](/lib/core/widgets/custom_widgets/custom_divider.dart) | Dart | 29 | 0 | 4 | 33 | +| [lib/core/widgets/custom\_widgets/custom\_icon.dart](/lib/core/widgets/custom_widgets/custom_icon.dart) | Dart | 25 | 0 | 2 | 27 | +| [lib/core/widgets/custom\_widgets/custom\_rounded\_elevated\_button.dart](/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart) | Dart | 45 | 0 | 4 | 49 | +| [lib/core/widgets/custom\_widgets/custom\_switch.dart](/lib/core/widgets/custom_widgets/custom_switch.dart) | Dart | 35 | 2 | 4 | 41 | +| [lib/core/widgets/custom\_widgets/error\_screen.dart](/lib/core/widgets/custom_widgets/error_screen.dart) | Dart | 26 | 0 | 2 | 28 | +| [lib/core/widgets/custom\_widgets/hero\_widget.dart](/lib/core/widgets/custom_widgets/hero_widget.dart) | Dart | 15 | 0 | 3 | 18 | +| [lib/core/widgets/custom\_widgets/keyboard\_detected.dart](/lib/core/widgets/custom_widgets/keyboard_detected.dart) | Dart | 47 | 0 | 9 | 56 | +| [lib/core/widgets/custom\_widgets/rounded\_outlined\_button.dart](/lib/core/widgets/custom_widgets/rounded_outlined_button.dart) | Dart | 44 | 0 | 4 | 48 | +| [lib/core/widgets/custom\_widgets/scale\_transition.dart](/lib/core/widgets/custom_widgets/scale_transition.dart) | Dart | 34 | 0 | 6 | 40 | +| [lib/core/widgets/custom\_widgets/vertical\_animation\_hero\_page.dart](/lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart) | Dart | 39 | 0 | 4 | 43 | +| [lib/features/base/view/base\_page.dart](/lib/features/base/view/base_page.dart) | Dart | 52 | 0 | 5 | 57 | +| [lib/features/searching/view/grid\_page.dart](/lib/features/searching/view/grid_page.dart) | Dart | 290 | 0 | 35 | 325 | +| [lib/features/searching/view\_model/grid\_notifier.dart](/lib/features/searching/view_model/grid_notifier.dart) | Dart | 384 | 18 | 109 | 511 | +| [lib/features/searching/view\_model/grid\_notifier\_state.dart](/lib/features/searching/view_model/grid_notifier_state.dart) | Dart | 50 | 1 | 7 | 58 | +| [lib/features/searching/widgets/searcher\_grid.dart](/lib/features/searching/widgets/searcher_grid.dart) | Dart | 79 | 3 | 14 | 96 | +| [lib/features/sorting/base/helper/sortable\_item.dart](/lib/features/sorting/base/helper/sortable_item.dart) | Dart | 45 | 1 | 8 | 54 | +| [lib/features/sorting/base/helper/sorting\_enums.dart](/lib/features/sorting/base/helper/sorting_enums.dart) | Dart | 9 | 6 | 4 | 19 | +| [lib/features/sorting/base/view/sorting\_list\_page.dart](/lib/features/sorting/base/view/sorting_list_page.dart) | Dart | 60 | 0 | 3 | 63 | +| [lib/features/sorting/base/view/sorting\_page.dart](/lib/features/sorting/base/view/sorting_page.dart) | Dart | 205 | 1 | 19 | 225 | +| [lib/features/sorting/base/view\_model/sorting\_notifier.dart](/lib/features/sorting/base/view_model/sorting_notifier.dart) | Dart | 143 | 4 | 48 | 195 | +| [lib/features/sorting/base/view\_model/sorting\_state.dart](/lib/features/sorting/base/view_model/sorting_state.dart) | Dart | 31 | 0 | 3 | 34 | +| [lib/features/sorting/base/widgets/control\_buttons.dart](/lib/features/sorting/base/widgets/control_buttons.dart) | Dart | 47 | 0 | 3 | 50 | +| [lib/features/sorting/base/widgets/sorting\_app\_bar.dart](/lib/features/sorting/base/widgets/sorting_app_bar.dart) | Dart | 1 | 43 | 1 | 45 | +| [lib/features/sorting/bubble/view/bubble\_sort\_page.dart](/lib/features/sorting/bubble/view/bubble_sort_page.dart) | Dart | 25 | 0 | 6 | 31 | +| [lib/features/sorting/bubble/view\_model/bubble\_sort\_notifier.dart](/lib/features/sorting/bubble/view_model/bubble_sort_notifier.dart) | Dart | 25 | 0 | 10 | 35 | +| [lib/features/sorting/insertion/view/insertion\_sort\_page.dart](/lib/features/sorting/insertion/view/insertion_sort_page.dart) | Dart | 25 | 0 | 6 | 31 | +| [lib/features/sorting/insertion/view\_model/insertion\_sort\_notifier.dart](/lib/features/sorting/insertion/view_model/insertion_sort_notifier.dart) | Dart | 22 | 0 | 7 | 29 | +| [lib/features/sorting/merge/view/merge\_sort\_page.dart](/lib/features/sorting/merge/view/merge_sort_page.dart) | Dart | 25 | 0 | 6 | 31 | +| [lib/features/sorting/merge/view\_model/merge\_sort\_notifier.dart](/lib/features/sorting/merge/view_model/merge_sort_notifier.dart) | Dart | 7 | 1 | 2 | 10 | +| [lib/features/sorting/selection/view/selection\_sort\_page.dart](/lib/features/sorting/selection/view/selection_sort_page.dart) | Dart | 25 | 0 | 6 | 31 | +| [lib/features/sorting/selection/view\_model/selection\_sort\_notifier.dart](/lib/features/sorting/selection/view_model/selection_sort_notifier.dart) | Dart | 31 | 1 | 11 | 43 | +| [lib/main.dart](/lib/main.dart) | Dart | 6 | 0 | 2 | 8 | +| [linux/CMakeLists.txt](/linux/CMakeLists.txt) | CMake | 118 | 0 | 28 | 146 | +| [linux/flutter/CMakeLists.txt](/linux/flutter/CMakeLists.txt) | CMake | 79 | 0 | 10 | 89 | +| [linux/flutter/generated\_plugin\_registrant.cc](/linux/flutter/generated_plugin_registrant.cc) | C++ | 3 | 4 | 5 | 12 | +| [linux/flutter/generated\_plugin\_registrant.h](/linux/flutter/generated_plugin_registrant.h) | C++ | 5 | 5 | 6 | 16 | +| [linux/flutter/generated\_plugins.cmake](/linux/flutter/generated_plugins.cmake) | CMake | 18 | 0 | 6 | 24 | +| [linux/main.cc](/linux/main.cc) | C++ | 5 | 0 | 2 | 7 | +| [linux/my\_application.cc](/linux/my_application.cc) | C++ | 82 | 17 | 26 | 125 | +| [linux/my\_application.h](/linux/my_application.h) | C++ | 7 | 7 | 5 | 19 | +| [macos/Flutter/GeneratedPluginRegistrant.swift](/macos/Flutter/GeneratedPluginRegistrant.swift) | Swift | 6 | 3 | 4 | 13 | +| [macos/Podfile](/macos/Podfile) | Ruby | 33 | 1 | 10 | 44 | +| [macos/Runner/AppDelegate.swift](/macos/Runner/AppDelegate.swift) | Swift | 8 | 0 | 2 | 10 | +| [macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json](/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json) | JSON | 68 | 0 | 1 | 69 | +| [macos/Runner/Base.lproj/MainMenu.xib](/macos/Runner/Base.lproj/MainMenu.xib) | XML | 343 | 0 | 1 | 344 | +| [macos/Runner/MainFlutterWindow.swift](/macos/Runner/MainFlutterWindow.swift) | Swift | 12 | 0 | 4 | 16 | +| [macos/RunnerTests/RunnerTests.swift](/macos/RunnerTests/RunnerTests.swift) | Swift | 7 | 2 | 4 | 13 | +| [pubspec.yaml](/pubspec.yaml) | YAML | 26 | 0 | 11 | 37 | +| [test/widget\_test.dart](/test/widget_test.dart) | Dart | 0 | 30 | 1 | 31 | +| [web/index.html](/web/index.html) | HTML | 19 | 15 | 5 | 39 | +| [web/manifest.json](/web/manifest.json) | JSON | 35 | 0 | 1 | 36 | +| [windows/CMakeLists.txt](/windows/CMakeLists.txt) | CMake | 89 | 0 | 20 | 109 | +| [windows/flutter/CMakeLists.txt](/windows/flutter/CMakeLists.txt) | CMake | 98 | 0 | 12 | 110 | +| [windows/flutter/generated\_plugin\_registrant.cc](/windows/flutter/generated_plugin_registrant.cc) | C++ | 3 | 4 | 5 | 12 | +| [windows/flutter/generated\_plugin\_registrant.h](/windows/flutter/generated_plugin_registrant.h) | C++ | 5 | 5 | 6 | 16 | +| [windows/flutter/generated\_plugins.cmake](/windows/flutter/generated_plugins.cmake) | CMake | 18 | 0 | 6 | 24 | +| [windows/runner/CMakeLists.txt](/windows/runner/CMakeLists.txt) | CMake | 34 | 0 | 7 | 41 | +| [windows/runner/flutter\_window.cpp](/windows/runner/flutter_window.cpp) | C++ | 49 | 7 | 16 | 72 | +| [windows/runner/flutter\_window.h](/windows/runner/flutter_window.h) | C++ | 20 | 5 | 9 | 34 | +| [windows/runner/main.cpp](/windows/runner/main.cpp) | C++ | 30 | 4 | 10 | 44 | +| [windows/runner/resource.h](/windows/runner/resource.h) | C++ | 9 | 6 | 2 | 17 | +| [windows/runner/utils.cpp](/windows/runner/utils.cpp) | C++ | 54 | 2 | 10 | 66 | +| [windows/runner/utils.h](/windows/runner/utils.h) | C++ | 8 | 6 | 6 | 20 | +| [windows/runner/win32\_window.cpp](/windows/runner/win32_window.cpp) | C++ | 210 | 24 | 55 | 289 | +| [windows/runner/win32\_window.h](/windows/runner/win32_window.h) | C++ | 48 | 31 | 24 | 103 | + +[Summary](results.md) / Details / [Diff Summary](diff.md) / [Diff Details](diff-details.md) \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/diff-details.md b/.VSCodeCounter/2025-08-24_12-43-46/diff-details.md new file mode 100644 index 0000000..b2b31db --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/diff-details.md @@ -0,0 +1,15 @@ +# Diff Details + +Date : 2025-08-24 12:43:46 + +Directory /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer + +Total : 0 files, 0 codes, 0 comments, 0 blanks, all 0 lines + +[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details + +## Files +| filename | language | code | comment | blank | total | +| :--- | :--- | ---: | ---: | ---: | ---: | + +[Summary](results.md) / [Details](details.md) / [Diff Summary](diff.md) / Diff Details \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/diff.csv b/.VSCodeCounter/2025-08-24_12-43-46/diff.csv new file mode 100644 index 0000000..b7d8d75 --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/diff.csv @@ -0,0 +1,2 @@ +"filename", "language", "", "comment", "blank", "total" +"Total", "-", , 0, 0, 0 \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/diff.md b/.VSCodeCounter/2025-08-24_12-43-46/diff.md new file mode 100644 index 0000000..9626b53 --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/diff.md @@ -0,0 +1,19 @@ +# Diff Summary + +Date : 2025-08-24 12:43:46 + +Directory /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer + +Total : 0 files, 0 codes, 0 comments, 0 blanks, all 0 lines + +[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md) + +## Languages +| language | files | code | comment | blank | total | +| :--- | ---: | ---: | ---: | ---: | ---: | + +## Directories +| path | files | code | comment | blank | total | +| :--- | ---: | ---: | ---: | ---: | ---: | + +[Summary](results.md) / [Details](details.md) / Diff Summary / [Diff Details](diff-details.md) \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/diff.txt b/.VSCodeCounter/2025-08-24_12-43-46/diff.txt new file mode 100644 index 0000000..5aa31d6 --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/diff.txt @@ -0,0 +1,22 @@ +Date : 2025-08-24 12:43:46 +Directory : /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer +Total : 0 files, 0 codes, 0 comments, 0 blanks, all 0 lines + +Languages ++----------+------------+------------+------------+------------+------------+ +| language | files | code | comment | blank | total | ++----------+------------+------------+------------+------------+------------+ ++----------+------------+------------+------------+------------+------------+ + +Directories ++------+------------+------------+------------+------------+------------+ +| path | files | code | comment | blank | total | ++------+------------+------------+------------+------------+------------+ ++------+------------+------------+------------+------------+------------+ + +Files ++----------+----------+------------+------------+------------+------------+ +| filename | language | code | comment | blank | total | ++----------+----------+------------+------------+------------+------------+ +| Total | | 0 | 0 | 0 | 0 | ++----------+----------+------------+------------+------------+------------+ \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/results.csv b/.VSCodeCounter/2025-08-24_12-43-46/results.csv new file mode 100644 index 0000000..51c748a --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/results.csv @@ -0,0 +1,135 @@ +"filename", "language", "Dart", "CMake", "C++", "YAML", "Markdown", "Ruby", "Swift", "JSON", "XML", "Groovy", "Properties", "HTML", "comment", "blank", "total" +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/.github/workflows/script.yml", "YAML", 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 31 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/README.md", "Markdown", 0, 0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 10, 63 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/analysis_options.yaml", "YAML", 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 22, 4, 29 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/build.gradle", "Groovy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 6, 9, 59 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/debug/AndroidManifest.xml", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 8 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/AndroidManifest.xml", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 11, 1, 46 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/drawable-v21/launch_background.xml", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 7, 2, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/drawable/launch_background.xml", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 7, 2, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/values-night/styles.xml", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 9, 1, 19 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/values/styles.xml", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 9, 1, 19 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/profile/AndroidManifest.xml", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 1, 8 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/build.gradle", "Groovy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 3, 19 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/gradle.properties", "Properties", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 4 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/gradle/wrapper/gradle-wrapper.properties", "Properties", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 1, 6 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/settings.gradle", "Groovy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 0, 0, 0, 5, 26 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Podfile", "Ruby", 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 3, 10, 45 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/AppDelegate.swift", "Swift", 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 2, 14 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json", "JSON", 0, 0, 0, 0, 0, 0, 0, 122, 0, 0, 0, 0, 0, 1, 123 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json", "JSON", 0, 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 1, 24 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md", "Markdown", 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Base.lproj/LaunchScreen.storyboard", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 1, 1, 38 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Base.lproj/Main.storyboard", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 1, 1, 27 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Runner-Bridging-Header.h", "C++", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/RunnerTests/RunnerTests.swift", "Swift", 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 4, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/config/routes/route_app.dart", "Dart", 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 9, 135 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/config/themes/app_theme.dart", "Dart", 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 14, 255 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/draggable_progress.dart", "Dart", 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 46 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/enums/app_settings_enum.dart", "Dart", 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/extensions/language.dart", "Dart", 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 25 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/extensions/navigators.dart", "Dart", 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 16, 145 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/app_bar/app_bar.dart", "Dart", 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13, 142 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/app_bar/back_button.dart", "Dart", 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 27 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/current_device.dart", "Dart", 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 9 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/custom_alert_dialog.dart", "Dart", 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 131 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/random_int.dart", "Dart", 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/random_text.dart", "Dart", 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 20 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/screen_size.dart", "Dart", 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 9 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/storage/app_settings/app_settings_cubit.dart", "Dart", 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 21, 93 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/storage/app_settings/app_settings_state.dart", "Dart", 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 23 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/svg_picture.dart", "Dart", 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 34 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/system_overlay_style.dart", "Dart", 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 57 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/material_app/my_app.dart", "Dart", 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 9, 88 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/color_manager.dart", "Dart", 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 8, 110 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/font_manager.dart", "Dart", 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 4, 41 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/strings_manager.dart", "Dart", 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 48 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/styles_manager.dart", "Dart", 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 84 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/theme_manager.dart", "Dart", 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 10, 98 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adapt_widget_size.dart", "Dart", 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 22 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/adaptive_padding.dart", "Dart", 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 22 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/all_padding.dart", "Dart", 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/bottom_padding.dart", "Dart", 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 14 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/end_padding.dart", "Dart", 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/horizontal_padding.dart", "Dart", 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 14 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/only_padding.dart", "Dart", 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 31 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/start_padding.dart", "Dart", 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/symmetric_padding.dart", "Dart", 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 19 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/top_padding.dart", "Dart", 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/vertical_padding.dart", "Dart", 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 14 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/adaptive_text.dart", "Dart", 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 13, 109 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/bold_text.dart", "Dart", 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 17 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/light_text.dart", "Dart", 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/medium_text.dart", "Dart", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 18 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/regular_text.dart", "Dart", 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/semi_bold_text.dart", "Dart", 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 17 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/check_box.dart", "Dart", 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 53 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_bottom_sheet.dart", "Dart", 197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 205 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_circulars_progress.dart", "Dart", 215, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 239 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_dialog.dart", "Dart", 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 97 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_divider.dart", "Dart", 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 33 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_icon.dart", "Dart", 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 27 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart", "Dart", 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 49 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_switch.dart", "Dart", 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 41 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/error_screen.dart", "Dart", 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 28 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/hero_widget.dart", "Dart", 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 18 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/keyboard_detected.dart", "Dart", 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 56 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/rounded_outlined_button.dart", "Dart", 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 48 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/scale_transition.dart", "Dart", 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 40 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart", "Dart", 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 43 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/base/view/base_page.dart", "Dart", 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 57 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view/grid_page.dart", "Dart", 290, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 325 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view_model/grid_notifier.dart", "Dart", 384, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 109, 511 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view_model/grid_notifier_state.dart", "Dart", 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 58 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/widgets/searcher_grid.dart", "Dart", 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 14, 96 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/helper/sortable_item.dart", "Dart", 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 8, 54 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/helper/sorting_enums.dart", "Dart", 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 19 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view/sorting_list_page.dart", "Dart", 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 63 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view/sorting_page.dart", "Dart", 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 19, 225 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view_model/sorting_notifier.dart", "Dart", 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 48, 195 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view_model/sorting_state.dart", "Dart", 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 34 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/widgets/control_buttons.dart", "Dart", 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 50 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/widgets/sorting_app_bar.dart", "Dart", 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 1, 45 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/bubble/view/bubble_sort_page.dart", "Dart", 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 31 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/bubble/view_model/bubble_sort_notifier.dart", "Dart", 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 35 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/insertion/view/insertion_sort_page.dart", "Dart", 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 31 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/insertion/view_model/insertion_sort_notifier.dart", "Dart", 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 29 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/merge/view/merge_sort_page.dart", "Dart", 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 31 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/merge/view_model/merge_sort_notifier.dart", "Dart", 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 10 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/selection/view/selection_sort_page.dart", "Dart", 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 31 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/selection/view_model/selection_sort_notifier.dart", "Dart", 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 43 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/main.dart", "Dart", 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/CMakeLists.txt", "CMake", 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 146 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/CMakeLists.txt", "CMake", 0, 79, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 89 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugin_registrant.cc", "C++", 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 12 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugin_registrant.h", "C++", 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 16 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugins.cmake", "CMake", 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 24 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/main.cc", "C++", 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 7 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/my_application.cc", "C++", 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 26, 125 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/my_application.h", "C++", 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 5, 19 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Flutter/GeneratedPluginRegistrant.swift", "Swift", 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 3, 4, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Podfile", "Ruby", 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 1, 10, 44 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/AppDelegate.swift", "Swift", 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 2, 10 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json", "JSON", 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 1, 69 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/Base.lproj/MainMenu.xib", "XML", 0, 0, 0, 0, 0, 0, 0, 0, 343, 0, 0, 0, 0, 1, 344 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/MainFlutterWindow.swift", "Swift", 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 4, 16 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/RunnerTests/RunnerTests.swift", "Swift", 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 4, 13 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/pubspec.yaml", "YAML", 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 37 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/test/widget_test.dart", "Dart", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 1, 31 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/web/index.html", "HTML", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 15, 5, 39 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/web/manifest.json", "JSON", 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 1, 36 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/CMakeLists.txt", "CMake", 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 109 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/CMakeLists.txt", "CMake", 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 110 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugin_registrant.cc", "C++", 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 12 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugin_registrant.h", "C++", 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 16 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugins.cmake", "CMake", 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 24 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/CMakeLists.txt", "CMake", 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 41 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/flutter_window.cpp", "C++", 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 16, 72 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/flutter_window.h", "C++", 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 9, 34 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/main.cpp", "C++", 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 10, 44 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/resource.h", "C++", 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 17 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/utils.cpp", "C++", 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 10, 66 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/utils.h", "C++", 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 20 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/win32_window.cpp", "C++", 0, 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 55, 289 +"/Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/win32_window.h", "C++", 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 24, 103 +"Total", "-", 4214, 454, 539, 53, 56, 65, 52, 248, 470, 81, 8, 19, 411, 1006, 7676 \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/results.json b/.VSCodeCounter/2025-08-24_12-43-46/results.json new file mode 100644 index 0000000..150a703 --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/results.json @@ -0,0 +1 @@ +{"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/test/widget_test.dart":{"language":"Dart","code":0,"comment":30,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugins.cmake":{"language":"CMake","code":18,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugin_registrant.cc":{"language":"C++","code":3,"comment":4,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/CMakeLists.txt":{"language":"CMake","code":98,"comment":0,"blank":12},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugin_registrant.h":{"language":"C++","code":5,"comment":5,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/main.cpp":{"language":"C++","code":30,"comment":4,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/flutter_window.h":{"language":"C++","code":20,"comment":5,"blank":9},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/resource.h":{"language":"C++","code":9,"comment":6,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/win32_window.h":{"language":"C++","code":48,"comment":31,"blank":24},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/CMakeLists.txt":{"language":"CMake","code":34,"comment":0,"blank":7},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/flutter_window.cpp":{"language":"C++","code":49,"comment":7,"blank":16},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/config/routes/route_app.dart":{"language":"Dart","code":125,"comment":1,"blank":9},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/widgets/sorting_app_bar.dart":{"language":"Dart","code":1,"comment":43,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/utils.h":{"language":"C++","code":8,"comment":6,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/analysis_options.yaml":{"language":"YAML","code":3,"comment":22,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/main.dart":{"language":"Dart","code":6,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/widgets/control_buttons.dart":{"language":"Dart","code":47,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_switch.dart":{"language":"Dart","code":35,"comment":2,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/base/view/base_page.dart":{"language":"Dart","code":52,"comment":0,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/error_screen.dart":{"language":"Dart","code":26,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/keyboard_detected.dart":{"language":"Dart","code":47,"comment":0,"blank":9},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_bottom_sheet.dart":{"language":"Dart","code":197,"comment":0,"blank":8},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adapt_widget_size.dart":{"language":"Dart","code":18,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/only_padding.dart":{"language":"Dart","code":28,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/all_padding.dart":{"language":"Dart","code":11,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/top_padding.dart":{"language":"Dart","code":12,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/bold_text.dart":{"language":"Dart","code":15,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view_model/sorting_state.dart":{"language":"Dart","code":31,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/end_padding.dart":{"language":"Dart","code":11,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view_model/sorting_notifier.dart":{"language":"Dart","code":143,"comment":4,"blank":48},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view/sorting_page.dart":{"language":"Dart","code":205,"comment":1,"blank":19},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/helper/sortable_item.dart":{"language":"Dart","code":45,"comment":1,"blank":8},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/semi_bold_text.dart":{"language":"Dart","code":15,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view/sorting_list_page.dart":{"language":"Dart","code":60,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/adaptive_text.dart":{"language":"Dart","code":91,"comment":5,"blank":13},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/light_text.dart":{"language":"Dart","code":14,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/medium_text.dart":{"language":"Dart","code":16,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/regular_text.dart":{"language":"Dart","code":14,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/helper/sorting_enums.dart":{"language":"Dart","code":9,"comment":6,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/selection/view/selection_sort_page.dart":{"language":"Dart","code":25,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/insertion/view_model/insertion_sort_notifier.dart":{"language":"Dart","code":22,"comment":0,"blank":7},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/insertion/view/insertion_sort_page.dart":{"language":"Dart","code":25,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/draggable_progress.dart":{"language":"Dart","code":42,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/extensions/navigators.dart":{"language":"Dart","code":126,"comment":3,"blank":16},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/extensions/language.dart":{"language":"Dart","code":20,"comment":0,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/selection/view_model/selection_sort_notifier.dart":{"language":"Dart","code":31,"comment":1,"blank":11},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/random_text.dart":{"language":"Dart","code":13,"comment":0,"blank":7},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/check_box.dart":{"language":"Dart","code":51,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/bubble/view_model/bubble_sort_notifier.dart":{"language":"Dart","code":25,"comment":0,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/system_overlay_style.dart":{"language":"Dart","code":51,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/hero_widget.dart":{"language":"Dart","code":15,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/bubble/view/bubble_sort_page.dart":{"language":"Dart","code":25,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/merge/view_model/merge_sort_notifier.dart":{"language":"Dart","code":7,"comment":1,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_divider.dart":{"language":"Dart","code":29,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_dialog.dart":{"language":"Dart","code":91,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_circulars_progress.dart":{"language":"Dart","code":215,"comment":0,"blank":24},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart":{"language":"Dart","code":39,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_icon.dart":{"language":"Dart","code":25,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/rounded_outlined_button.dart":{"language":"Dart","code":44,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/scale_transition.dart":{"language":"Dart","code":34,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/merge/view/merge_sort_page.dart":{"language":"Dart","code":25,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart":{"language":"Dart","code":45,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/color_manager.dart":{"language":"Dart","code":79,"comment":23,"blank":8},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/strings_manager.dart":{"language":"Dart","code":41,"comment":2,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/config/themes/app_theme.dart":{"language":"Dart","code":239,"comment":2,"blank":14},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/styles_manager.dart":{"language":"Dart","code":77,"comment":0,"blank":7},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/pubspec.yaml":{"language":"YAML","code":26,"comment":0,"blank":11},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/font_manager.dart":{"language":"Dart","code":26,"comment":11,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/horizontal_padding.dart":{"language":"Dart","code":12,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/theme_manager.dart":{"language":"Dart","code":86,"comment":2,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/win32_window.cpp":{"language":"C++","code":210,"comment":24,"blank":55},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/enums/app_settings_enum.dart":{"language":"Dart","code":1,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/current_device.dart":{"language":"Dart","code":7,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/custom_alert_dialog.dart":{"language":"Dart","code":123,"comment":0,"blank":8},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/screen_size.dart":{"language":"Dart","code":7,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/random_int.dart":{"language":"Dart","code":9,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/svg_picture.dart":{"language":"Dart","code":31,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/widgets/searcher_grid.dart":{"language":"Dart","code":79,"comment":3,"blank":14},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view/grid_page.dart":{"language":"Dart","code":290,"comment":0,"blank":35},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/start_padding.dart":{"language":"Dart","code":12,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view_model/grid_notifier_state.dart":{"language":"Dart","code":50,"comment":1,"blank":7},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view_model/grid_notifier.dart":{"language":"Dart","code":384,"comment":18,"blank":109},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/bottom_padding.dart":{"language":"Dart","code":11,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/symmetric_padding.dart":{"language":"Dart","code":17,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/vertical_padding.dart":{"language":"Dart","code":12,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/utils.cpp":{"language":"C++","code":54,"comment":2,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/adaptive_padding.dart":{"language":"Dart","code":20,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/storage/app_settings/app_settings_state.dart":{"language":"Dart","code":18,"comment":0,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/storage/app_settings/app_settings_cubit.dart":{"language":"Dart","code":62,"comment":10,"blank":21},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/README.md":{"language":"Markdown","code":53,"comment":0,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Podfile":{"language":"Ruby","code":32,"comment":3,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/AppDelegate.swift":{"language":"Swift","code":12,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json":{"language":"JSON","code":23,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Base.lproj/LaunchScreen.storyboard":{"language":"XML","code":36,"comment":1,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/CMakeLists.txt":{"language":"CMake","code":89,"comment":0,"blank":20},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md":{"language":"Markdown","code":3,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Base.lproj/Main.storyboard":{"language":"XML","code":25,"comment":1,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/build.gradle":{"language":"Groovy","code":16,"comment":0,"blank":3},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/settings.gradle":{"language":"Groovy","code":21,"comment":0,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/.github/workflows/script.yml":{"language":"YAML","code":24,"comment":0,"blank":7},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json":{"language":"JSON","code":122,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/app_bar/app_bar.dart":{"language":"Dart","code":127,"comment":2,"blank":13},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Runner-Bridging-Header.h":{"language":"C++","code":1,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/profile/AndroidManifest.xml":{"language":"XML","code":3,"comment":4,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/debug/AndroidManifest.xml":{"language":"XML","code":3,"comment":4,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/app_bar/back_button.dart":{"language":"Dart","code":21,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/AndroidManifest.xml":{"language":"XML","code":34,"comment":11,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/gradle.properties":{"language":"Properties","code":3,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/RunnerTests/RunnerTests.swift":{"language":"Swift","code":7,"comment":2,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/CMakeLists.txt":{"language":"CMake","code":79,"comment":0,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/gradle/wrapper/gradle-wrapper.properties":{"language":"Properties","code":5,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/build.gradle":{"language":"Groovy","code":44,"comment":6,"blank":9},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/drawable-v21/launch_background.xml":{"language":"XML","code":4,"comment":7,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugin_registrant.h":{"language":"C++","code":5,"comment":5,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugin_registrant.cc":{"language":"C++","code":3,"comment":4,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugins.cmake":{"language":"CMake","code":18,"comment":0,"blank":6},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/material_app/my_app.dart":{"language":"Dart","code":74,"comment":5,"blank":9},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/values-night/styles.xml":{"language":"XML","code":9,"comment":9,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/my_application.h":{"language":"C++","code":7,"comment":7,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/drawable/launch_background.xml":{"language":"XML","code":4,"comment":7,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/my_application.cc":{"language":"C++","code":82,"comment":17,"blank":26},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/CMakeLists.txt":{"language":"CMake","code":118,"comment":0,"blank":28},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/web/manifest.json":{"language":"JSON","code":35,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/main.cc":{"language":"C++","code":5,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Podfile":{"language":"Ruby","code":33,"comment":1,"blank":10},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/AppDelegate.swift":{"language":"Swift","code":8,"comment":0,"blank":2},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/RunnerTests/RunnerTests.swift":{"language":"Swift","code":7,"comment":2,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/MainFlutterWindow.swift":{"language":"Swift","code":12,"comment":0,"blank":4},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json":{"language":"JSON","code":68,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/web/index.html":{"language":"HTML","code":19,"comment":15,"blank":5},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/Base.lproj/MainMenu.xib":{"language":"XML","code":343,"comment":0,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/values/styles.xml":{"language":"XML","code":9,"comment":9,"blank":1},"file:///Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Flutter/GeneratedPluginRegistrant.swift":{"language":"Swift","code":6,"comment":3,"blank":4}} \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/results.md b/.VSCodeCounter/2025-08-24_12-43-46/results.md new file mode 100644 index 0000000..5d45dac --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/results.md @@ -0,0 +1,125 @@ +# Summary + +Date : 2025-08-24 12:43:46 + +Directory /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer + +Total : 133 files, 6259 codes, 411 comments, 1006 blanks, all 7676 lines + +Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md) + +## Languages +| language | files | code | comment | blank | total | +| :--- | ---: | ---: | ---: | ---: | ---: | +| Dart | 77 | 4,214 | 177 | 615 | 5,006 | +| C++ | 16 | 539 | 127 | 188 | 854 | +| XML | 10 | 470 | 53 | 12 | 535 | +| CMake | 7 | 454 | 0 | 89 | 543 | +| JSON | 4 | 248 | 0 | 4 | 252 | +| Groovy | 3 | 81 | 6 | 17 | 104 | +| Ruby | 2 | 65 | 4 | 20 | 89 | +| Markdown | 2 | 56 | 0 | 12 | 68 | +| YAML | 3 | 53 | 22 | 22 | 97 | +| Swift | 6 | 52 | 7 | 20 | 79 | +| HTML | 1 | 19 | 15 | 5 | 39 | +| Properties | 2 | 8 | 0 | 2 | 10 | + +## Directories +| path | files | code | comment | blank | total | +| :--- | ---: | ---: | ---: | ---: | ---: | +| . | 133 | 6,259 | 411 | 1,006 | 7,676 | +| . (Files) | 3 | 82 | 22 | 25 | 129 | +| .github | 1 | 24 | 0 | 7 | 31 | +| .github/workflows | 1 | 24 | 0 | 7 | 31 | +| android | 12 | 155 | 57 | 28 | 240 | +| android (Files) | 3 | 40 | 0 | 9 | 49 | +| android/app | 8 | 110 | 57 | 18 | 185 | +| android/app (Files) | 1 | 44 | 6 | 9 | 59 | +| android/app/src | 7 | 66 | 51 | 9 | 126 | +| android/app/src/debug | 1 | 3 | 4 | 1 | 8 | +| android/app/src/main | 5 | 60 | 43 | 7 | 110 | +| android/app/src/main (Files) | 1 | 34 | 11 | 1 | 46 | +| android/app/src/main/res | 4 | 26 | 32 | 6 | 64 | +| android/app/src/main/res/drawable | 1 | 4 | 7 | 2 | 13 | +| android/app/src/main/res/drawable-v21 | 1 | 4 | 7 | 2 | 13 | +| android/app/src/main/res/values | 1 | 9 | 9 | 1 | 19 | +| android/app/src/main/res/values-night | 1 | 9 | 9 | 1 | 19 | +| android/app/src/profile | 1 | 3 | 4 | 1 | 8 | +| android/gradle | 1 | 5 | 0 | 1 | 6 | +| android/gradle/wrapper | 1 | 5 | 0 | 1 | 6 | +| ios | 9 | 261 | 7 | 23 | 291 | +| ios (Files) | 1 | 32 | 3 | 10 | 45 | +| ios/Runner | 7 | 222 | 2 | 9 | 233 | +| ios/Runner (Files) | 2 | 13 | 0 | 3 | 16 | +| ios/Runner/Assets.xcassets | 3 | 148 | 0 | 4 | 152 | +| ios/Runner/Assets.xcassets/AppIcon.appiconset | 1 | 122 | 0 | 1 | 123 | +| ios/Runner/Assets.xcassets/LaunchImage.imageset | 2 | 26 | 0 | 3 | 29 | +| ios/Runner/Base.lproj | 2 | 61 | 2 | 2 | 65 | +| ios/RunnerTests | 1 | 7 | 2 | 4 | 13 | +| lib | 76 | 4,214 | 147 | 614 | 4,975 | +| lib (Files) | 1 | 6 | 0 | 2 | 8 | +| lib/config | 2 | 364 | 3 | 23 | 390 | +| lib/config/routes | 1 | 125 | 1 | 9 | 135 | +| lib/config/themes | 1 | 239 | 2 | 14 | 255 | +| lib/core | 52 | 2,263 | 65 | 276 | 2,604 | +| lib/core (Files) | 1 | 42 | 0 | 4 | 46 | +| lib/core/enums | 1 | 1 | 0 | 2 | 3 | +| lib/core/extensions | 2 | 146 | 3 | 21 | 170 | +| lib/core/helpers | 11 | 469 | 12 | 77 | 558 | +| lib/core/helpers (Files) | 7 | 241 | 0 | 32 | 273 | +| lib/core/helpers/app_bar | 2 | 148 | 2 | 19 | 169 | +| lib/core/helpers/storage | 2 | 80 | 10 | 26 | 116 | +| lib/core/helpers/storage/app_settings | 2 | 80 | 10 | 26 | 116 | +| lib/core/material_app | 1 | 74 | 5 | 9 | 88 | +| lib/core/resources | 5 | 309 | 38 | 34 | 381 | +| lib/core/widgets | 31 | 1,222 | 7 | 129 | 1,358 | +| lib/core/widgets (Files) | 1 | 18 | 0 | 4 | 22 | +| lib/core/widgets/adaptive | 16 | 311 | 5 | 43 | 359 | +| lib/core/widgets/adaptive/padding | 10 | 146 | 0 | 20 | 166 | +| lib/core/widgets/adaptive/text | 6 | 165 | 5 | 23 | 193 | +| lib/core/widgets/custom_widgets | 14 | 893 | 2 | 82 | 977 | +| lib/features | 21 | 1,581 | 79 | 313 | 1,973 | +| lib/features/base | 1 | 52 | 0 | 5 | 57 | +| lib/features/base/view | 1 | 52 | 0 | 5 | 57 | +| lib/features/searching | 4 | 803 | 22 | 165 | 990 | +| lib/features/searching/view | 1 | 290 | 0 | 35 | 325 | +| lib/features/searching/view_model | 2 | 434 | 19 | 116 | 569 | +| lib/features/searching/widgets | 1 | 79 | 3 | 14 | 96 | +| lib/features/sorting | 16 | 726 | 57 | 143 | 926 | +| lib/features/sorting/base | 8 | 541 | 55 | 89 | 685 | +| lib/features/sorting/base/helper | 2 | 54 | 7 | 12 | 73 | +| lib/features/sorting/base/view | 2 | 265 | 1 | 22 | 288 | +| lib/features/sorting/base/view_model | 2 | 174 | 4 | 51 | 229 | +| lib/features/sorting/base/widgets | 2 | 48 | 43 | 4 | 95 | +| lib/features/sorting/bubble | 2 | 50 | 0 | 16 | 66 | +| lib/features/sorting/bubble/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/bubble/view_model | 1 | 25 | 0 | 10 | 35 | +| lib/features/sorting/insertion | 2 | 47 | 0 | 13 | 60 | +| lib/features/sorting/insertion/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/insertion/view_model | 1 | 22 | 0 | 7 | 29 | +| lib/features/sorting/merge | 2 | 32 | 1 | 8 | 41 | +| lib/features/sorting/merge/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/merge/view_model | 1 | 7 | 1 | 2 | 10 | +| lib/features/sorting/selection | 2 | 56 | 1 | 17 | 74 | +| lib/features/sorting/selection/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/selection/view_model | 1 | 31 | 1 | 11 | 43 | +| linux | 8 | 317 | 33 | 88 | 438 | +| linux (Files) | 4 | 212 | 24 | 61 | 297 | +| linux/flutter | 4 | 105 | 9 | 27 | 141 | +| macos | 7 | 477 | 6 | 26 | 509 | +| macos (Files) | 1 | 33 | 1 | 10 | 44 | +| macos/Flutter | 1 | 6 | 3 | 4 | 13 | +| macos/Runner | 4 | 431 | 0 | 8 | 439 | +| macos/Runner (Files) | 2 | 20 | 0 | 6 | 26 | +| macos/Runner/Assets.xcassets | 1 | 68 | 0 | 1 | 69 | +| macos/Runner/Assets.xcassets/AppIcon.appiconset | 1 | 68 | 0 | 1 | 69 | +| macos/Runner/Base.lproj | 1 | 343 | 0 | 1 | 344 | +| macos/RunnerTests | 1 | 7 | 2 | 4 | 13 | +| test | 1 | 0 | 30 | 1 | 31 | +| web | 2 | 54 | 15 | 6 | 75 | +| windows | 14 | 675 | 94 | 188 | 957 | +| windows (Files) | 1 | 89 | 0 | 20 | 109 | +| windows/flutter | 4 | 124 | 9 | 29 | 162 | +| windows/runner | 9 | 462 | 85 | 139 | 686 | + +Summary / [Details](details.md) / [Diff Summary](diff.md) / [Diff Details](diff-details.md) \ No newline at end of file diff --git a/.VSCodeCounter/2025-08-24_12-43-46/results.txt b/.VSCodeCounter/2025-08-24_12-43-46/results.txt new file mode 100644 index 0000000..fc545f1 --- /dev/null +++ b/.VSCodeCounter/2025-08-24_12-43-46/results.txt @@ -0,0 +1,261 @@ +Date : 2025-08-24 12:43:46 +Directory : /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer +Total : 133 files, 6259 codes, 411 comments, 1006 blanks, all 7676 lines + +Languages ++------------+------------+------------+------------+------------+------------+ +| language | files | code | comment | blank | total | ++------------+------------+------------+------------+------------+------------+ +| Dart | 77 | 4,214 | 177 | 615 | 5,006 | +| C++ | 16 | 539 | 127 | 188 | 854 | +| XML | 10 | 470 | 53 | 12 | 535 | +| CMake | 7 | 454 | 0 | 89 | 543 | +| JSON | 4 | 248 | 0 | 4 | 252 | +| Groovy | 3 | 81 | 6 | 17 | 104 | +| Ruby | 2 | 65 | 4 | 20 | 89 | +| Markdown | 2 | 56 | 0 | 12 | 68 | +| YAML | 3 | 53 | 22 | 22 | 97 | +| Swift | 6 | 52 | 7 | 20 | 79 | +| HTML | 1 | 19 | 15 | 5 | 39 | +| Properties | 2 | 8 | 0 | 2 | 10 | ++------------+------------+------------+------------+------------+------------+ + +Directories ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+ +| path | files | code | comment | blank | total | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+ +| . | 133 | 6,259 | 411 | 1,006 | 7,676 | +| . (Files) | 3 | 82 | 22 | 25 | 129 | +| .github | 1 | 24 | 0 | 7 | 31 | +| .github/workflows | 1 | 24 | 0 | 7 | 31 | +| android | 12 | 155 | 57 | 28 | 240 | +| android (Files) | 3 | 40 | 0 | 9 | 49 | +| android/app | 8 | 110 | 57 | 18 | 185 | +| android/app (Files) | 1 | 44 | 6 | 9 | 59 | +| android/app/src | 7 | 66 | 51 | 9 | 126 | +| android/app/src/debug | 1 | 3 | 4 | 1 | 8 | +| android/app/src/main | 5 | 60 | 43 | 7 | 110 | +| android/app/src/main (Files) | 1 | 34 | 11 | 1 | 46 | +| android/app/src/main/res | 4 | 26 | 32 | 6 | 64 | +| android/app/src/main/res/drawable | 1 | 4 | 7 | 2 | 13 | +| android/app/src/main/res/drawable-v21 | 1 | 4 | 7 | 2 | 13 | +| android/app/src/main/res/values | 1 | 9 | 9 | 1 | 19 | +| android/app/src/main/res/values-night | 1 | 9 | 9 | 1 | 19 | +| android/app/src/profile | 1 | 3 | 4 | 1 | 8 | +| android/gradle | 1 | 5 | 0 | 1 | 6 | +| android/gradle/wrapper | 1 | 5 | 0 | 1 | 6 | +| ios | 9 | 261 | 7 | 23 | 291 | +| ios (Files) | 1 | 32 | 3 | 10 | 45 | +| ios/Runner | 7 | 222 | 2 | 9 | 233 | +| ios/Runner (Files) | 2 | 13 | 0 | 3 | 16 | +| ios/Runner/Assets.xcassets | 3 | 148 | 0 | 4 | 152 | +| ios/Runner/Assets.xcassets/AppIcon.appiconset | 1 | 122 | 0 | 1 | 123 | +| ios/Runner/Assets.xcassets/LaunchImage.imageset | 2 | 26 | 0 | 3 | 29 | +| ios/Runner/Base.lproj | 2 | 61 | 2 | 2 | 65 | +| ios/RunnerTests | 1 | 7 | 2 | 4 | 13 | +| lib | 76 | 4,214 | 147 | 614 | 4,975 | +| lib (Files) | 1 | 6 | 0 | 2 | 8 | +| lib/config | 2 | 364 | 3 | 23 | 390 | +| lib/config/routes | 1 | 125 | 1 | 9 | 135 | +| lib/config/themes | 1 | 239 | 2 | 14 | 255 | +| lib/core | 52 | 2,263 | 65 | 276 | 2,604 | +| lib/core (Files) | 1 | 42 | 0 | 4 | 46 | +| lib/core/enums | 1 | 1 | 0 | 2 | 3 | +| lib/core/extensions | 2 | 146 | 3 | 21 | 170 | +| lib/core/helpers | 11 | 469 | 12 | 77 | 558 | +| lib/core/helpers (Files) | 7 | 241 | 0 | 32 | 273 | +| lib/core/helpers/app_bar | 2 | 148 | 2 | 19 | 169 | +| lib/core/helpers/storage | 2 | 80 | 10 | 26 | 116 | +| lib/core/helpers/storage/app_settings | 2 | 80 | 10 | 26 | 116 | +| lib/core/material_app | 1 | 74 | 5 | 9 | 88 | +| lib/core/resources | 5 | 309 | 38 | 34 | 381 | +| lib/core/widgets | 31 | 1,222 | 7 | 129 | 1,358 | +| lib/core/widgets (Files) | 1 | 18 | 0 | 4 | 22 | +| lib/core/widgets/adaptive | 16 | 311 | 5 | 43 | 359 | +| lib/core/widgets/adaptive/padding | 10 | 146 | 0 | 20 | 166 | +| lib/core/widgets/adaptive/text | 6 | 165 | 5 | 23 | 193 | +| lib/core/widgets/custom_widgets | 14 | 893 | 2 | 82 | 977 | +| lib/features | 21 | 1,581 | 79 | 313 | 1,973 | +| lib/features/base | 1 | 52 | 0 | 5 | 57 | +| lib/features/base/view | 1 | 52 | 0 | 5 | 57 | +| lib/features/searching | 4 | 803 | 22 | 165 | 990 | +| lib/features/searching/view | 1 | 290 | 0 | 35 | 325 | +| lib/features/searching/view_model | 2 | 434 | 19 | 116 | 569 | +| lib/features/searching/widgets | 1 | 79 | 3 | 14 | 96 | +| lib/features/sorting | 16 | 726 | 57 | 143 | 926 | +| lib/features/sorting/base | 8 | 541 | 55 | 89 | 685 | +| lib/features/sorting/base/helper | 2 | 54 | 7 | 12 | 73 | +| lib/features/sorting/base/view | 2 | 265 | 1 | 22 | 288 | +| lib/features/sorting/base/view_model | 2 | 174 | 4 | 51 | 229 | +| lib/features/sorting/base/widgets | 2 | 48 | 43 | 4 | 95 | +| lib/features/sorting/bubble | 2 | 50 | 0 | 16 | 66 | +| lib/features/sorting/bubble/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/bubble/view_model | 1 | 25 | 0 | 10 | 35 | +| lib/features/sorting/insertion | 2 | 47 | 0 | 13 | 60 | +| lib/features/sorting/insertion/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/insertion/view_model | 1 | 22 | 0 | 7 | 29 | +| lib/features/sorting/merge | 2 | 32 | 1 | 8 | 41 | +| lib/features/sorting/merge/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/merge/view_model | 1 | 7 | 1 | 2 | 10 | +| lib/features/sorting/selection | 2 | 56 | 1 | 17 | 74 | +| lib/features/sorting/selection/view | 1 | 25 | 0 | 6 | 31 | +| lib/features/sorting/selection/view_model | 1 | 31 | 1 | 11 | 43 | +| linux | 8 | 317 | 33 | 88 | 438 | +| linux (Files) | 4 | 212 | 24 | 61 | 297 | +| linux/flutter | 4 | 105 | 9 | 27 | 141 | +| macos | 7 | 477 | 6 | 26 | 509 | +| macos (Files) | 1 | 33 | 1 | 10 | 44 | +| macos/Flutter | 1 | 6 | 3 | 4 | 13 | +| macos/Runner | 4 | 431 | 0 | 8 | 439 | +| macos/Runner (Files) | 2 | 20 | 0 | 6 | 26 | +| macos/Runner/Assets.xcassets | 1 | 68 | 0 | 1 | 69 | +| macos/Runner/Assets.xcassets/AppIcon.appiconset | 1 | 68 | 0 | 1 | 69 | +| macos/Runner/Base.lproj | 1 | 343 | 0 | 1 | 344 | +| macos/RunnerTests | 1 | 7 | 2 | 4 | 13 | +| test | 1 | 0 | 30 | 1 | 31 | +| web | 2 | 54 | 15 | 6 | 75 | +| windows | 14 | 675 | 94 | 188 | 957 | +| windows (Files) | 1 | 89 | 0 | 20 | 109 | +| windows/flutter | 4 | 124 | 9 | 29 | 162 | +| windows/runner | 9 | 462 | 85 | 139 | 686 | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+ + +Files ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+ +| filename | language | code | comment | blank | total | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+ +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/.github/workflows/script.yml | YAML | 24 | 0 | 7 | 31 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/README.md | Markdown | 53 | 0 | 10 | 63 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/analysis_options.yaml | YAML | 3 | 22 | 4 | 29 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/build.gradle | Groovy | 44 | 6 | 9 | 59 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/debug/AndroidManifest.xml | XML | 3 | 4 | 1 | 8 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/AndroidManifest.xml | XML | 34 | 11 | 1 | 46 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/drawable-v21/launch_background.xml | XML | 4 | 7 | 2 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/drawable/launch_background.xml | XML | 4 | 7 | 2 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/values-night/styles.xml | XML | 9 | 9 | 1 | 19 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/main/res/values/styles.xml | XML | 9 | 9 | 1 | 19 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/app/src/profile/AndroidManifest.xml | XML | 3 | 4 | 1 | 8 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/build.gradle | Groovy | 16 | 0 | 3 | 19 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/gradle.properties | Properties | 3 | 0 | 1 | 4 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/gradle/wrapper/gradle-wrapper.properties | Properties | 5 | 0 | 1 | 6 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/android/settings.gradle | Groovy | 21 | 0 | 5 | 26 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Podfile | Ruby | 32 | 3 | 10 | 45 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/AppDelegate.swift | Swift | 12 | 0 | 2 | 14 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json | JSON | 122 | 0 | 1 | 123 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json | JSON | 23 | 0 | 1 | 24 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md | Markdown | 3 | 0 | 2 | 5 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Base.lproj/LaunchScreen.storyboard | XML | 36 | 1 | 1 | 38 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Base.lproj/Main.storyboard | XML | 25 | 1 | 1 | 27 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/Runner/Runner-Bridging-Header.h | C++ | 1 | 0 | 1 | 2 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/ios/RunnerTests/RunnerTests.swift | Swift | 7 | 2 | 4 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/config/routes/route_app.dart | Dart | 125 | 1 | 9 | 135 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/config/themes/app_theme.dart | Dart | 239 | 2 | 14 | 255 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/draggable_progress.dart | Dart | 42 | 0 | 4 | 46 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/enums/app_settings_enum.dart | Dart | 1 | 0 | 2 | 3 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/extensions/language.dart | Dart | 20 | 0 | 5 | 25 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/extensions/navigators.dart | Dart | 126 | 3 | 16 | 145 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/app_bar/app_bar.dart | Dart | 127 | 2 | 13 | 142 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/app_bar/back_button.dart | Dart | 21 | 0 | 6 | 27 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/current_device.dart | Dart | 7 | 0 | 2 | 9 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/custom_alert_dialog.dart | Dart | 123 | 0 | 8 | 131 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/random_int.dart | Dart | 9 | 0 | 4 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/random_text.dart | Dart | 13 | 0 | 7 | 20 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/screen_size.dart | Dart | 7 | 0 | 2 | 9 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/storage/app_settings/app_settings_cubit.dart | Dart | 62 | 10 | 21 | 93 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/storage/app_settings/app_settings_state.dart | Dart | 18 | 0 | 5 | 23 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/svg_picture.dart | Dart | 31 | 0 | 3 | 34 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/helpers/system_overlay_style.dart | Dart | 51 | 0 | 6 | 57 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/material_app/my_app.dart | Dart | 74 | 5 | 9 | 88 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/color_manager.dart | Dart | 79 | 23 | 8 | 110 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/font_manager.dart | Dart | 26 | 11 | 4 | 41 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/strings_manager.dart | Dart | 41 | 2 | 5 | 48 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/styles_manager.dart | Dart | 77 | 0 | 7 | 84 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/resources/theme_manager.dart | Dart | 86 | 2 | 10 | 98 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adapt_widget_size.dart | Dart | 18 | 0 | 4 | 22 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/adaptive_padding.dart | Dart | 20 | 0 | 2 | 22 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/all_padding.dart | Dart | 11 | 0 | 2 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/bottom_padding.dart | Dart | 11 | 0 | 3 | 14 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/end_padding.dart | Dart | 11 | 0 | 2 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/horizontal_padding.dart | Dart | 12 | 0 | 2 | 14 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/only_padding.dart | Dart | 28 | 0 | 3 | 31 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/start_padding.dart | Dart | 12 | 0 | 1 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/symmetric_padding.dart | Dart | 17 | 0 | 2 | 19 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/top_padding.dart | Dart | 12 | 0 | 1 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/padding/vertical_padding.dart | Dart | 12 | 0 | 2 | 14 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/adaptive_text.dart | Dart | 91 | 5 | 13 | 109 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/bold_text.dart | Dart | 15 | 0 | 2 | 17 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/light_text.dart | Dart | 14 | 0 | 2 | 16 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/medium_text.dart | Dart | 16 | 0 | 2 | 18 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/regular_text.dart | Dart | 14 | 0 | 2 | 16 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/adaptive/text/semi_bold_text.dart | Dart | 15 | 0 | 2 | 17 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/check_box.dart | Dart | 51 | 0 | 2 | 53 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_bottom_sheet.dart | Dart | 197 | 0 | 8 | 205 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_circulars_progress.dart | Dart | 215 | 0 | 24 | 239 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_dialog.dart | Dart | 91 | 0 | 6 | 97 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_divider.dart | Dart | 29 | 0 | 4 | 33 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_icon.dart | Dart | 25 | 0 | 2 | 27 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_rounded_elevated_button.dart | Dart | 45 | 0 | 4 | 49 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/custom_switch.dart | Dart | 35 | 2 | 4 | 41 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/error_screen.dart | Dart | 26 | 0 | 2 | 28 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/hero_widget.dart | Dart | 15 | 0 | 3 | 18 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/keyboard_detected.dart | Dart | 47 | 0 | 9 | 56 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/rounded_outlined_button.dart | Dart | 44 | 0 | 4 | 48 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/scale_transition.dart | Dart | 34 | 0 | 6 | 40 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/core/widgets/custom_widgets/vertical_animation_hero_page.dart | Dart | 39 | 0 | 4 | 43 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/base/view/base_page.dart | Dart | 52 | 0 | 5 | 57 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view/grid_page.dart | Dart | 290 | 0 | 35 | 325 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view_model/grid_notifier.dart | Dart | 384 | 18 | 109 | 511 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/view_model/grid_notifier_state.dart | Dart | 50 | 1 | 7 | 58 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/searching/widgets/searcher_grid.dart | Dart | 79 | 3 | 14 | 96 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/helper/sortable_item.dart | Dart | 45 | 1 | 8 | 54 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/helper/sorting_enums.dart | Dart | 9 | 6 | 4 | 19 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view/sorting_list_page.dart | Dart | 60 | 0 | 3 | 63 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view/sorting_page.dart | Dart | 205 | 1 | 19 | 225 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view_model/sorting_notifier.dart | Dart | 143 | 4 | 48 | 195 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/view_model/sorting_state.dart | Dart | 31 | 0 | 3 | 34 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/widgets/control_buttons.dart | Dart | 47 | 0 | 3 | 50 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/base/widgets/sorting_app_bar.dart | Dart | 1 | 43 | 1 | 45 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/bubble/view/bubble_sort_page.dart | Dart | 25 | 0 | 6 | 31 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/bubble/view_model/bubble_sort_notifier.dart | Dart | 25 | 0 | 10 | 35 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/insertion/view/insertion_sort_page.dart | Dart | 25 | 0 | 6 | 31 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/insertion/view_model/insertion_sort_notifier.dart | Dart | 22 | 0 | 7 | 29 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/merge/view/merge_sort_page.dart | Dart | 25 | 0 | 6 | 31 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/merge/view_model/merge_sort_notifier.dart | Dart | 7 | 1 | 2 | 10 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/selection/view/selection_sort_page.dart | Dart | 25 | 0 | 6 | 31 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/features/sorting/selection/view_model/selection_sort_notifier.dart | Dart | 31 | 1 | 11 | 43 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/lib/main.dart | Dart | 6 | 0 | 2 | 8 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/CMakeLists.txt | CMake | 118 | 0 | 28 | 146 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/CMakeLists.txt | CMake | 79 | 0 | 10 | 89 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugin_registrant.cc | C++ | 3 | 4 | 5 | 12 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugin_registrant.h | C++ | 5 | 5 | 6 | 16 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/flutter/generated_plugins.cmake | CMake | 18 | 0 | 6 | 24 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/main.cc | C++ | 5 | 0 | 2 | 7 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/my_application.cc | C++ | 82 | 17 | 26 | 125 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/linux/my_application.h | C++ | 7 | 7 | 5 | 19 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Flutter/GeneratedPluginRegistrant.swift | Swift | 6 | 3 | 4 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Podfile | Ruby | 33 | 1 | 10 | 44 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/AppDelegate.swift | Swift | 8 | 0 | 2 | 10 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json | JSON | 68 | 0 | 1 | 69 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/Base.lproj/MainMenu.xib | XML | 343 | 0 | 1 | 344 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/Runner/MainFlutterWindow.swift | Swift | 12 | 0 | 4 | 16 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/macos/RunnerTests/RunnerTests.swift | Swift | 7 | 2 | 4 | 13 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/pubspec.yaml | YAML | 26 | 0 | 11 | 37 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/test/widget_test.dart | Dart | 0 | 30 | 1 | 31 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/web/index.html | HTML | 19 | 15 | 5 | 39 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/web/manifest.json | JSON | 35 | 0 | 1 | 36 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/CMakeLists.txt | CMake | 89 | 0 | 20 | 109 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/CMakeLists.txt | CMake | 98 | 0 | 12 | 110 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugin_registrant.cc | C++ | 3 | 4 | 5 | 12 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugin_registrant.h | C++ | 5 | 5 | 6 | 16 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/flutter/generated_plugins.cmake | CMake | 18 | 0 | 6 | 24 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/CMakeLists.txt | CMake | 34 | 0 | 7 | 41 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/flutter_window.cpp | C++ | 49 | 7 | 16 | 72 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/flutter_window.h | C++ | 20 | 5 | 9 | 34 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/main.cpp | C++ | 30 | 4 | 10 | 44 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/resource.h | C++ | 9 | 6 | 2 | 17 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/utils.cpp | C++ | 54 | 2 | 10 | 66 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/utils.h | C++ | 8 | 6 | 6 | 20 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/win32_window.cpp | C++ | 210 | 24 | 55 | 289 | +| /Users/ahmedelhawary/Documents/side_projects/flutter_projects/projects/algorithm-visualizer/windows/runner/win32_window.h | C++ | 48 | 31 | 24 | 103 | +| Total | | 6,259 | 411 | 1,006 | 7,676 | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------+------------+------------+------------+------------+ \ No newline at end of file diff --git a/macos/Podfile.lock b/macos/Podfile.lock new file mode 100644 index 0000000..8590126 --- /dev/null +++ b/macos/Podfile.lock @@ -0,0 +1,23 @@ +PODS: + - FlutterMacOS (1.0.0) + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + +DEPENDENCIES: + - FlutterMacOS (from `Flutter/ephemeral`) + - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) + +EXTERNAL SOURCES: + FlutterMacOS: + :path: Flutter/ephemeral + path_provider_foundation: + :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin + +SPEC CHECKSUMS: + FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + +PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367 + +COCOAPODS: 1.16.2