all parameters are now required

This commit is contained in:
gelbeinhalb
2026-01-29 15:39:52 +01:00
parent 3bd6dd4189
commit 1d352821fc
29 changed files with 227 additions and 197 deletions

View File

@@ -17,13 +17,14 @@
"type": "string" "type": "string"
}, },
"description": { "description": {
"type": ["string", "null"] "type": "string"
} }
}, },
"required": [ "required": [
"id", "id",
"createdAt", "createdAt",
"name" "name",
"description"
] ]
} }
}, },
@@ -42,22 +43,26 @@
"type": "string" "type": "string"
}, },
"ruleset": { "ruleset": {
"type": ["string", "null"] "type": "string"
}, },
"description": { "description": {
"type": ["string", "null"] "type": "string"
}, },
"color": { "color": {
"type": ["integer", "null"] "type": "string"
}, },
"icon": { "icon": {
"type": ["string", "null"] "type": "string"
} }
}, },
"required": [ "required": [
"id", "id",
"createdAt", "createdAt",
"name" "name",
"ruleset",
"description",
"color",
"icon"
] ]
} }
}, },
@@ -76,7 +81,7 @@
"type": "string" "type": "string"
}, },
"description": { "description": {
"type": ["string", "null"] "type": "string"
}, },
"memberIds": { "memberIds": {
"type": "array", "type": "array",
@@ -89,6 +94,7 @@
"id", "id",
"name", "name",
"createdAt", "createdAt",
"description",
"memberIds" "memberIds"
] ]
} }
@@ -137,10 +143,7 @@
"type": "string" "type": "string"
}, },
"gameId": { "gameId": {
"anyOf": [ "type": "string"
{"type": "string"},
{"type": "null"}
]
}, },
"groupId": { "groupId": {
"anyOf": [ "anyOf": [
@@ -155,17 +158,16 @@
} }
}, },
"notes": { "notes": {
"anyOf": [ "type": "string"
{"type": "string"},
{"type": "null"}
]
} }
}, },
"required": [ "required": [
"id", "id",
"name", "name",
"createdAt", "createdAt",
"playerIds" "gameId",
"playerIds",
"notes"
] ]
} }
} }

View File

