From ae3a8b496e8436800b7a3b81e0ddf2eae927a10a Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 1 May 2026 17:22:20 +0200 Subject: [PATCH] Added copyWith(), == and hashCode overwrites for model classes --- lib/data/models/game.dart | 39 +++++++++++++++++++- lib/data/models/group.dart | 37 +++++++++++++++++++ lib/data/models/match.dart | 63 +++++++++++++++++++++++++++++--- lib/data/models/player.dart | 32 +++++++++++++++- lib/data/models/score_entry.dart | 20 ++++++++++ lib/data/models/team.dart | 37 +++++++++++++++++-- pubspec.yaml | 1 + 7 files changed, 215 insertions(+), 14 deletions(-) diff --git a/lib/data/models/game.dart b/lib/data/models/game.dart index 607db0a..c02f455 100644 --- a/lib/data/models/game.dart +++ b/lib/data/models/game.dart @@ -28,7 +28,43 @@ class Game { return 'Game{id: $id, name: $name, ruleset: $ruleset, description: $description, color: $color, icon: $icon}'; } - /// Creates a Game instance from a JSON object. + Game copyWith({ + String? id, + DateTime? createdAt, + String? name, + Ruleset? ruleset, + String? description, + GameColor? color, + String? icon, + }) { + return Game( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + name: name ?? this.name, + ruleset: ruleset ?? this.ruleset, + description: description ?? this.description, + color: color ?? this.color, + icon: icon ?? this.icon, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Game && + runtimeType == other.runtimeType && + id == other.id && + createdAt == other.createdAt && + name == other.name && + ruleset == other.ruleset && + description == other.description && + color == other.color && + icon == other.icon; + + @override + int get hashCode => + Object.hash(id, createdAt, name, ruleset, description, color, icon); + Game.fromJson(Map json) : id = json['id'], createdAt = DateTime.parse(json['createdAt']), @@ -41,7 +77,6 @@ class Game { color = GameColor.values.firstWhere((e) => e.name == json['color']), icon = json['icon']; - /// Converts the Game instance to a JSON object. Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), diff --git a/lib/data/models/group.dart b/lib/data/models/group.dart index c684541..5c1515c 100644 --- a/lib/data/models/group.dart +++ b/lib/data/models/group.dart @@ -1,4 +1,5 @@ import 'package:clock/clock.dart'; +import 'package:collection/collection.dart'; import 'package:tallee/data/models/player.dart'; import 'package:uuid/uuid.dart'; @@ -24,6 +25,42 @@ class Group { return 'Group{id: $id, name: $name, description: $description, members: $members}'; } + Group copyWith({ + String? id, + String? name, + String? description, + DateTime? createdAt, + List? members, + }) { + return Group( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + members: members ?? this.members, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Group && + runtimeType == other.runtimeType && + id == other.id && + name == other.name && + description == other.description && + createdAt == other.createdAt && + const DeepCollectionEquality().equals(members, other.members); + + @override + int get hashCode => Object.hash( + id, + name, + description, + createdAt, + const DeepCollectionEquality().hash(members), + ); + /// Creates a Group instance from a JSON object where the related [Player] /// objects are represented by their IDs. Group.fromJson(Map json) diff --git a/lib/data/models/match.dart b/lib/data/models/match.dart index b0b487c..9d14bb3 100644 --- a/lib/data/models/match.dart +++ b/lib/data/models/match.dart @@ -1,4 +1,5 @@ import 'package:clock/clock.dart'; +import 'package:collection/collection.dart'; import 'package:tallee/core/enums.dart'; import 'package:tallee/data/models/game.dart'; import 'package:tallee/data/models/group.dart'; @@ -39,9 +40,62 @@ class Match { return 'Match{id: $id, createdAt: $createdAt, endedAt: $endedAt, name: $name, game: $game, group: $group, players: $players, notes: $notes, scores: $scores, mvp: $mvp}'; } - /// Creates a Match instance from a JSON object where related objects are - /// represented by their IDs. Therefore, the game, group, and players are not - /// fully constructed here. + Match copyWith({ + String? id, + DateTime? createdAt, + DateTime? endedAt, + String? name, + Game? game, + Group? group, + List? players, + List? teams, + String? notes, + Map? scores, + }) { + return Match( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + endedAt: endedAt ?? this.endedAt, + name: name ?? this.name, + game: game ?? this.game, + group: group ?? this.group, + players: players ?? this.players, + teams: teams ?? this.teams, + notes: notes ?? this.notes, + scores: scores ?? this.scores, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Match && + runtimeType == other.runtimeType && + id == other.id && + createdAt == other.createdAt && + endedAt == other.endedAt && + name == other.name && + game == other.game && + group == other.group && + const DeepCollectionEquality().equals(players, other.players) && + const DeepCollectionEquality().equals(teams, other.teams) && + notes == other.notes && + const DeepCollectionEquality().equals(scores, other.scores); + + @override + int get hashCode => Object.hash( + id, + createdAt, + endedAt, + name, + game, + group, + const DeepCollectionEquality().hash(players), + const DeepCollectionEquality().hash(teams), + notes, + const DeepCollectionEquality().hash(scores), + ); + Match.fromJson(Map json) : id = json['id'], createdAt = DateTime.parse(json['createdAt']), @@ -71,9 +125,6 @@ class Match { : {}, notes = json['notes'] ?? ''; - /// Converts the Match instance to a JSON object. Related objects are - /// represented by their IDs, so the game, group, and players are not fully - /// serialized here. Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), diff --git a/lib/data/models/player.dart b/lib/data/models/player.dart index 12d17f0..3e42fb9 100644 --- a/lib/data/models/player.dart +++ b/lib/data/models/player.dart @@ -23,7 +23,36 @@ class Player { return 'Player{id: $id, createdAt: $createdAt, name: $name, nameCount: $nameCount, description: $description}'; } - /// Creates a Player instance from a JSON object. + Player copyWith({ + String? id, + DateTime? createdAt, + String? name, + int? nameCount, + String? description, + }) { + return Player( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + name: name ?? this.name, + nameCount: nameCount ?? this.nameCount, + description: description ?? this.description, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Player && + runtimeType == other.runtimeType && + id == other.id && + createdAt == other.createdAt && + name == other.name && + nameCount == other.nameCount && + description == other.description; + + @override + int get hashCode => Object.hash(id, createdAt, name, nameCount, description); + Player.fromJson(Map json) : id = json['id'], createdAt = DateTime.parse(json['createdAt']), @@ -31,7 +60,6 @@ class Player { nameCount = 0, description = json['description']; - /// Converts the Player instance to a JSON object. Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), diff --git a/lib/data/models/score_entry.dart b/lib/data/models/score_entry.dart index f9c5ff0..a88f304 100644 --- a/lib/data/models/score_entry.dart +++ b/lib/data/models/score_entry.dart @@ -10,6 +10,26 @@ class ScoreEntry { return 'ScoreEntry{roundNumber: $roundNumber, score: $score, change: $change}'; } + ScoreEntry copyWith({int? roundNumber, int? score, int? change}) { + return ScoreEntry( + roundNumber: roundNumber ?? this.roundNumber, + score: score ?? this.score, + change: change ?? this.change, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is ScoreEntry && + runtimeType == other.runtimeType && + roundNumber == other.roundNumber && + score == other.score && + change == other.change; + + @override + int get hashCode => Object.hash(roundNumber, score, change); + ScoreEntry.fromJson(Map json) : roundNumber = json['roundNumber'], score = json['score'], diff --git a/lib/data/models/team.dart b/lib/data/models/team.dart index f5941c4..b16e2ec 100644 --- a/lib/data/models/team.dart +++ b/lib/data/models/team.dart @@ -1,4 +1,5 @@ import 'package:clock/clock.dart'; +import 'package:collection/collection.dart'; import 'package:tallee/data/models/player.dart'; import 'package:uuid/uuid.dart'; @@ -21,16 +22,44 @@ class Team { return 'Team{id: $id, name: $name, members: $members}'; } - /// Creates a Team instance from a JSON object (memberIds format). - /// Player objects are reconstructed from memberIds by the DataTransferService. + Team copyWith({ + String? id, + String? name, + DateTime? createdAt, + List? members, + }) { + return Team( + id: id ?? this.id, + name: name ?? this.name, + createdAt: createdAt ?? this.createdAt, + members: members ?? this.members, + ); + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Team && + runtimeType == other.runtimeType && + id == other.id && + name == other.name && + createdAt == other.createdAt && + const DeepCollectionEquality().equals(members, other.members); + + @override + int get hashCode => Object.hash( + id, + name, + createdAt, + const DeepCollectionEquality().hash(members), + ); + Team.fromJson(Map json) : id = json['id'], name = json['name'], createdAt = DateTime.parse(json['createdAt']), members = []; // Populated during import via DataTransferService - /// Converts the Team instance to a JSON object. Related objects are - /// represented by their IDs. Map toJson() => { 'id': id, 'name': name, diff --git a/pubspec.yaml b/pubspec.yaml index 363ea7f..d5ed039 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,6 +8,7 @@ environment: dependencies: clock: ^1.1.2 + collection: ^1.19.1 cupertino_icons: ^1.0.6 drift: ^2.27.0 drift_flutter: ^0.2.4