mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 14:28:40 +00:00
websocket works
This commit is contained in:
parent
3b3c5e61b9
commit
e358cf2e57
5 changed files with 108 additions and 209 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:twonly/src/providers/api_provider.dart';
|
import 'package:twonly/src/providers/api_provider.dart';
|
||||||
import 'package:twonly/src/providers/db_provider.dart';
|
import 'package:twonly/src/providers/db_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -10,6 +9,7 @@ import 'src/settings/settings_controller.dart';
|
||||||
import 'src/settings/settings_service.dart';
|
import 'src/settings/settings_service.dart';
|
||||||
|
|
||||||
late DbProvider dbProvider;
|
late DbProvider dbProvider;
|
||||||
|
late ApiProvider apiProvider;
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
// Set up the SettingsController, which will glue user settings to multiple
|
// Set up the SettingsController, which will glue user settings to multiple
|
||||||
|
|
@ -27,7 +27,7 @@ void main() async {
|
||||||
// check if release build or debug build
|
// check if release build or debug build
|
||||||
final kDebugMode = true;
|
final kDebugMode = true;
|
||||||
|
|
||||||
Logger.root.level = Level.FINEST; // defaults to Level.INFO
|
Logger.root.level = Level.ALL; // defaults to Level.INFO
|
||||||
Logger.root.onRecord.listen((record) {
|
Logger.root.onRecord.listen((record) {
|
||||||
// if (kDebugMode) {
|
// if (kDebugMode) {
|
||||||
// ignore: avoid_print
|
// ignore: avoid_print
|
||||||
|
|
@ -36,25 +36,31 @@ void main() async {
|
||||||
});
|
});
|
||||||
|
|
||||||
var cameras = await availableCameras();
|
var cameras = await availableCameras();
|
||||||
t
|
|
||||||
// Create or open the database
|
// Create or open the database
|
||||||
dbProvider = DbProvider();
|
dbProvider = DbProvider();
|
||||||
await dbProvider.ready;
|
await dbProvider.ready;
|
||||||
|
|
||||||
// Create an option to select different servers.
|
// Create an option to select different servers.
|
||||||
var apiUrl = "ws://api.theconnectapp.de/v-1/";
|
var apiUrl = "ws://api.theconnectapp.de/v-1/";
|
||||||
if (true) {
|
if (true) {
|
||||||
// Overwrite the domain in your local network so you can test the app locally
|
// Overwrite the domain in your local network so you can test the app locally
|
||||||
apiUrl = "ws://9.99.0.6:3030/api/client";
|
apiUrl = "ws://10.99.0.6:3030/api/client";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apiProvider = ApiProvider(apiUrl: apiUrl, backupApiUrl: null);
|
||||||
|
|
||||||
|
// TODO: Open the connection in the background so the app launch is not delayed.
|
||||||
|
//await apiProvider.connect();
|
||||||
|
|
||||||
// Workmanager.executeTask((task, inputData) async {
|
// Workmanager.executeTask((task, inputData) async {
|
||||||
// await _HomeState().manager();
|
// await _HomeState().manager();
|
||||||
// print('Background Services are Working!');//This is Working
|
// print('Background Services are Working!');//This is Working
|
||||||
// return true;
|
// return true;
|
||||||
// });
|
// });
|
||||||
|
|
||||||
runApp(ChangeNotifierProvider<ApiProvider>(
|
// Run the app and pass in the SettingsController. The app listens to the
|
||||||
child: MyApp(settingsController: settingsController, cameras: cameras),
|
// SettingsController for changes, then passes it further down to the
|
||||||
create: (_) => ApiProvider(apiUrl: apiUrl, backupApiUrl: apiUrl)));
|
// SettingsView.
|
||||||
|
runApp(MyApp(settingsController: settingsController, cameras: cameras));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
|
import 'package:twonly/main.dart';
|
||||||
import 'package:twonly/src/providers/api_provider.dart';
|
import 'package:twonly/src/providers/api_provider.dart';
|
||||||
import 'views/home_view.dart';
|
import 'views/home_view.dart';
|
||||||
import 'views/register_view.dart';
|
import 'views/register_view.dart';
|
||||||
|
|
@ -26,6 +27,7 @@ class MyApp extends StatefulWidget {
|
||||||
|
|
||||||
class _MyAppState extends State<MyApp> {
|
class _MyAppState extends State<MyApp> {
|
||||||
Future<bool> _isUserCreated = isUserCreated();
|
Future<bool> _isUserCreated = isUserCreated();
|
||||||
|
bool _isConnected = false;
|
||||||
int redColorOpacity = 0; // Start with dark red
|
int redColorOpacity = 0; // Start with dark red
|
||||||
bool redColorGoUp = true;
|
bool redColorGoUp = true;
|
||||||
bool isConnected = false;
|
bool isConnected = false;
|
||||||
|
|
@ -35,6 +37,11 @@ class _MyAppState extends State<MyApp> {
|
||||||
super.initState();
|
super.initState();
|
||||||
// Start the color animation
|
// Start the color animation
|
||||||
_startColorAnimation();
|
_startColorAnimation();
|
||||||
|
apiProvider.connect((isConnected) {
|
||||||
|
setState(() {
|
||||||
|
_isConnected = isConnected;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startColorAnimation() {
|
void _startColorAnimation() {
|
||||||
|
|
@ -60,7 +67,7 @@ class _MyAppState extends State<MyApp> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
double screenWidth = MediaQuery.of(context).size.width;
|
double screenWidth = MediaQuery.of(context).size.width;
|
||||||
var isConnected = context.watch<ApiProvider>().isConnected;
|
// var isConnected = context.watch<ApiProvider>().isConnected;
|
||||||
// Glue the SettingsController to the MaterialApp.
|
// Glue the SettingsController to the MaterialApp.
|
||||||
//
|
//
|
||||||
// The ListenableBuilder Widget listens to the SettingsController for changes.
|
// The ListenableBuilder Widget listens to the SettingsController for changes.
|
||||||
|
|
@ -97,29 +104,24 @@ class _MyAppState extends State<MyApp> {
|
||||||
home: Stack(
|
home: Stack(
|
||||||
children: [
|
children: [
|
||||||
FutureBuilder<bool>(
|
FutureBuilder<bool>(
|
||||||
future: context.watch<ApiProvider>().startBackend(),
|
future: _isUserCreated,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
return FutureBuilder<bool>(
|
if (snapshot.hasData) {
|
||||||
future: _isUserCreated,
|
return snapshot.data!
|
||||||
builder: (context, snapshot) {
|
? HomeView(
|
||||||
if (snapshot.hasData) {
|
settingsController: widget.settingsController,
|
||||||
return snapshot.data!
|
cameras: widget.cameras)
|
||||||
? HomeView(
|
: RegisterView(
|
||||||
settingsController:
|
callbackOnSuccess: () {
|
||||||
widget.settingsController,
|
_isUserCreated = isUserCreated();
|
||||||
cameras: widget.cameras)
|
setState(() {});
|
||||||
: RegisterView(
|
},
|
||||||
callbackOnSuccess: () {
|
); // Show the red line if not connected
|
||||||
_isUserCreated = isUserCreated();
|
} else {
|
||||||
setState(() {});
|
return Container();
|
||||||
},
|
}
|
||||||
); // Show the red line if not connected
|
|
||||||
} else {
|
|
||||||
return Container();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}),
|
}),
|
||||||
if (!isConnected)
|
if (!_isConnected)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 3, // Position it at the top
|
top: 3, // Position it at the top
|
||||||
left: (screenWidth * 0.5) / 2, // Center it horizontally
|
left: (screenWidth * 0.5) / 2, // Center it horizontally
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'dart:isolate';
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:twonly/src/proto/api/client_to_server.pb.dart' as c;
|
import 'package:twonly/src/proto/api/client_to_server.pb.dart';
|
||||||
import 'package:twonly/src/proto/api/error.pb.dart';
|
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/proto/api/server_to_client.pb.dart' as server;
|
||||||
import 'package:twonly/src/proto/api/server_to_client.pbserver.dart';
|
|
||||||
import 'package:twonly/src/signal/signal_helper.dart';
|
import 'package:twonly/src/signal/signal_helper.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
|
|
@ -27,170 +25,13 @@ class Result<T, E> {
|
||||||
Result.error(this.error) : value = null;
|
Result.error(this.error) : value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ExchangeKind { connectionStateChange, sendRequestV0 }
|
class ApiProvider {
|
||||||
|
|
||||||
class Exchange {
|
|
||||||
Exchange({required this.kind, required this.body, required this.seq});
|
|
||||||
final int seq;
|
|
||||||
final ExchangeKind kind;
|
|
||||||
final dynamic body;
|
|
||||||
}
|
|
||||||
|
|
||||||
c.ClientToServer createClientToServerFromHandshake(c.Handshake handshake) {
|
|
||||||
// Create the V0 message
|
|
||||||
var v0 = c.V0()
|
|
||||||
..seq = Int64(0) // You can set this to the appropriate sequence number
|
|
||||||
..handshake = handshake;
|
|
||||||
|
|
||||||
// Create the ClientToServer message
|
|
||||||
var clientToServer = c.ClientToServer()..v0 = v0;
|
|
||||||
|
|
||||||
return clientToServer;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result asResult(server.ServerToClient msg) {
|
|
||||||
if (msg.v0.response.hasOk()) {
|
|
||||||
return Result.success(msg.v0.response.ok);
|
|
||||||
} else {
|
|
||||||
return Result.error(msg.v0.response.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BackendIsolatedArgs {
|
|
||||||
BackendIsolatedArgs(
|
|
||||||
{required this.apiUrl,
|
|
||||||
required this.backupApiUrl,
|
|
||||||
required this.receivePort,
|
|
||||||
required this.sendPort});
|
|
||||||
final String apiUrl;
|
|
||||||
final String backupApiUrl;
|
|
||||||
final ReceivePort receivePort;
|
|
||||||
final SendPort sendPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ApiProvider with ChangeNotifier {
|
|
||||||
ApiProvider({required this.apiUrl, required this.backupApiUrl});
|
ApiProvider({required this.apiUrl, required this.backupApiUrl});
|
||||||
|
|
||||||
final String apiUrl;
|
|
||||||
final String backupApiUrl;
|
|
||||||
bool _isConnected = false;
|
|
||||||
final Map<int, ServerToClient> _sendRequestV0Resp = HashMap();
|
|
||||||
final log = Logger("twonly::ApiProvider");
|
|
||||||
|
|
||||||
final ReceivePort _receivePort = ReceivePort();
|
|
||||||
SendPort? _sendPort;
|
|
||||||
|
|
||||||
Future<ServerToClient?> _waitForResponse(int seq) async {
|
|
||||||
final startTime = DateTime.now();
|
|
||||||
|
|
||||||
final timeout = Duration(seconds: 5);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (_sendRequestV0Resp[seq] != null) {
|
|
||||||
final tmp = _sendRequestV0Resp[seq];
|
|
||||||
_sendRequestV0Resp.remove(seq);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
if (DateTime.now().difference(startTime) > timeout) {
|
|
||||||
log.shout("Timeout for message $seq");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
await Future.delayed(Duration(milliseconds: 10));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _startBackendIsolated(BackendIsolatedArgs args) async {
|
|
||||||
final backend =
|
|
||||||
Backend(apiUrl: args.apiUrl, backupApiUrl: args.backupApiUrl);
|
|
||||||
|
|
||||||
await backend.connect();
|
|
||||||
|
|
||||||
args.receivePort.listen((msg) async {
|
|
||||||
switch (msg.kind) {
|
|
||||||
case ExchangeKind.sendRequestV0:
|
|
||||||
final resp = await backend._sendRequestV0(msg.body);
|
|
||||||
args.sendPort.send(Exchange(
|
|
||||||
kind: ExchangeKind.sendRequestV0, body: resp, seq: msg.seq));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
});
|
|
||||||
args.sendPort.send(
|
|
||||||
Exchange(kind: ExchangeKind.connectionStateChange, body: true, seq: 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> startBackend() async {
|
|
||||||
ReceivePort port = ReceivePort();
|
|
||||||
_sendPort = port.sendPort;
|
|
||||||
|
|
||||||
await Isolate.spawn(
|
|
||||||
_startBackendIsolated,
|
|
||||||
BackendIsolatedArgs(
|
|
||||||
sendPort: _receivePort.sendPort,
|
|
||||||
receivePort: port,
|
|
||||||
apiUrl: apiUrl,
|
|
||||||
backupApiUrl: backupApiUrl));
|
|
||||||
|
|
||||||
_receivePort.listen((msg) {
|
|
||||||
switch (msg.kind) {
|
|
||||||
case ExchangeKind.sendRequestV0:
|
|
||||||
_sendRequestV0Resp[msg.seq] = msg.body;
|
|
||||||
// final resp = await backend._sendRequestV0(msg.body);
|
|
||||||
// args.sendPort.send(Exchange(
|
|
||||||
// kind: ExchangeKind.sendRequestV0, body: resp, seq: msg.seq));
|
|
||||||
break;
|
|
||||||
case ExchangeKind.connectionStateChange:
|
|
||||||
_isConnected = msg.body;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool get isConnected => _isConnected;
|
|
||||||
|
|
||||||
Future<Result> register(String username, String? inviteCode) async {
|
|
||||||
if (_sendPort == null) return Result.error("Unknown error");
|
|
||||||
final reqSignal = await SignalHelper.getRegisterData();
|
|
||||||
|
|
||||||
if (reqSignal == null) {
|
|
||||||
return Result.error(
|
|
||||||
"There was an fatal error. Try reinstalling the app.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var register = c.Handshake_Register()
|
|
||||||
..username = username
|
|
||||||
..publicIdentityKey = reqSignal["identityKey"]
|
|
||||||
..signedPrekey = reqSignal["signedPreKey"]?["key"]
|
|
||||||
..signedPrekeySignature = reqSignal["signedPreKey"]?["signature"]
|
|
||||||
..signedPrekeyId = Int64(reqSignal["signedPreKey"]?["id"]);
|
|
||||||
|
|
||||||
if (inviteCode != null && inviteCode != "") {
|
|
||||||
register.inviteCode = inviteCode;
|
|
||||||
}
|
|
||||||
// Create the Handshake message
|
|
||||||
var handshake = c.Handshake()..register = register;
|
|
||||||
var req = createClientToServerFromHandshake(handshake);
|
|
||||||
|
|
||||||
var seq = Random().nextInt(4294967296);
|
|
||||||
final tmp = Exchange(seq: seq, kind: ExchangeKind.sendRequestV0, body: req);
|
|
||||||
_sendPort!.send(tmp);
|
|
||||||
|
|
||||||
final resp = await _waitForResponse(seq);
|
|
||||||
|
|
||||||
if (resp == null) {
|
|
||||||
return Result.error("Server is not reachable!");
|
|
||||||
}
|
|
||||||
return asResult(resp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Backend {
|
|
||||||
Backend({required this.apiUrl, required this.backupApiUrl});
|
|
||||||
|
|
||||||
final String apiUrl;
|
final String apiUrl;
|
||||||
final String? backupApiUrl;
|
final String? backupApiUrl;
|
||||||
final log = Logger("twonly::backend");
|
final log = Logger("connect::ApiProvider");
|
||||||
|
final HashMap<String, List<Function>> _callbacks = HashMap();
|
||||||
|
|
||||||
final HashMap<Int64, server.ServerToClient?> messagesV0 = HashMap();
|
final HashMap<Int64, server.ServerToClient?> messagesV0 = HashMap();
|
||||||
|
|
||||||
|
|
@ -213,18 +54,20 @@ class Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> connect() async {
|
Future<bool> connect(Function(bool)? callBack) async {
|
||||||
print("Trying to connect to the backend $apiUrl!");
|
print("Trying to connect to the backend $apiUrl!");
|
||||||
if (_channel != null && _channel!.closeCode != null) {
|
if (_channel != null && _channel!.closeCode != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
log.info("Trying to connect to the backend $apiUrl!");
|
log.info("Trying to connect to the backend $apiUrl!");
|
||||||
if (await _connectTo(apiUrl)) {
|
if (await _connectTo(apiUrl)) {
|
||||||
|
if (callBack != null) callBack(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (backupApiUrl != null) {
|
if (backupApiUrl != null) {
|
||||||
log.info("Trying to connect to the backup backend $backupApiUrl!");
|
log.info("Trying to connect to the backup backend $backupApiUrl!");
|
||||||
if (await _connectTo(backupApiUrl!)) {
|
if (await _connectTo(backupApiUrl!)) {
|
||||||
|
if (callBack != null) callBack(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -246,6 +89,13 @@ class Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 :/
|
// TODO: There must be a smarter move to do that :/
|
||||||
Future<server.ServerToClient?> _waitForResponse(Int64 seq) async {
|
Future<server.ServerToClient?> _waitForResponse(Int64 seq) async {
|
||||||
final startTime = DateTime.now();
|
final startTime = DateTime.now();
|
||||||
|
|
@ -266,8 +116,7 @@ class Backend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<server.ServerToClient?> _sendRequestV0(
|
Future<server.ServerToClient?> _sendRequestV0(ClientToServer request) async {
|
||||||
c.ClientToServer request) async {
|
|
||||||
var seq = Int64(Random().nextInt(4294967296));
|
var seq = Int64(Random().nextInt(4294967296));
|
||||||
while (messagesV0.containsKey(seq)) {
|
while (messagesV0.containsKey(seq)) {
|
||||||
seq = Int64(Random().nextInt(4294967296));
|
seq = Int64(Random().nextInt(4294967296));
|
||||||
|
|
@ -278,7 +127,7 @@ class Backend {
|
||||||
|
|
||||||
log.info("Check if is connected?");
|
log.info("Check if is connected?");
|
||||||
// check if it is connected to the backend. if not try to reconnect.
|
// check if it is connected to the backend. if not try to reconnect.
|
||||||
if (!await connect()) {
|
if (!await connect(null)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,6 +136,18 @@ class Backend {
|
||||||
return await _waitForResponse(seq);
|
return await _waitForResponse(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientToServer createClientToServerFromHandshake(Handshake handshake) {
|
||||||
|
// Create the V0 message
|
||||||
|
var v0 = V0()
|
||||||
|
..seq = Int64(0) // You can set this to the appropriate sequence number
|
||||||
|
..handshake = handshake;
|
||||||
|
|
||||||
|
// Create the ClientToServer message
|
||||||
|
var clientToServer = ClientToServer()..v0 = v0;
|
||||||
|
|
||||||
|
return clientToServer;
|
||||||
|
}
|
||||||
|
|
||||||
static String getLocalizedString(BuildContext context, ErrorCode code) {
|
static String getLocalizedString(BuildContext context, ErrorCode code) {
|
||||||
switch (code.toString()) {
|
switch (code.toString()) {
|
||||||
case "Unknown":
|
case "Unknown":
|
||||||
|
|
@ -319,4 +180,41 @@ class Backend {
|
||||||
return code.toString(); // Fallback for unrecognized keys
|
return code.toString(); // Fallback for unrecognized keys
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result _asResult(server.ServerToClient msg) {
|
||||||
|
if (msg.v0.response.hasOk()) {
|
||||||
|
return Result.success(msg.v0.response.ok);
|
||||||
|
} else {
|
||||||
|
return Result.error(msg.v0.response.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Result> register(String username, String? inviteCode) async {
|
||||||
|
final reqSignal = await SignalHelper.getRegisterData();
|
||||||
|
|
||||||
|
if (reqSignal == null) {
|
||||||
|
return Result.error(
|
||||||
|
"There was an fatal error. Try reinstalling the app.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var register = Handshake_Register()
|
||||||
|
..username = username
|
||||||
|
..publicIdentityKey = reqSignal["identityKey"]
|
||||||
|
..signedPrekey = reqSignal["signedPreKey"]?["key"]
|
||||||
|
..signedPrekeySignature = reqSignal["signedPreKey"]?["signature"]
|
||||||
|
..signedPrekeyId = Int64(reqSignal["signedPreKey"]?["id"]);
|
||||||
|
|
||||||
|
if (inviteCode != null && inviteCode != "") {
|
||||||
|
register.inviteCode = inviteCode;
|
||||||
|
}
|
||||||
|
// Create the Handshake message
|
||||||
|
var handshake = Handshake()..register = register;
|
||||||
|
var req = createClientToServerFromHandshake(handshake);
|
||||||
|
|
||||||
|
final resp = await _sendRequestV0(req);
|
||||||
|
if (resp == null) {
|
||||||
|
return Result.error("Server is not reachable!");
|
||||||
|
}
|
||||||
|
return _asResult(resp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:twonly/main.dart';
|
import 'package:twonly/main.dart';
|
||||||
import 'package:twonly/src/signal/signal_helper.dart';
|
import 'package:twonly/src/signal/signal_helper.dart';
|
||||||
import 'package:twonly/src/providers/api_provider.dart';
|
import 'package:twonly/src/providers/api_provider.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'model/user_data_json.dart';
|
import 'model/user_data_json.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
// Just a helper function to get the secure storage
|
// Just a helper function to get the secure storage
|
||||||
|
|
@ -46,18 +44,13 @@ Future<bool> deleteLocalUserData() async {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Result> createNewUser(
|
Future<Result> createNewUser(String username, String inviteCode) async {
|
||||||
BuildContext context, String username, String inviteCode) async {
|
|
||||||
final storage = getSecureStorage();
|
final storage = getSecureStorage();
|
||||||
if (!context.mounted) {
|
|
||||||
return Result.error("not mounted");
|
|
||||||
}
|
|
||||||
|
|
||||||
await SignalHelper.createIfNotExistsSignalIdentity();
|
await SignalHelper.createIfNotExistsSignalIdentity();
|
||||||
|
|
||||||
// TODO: API call to server to check username and inviteCode
|
// TODO: API call to server to check username and inviteCode
|
||||||
// final res = await apiProvider.register(username, inviteCode);
|
final res = await apiProvider.register(username, inviteCode);
|
||||||
final res = await context.watch<ApiProvider>().register(username, inviteCode);
|
|
||||||
|
|
||||||
if (res.isSuccess) {
|
if (res.isSuccess) {
|
||||||
print("Got user_id ${res.value}");
|
print("Got user_id ${res.value}");
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ class _RegisterViewState extends State<RegisterView> {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isTryingToRegister = true;
|
_isTryingToRegister = true;
|
||||||
});
|
});
|
||||||
final res = await createNewUser(context,
|
final res = await createNewUser(
|
||||||
usernameController.text, inviteCodeController.text);
|
usernameController.text, inviteCodeController.text);
|
||||||
setState(() {
|
setState(() {
|
||||||
_isTryingToRegister = false;
|
_isTryingToRegister = false;
|
||||||
|
|
@ -130,7 +130,7 @@ class _RegisterViewState extends State<RegisterView> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final errMsg =
|
final errMsg =
|
||||||
Backend.getLocalizedString(context, res.error);
|
ApiProvider.getLocalizedString(context, res.error);
|
||||||
showAlertDialog(context, "Oh no!", errMsg);
|
showAlertDialog(context, "Oh no!", errMsg);
|
||||||
},
|
},
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue