我给你一个我的代码的 sn-p 以便更快地完成它:下面的代码只是针对每个用户。它是聊天的子集合。因此,用户可以为每个聊天设置一个 chatMembre。
import 'package:cloud_firestore/cloud_firestore.dart';
enum IsDoing { reading, notReading, writing, recording }
class ChatMembre {
final String id;
final DateTime lastReading;
final DateTime lastReceived;
final IsDoing isDoing;
final bool hasSubscribeToTopic;
ChatMembre(
{required this.id,
required this.lastReading,
required this.lastReceived,
required this.isDoing,
required this.hasSubscribeToTopic});
Map<String, dynamic> toMap() {
return {
'id': id,
'lastReading': lastReading == DateTime.now()
? FieldValue.serverTimestamp()
: DateTime.now(),
'lastReceived': lastReceived == DateTime.now()
? FieldValue.serverTimestamp()
: DateTime.now(),
'isDoing':
isDoing.toString().substring(isDoing.toString().indexOf(".") + 1),
'isSubscribeToTopic': hasSubscribeToTopic
};
}
factory ChatMembre.fromMap(Map<String, dynamic>? map) {
if (map == null || map.isEmpty) {
return ChatMembre(
id: '',
lastReading: DateTime.now(),
lastReceived: DateTime.now(),
hasSubscribeToTopic: false,
isDoing: IsDoing.notReading);
}
IsDoing isDoing;
switch (map["isDoing"]) {
case "reading":
isDoing = IsDoing.reading;
break;
case "writing":
isDoing = IsDoing.writing;
break;
case "recording":
isDoing = IsDoing.recording;
break;
default:
isDoing = IsDoing.notReading;
break;
}
return ChatMembre(
id: (map['id'] ?? '') as String,
lastReading:
((map['lastReading'] ?? Timestamp.now()) as Timestamp).toDate(),
lastReceived:
((map['lastReceived'] ?? Timestamp.now()) as Timestamp).toDate(),
isDoing: isDoing,
hasSubscribeToTopic: (map['isSubscribeToTopic'] ?? false) as bool);
}
@override
String toString() {
return 'ChatMembre{id: $id, lastReading: $lastReading, lastReceived: $lastReceived, isDoing: $isDoing, hasSubscribeToTopic: $hasSubscribeToTopic}';
}
}
下面是查找聊天页面的状态。
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:customer/constants/credentials.dart';
import 'package:customer/constants/firestore_path.dart';
import 'package:customer/domain/repositories/my_chat_repository.dart';
import 'package:customer/services/firestore_service.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart' as http;
class ChatRoomLifeCycle extends StatefulWidget {
final Widget child;
final MyChatRepository chatRepo;
final String chatId;
final String? token;
final String? idTo;
final Timestamp? lastReceivedOfFriend;
const ChatRoomLifeCycle(
{Key? key,
required this.chatId,
required this.chatRepo,
required this.child,
this.token,
this.idTo,
this.lastReceivedOfFriend})
: super(key: key);
@override
_ChatRoomLifeCycleState createState() => _ChatRoomLifeCycleState();
}
class _ChatRoomLifeCycleState extends State<ChatRoomLifeCycle>
with WidgetsBindingObserver {
late GlobalKey<AnimatedListState> listKey;
bool hasSentFcm = false;
@override
void initState() {
super.initState();
sendPushMessage();
WidgetsBinding.instance!.addObserver(this);
widget.chatRepo.setIsReading();
}
@override
void dispose() {
widget.chatRepo.setIsNotReading(isFromDispose: true);
WidgetsBinding.instance!.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.paused:
widget.chatRepo.setIsNotReading();
break;
case AppLifecycleState.resumed:
widget.chatRepo.setIsReading();
break;
case AppLifecycleState.inactive:
widget.chatRepo.setIsNotReading();
break;
case AppLifecycleState.detached:
widget.chatRepo.setIsNotReading();
break;
}
}
Future<void> sendPushMessage() async {
if (hasSentFcm || widget.idTo == null || widget.token == null) {
return;
}
FirestoreService.instance.updateData(
path: MyPath.myUserStatus(uid: widget.idTo!), data: {'isLogin': false});
try {
await http
.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=$serverToken',
},
body: constructFCMPayload(widget.token!),
)
.catchError((onError) {});
hasSentFcm = true;
} catch (e) {
Fluttertoast.showToast(msg: e.toString());
}
}
// Crude counter to make messages unique
/// The API endpoint here accepts a raw FCM payload for demonstration purposes.
String constructFCMPayload(String token) {
return jsonEncode(<String, dynamic>{
'data': <String, dynamic>{
'test': 'check online',
'chatId': widget.chatId,
'idTo': widget.idTo
},
'to': token,
});
}
}