-
Notifications
You must be signed in to change notification settings - Fork 19
Open
Labels
Description
Summary
The EmptyCard and InitialCard widgets are functionally identical - both render empty centered columns with the same implementation. This is a 100% code duplication that should be consolidated into a single reusable component.
Duplication Details
Pattern: Identical Widget Implementations
- Severity: High
- Occurrences: 2 instances
- Locations:
lib/ui/widgets/empty_card.dart:3-17lib/ui/widgets/initial_card.dart:3-17
Code Sample:
// empty_card.dart
class EmptyCard extends StatelessWidget {
const EmptyCard({
Key? key,
}) : super(key: key);
`@override`
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [],
),
);
}
}
// initial_card.dart - IDENTICAL except class name
class InitialCard extends StatelessWidget {
const InitialCard({
Key? key,
}) : super(key: key);
`@override`
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [],
),
);
}
}Impact Analysis
- Maintainability: Any changes to the empty state UI must be duplicated across both files, increasing the risk of inconsistencies
- Bug Risk: If one widget is updated but not the other, the app will have inconsistent empty state behavior
- Code Bloat: 17 lines of unnecessary duplicate code
Refactoring Recommendations
Option 1: Single Widget with Type Parameter (Recommended)
Extract to a single PlaceholderCard widget with a parameter to distinguish between states:
class PlaceholderCard extends StatelessWidget {
final PlaceholderType type;
const PlaceholderCard({
Key? key,
this.type = PlaceholderType.empty,
}) : super(key: key);
`@override`
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [],
),
);
}
}
enum PlaceholderType { empty, initial }Option 2: Named Constructors
Use a single widget with named constructors:
class PlaceholderCard extends StatelessWidget {
const PlaceholderCard({Key? key}) : super(key: key);
const PlaceholderCard.empty({Key? key}) : super(key: key);
const PlaceholderCard.initial({Key? key}) : super(key: key);
`@override`
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [],
),
);
}
}Option 3: Type Aliases
If the widgets truly need to remain separate for semantic reasons, use type aliases:
typedef EmptyCard = PlaceholderCard;
typedef InitialCard = PlaceholderCard;Implementation Checklist
- Review current usage of
EmptyCardandInitialCardto determine if they need different behavior - Choose refactoring approach (Option 1 recommended)
- Create unified
PlaceholderCardwidget - Update all references to
EmptyCardandInitialCard - Remove duplicate widget files
- Update widget exports in
lib/ui/widgets/widgets.dart - Run tests to verify no functionality broken
Analysis Metadata
- Analyzed Files: 25 Dart files
- Detection Method: Semantic code analysis
- Commit: eaf30ea
- Analysis Date: 2026-02-18
- Duplication Size: 17 lines (100% match)
AI generated by Duplicate Code Detector
To add this workflow in your repository, run
gh aw add github/gh-aw/.github/workflows/duplicate-code-detector.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4. See usage guide.
Reactions are currently unavailable