Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions client/deepdame/lib/features/game/chat/game_chat_message.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:freezed_annotation/freezed_annotation.dart';

part 'game_chat_message.freezed.dart';
part 'game_chat_message.g.dart';

@freezed
abstract class GameChatMessage with _$GameChatMessage {
const factory GameChatMessage({
required String sender,
required String content,
// Freezed processes @JsonKey on constructor params; analyzer doesn't know.
// ignore: invalid_annotation_target
@JsonKey(name: 'timestamp') required DateTime createdAt,
required String gameId,
}) = _GameChatMessage;

factory GameChatMessage.fromJson(Map<String, dynamic> json) =>
_$GameChatMessageFromJson(json);
}
286 changes: 286 additions & 0 deletions client/deepdame/lib/features/game/chat/game_chat_message.freezed.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions client/deepdame/lib/features/game/chat/game_chat_message.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 64 additions & 0 deletions client/deepdame/lib/features/game/chat/game_chat_notifier.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import 'dart:async';

import 'package:deepdame/features/game/chat/game_chat_message.dart';
import 'package:deepdame/features/game/chat/game_chat_repository.dart';
import 'package:deepdame/features/user/application/user_controller.dart';
import 'package:flutter/foundation.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'game_chat_notifier.g.dart';

@riverpod
class GameChatMessages extends _$GameChatMessages {
@override
List<GameChatMessage> build(String gameId) => [];

// Riverpod notifiers use void methods, not setters, for state mutations.
// ignore: use_setters_to_change_properties
void setHistory(List<GameChatMessage> msgs) => state = msgs;

void addMessage(GameChatMessage msg) => state = [...state, msg];
}

@riverpod
Future<void> gameChatService(Ref ref, String gameId) async {
final repo = ref.watch(gameChatRepositoryProvider);

try {
final history = await repo.getHistory(gameId);
ref.read(gameChatMessagesProvider(gameId).notifier).setHistory(history);
} on Object catch (e) {
debugPrint('gameChatService: failed to load history: $e');
}

final sub = repo
.watchMessages(gameId)
.listen(
(msg) {
ref.read(gameChatMessagesProvider(gameId).notifier).addMessage(msg);
final myUsername = ref
.read(userControllerProvider)
.asData
?.value
.username;
if (myUsername == null || msg.sender != myUsername) {
ref.read(gameChatUnreadProvider(gameId).notifier).markUnread();
}
},
onError: (Object e, StackTrace st) =>
debugPrint('gameChatService: stream error: $e'),
cancelOnError: false,
);

ref.onDispose(() => unawaited(sub.cancel()));
}

@riverpod
class GameChatUnread extends _$GameChatUnread {
@override
bool build(String gameId) => false;

void markUnread() => state = true;

void clear() => state = false;
}
Loading
Loading