♻️ Better chat connection method

This commit is contained in:
2024-05-07 23:07:51 +08:00
parent dffa0077de
commit 3bcdc67285
5 changed files with 142 additions and 208 deletions

View File

@ -3,11 +3,15 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:livekit_client/livekit_client.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:solian/models/call.dart';
import 'package:solian/models/channel.dart';
import 'package:solian/models/message.dart';
import 'package:solian/models/packet.dart';
import 'package:solian/models/pagination.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/utils/service_url.dart';
import 'package:solian/widgets/chat/call/exts.dart';
@ -22,8 +26,11 @@ class ChatProvider extends ChangeNotifier {
Call? ongoingCall;
Channel? focusChannel;
String? focusChannelRealm;
ChatCallInstance? currentCall;
PagingController<int, Message>? historyPagingController;
Future<WebSocketChannel?> connect(AuthProvider auth) async {
if (auth.client == null) await auth.loadClient();
if (!await auth.isAuthorized()) return null;
@ -39,19 +46,107 @@ class ChatProvider extends ChangeNotifier {
);
final channel = WebSocketChannel.connect(uri);
await channel.ready;
isOpened = true;
channel.stream.listen(
(event) {
final result = NetworkPackage.fromJson(jsonDecode(event));
if (focusChannel == null || historyPagingController == null) return;
switch (result.method) {
case 'messages.new':
final payload = Message.fromJson(result.payload!);
if (payload.channelId == focusChannel?.id) {
historyPagingController?.itemList?.insert(0, payload);
}
break;
case 'messages.update':
final payload = Message.fromJson(result.payload!);
if (payload.channelId == focusChannel?.id) {
historyPagingController?.itemList =
historyPagingController?.itemList?.map((x) => x.id == payload.id ? payload : x).toList();
}
break;
case 'messages.burnt':
final payload = Message.fromJson(result.payload!);
if (payload.channelId == focusChannel?.id) {
historyPagingController?.itemList =
historyPagingController?.itemList?.where((x) => x.id != payload.id).toList();
}
break;
case 'calls.new':
final payload = Call.fromJson(result.payload!);
if (payload.channelId == focusChannel?.id) {
setOngoingCall(payload);
}
break;
case 'calls.end':
final payload = Call.fromJson(result.payload!);
if (payload.channelId == focusChannel?.id) {
setOngoingCall(null);
}
break;
}
notifyListeners();
},
onError: (_, __) => connect(auth),
onDone: () => connect(auth),
);
return channel;
}
Future<Channel> fetchChannel(AuthProvider auth, String alias, String realm) async {
Future<void> fetchMessages(int pageKey, BuildContext context) async {
final auth = context.read<AuthProvider>();
if (!await auth.isAuthorized()) return;
if (focusChannel == null || focusChannelRealm == null) return;
final offset = pageKey;
const take = 10;
var uri = getRequestUri(
'messaging',
'/api/channels/$focusChannelRealm/${focusChannel!.alias}/messages?take=$take&offset=$offset',
);
var res = await auth.client!.get(uri);
if (res.statusCode == 200) {
final result = PaginationResult.fromJson(jsonDecode(utf8.decode(res.bodyBytes)));
final items = result.data?.map((x) => Message.fromJson(x)).toList() ?? List.empty();
final isLastPage = (result.count - pageKey) < take;
if (isLastPage || result.data == null) {
historyPagingController!.appendLastPage(items);
} else {
final nextPageKey = pageKey + items.length;
historyPagingController!.appendPage(items, nextPageKey);
}
} else if (res.statusCode == 403) {
historyPagingController!.appendLastPage([]);
} else {
historyPagingController!.error = utf8.decode(res.bodyBytes);
}
}
Future<Channel> fetchChannel(BuildContext context, AuthProvider auth, String alias, String realm) async {
if (focusChannel != null) {
unFocus();
}
var uri = getRequestUri('messaging', '/api/channels/$realm/$alias/availability');
var res = await auth.client!.get(uri);
if (res.statusCode == 200 || res.statusCode == 403) {
final result = jsonDecode(utf8.decode(res.bodyBytes));
focusChannel = Channel.fromJson(result);
focusChannel?.isAvailable = res.statusCode == 200;
focusChannelRealm = realm;
if (historyPagingController == null) {
historyPagingController = PagingController(firstPageKey: 0);
historyPagingController?.addPageRequestListener((pageKey) => fetchMessages(pageKey, context));
}
notifyListeners();
return focusChannel!;
} else {
var message = utf8.decode(res.bodyBytes);
@ -110,6 +205,7 @@ class ChatProvider extends ChangeNotifier {
void unFocus() {
currentCall = null;
focusChannel = null;
historyPagingController = null;
notifyListeners();
}
}