mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 09:28:41 +00:00
websocket automatic reconnection
This commit is contained in:
parent
e358cf2e57
commit
aa608be1e4
5 changed files with 57 additions and 18 deletions
3
devtools_options.yaml
Normal file
3
devtools_options.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
|
|
@ -12,6 +12,7 @@ import 'package:twonly/src/proto/api/error.pb.dart';
|
|||
import 'package:twonly/src/proto/api/server_to_client.pb.dart' as server;
|
||||
import 'package:twonly/src/signal/signal_helper.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:web_socket_channel/io.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
class Result<T, E> {
|
||||
|
|
@ -31,19 +32,19 @@ class ApiProvider {
|
|||
final String apiUrl;
|
||||
final String? backupApiUrl;
|
||||
final log = Logger("connect::ApiProvider");
|
||||
final HashMap<String, List<Function>> _callbacks = HashMap();
|
||||
Function(bool)? _connectionStateCallback;
|
||||
|
||||
final HashMap<Int64, server.ServerToClient?> messagesV0 = HashMap();
|
||||
|
||||
WebSocketChannel? _channel;
|
||||
IOWebSocketChannel? _channel;
|
||||
|
||||
Future<bool> _connectTo(String apiUrl) async {
|
||||
try {
|
||||
var channel = WebSocketChannel.connect(
|
||||
var channel = IOWebSocketChannel.connect(
|
||||
Uri.parse(apiUrl),
|
||||
);
|
||||
_channel = channel;
|
||||
_channel!.stream.listen(_onData);
|
||||
_channel!.stream.listen(_onData, onDone: _onDone, onError: _onError);
|
||||
await _channel!.ready;
|
||||
log.info("Websocket is connected!");
|
||||
print("Websocket is connected!");
|
||||
|
|
@ -56,9 +57,14 @@ class ApiProvider {
|
|||
|
||||
Future<bool> connect(Function(bool)? callBack) async {
|
||||
print("Trying to connect to the backend $apiUrl!");
|
||||
if (callBack != null) {
|
||||
_connectionStateCallback = callBack;
|
||||
}
|
||||
if (_channel != null && _channel!.closeCode != null) {
|
||||
print("is connected");
|
||||
return true;
|
||||
}
|
||||
|
||||
log.info("Trying to connect to the backend $apiUrl!");
|
||||
if (await _connectTo(apiUrl)) {
|
||||
if (callBack != null) callBack(true);
|
||||
|
|
@ -76,6 +82,37 @@ class ApiProvider {
|
|||
|
||||
bool get isConnected => _channel != null && _channel!.closeCode != null;
|
||||
|
||||
void _onDone() {
|
||||
if (_connectionStateCallback != null) {
|
||||
_connectionStateCallback!(false);
|
||||
}
|
||||
_channel = null;
|
||||
tryToReconnect(5);
|
||||
}
|
||||
|
||||
void _onError(dynamic e) {
|
||||
if (_connectionStateCallback != null) {
|
||||
_connectionStateCallback!(false);
|
||||
}
|
||||
_channel = null;
|
||||
tryToReconnect(5);
|
||||
}
|
||||
|
||||
void tryToReconnect(int delay) {
|
||||
Future.delayed(Duration(seconds: delay)).then(
|
||||
(value) async {
|
||||
if (!await connect(_connectionStateCallback)) {
|
||||
if (delay > 60 * 5) {
|
||||
delay = 60 * 5;
|
||||
} else {
|
||||
delay = delay * 2;
|
||||
}
|
||||
tryToReconnect(delay);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _onData(dynamic msgBuffer) {
|
||||
try {
|
||||
final msg = server.ServerToClient.fromBuffer(msgBuffer);
|
||||
|
|
@ -89,13 +126,6 @@ class ApiProvider {
|
|||
}
|
||||
}
|
||||
|
||||
void addNotifier(String messageType, Function callBackFunction) {
|
||||
if (!_callbacks.containsKey(messageType)) {
|
||||
_callbacks[messageType] = [];
|
||||
}
|
||||
_callbacks[messageType]!.add(callBackFunction);
|
||||
}
|
||||
|
||||
// TODO: There must be a smarter move to do that :/
|
||||
Future<server.ServerToClient?> _waitForResponse(Int64 seq) async {
|
||||
final startTime = DateTime.now();
|
||||
|
|
|
|||
|
|
@ -25,14 +25,17 @@ Future<bool> isUserCreated() async {
|
|||
Future<UserData?> getUser() async {
|
||||
final storage = getSecureStorage();
|
||||
String? userJson = await storage.read(key: "user_data");
|
||||
print(userJson);
|
||||
if (userJson == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
final userMap = jsonDecode(userJson) as Map<String, dynamic>;
|
||||
final user = UserData.fromJson(userMap);
|
||||
print(user);
|
||||
return user;
|
||||
} catch (_) {
|
||||
} catch (e) {
|
||||
print(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ class CameraPreviewViewState extends State<CameraPreviewView> {
|
|||
|
||||
final size = Size(50, 300);
|
||||
|
||||
_controller.initialize().then((_) {
|
||||
_controller.value = _controller.value.copyWith(previewSize: size);
|
||||
setState(() {});
|
||||
});
|
||||
// _controller.initialize().then((_) {
|
||||
// _controller.value = _controller.value.copyWith(previewSize: size);
|
||||
// setState(() {});
|
||||
// });
|
||||
|
||||
// Next, initialize the controller. This returns a Future.
|
||||
_initializeControllerFuture = _controller.initialize();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'package:twonly/src/model/user_data_json.dart';
|
||||
|
||||
import '../settings/settings_controller.dart';
|
||||
import '../settings/settings_view.dart';
|
||||
import '../utils.dart';
|
||||
|
|
@ -14,13 +16,14 @@ class ProfileView extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ProfileViewState extends State<ProfileView> {
|
||||
final Future<UserData?> _userData = getUser();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// var user = await getUser();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: FutureBuilder(
|
||||
future: getUser(),
|
||||
future: _userData,
|
||||
builder: (context, snap) {
|
||||
if (snap.hasData) {
|
||||
return Text("Hello ${snap.data!.username}!");
|
||||
|
|
|
|||
Loading…
Reference in a new issue