@@ -56,7 +56,7 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
ruleset: game.ruleset.name, ruleset: game.ruleset.name,
description: game.description, description: game.description,
color: game.color, color: game.color,
icon: Value(game.icon), icon: game.icon,
createdAt: game.createdAt, createdAt: game.createdAt,
), ),
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
@@ -82,7 +82,7 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
ruleset: game.ruleset.name, ruleset: game.ruleset.name,
description: game.description, description: game.description,
color: game.color, color: game.color,
icon: Value(game.icon), icon: game.icon,
createdAt: game.createdAt, createdAt: game.createdAt,
), ),
) )
@@ -153,7 +153,7 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
/// Updates the icon of the game with the given [gameId]. /// Updates the icon of the game with the given [gameId].
Future<void> updateGameIcon({ Future<void> updateGameIcon({
required String gameId, required String gameId,
required String? newIcon, required String newIcon,
}) async { }) async {
await (update(gameTable)..where((g) => g.id.equals(gameId))).write( await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(icon: Value(newIcon)), GameTableCompanion(icon: Value(newIcon)),

View File

@@ -58,7 +58,7 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
GroupTableCompanion.insert( GroupTableCompanion.insert(
id: group.id, id: group.id,
name: group.name, name: group.name,
description: Value(group.description), description: group.description,
createdAt: group.createdAt, createdAt: group.createdAt,
), ),
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
@@ -108,7 +108,7 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
(group) => GroupTableCompanion.insert( (group) => GroupTableCompanion.insert(
id: group.id, id: group.id,
name: group.name, name: group.name,
description: Value(group.description), description: group.description,
createdAt: group.createdAt, createdAt: group.createdAt,
), ),
) )
@@ -136,7 +136,7 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
(p) => PlayerTableCompanion.insert( (p) => PlayerTableCompanion.insert(
id: p.id, id: p.id,
name: p.name, name: p.name,
description: Value(p.description), description: p.description,
createdAt: p.createdAt, createdAt: p.createdAt,
), ),
) )
@@ -196,7 +196,7 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
/// Returns `true` if more than 0 rows were affected, otherwise `false`. /// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateGroupDescription({ Future<bool> updateGroupDescription({
required String groupId, required String groupId,
required String? newDescription, required String newDescription,
}) async { }) async {
final rowsAffected = final rowsAffected =
await (update(groupTable)..where((g) => g.id.equals(groupId))).write( await (update(groupTable)..where((g) => g.id.equals(groupId))).write(

View File

@@ -36,7 +36,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
game: game, game: game,
group: group, group: group,
players: players, players: players,
notes: row.notes, notes: row.notes ?? '',
createdAt: row.createdAt, createdAt: row.createdAt,
); );
}), }),
@@ -66,7 +66,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
game: game, game: game,
group: group, group: group,
players: players, players: players,
notes: result.notes, notes: result.notes ?? '',
createdAt: result.createdAt, createdAt: result.createdAt,
); );
} }
@@ -75,15 +75,11 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
/// This method assumes that the game and group (if any) are already present /// This method assumes that the game and group (if any) are already present
/// in the database. /// in the database.
Future<void> addMatch({required Match match}) async { Future<void> addMatch({required Match match}) async {
if (match.game == null) {
throw ArgumentError('Match must have a game associated with it');
}
await db.transaction(() async { await db.transaction(() async {
await into(matchTable).insert( await into(matchTable).insert(
MatchTableCompanion.insert( MatchTableCompanion.insert(
id: match.id, id: match.id,
gameId: match.game!.id, gameId: match.game.id,
groupId: Value(match.group?.id), groupId: Value(match.group?.id),
name: Value(match.name), name: Value(match.name),
notes: Value(match.notes), notes: Value(match.notes),
@@ -113,9 +109,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
// Add all games first (deduplicated) // Add all games first (deduplicated)
final uniqueGames = <String, Game>{}; final uniqueGames = <String, Game>{};
for (final match in matches) { for (final match in matches) {
if (match.game != null) { uniqueGames[match.game.id] = match.game;
uniqueGames[match.game!.id] = match.game!;
}
} }
if (uniqueGames.isNotEmpty) { if (uniqueGames.isNotEmpty) {
@@ -130,7 +124,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
ruleset: game.ruleset.name, ruleset: game.ruleset.name,
description: game.description, description: game.description,
color: game.color, color: game.color,
icon: Value(game.icon), icon: game.icon,
createdAt: game.createdAt, createdAt: game.createdAt,
), ),
) )
@@ -150,7 +144,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
(match) => GroupTableCompanion.insert( (match) => GroupTableCompanion.insert(
id: match.group!.id, id: match.group!.id,
name: match.group!.name, name: match.group!.name,
description: Value(match.group!.description), description: match.group!.description,
createdAt: match.group!.createdAt, createdAt: match.group!.createdAt,
), ),
) )
@@ -164,11 +158,10 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
(b) => b.insertAll( (b) => b.insertAll(
matchTable, matchTable,
matches matches
.where((match) => match.game != null)
.map( .map(
(match) => MatchTableCompanion.insert( (match) => MatchTableCompanion.insert(
id: match.id, id: match.id,
gameId: match.game!.id, gameId: match.game.id,
groupId: Value(match.group?.id), groupId: Value(match.group?.id),
name: Value(match.name), name: Value(match.name),
notes: Value(match.notes), notes: Value(match.notes),
@@ -205,7 +198,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
(p) => PlayerTableCompanion.insert( (p) => PlayerTableCompanion.insert(
id: p.id, id: p.id,
name: p.name, name: p.name,
description: Value(p.description), description: p.description,
createdAt: p.createdAt, createdAt: p.createdAt,
), ),
) )

View File

@@ -46,7 +46,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
PlayerTableCompanion.insert( PlayerTableCompanion.insert(
id: player.id, id: player.id,
name: player.name, name: player.name,
description: Value(player.description), description: player.description,
createdAt: player.createdAt, createdAt: player.createdAt,
), ),
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
@@ -70,7 +70,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
(player) => PlayerTableCompanion.insert( (player) => PlayerTableCompanion.insert(
id: player.id, id: player.id,
name: player.name, name: player.name,
description: Value(player.description), description: player.description,
createdAt: player.createdAt, createdAt: player.createdAt,
), ),
) )

View File

@@ -34,9 +34,9 @@ class $PlayerTableTable extends PlayerTable
late final GeneratedColumn<String> description = GeneratedColumn<String>( late final GeneratedColumn<String> description = GeneratedColumn<String>(
'description', 'description',
aliasedName, aliasedName,
true, false,
type: DriftSqlType.string, type: DriftSqlType.string,
requiredDuringInsert: false, requiredDuringInsert: true,
); );
static const VerificationMeta _createdAtMeta = const VerificationMeta( static const VerificationMeta _createdAtMeta = const VerificationMeta(
'createdAt', 'createdAt',
@@ -84,6 +84,8 @@ class $PlayerTableTable extends PlayerTable
_descriptionMeta, _descriptionMeta,
), ),
); );
} else if (isInserting) {
context.missing(_descriptionMeta);
} }
if (data.containsKey('created_at')) { if (data.containsKey('created_at')) {
context.handle( context.handle(
@@ -113,7 +115,7 @@ class $PlayerTableTable extends PlayerTable
description: attachedDatabase.typeMapping.read( description: attachedDatabase.typeMapping.read(
DriftSqlType.string, DriftSqlType.string,
data['${effectivePrefix}description'], data['${effectivePrefix}description'],
), )!,
createdAt: attachedDatabase.typeMapping.read( createdAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, DriftSqlType.dateTime,
data['${effectivePrefix}created_at'], data['${effectivePrefix}created_at'],
@@ -130,12 +132,12 @@ class $PlayerTableTable extends PlayerTable
class PlayerTableData extends DataClass implements Insertable<PlayerTableData> { class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
final String id; final String id;
final String name; final String name;
final String? description; final String description;
final DateTime createdAt; final DateTime createdAt;
const PlayerTableData({ const PlayerTableData({
required this.id, required this.id,
required this.name, required this.name,
this.description, required this.description,
required this.createdAt, required this.createdAt,
}); });
@override @override
@@ -143,9 +145,7 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
final map = <String, Expression>{}; final map = <String, Expression>{};
map['id'] = Variable<String>(id); map['id'] = Variable<String>(id);
map['name'] = Variable<String>(name); map['name'] = Variable<String>(name);
if (!nullToAbsent || description != null) { map['description'] = Variable<String>(description);
map['description'] = Variable<String>(description);
}
map['created_at'] = Variable<DateTime>(createdAt); map['created_at'] = Variable<DateTime>(createdAt);
return map; return map;
} }
@@ -154,9 +154,7 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
return PlayerTableCompanion( return PlayerTableCompanion(
id: Value(id), id: Value(id),
name: Value(name), name: Value(name),
description: description == null && nullToAbsent description: Value(description),
? const Value.absent()
: Value(description),
createdAt: Value(createdAt), createdAt: Value(createdAt),
); );
} }
@@ -169,7 +167,7 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
return PlayerTableData( return PlayerTableData(
id: serializer.fromJson<String>(json['id']), id: serializer.fromJson<String>(json['id']),
name: serializer.fromJson<String>(json['name']), name: serializer.fromJson<String>(json['name']),
description: serializer.fromJson<String?>(json['description']), description: serializer.fromJson<String>(json['description']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']), createdAt: serializer.fromJson<DateTime>(json['createdAt']),
); );
} }
@@ -179,7 +177,7 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
return <String, dynamic>{ return <String, dynamic>{
'id': serializer.toJson<String>(id), 'id': serializer.toJson<String>(id),
'name': serializer.toJson<String>(name), 'name': serializer.toJson<String>(name),
'description': serializer.toJson<String?>(description), 'description': serializer.toJson<String>(description),
'createdAt': serializer.toJson<DateTime>(createdAt), 'createdAt': serializer.toJson<DateTime>(createdAt),
}; };
} }
@@ -187,12 +185,12 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
PlayerTableData copyWith({ PlayerTableData copyWith({
String? id, String? id,
String? name, String? name,
Value<String?> description = const Value.absent(), String? description,
DateTime? createdAt, DateTime? createdAt,
}) => PlayerTableData( }) => PlayerTableData(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
description: description.present ? description.value : this.description, description: description ?? this.description,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
); );
PlayerTableData copyWithCompanion(PlayerTableCompanion data) { PlayerTableData copyWithCompanion(PlayerTableCompanion data) {
@@ -232,7 +230,7 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> { class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> {
final Value<String> id; final Value<String> id;
final Value<String> name; final Value<String> name;
final Value<String?> description; final Value<String> description;
final Value<DateTime> createdAt; final Value<DateTime> createdAt;
final Value<int> rowid; final Value<int> rowid;
const PlayerTableCompanion({ const PlayerTableCompanion({
@@ -245,11 +243,12 @@ class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> {
PlayerTableCompanion.insert({ PlayerTableCompanion.insert({
required String id, required String id,
required String name, required String name,
this.description = const Value.absent(), required String description,
required DateTime createdAt, required DateTime createdAt,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : id = Value(id), }) : id = Value(id),
name = Value(name), name = Value(name),
description = Value(description),
createdAt = Value(createdAt); createdAt = Value(createdAt);
static Insertable<PlayerTableData> custom({ static Insertable<PlayerTableData> custom({
Expression<String>? id, Expression<String>? id,
@@ -270,7 +269,7 @@ class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> {
PlayerTableCompanion copyWith({ PlayerTableCompanion copyWith({
Value<String>? id, Value<String>? id,
Value<String>? name, Value<String>? name,
Value<String?>? description, Value<String>? description,
Value<DateTime>? createdAt, Value<DateTime>? createdAt,
Value<int>? rowid, Value<int>? rowid,
}) { }) {
@@ -348,9 +347,9 @@ class $GroupTableTable extends GroupTable
late final GeneratedColumn<String> description = GeneratedColumn<String>( late final GeneratedColumn<String> description = GeneratedColumn<String>(
'description', 'description',
aliasedName, aliasedName,
true, false,
type: DriftSqlType.string, type: DriftSqlType.string,
requiredDuringInsert: false, requiredDuringInsert: true,
); );
static const VerificationMeta _createdAtMeta = const VerificationMeta( static const VerificationMeta _createdAtMeta = const VerificationMeta(
'createdAt', 'createdAt',
@@ -398,6 +397,8 @@ class $GroupTableTable extends GroupTable
_descriptionMeta, _descriptionMeta,
), ),
); );
} else if (isInserting) {
context.missing(_descriptionMeta);
} }
if (data.containsKey('created_at')) { if (data.containsKey('created_at')) {
context.handle( context.handle(
@@ -427,7 +428,7 @@ class $GroupTableTable extends GroupTable
description: attachedDatabase.typeMapping.read( description: attachedDatabase.typeMapping.read(
DriftSqlType.string, DriftSqlType.string,
data['${effectivePrefix}description'], data['${effectivePrefix}description'],
), )!,
createdAt: attachedDatabase.typeMapping.read( createdAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, DriftSqlType.dateTime,
data['${effectivePrefix}created_at'], data['${effectivePrefix}created_at'],
@@ -444,12 +445,12 @@ class $GroupTableTable extends GroupTable
class GroupTableData extends DataClass implements Insertable<GroupTableData> { class GroupTableData extends DataClass implements Insertable<GroupTableData> {
final String id; final String id;
final String name; final String name;
final String? description; final String description;
final DateTime createdAt; final DateTime createdAt;
const GroupTableData({ const GroupTableData({
required this.id, required this.id,
required this.name, required this.name,
this.description, required this.description,
required this.createdAt, required this.createdAt,
}); });
@override @override
@@ -457,9 +458,7 @@ class GroupTableData extends DataClass implements Insertable<GroupTableData> {
final map = <String, Expression>{}; final map = <String, Expression>{};
map['id'] = Variable<String>(id); map['id'] = Variable<String>(id);
map['name'] = Variable<String>(name); map['name'] = Variable<String>(name);
if (!nullToAbsent || description != null) { map['description'] = Variable<String>(description);
map['description'] = Variable<String>(description);
}
map['created_at'] = Variable<DateTime>(createdAt); map['created_at'] = Variable<DateTime>(createdAt);
return map; return map;
} }
@@ -468,9 +467,7 @@ class GroupTableData extends DataClass implements Insertable<GroupTableData> {
return GroupTableCompanion( return GroupTableCompanion(
id: Value(id), id: Value(id),
name: Value(name), name: Value(name),
description: description == null && nullToAbsent description: Value(description),
? const Value.absent()
: Value(description),
createdAt: Value(createdAt), createdAt: Value(createdAt),
); );
} }
@@ -483,7 +480,7 @@ class GroupTableData extends DataClass implements Insertable<GroupTableData> {
return GroupTableData( return GroupTableData(
id: serializer.fromJson<String>(json['id']), id: serializer.fromJson<String>(json['id']),
name: serializer.fromJson<String>(json['name']), name: serializer.fromJson<String>(json['name']),
description: serializer.fromJson<String?>(json['description']), description: serializer.fromJson<String>(json['description']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']), createdAt: serializer.fromJson<DateTime>(json['createdAt']),
); );
} }
@@ -493,7 +490,7 @@ class GroupTableData extends DataClass implements Insertable<GroupTableData> {
return <String, dynamic>{ return <String, dynamic>{
'id': serializer.toJson<String>(id), 'id': serializer.toJson<String>(id),
'name': serializer.toJson<String>(name), 'name': serializer.toJson<String>(name),
'description': serializer.toJson<String?>(description), 'description': serializer.toJson<String>(description),
'createdAt': serializer.toJson<DateTime>(createdAt), 'createdAt': serializer.toJson<DateTime>(createdAt),
}; };
} }
@@ -501,12 +498,12 @@ class GroupTableData extends DataClass implements Insertable<GroupTableData> {
GroupTableData copyWith({ GroupTableData copyWith({
String? id, String? id,
String? name, String? name,
Value<String?> description = const Value.absent(), String? description,
DateTime? createdAt, DateTime? createdAt,
}) => GroupTableData( }) => GroupTableData(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
description: description.present ? description.value : this.description, description: description ?? this.description,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
); );
GroupTableData copyWithCompanion(GroupTableCompanion data) { GroupTableData copyWithCompanion(GroupTableCompanion data) {
@@ -546,7 +543,7 @@ class GroupTableData extends DataClass implements Insertable<GroupTableData> {
class GroupTableCompanion extends UpdateCompanion<GroupTableData> { class GroupTableCompanion extends UpdateCompanion<GroupTableData> {
final Value<String> id; final Value<String> id;
final Value<String> name; final Value<String> name;
final Value<String?> description; final Value<String> description;
final Value<DateTime> createdAt; final Value<DateTime> createdAt;
final Value<int> rowid; final Value<int> rowid;
const GroupTableCompanion({ const GroupTableCompanion({
@@ -559,11 +556,12 @@ class GroupTableCompanion extends UpdateCompanion<GroupTableData> {
GroupTableCompanion.insert({ GroupTableCompanion.insert({
required String id, required String id,
required String name, required String name,
this.description = const Value.absent(), required String description,
required DateTime createdAt, required DateTime createdAt,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : id = Value(id), }) : id = Value(id),
name = Value(name), name = Value(name),
description = Value(description),
createdAt = Value(createdAt); createdAt = Value(createdAt);
static Insertable<GroupTableData> custom({ static Insertable<GroupTableData> custom({
Expression<String>? id, Expression<String>? id,
@@ -584,7 +582,7 @@ class GroupTableCompanion extends UpdateCompanion<GroupTableData> {
GroupTableCompanion copyWith({ GroupTableCompanion copyWith({
Value<String>? id, Value<String>? id,
Value<String>? name, Value<String>? name,
Value<String?>? description, Value<String>? description,
Value<DateTime>? createdAt, Value<DateTime>? createdAt,
Value<int>? rowid, Value<int>? rowid,
}) { }) {
@@ -691,9 +689,9 @@ class $GameTableTable extends GameTable
late final GeneratedColumn<String> icon = GeneratedColumn<String>( late final GeneratedColumn<String> icon = GeneratedColumn<String>(
'icon', 'icon',
aliasedName, aliasedName,
true, false,
type: DriftSqlType.string, type: DriftSqlType.string,
requiredDuringInsert: false, requiredDuringInsert: true,
); );
static const VerificationMeta _createdAtMeta = const VerificationMeta( static const VerificationMeta _createdAtMeta = const VerificationMeta(
'createdAt', 'createdAt',
@@ -773,6 +771,8 @@ class $GameTableTable extends GameTable
_iconMeta, _iconMeta,
icon.isAcceptableOrUnknown(data['icon']!, _iconMeta), icon.isAcceptableOrUnknown(data['icon']!, _iconMeta),
); );
} else if (isInserting) {
context.missing(_iconMeta);
} }
if (data.containsKey('created_at')) { if (data.containsKey('created_at')) {
context.handle( context.handle(
@@ -814,7 +814,7 @@ class $GameTableTable extends GameTable
icon: attachedDatabase.typeMapping.read( icon: attachedDatabase.typeMapping.read(
DriftSqlType.string, DriftSqlType.string,
data['${effectivePrefix}icon'], data['${effectivePrefix}icon'],
), )!,
createdAt: attachedDatabase.typeMapping.read( createdAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime, DriftSqlType.dateTime,
data['${effectivePrefix}created_at'], data['${effectivePrefix}created_at'],
@@ -834,7 +834,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
final String ruleset; final String ruleset;
final String description; final String description;
final String color; final String color;
final String? icon; final String icon;
final DateTime createdAt; final DateTime createdAt;
const GameTableData({ const GameTableData({
required this.id, required this.id,
@@ -842,7 +842,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
required this.ruleset, required this.ruleset,
required this.description, required this.description,
required this.color, required this.color,
this.icon, required this.icon,
required this.createdAt, required this.createdAt,
}); });
@override @override
@@ -853,9 +853,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
map['ruleset'] = Variable<String>(ruleset); map['ruleset'] = Variable<String>(ruleset);
map['description'] = Variable<String>(description); map['description'] = Variable<String>(description);
map['color'] = Variable<String>(color); map['color'] = Variable<String>(color);
if (!nullToAbsent || icon != null) { map['icon'] = Variable<String>(icon);
map['icon'] = Variable<String>(icon);
}
map['created_at'] = Variable<DateTime>(createdAt); map['created_at'] = Variable<DateTime>(createdAt);
return map; return map;
} }
@@ -867,7 +865,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
ruleset: Value(ruleset), ruleset: Value(ruleset),
description: Value(description), description: Value(description),
color: Value(color), color: Value(color),
icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), icon: Value(icon),
createdAt: Value(createdAt), createdAt: Value(createdAt),
); );
} }
@@ -883,7 +881,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
ruleset: serializer.fromJson<String>(json['ruleset']), ruleset: serializer.fromJson<String>(json['ruleset']),
description: serializer.fromJson<String>(json['description']), description: serializer.fromJson<String>(json['description']),
color: serializer.fromJson<String>(json['color']), color: serializer.fromJson<String>(json['color']),
icon: serializer.fromJson<String?>(json['icon']), icon: serializer.fromJson<String>(json['icon']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']), createdAt: serializer.fromJson<DateTime>(json['createdAt']),
); );
} }
@@ -896,7 +894,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
'ruleset': serializer.toJson<String>(ruleset), 'ruleset': serializer.toJson<String>(ruleset),
'description': serializer.toJson<String>(description), 'description': serializer.toJson<String>(description),
'color': serializer.toJson<String>(color), 'color': serializer.toJson<String>(color),
'icon': serializer.toJson<String?>(icon), 'icon': serializer.toJson<String>(icon),
'createdAt': serializer.toJson<DateTime>(createdAt), 'createdAt': serializer.toJson<DateTime>(createdAt),
}; };
} }
@@ -907,7 +905,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
String? ruleset, String? ruleset,
String? description, String? description,
String? color, String? color,
Value<String?> icon = const Value.absent(), String? icon,
DateTime? createdAt, DateTime? createdAt,
}) => GameTableData( }) => GameTableData(
id: id ?? this.id, id: id ?? this.id,
@@ -915,7 +913,7 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
ruleset: ruleset ?? this.ruleset, ruleset: ruleset ?? this.ruleset,
description: description ?? this.description, description: description ?? this.description,
color: color ?? this.color, color: color ?? this.color,
icon: icon.present ? icon.value : this.icon, icon: icon ?? this.icon,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
); );
GameTableData copyWithCompanion(GameTableCompanion data) { GameTableData copyWithCompanion(GameTableCompanion data) {
@@ -968,7 +966,7 @@ class GameTableCompanion extends UpdateCompanion<GameTableData> {
final Value<String> ruleset; final Value<String> ruleset;
final Value<String> description; final Value<String> description;
final Value<String> color; final Value<String> color;
final Value<String?> icon; final Value<String> icon;
final Value<DateTime> createdAt; final Value<DateTime> createdAt;
final Value<int> rowid; final Value<int> rowid;
const GameTableCompanion({ const GameTableCompanion({
@@ -987,7 +985,7 @@ class GameTableCompanion extends UpdateCompanion<GameTableData> {
required String ruleset, required String ruleset,
required String description, required String description,
required String color, required String color,
this.icon = const Value.absent(), required String icon,
required DateTime createdAt, required DateTime createdAt,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : id = Value(id), }) : id = Value(id),
@@ -995,6 +993,7 @@ class GameTableCompanion extends UpdateCompanion<GameTableData> {
ruleset = Value(ruleset), ruleset = Value(ruleset),
description = Value(description), description = Value(description),
color = Value(color), color = Value(color),
icon = Value(icon),
createdAt = Value(createdAt); createdAt = Value(createdAt);
static Insertable<GameTableData> custom({ static Insertable<GameTableData> custom({
Expression<String>? id, Expression<String>? id,
@@ -1024,7 +1023,7 @@ class GameTableCompanion extends UpdateCompanion<GameTableData> {
Value<String>? ruleset, Value<String>? ruleset,
Value<String>? description, Value<String>? description,
Value<String>? color, Value<String>? color,
Value<String?>? icon, Value<String>? icon,
Value<DateTime>? createdAt, Value<DateTime>? createdAt,
Value<int>? rowid, Value<int>? rowid,
}) { }) {
@@ -2783,7 +2782,7 @@ typedef $$PlayerTableTableCreateCompanionBuilder =
PlayerTableCompanion Function({ PlayerTableCompanion Function({
required String id, required String id,
required String name, required String name,
Value<String?> description, required String description,
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid, Value<int> rowid,
}); });
@@ -2791,7 +2790,7 @@ typedef $$PlayerTableTableUpdateCompanionBuilder =
PlayerTableCompanion Function({ PlayerTableCompanion Function({
Value<String> id, Value<String> id,
Value<String> name, Value<String> name,
Value<String?> description, Value<String> description,
Value<DateTime> createdAt, Value<DateTime> createdAt,
Value<int> rowid, Value<int> rowid,
}); });
@@ -3133,7 +3132,7 @@ class $$PlayerTableTableTableManager
({ ({
Value<String> id = const Value.absent(), Value<String> id = const Value.absent(),
Value<String> name = const Value.absent(), Value<String> name = const Value.absent(),
Value<String?> description = const Value.absent(), Value<String> description = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(), Value<DateTime> createdAt = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => PlayerTableCompanion( }) => PlayerTableCompanion(
@@ -3147,7 +3146,7 @@ class $$PlayerTableTableTableManager
({ ({
required String id, required String id,
required String name, required String name,
Value<String?> description = const Value.absent(), required String description,
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => PlayerTableCompanion.insert( }) => PlayerTableCompanion.insert(
@@ -3274,7 +3273,7 @@ typedef $$GroupTableTableCreateCompanionBuilder =
GroupTableCompanion Function({ GroupTableCompanion Function({
required String id, required String id,
required String name, required String name,
Value<String?> description, required String description,
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid, Value<int> rowid,
}); });
@@ -3282,7 +3281,7 @@ typedef $$GroupTableTableUpdateCompanionBuilder =
GroupTableCompanion Function({ GroupTableCompanion Function({
Value<String> id, Value<String> id,
Value<String> name, Value<String> name,
Value<String?> description, Value<String> description,
Value<DateTime> createdAt, Value<DateTime> createdAt,
Value<int> rowid, Value<int> rowid,
}); });
@@ -3550,7 +3549,7 @@ class $$GroupTableTableTableManager
({ ({
Value<String> id = const Value.absent(), Value<String> id = const Value.absent(),
Value<String> name = const Value.absent(), Value<String> name = const Value.absent(),
Value<String?> description = const Value.absent(), Value<String> description = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(), Value<DateTime> createdAt = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => GroupTableCompanion( }) => GroupTableCompanion(
@@ -3564,7 +3563,7 @@ class $$GroupTableTableTableManager
({ ({
required String id, required String id,
required String name, required String name,
Value<String?> description = const Value.absent(), required String description,
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => GroupTableCompanion.insert( }) => GroupTableCompanion.insert(
@@ -3664,7 +3663,7 @@ typedef $$GameTableTableCreateCompanionBuilder =
required String ruleset, required String ruleset,
required String description, required String description,
required String color, required String color,
Value<String?> icon, required String icon,
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid, Value<int> rowid,
}); });
@@ -3675,7 +3674,7 @@ typedef $$GameTableTableUpdateCompanionBuilder =
Value<String> ruleset, Value<String> ruleset,
Value<String> description, Value<String> description,
Value<String> color, Value<String> color,
Value<String?> icon, Value<String> icon,
Value<DateTime> createdAt, Value<DateTime> createdAt,
Value<int> rowid, Value<int> rowid,
}); });
@@ -3909,7 +3908,7 @@ class $$GameTableTableTableManager
Value<String> ruleset = const Value.absent(), Value<String> ruleset = const Value.absent(),
Value<String> description = const Value.absent(), Value<String> description = const Value.absent(),
Value<String> color = const Value.absent(), Value<String> color = const Value.absent(),
Value<String?> icon = const Value.absent(), Value<String> icon = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(), Value<DateTime> createdAt = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => GameTableCompanion( }) => GameTableCompanion(
@@ -3929,7 +3928,7 @@ class $$GameTableTableTableManager
required String ruleset, required String ruleset,
required String description, required String description,
required String color, required String color,
Value<String?> icon = const Value.absent(), required String icon,
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => GameTableCompanion.insert( }) => GameTableCompanion.insert(

View File

@@ -6,7 +6,7 @@ class GameTable extends Table {
TextColumn get ruleset => text()(); TextColumn get ruleset => text()();
TextColumn get description => text()(); TextColumn get description => text()();
TextColumn get color => text()(); TextColumn get color => text()();
TextColumn get icon => text().nullable()(); TextColumn get icon => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
@override @override

View File

@@ -3,7 +3,7 @@ import 'package:drift/drift.dart';
class GroupTable extends Table { class GroupTable extends Table {
TextColumn get id => text()(); TextColumn get id => text()();
TextColumn get name => text()(); TextColumn get name => text()();
TextColumn get description => text().nullable()(); TextColumn get description => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
@override @override

View File

@@ -3,7 +3,7 @@ import 'package:drift/drift.dart';
class PlayerTable extends Table { class PlayerTable extends Table {
TextColumn get id => text()(); TextColumn get id => text()();
TextColumn get name => text()(); TextColumn get name => text()();
TextColumn get description => text().nullable()(); TextColumn get description => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
@override @override

View File

@@ -9,7 +9,7 @@ class Game {
final Ruleset ruleset; final Ruleset ruleset;
final String description; final String description;
final String color; final String color;
final String? icon; final String icon;
Game({ Game({
String? id, String? id,
@@ -18,7 +18,7 @@ class Game {
required this.ruleset, required this.ruleset,
required this.description, required this.description,
required this.color, required this.color,
this.icon, required this.icon,
}) : id = id ?? const Uuid().v4(), }) : id = id ?? const Uuid().v4(),
createdAt = createdAt ?? clock.now(); createdAt = createdAt ?? clock.now();

View File

@@ -5,7 +5,7 @@ import 'package:uuid/uuid.dart';
class Group { class Group {
final String id; final String id;
final String name; final String name;
final String? description; final String description;
final DateTime createdAt; final DateTime createdAt;
final List<Player> members; final List<Player> members;
@@ -13,7 +13,7 @@ class Group {
String? id, String? id,
DateTime? createdAt, DateTime? createdAt,
required this.name, required this.name,
this.description, required this.description,
required this.members, required this.members,
}) : id = id ?? const Uuid().v4(), }) : id = id ?? const Uuid().v4(),
createdAt = createdAt ?? clock.now(); createdAt = createdAt ?? clock.now();

View File

@@ -1,4 +1,5 @@
import 'package:clock/clock.dart'; import 'package:clock/clock.dart';
import 'package:game_tracker/core/enums.dart';
import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/data/dto/player.dart';
@@ -8,20 +9,20 @@ class Match {
final String id; final String id;
final DateTime createdAt; final DateTime createdAt;
final String name; final String name;
final Game? game; final Game game;
final Group? group; final Group? group;
final List<Player>? players; final List<Player>? players;
final String? notes; final String notes;
Player? winner; Player? winner;
Match({ Match({
String? id, String? id,
DateTime? createdAt, DateTime? createdAt,
required this.name, required this.name,
this.game, required this.game,
this.group, this.group,
this.players, this.players,
this.notes, required this.notes,
this.winner, this.winner,
}) : id = id ?? const Uuid().v4(), }) : id = id ?? const Uuid().v4(),
createdAt = createdAt ?? clock.now(); createdAt = createdAt ?? clock.now();
@@ -37,17 +38,17 @@ class Match {
: id = json['id'], : id = json['id'],
createdAt = DateTime.parse(json['createdAt']), createdAt = DateTime.parse(json['createdAt']),
name = json['name'], name = json['name'],
game = null, // Populated during import via DataTransferService game = Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), // Populated during import via DataTransferService
group = null, // Populated during import via DataTransferService group = null, // Populated during import via DataTransferService
players = [], // Populated during import via DataTransferService players = [], // Populated during import via DataTransferService
notes = json['notes']; notes = json['notes'] ?? '';
/// Converts the Match instance to a JSON object using normalized format (ID references only). /// Converts the Match instance to a JSON object using normalized format (ID references only).
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'id': id, 'id': id,
'createdAt': createdAt.toIso8601String(), 'createdAt': createdAt.toIso8601String(),
'name': name, 'name': name,
'gameId': game?.id, 'gameId': game.id,
'groupId': group?.id, 'groupId': group?.id,
'playerIds': (players ?? []).map((player) => player.id).toList(), 'playerIds': (players ?? []).map((player) => player.id).toList(),
'notes': notes, 'notes': notes,

View File

@@ -5,13 +5,13 @@ class Player {
final String id; final String id;
final DateTime createdAt; final DateTime createdAt;
final String name; final String name;
final String? description; final String description;
Player({ Player({
String? id, String? id,
DateTime? createdAt, DateTime? createdAt,
required this.name, required this.name,
this.description, required this.description,
}) : id = id ?? const Uuid().v4(), }) : id = id ?? const Uuid().v4(),
createdAt = createdAt ?? clock.now(); createdAt = createdAt ?? clock.now();

View File

@@ -84,6 +84,7 @@ class _CreateGroupViewState extends State<CreateGroupView> {
bool success = await db.groupDao.addGroup( bool success = await db.groupDao.addGroup(
group: Group( group: Group(
name: _groupNameController.text.trim(), name: _groupNameController.text.trim(),
description: '',
members: selectedPlayers, members: selectedPlayers,
), ),
); );

View File

@@ -35,7 +35,8 @@ class _GroupsViewState extends State<GroupsView> {
7, 7,
Group( Group(
name: 'Skeleton Group', name: 'Skeleton Group',
members: List.filled(6, Player(name: 'Skeleton Player')), description: '',
members: List.filled(6, Player(name: 'Skeleton Player', description: '')),
), ),
); );

View File

@@ -1,7 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/adaptive_page_route.dart';
import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/core/constants.dart';
import 'package:game_tracker/core/enums.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/match.dart'; import 'package:game_tracker/data/dto/match.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/data/dto/player.dart';
@@ -40,13 +42,16 @@ class _HomeViewState extends State<HomeView> {
2, 2,
Match( Match(
name: 'Skeleton Match', name: 'Skeleton Match',
game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''),
group: Group( group: Group(
name: 'Skeleton Group', name: 'Skeleton Group',
description: '',
members: [ members: [
Player(name: 'Skeleton Player 1'), Player(name: 'Skeleton Player 1', description: ''),
Player(name: 'Skeleton Player 2'), Player(name: 'Skeleton Player 2', description: ''),
], ],
), ),
notes: '',
), ),
); );
@@ -114,7 +119,7 @@ class _HomeViewState extends State<HomeView> {
MatchResultView(match: match), MatchResultView(match: match),
), ),
); );
await updatedWinnerinRecentMatches(match.id); await updatedWinnerInRecentMatches(match.id);
}, },
), ),
) )
@@ -214,7 +219,7 @@ class _HomeViewState extends State<HomeView> {
} }
/// Updates the winner information for a specific match in the recent matches list. /// Updates the winner information for a specific match in the recent matches list.
Future<void> updatedWinnerinRecentMatches(String matchId) async { Future<void> updatedWinnerInRecentMatches(String matchId) async {
final db = Provider.of<AppDatabase>(context, listen: false); final db = Provider.of<AppDatabase>(context, listen: false);
final winner = await db.matchDao.getWinner(matchId: matchId); final winner = await db.matchDao.getWinner(matchId: matchId);
final matchIndex = recentMatches.indexWhere((match) => match.id == matchId); final matchIndex = recentMatches.indexWhere((match) => match.id == matchId);

View File

@@ -203,6 +203,7 @@ class _CreateMatchViewState extends State<CreateMatchView> {
description: selectedGame.$2, description: selectedGame.$2,
ruleset: selectedGame.$3, ruleset: selectedGame.$3,
color: '0xFF000000', color: '0xFF000000',
icon: '',
); );
} else { } else {
// Use the selected game from the list // Use the selected game from the list
@@ -212,6 +213,7 @@ class _CreateMatchViewState extends State<CreateMatchView> {
description: selectedGame.$2, description: selectedGame.$2,
ruleset: selectedGame.$3, ruleset: selectedGame.$3,
color: '0xFF000000', color: '0xFF000000',
icon: '',
); );
} }
// Add the game to the database if it doesn't exist // Add the game to the database if it doesn't exist
@@ -225,6 +227,7 @@ class _CreateMatchViewState extends State<CreateMatchView> {
game: gameToUse, game: gameToUse,
group: selectedGroup, group: selectedGroup,
players: selectedPlayers, players: selectedPlayers,
notes: '',
); );
await db.matchDao.addMatch(match: match); await db.matchDao.addMatch(match: match);
if (context.mounted) { if (context.mounted) {

View File

@@ -5,7 +5,9 @@ import 'package:fluttericon/rpg_awesome_icons.dart';
import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/adaptive_page_route.dart';
import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/core/constants.dart';
import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/core/custom_theme.dart';
import 'package:game_tracker/core/enums.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/match.dart'; import 'package:game_tracker/data/dto/match.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/data/dto/player.dart';
@@ -36,12 +38,15 @@ class _MatchViewState extends State<MatchView> {
4, 4,
Match( Match(
name: 'Skeleton match name', name: 'Skeleton match name',
game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''),
group: Group( group: Group(
name: 'Group name', name: 'Group name',
members: List.filled(5, Player(name: 'Player')), description: '',
members: List.filled(5, Player(name: 'Player', description: '')),
), ),
winner: Player(name: 'Player'), winner: Player(name: 'Player', description: ''),
players: [Player(name: 'Player')], players: [Player(name: 'Player', description: '')],
notes: '',
), ),
); );

View File

@@ -167,7 +167,7 @@ class _StatisticsViewState extends State<StatisticsView> {
final playerId = winCounts[i].$1; final playerId = winCounts[i].$1;
final player = players.firstWhere( final player = players.firstWhere(
(p) => p.id == playerId, (p) => p.id == playerId,
orElse: () => Player(id: playerId, name: loc.not_available), orElse: () => Player(id: playerId, name: loc.not_available, description: ''),
); );
winCounts[i] = (player.name, winCounts[i].$2); winCounts[i] = (player.name, winCounts[i].$2);
} }
@@ -231,7 +231,7 @@ class _StatisticsViewState extends State<StatisticsView> {
final playerId = matchCounts[i].$1; final playerId = matchCounts[i].$1;
final player = players.firstWhere( final player = players.firstWhere(
(p) => p.id == playerId, (p) => p.id == playerId,
orElse: () => Player(id: playerId, name: loc.not_available), orElse: () => Player(id: playerId, name: loc.not_available, description: ''),
); );
matchCounts[i] = (player.name, matchCounts[i].$2); matchCounts[i] = (player.name, matchCounts[i].$2);
} }

View File

@@ -62,7 +62,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
/// Skeleton data used while loading players. /// Skeleton data used while loading players.
late final List<Player> skeletonData = List.filled( late final List<Player> skeletonData = List.filled(
7, 7,
Player(name: 'Player 0'), Player(name: 'Player 0', description: ''),
); );
@override @override
@@ -260,7 +260,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
final loc = AppLocalizations.of(context); final loc = AppLocalizations.of(context);
final playerName = _searchBarController.text.trim(); final playerName = _searchBarController.text.trim();
final createdPlayer = Player(name: playerName); final createdPlayer = Player(name: playerName, description: '');
final success = await db.playerDao.addPlayer(player: createdPlayer); final success = await db.playerDao.addPlayer(player: createdPlayer);
if (!context.mounted) return; if (!context.mounted) return;

View File

@@ -61,7 +61,7 @@ class DataTransferService {
'id': m.id, 'id': m.id,
'name': m.name, 'name': m.name,
'createdAt': m.createdAt.toIso8601String(), 'createdAt': m.createdAt.toIso8601String(),
'gameId': m.game?.id, 'gameId': m.game.id,
'groupId': m.group?.id, 'groupId': m.group?.id,
'playerIds': (m.players ?? []).map((p) => p.id).toList(), 'playerIds': (m.players ?? []).map((p) => p.id).toList(),
'notes': m.notes, 'notes': m.notes,
@@ -160,7 +160,7 @@ class DataTransferService {
return Group( return Group(
id: map['id'] as String, id: map['id'] as String,
name: map['name'] as String, name: map['name'] as String,
description: map['description'] as String?, description: map['description'] as String,
members: members, members: members,
createdAt: DateTime.parse(map['createdAt'] as String), createdAt: DateTime.parse(map['createdAt'] as String),
); );
@@ -192,11 +192,11 @@ class DataTransferService {
final List<Match> importedMatches = matchesJson.map((m) { final List<Match> importedMatches = matchesJson.map((m) {
final map = m as Map<String, dynamic>; final map = m as Map<String, dynamic>;
final String? gameId = map['gameId'] as String?; final String gameId = map['gameId'] as String;
final String? groupId = map['groupId'] as String?; final String? groupId = map['groupId'] as String?;
final List<String> playerIds = (map['playerIds'] as List<dynamic>? ?? []).cast<String>(); final List<String> playerIds = (map['playerIds'] as List<dynamic>? ?? []).cast<String>();
final game = (gameId == null) ? null : gameById[gameId]; final game = gameById[gameId];
final group = (groupId == null) ? null : groupById[groupId]; final group = (groupId == null) ? null : groupById[groupId];
final players = playerIds final players = playerIds
.map((id) => playerById[id]) .map((id) => playerById[id])
@@ -206,11 +206,11 @@ class DataTransferService {
return Match( return Match(
id: map['id'] as String, id: map['id'] as String,
name: map['name'] as String, name: map['name'] as String,
game: game, game: game ?? Game(name: 'Unknown', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''),
group: group, group: group,
players: players.isNotEmpty ? players : null, players: players.isNotEmpty ? players : null,
createdAt: DateTime.parse(map['createdAt'] as String), createdAt: DateTime.parse(map['createdAt'] as String),
notes: map['notes'] as String?, notes: map['notes'] as String? ?? '',
); );
}).toList(); }).toList();

View File

@@ -44,6 +44,7 @@ void main() {
ruleset: Ruleset.highestScore, ruleset: Ruleset.highestScore,
description: 'A board game about real estate', description: 'A board game about real estate',
color: '0xFF000000', color: '0xFF000000',
icon: '',
); );
}); });
}); });
@@ -133,7 +134,7 @@ void main() {
// Verifies that a game with null optional fields can be added and retrieved. // Verifies that a game with null optional fields can be added and retrieved.
test('addGame handles game with null optional fields', () async { test('addGame handles game with null optional fields', () async {
final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: '0xFF000000'); final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: '0xFF000000', icon: '');
final result = await database.gameDao.addGame(game: gameWithNulls); final result = await database.gameDao.addGame(game: gameWithNulls);
expect(result, true); expect(result, true);
@@ -374,19 +375,19 @@ void main() {
expect(updatedGame.icon, 'new_chess_icon'); expect(updatedGame.icon, 'new_chess_icon');
}); });
// Verifies that updateGameIcon can set the icon to null. // Verifies that updateGameIcon can update the icon.
test('updateGameIcon can set icon to null', () async { test('updateGameIcon updates icon correctly', () async {
await database.gameDao.addGame(game: testGame1); await database.gameDao.addGame(game: testGame1);
await database.gameDao.updateGameIcon( await database.gameDao.updateGameIcon(
gameId: testGame1.id, gameId: testGame1.id,
newIcon: null, newIcon: 'new_icon',
); );
final updatedGame = await database.gameDao.getGameById( final updatedGame = await database.gameDao.getGameById(
gameId: testGame1.id, gameId: testGame1.id,
); );
expect(updatedGame.icon, isNull); expect(updatedGame.icon, 'new_icon');
}); });
// Verifies that updateGameIcon does nothing when game doesn't exist. // Verifies that updateGameIcon does nothing when game doesn't exist.
@@ -460,6 +461,7 @@ void main() {
ruleset: Ruleset.multipleWinners, ruleset: Ruleset.multipleWinners,
description: 'Description with émojis 🎮🎲', description: 'Description with émojis 🎮🎲',
color: '0xFF000000', color: '0xFF000000',
icon: '',
); );
await database.gameDao.addGame(game: specialGame); await database.gameDao.addGame(game: specialGame);
@@ -498,6 +500,7 @@ void main() {
description: longString, description: longString,
ruleset: Ruleset.multipleWinners, ruleset: Ruleset.multipleWinners,
color: '0xFF000000', color: '0xFF000000',
icon: '',
); );
await database.gameDao.addGame(game: longGame); await database.gameDao.addGame(game: longGame);

View File

@@ -29,27 +29,31 @@ void main() {
); );
withClock(fakeClock, () { withClock(fakeClock, () {
testPlayer1 = Player(name: 'Alice'); testPlayer1 = Player(name: 'Alice', description: '');
testPlayer2 = Player(name: 'Bob'); testPlayer2 = Player(name: 'Bob', description: '');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie', description: '');
testPlayer4 = Player(name: 'Diana'); testPlayer4 = Player(name: 'Diana', description: '');
testGroup1 = Group( testGroup1 = Group(
name: 'Test Group', name: 'Test Group',
description: '',
members: [testPlayer1, testPlayer2, testPlayer3], members: [testPlayer1, testPlayer2, testPlayer3],
); );
testGroup2 = Group( testGroup2 = Group(
id: 'gr2', id: 'gr2',
name: 'Second Group', name: 'Second Group',
description: '',
members: [testPlayer2, testPlayer3, testPlayer4], members: [testPlayer2, testPlayer3, testPlayer4],
); );
testGroup3 = Group( testGroup3 = Group(
id: 'gr2', id: 'gr2',
name: 'Second Group', name: 'Second Group',
description: '',
members: [testPlayer2, testPlayer4], members: [testPlayer2, testPlayer4],
); );
testGroup4 = Group( testGroup4 = Group(
id: 'gr2', id: 'gr2',
name: 'Second Group', name: 'Second Group',
description: '',
members: [testPlayer1, testPlayer2, testPlayer3, testPlayer4], members: [testPlayer1, testPlayer2, testPlayer3, testPlayer4],
); );
}); });
@@ -262,14 +266,14 @@ void main() {
final updated = await database.groupDao.updateGroupDescription( final updated = await database.groupDao.updateGroupDescription(
groupId: groupWithDescription.id, groupId: groupWithDescription.id,
newDescription: null, newDescription: 'Updated description',
); );
expect(updated, true); expect(updated, true);
final result = await database.groupDao.getGroupById( final result = await database.groupDao.getGroupById(
groupId: groupWithDescription.id, groupId: groupWithDescription.id,
); );
expect(result.description, isNull); expect(result.description, 'Updated description');
}); });
// Verifies that updateGroupDescription returns false for a non-existent group. // Verifies that updateGroupDescription returns false for a non-existent group.
@@ -324,6 +328,7 @@ void main() {
test('Group with empty members list is stored correctly', () async { test('Group with empty members list is stored correctly', () async {
final emptyGroup = Group( final emptyGroup = Group(
name: 'Empty Group', name: 'Empty Group',
description: '',
members: [], members: [],
); );
await database.groupDao.addGroup(group: emptyGroup); await database.groupDao.addGroup(group: emptyGroup);

View File

@@ -36,26 +36,29 @@ void main() {
); );
withClock(fakeClock, () { withClock(fakeClock, () {
testPlayer1 = Player(name: 'Alice'); testPlayer1 = Player(name: 'Alice', description: '');
testPlayer2 = Player(name: 'Bob'); testPlayer2 = Player(name: 'Bob', description: '');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie', description: '');
testPlayer4 = Player(name: 'Diana'); testPlayer4 = Player(name: 'Diana', description: '');
testPlayer5 = Player(name: 'Eve'); testPlayer5 = Player(name: 'Eve', description: '');
testGroup1 = Group( testGroup1 = Group(
name: 'Test Group 2', name: 'Test Group 2',
description: '',
members: [testPlayer1, testPlayer2, testPlayer3], members: [testPlayer1, testPlayer2, testPlayer3],
); );
testGroup2 = Group( testGroup2 = Group(
name: 'Test Group 2', name: 'Test Group 2',
description: '',
members: [testPlayer4, testPlayer5], members: [testPlayer4, testPlayer5],
); );
testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: '');
testMatch1 = Match( testMatch1 = Match(
name: 'First Test Match', name: 'First Test Match',
game: testGame, game: testGame,
group: testGroup1, group: testGroup1,
players: [testPlayer4, testPlayer5], players: [testPlayer4, testPlayer5],
winner: testPlayer4, winner: testPlayer4,
notes: '',
); );
testMatch2 = Match( testMatch2 = Match(
name: 'Second Test Match', name: 'Second Test Match',
@@ -63,17 +66,20 @@ void main() {
group: testGroup2, group: testGroup2,
players: [testPlayer1, testPlayer2, testPlayer3], players: [testPlayer1, testPlayer2, testPlayer3],
winner: testPlayer2, winner: testPlayer2,
notes: '',
); );
testMatchOnlyPlayers = Match( testMatchOnlyPlayers = Match(
name: 'Test Match with Players', name: 'Test Match with Players',
game: testGame, game: testGame,
players: [testPlayer1, testPlayer2, testPlayer3], players: [testPlayer1, testPlayer2, testPlayer3],
winner: testPlayer3, winner: testPlayer3,
notes: '',
); );
testMatchOnlyGroup = Match( testMatchOnlyGroup = Match(
name: 'Test Match with Group', name: 'Test Match with Group',
game: testGame, game: testGame,
group: testGroup2, group: testGroup2,
notes: '',
); );
}); });
await database.playerDao.addPlayersAsList( await database.playerDao.addPlayersAsList(

View File

@@ -26,12 +26,13 @@ void main() {
); );
withClock(fakeClock, () { withClock(fakeClock, () {
testPlayer1 = Player(name: 'Alice'); testPlayer1 = Player(name: 'Alice', description: '');
testPlayer2 = Player(name: 'Bob'); testPlayer2 = Player(name: 'Bob', description: '');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie', description: '');
testPlayer4 = Player(name: 'Diana'); testPlayer4 = Player(name: 'Diana', description: '');
testGroup = Group( testGroup = Group(
name: 'Test Group', name: 'Test Group',
description: '',
members: [testPlayer1, testPlayer2, testPlayer3], members: [testPlayer1, testPlayer2, testPlayer3],
); );
}); });
@@ -186,7 +187,7 @@ void main() {
// Verifies that getPlayersOfGroup returns empty list for group with no members. // Verifies that getPlayersOfGroup returns empty list for group with no members.
test('getPlayersOfGroup returns empty list for empty group', () async { test('getPlayersOfGroup returns empty list for empty group', () async {
final emptyGroup = Group(name: 'Empty Group', members: []); final emptyGroup = Group(name: 'Empty Group', description: '', members: []);
await database.groupDao.addGroup(group: emptyGroup); await database.groupDao.addGroup(group: emptyGroup);
final players = await database.playerGroupDao.getPlayersOfGroup( final players = await database.playerGroupDao.getPlayersOfGroup(
@@ -230,7 +231,7 @@ void main() {
// Verifies that a player can be in multiple groups. // Verifies that a player can be in multiple groups.
test('Player can be in multiple groups', () async { test('Player can be in multiple groups', () async {
final secondGroup = Group(name: 'Second Group', members: []); final secondGroup = Group(name: 'Second Group', description: '', members: []);
await database.groupDao.addGroup(group: testGroup); await database.groupDao.addGroup(group: testGroup);
await database.groupDao.addGroup(group: secondGroup); await database.groupDao.addGroup(group: secondGroup);
@@ -255,7 +256,7 @@ void main() {
// Verifies that removing player from one group doesn't affect other groups. // Verifies that removing player from one group doesn't affect other groups.
test('Removing player from one group does not affect other groups', () async { test('Removing player from one group does not affect other groups', () async {
final secondGroup = Group(name: 'Second Group', members: [testPlayer1]); final secondGroup = Group(name: 'Second Group', description: '', members: [testPlayer1]);
await database.groupDao.addGroup(group: testGroup); await database.groupDao.addGroup(group: testGroup);
await database.groupDao.addGroup(group: secondGroup); await database.groupDao.addGroup(group: secondGroup);

View File

@@ -37,26 +37,29 @@ void main() {
); );
withClock(fakeClock, () { withClock(fakeClock, () {
testPlayer1 = Player(name: 'Alice'); testPlayer1 = Player(name: 'Alice', description: '');
testPlayer2 = Player(name: 'Bob'); testPlayer2 = Player(name: 'Bob', description: '');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie', description: '');
testPlayer4 = Player(name: 'Diana'); testPlayer4 = Player(name: 'Diana', description: '');
testPlayer5 = Player(name: 'Eve'); testPlayer5 = Player(name: 'Eve', description: '');
testPlayer6 = Player(name: 'Frank'); testPlayer6 = Player(name: 'Frank', description: '');
testGroup = Group( testGroup = Group(
name: 'Test Group', name: 'Test Group',
description: '',
members: [testPlayer1, testPlayer2, testPlayer3], members: [testPlayer1, testPlayer2, testPlayer3],
); );
testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: '');
testMatchOnlyGroup = Match( testMatchOnlyGroup = Match(
name: 'Test Match with Group', name: 'Test Match with Group',
game: testGame, game: testGame,
group: testGroup, group: testGroup,
notes: '',
); );
testMatchOnlyPlayers = Match( testMatchOnlyPlayers = Match(
name: 'Test Match with Players', name: 'Test Match with Players',
game: testGame, game: testGame,
players: [testPlayer4, testPlayer5, testPlayer6], players: [testPlayer4, testPlayer5, testPlayer6],
notes: '',
); );
testTeam1 = Team( testTeam1 = Team(
name: 'Team Alpha', name: 'Team Alpha',
@@ -226,8 +229,8 @@ void main() {
'Adding the same player to separate matches works correctly', 'Adding the same player to separate matches works correctly',
() async { () async {
final playersList = [testPlayer1, testPlayer2, testPlayer3]; final playersList = [testPlayer1, testPlayer2, testPlayer3];
final match1 = Match(name: 'Match 1', game: testGame, players: playersList); final match1 = Match(name: 'Match 1', game: testGame, players: playersList, notes: '');
final match2 = Match(name: 'Match 2', game: testGame, players: playersList); final match2 = Match(name: 'Match 2', game: testGame, players: playersList, notes: '');
await Future.wait([ await Future.wait([
database.matchDao.addMatch(match: match1), database.matchDao.addMatch(match: match1),
@@ -760,8 +763,8 @@ void main() {
// Verifies that removePlayerFromMatch does not affect other matches. // Verifies that removePlayerFromMatch does not affect other matches.
test('removePlayerFromMatch does not affect other matches', () async { test('removePlayerFromMatch does not affect other matches', () async {
final playersList = [testPlayer1, testPlayer2]; final playersList = [testPlayer1, testPlayer2];
final match1 = Match(name: 'Match 1', game: testGame, players: playersList); final match1 = Match(name: 'Match 1', game: testGame, players: playersList, notes: '');
final match2 = Match(name: 'Match 2', game: testGame, players: playersList); final match2 = Match(name: 'Match 2', game: testGame, players: playersList, notes: '');
await Future.wait([ await Future.wait([
database.matchDao.addMatch(match: match1), database.matchDao.addMatch(match: match1),
@@ -793,8 +796,8 @@ void main() {
// Verifies that updating scores for players in different matches are independent. // Verifies that updating scores for players in different matches are independent.
test('Player scores are independent across matches', () async { test('Player scores are independent across matches', () async {
final playersList = [testPlayer1]; final playersList = [testPlayer1];
final match1 = Match(name: 'Match 1', game: testGame, players: playersList); final match1 = Match(name: 'Match 1', game: testGame, players: playersList, notes: '');
final match2 = Match(name: 'Match 2', game: testGame, players: playersList); final match2 = Match(name: 'Match 2', game: testGame, players: playersList, notes: '');
await Future.wait([ await Future.wait([
database.matchDao.addMatch(match: match1), database.matchDao.addMatch(match: match1),

View File

@@ -24,10 +24,10 @@ void main() {
); );
withClock(fakeClock, () { withClock(fakeClock, () {
testPlayer1 = Player(name: 'Test Player'); testPlayer1 = Player(name: 'Test Player', description: '');
testPlayer2 = Player(name: 'Second Player'); testPlayer2 = Player(name: 'Second Player', description: '');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie', description: '');
testPlayer4 = Player(name: 'Diana'); testPlayer4 = Player(name: 'Diana', description: '');
}); });
}); });
tearDown(() async { tearDown(() async {
@@ -265,7 +265,7 @@ void main() {
// Verifies that a player with special characters in name is stored correctly. // Verifies that a player with special characters in name is stored correctly.
test('Player with special characters in name is stored correctly', () async { test('Player with special characters in name is stored correctly', () async {
final specialPlayer = Player(name: 'Test!@#\$%^&*()_+-=[]{}|;\':",.<>?/`~'); final specialPlayer = Player(name: 'Test!@#\$%^&*()_+-=[]{}|;\':",.<>?/`~', description: '');
await database.playerDao.addPlayer(player: specialPlayer); await database.playerDao.addPlayer(player: specialPlayer);
@@ -293,14 +293,14 @@ void main() {
// Verifies that a player with null description is stored correctly. // Verifies that a player with null description is stored correctly.
test('Player with null description is stored correctly', () async { test('Player with null description is stored correctly', () async {
final playerWithoutDescription = Player(name: 'No Description Player'); final playerWithoutDescription = Player(name: 'No Description Player', description: '');
await database.playerDao.addPlayer(player: playerWithoutDescription); await database.playerDao.addPlayer(player: playerWithoutDescription);
final fetchedPlayer = await database.playerDao.getPlayerById( final fetchedPlayer = await database.playerDao.getPlayerById(
playerId: playerWithoutDescription.id, playerId: playerWithoutDescription.id,
); );
expect(fetchedPlayer.description, isNull); expect(fetchedPlayer.description, '');
}); });
// Verifies that multiple updates to the same player work correctly. // Verifies that multiple updates to the same player work correctly.
@@ -340,7 +340,7 @@ void main() {
// Verifies that a player with empty string name is stored correctly. // Verifies that a player with empty string name is stored correctly.
test('Player with empty string name is stored correctly', () async { test('Player with empty string name is stored correctly', () async {
final emptyNamePlayer = Player(name: ''); final emptyNamePlayer = Player(name: '', description: '');
await database.playerDao.addPlayer(player: emptyNamePlayer); await database.playerDao.addPlayer(player: emptyNamePlayer);
@@ -353,7 +353,7 @@ void main() {
// Verifies that a player with very long name is stored correctly. // Verifies that a player with very long name is stored correctly.
test('Player with very long name is stored correctly', () async { test('Player with very long name is stored correctly', () async {
final longName = 'A' * 1000; final longName = 'A' * 1000;
final longNamePlayer = Player(name: longName); final longNamePlayer = Player(name: longName, description: '');
await database.playerDao.addPlayer(player: longNamePlayer); await database.playerDao.addPlayer(player: longNamePlayer);

View File

@@ -29,19 +29,21 @@ void main() {
); );
withClock(fakeClock, () { withClock(fakeClock, () {
testPlayer1 = Player(name: 'Alice'); testPlayer1 = Player(name: 'Alice', description: '');
testPlayer2 = Player(name: 'Bob'); testPlayer2 = Player(name: 'Bob', description: '');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie', description: '');
testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: '');
testMatch1 = Match( testMatch1 = Match(
name: 'Test Match 1', name: 'Test Match 1',
game: testGame, game: testGame,
players: [testPlayer1, testPlayer2], players: [testPlayer1, testPlayer2],
notes: '',
); );
testMatch2 = Match( testMatch2 = Match(
name: 'Test Match 2', name: 'Test Match 2',
game: testGame, game: testGame,
players: [testPlayer2, testPlayer3], players: [testPlayer2, testPlayer3],
notes: '',
); );
}); });

View File

@@ -33,10 +33,10 @@ void main() {
); );
withClock(fakeClock, () { withClock(fakeClock, () {
testPlayer1 = Player(name: 'Alice'); testPlayer1 = Player(name: 'Alice', description: '');
testPlayer2 = Player(name: 'Bob'); testPlayer2 = Player(name: 'Bob', description: '');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie', description: '');
testPlayer4 = Player(name: 'Diana'); testPlayer4 = Player(name: 'Diana', description: '');
testTeam1 = Team( testTeam1 = Team(
name: 'Team Alpha', name: 'Team Alpha',
members: [testPlayer1, testPlayer2], members: [testPlayer1, testPlayer2],
@@ -49,8 +49,8 @@ void main() {
name: 'Team Gamma', name: 'Team Gamma',
members: [testPlayer1, testPlayer3], members: [testPlayer1, testPlayer3],
); );
testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: '0xFF000000'); testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: '0xFF000000', icon: '');
testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: '0xFF000000'); testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: '0xFF000000', icon: '');
}); });
await database.playerDao.addPlayersAsList( await database.playerDao.addPlayersAsList(
@@ -344,8 +344,8 @@ void main() {
// Verifies that teams with overlapping members are independent. // Verifies that teams with overlapping members are independent.
test('Teams with overlapping members are independent', () async { test('Teams with overlapping members are independent', () async {
// Create two matches since player_match has primary key {playerId, matchId} // Create two matches since player_match has primary key {playerId, matchId}
final match1 = Match(name: 'Match 1', game: testGame1); final match1 = Match(name: 'Match 1', game: testGame1, notes: '');
final match2 = Match(name: 'Match 2', game: testGame2); final match2 = Match(name: 'Match 2', game: testGame2, notes: '');
await database.matchDao.addMatch(match: match1); await database.matchDao.addMatch(match: match1);
await database.matchDao.addMatch(match: match2); await database.matchDao.addMatch(match: match2);