mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 11:18:41 +00:00
register process works
This commit is contained in:
parent
d895fd450e
commit
d152240c16
8 changed files with 239 additions and 141 deletions
|
|
@ -3,8 +3,8 @@ import 'views/home_view.dart';
|
||||||
import 'views/register_view.dart';
|
import 'views/register_view.dart';
|
||||||
import 'utils.dart';
|
import 'utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
// import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
// import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
import 'settings/settings_controller.dart';
|
import 'settings/settings_controller.dart';
|
||||||
|
|
||||||
|
|
@ -34,16 +34,17 @@ class _MyAppState extends State<MyApp> {
|
||||||
builder: (BuildContext context, Widget? child) {
|
builder: (BuildContext context, Widget? child) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
restorationScopeId: 'app',
|
restorationScopeId: 'app',
|
||||||
// localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
// AppLocalizations.delegate,
|
AppLocalizations.delegate,
|
||||||
// GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
// GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
// GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
// ],
|
|
||||||
supportedLocales: const [
|
|
||||||
Locale('en', ''), // English, no country code
|
|
||||||
],
|
],
|
||||||
onGenerateTitle: (BuildContext context) => "Connect!",
|
supportedLocales: const [
|
||||||
|
Locale('en', ''),
|
||||||
|
Locale('de', ''),
|
||||||
|
],
|
||||||
|
onGenerateTitle: (BuildContext context) => "twonly",
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
colorScheme:
|
colorScheme:
|
||||||
ColorScheme.fromSeed(seedColor: const Color(0xFF57CC99)),
|
ColorScheme.fromSeed(seedColor: const Color(0xFF57CC99)),
|
||||||
|
|
|
||||||
6
lib/src/localization/app_de.arb
Normal file
6
lib/src/localization/app_de.arb
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"@@locale": "de",
|
||||||
|
"registerTitle": "Willkommen bei twonly",
|
||||||
|
"@registerTitle": {},
|
||||||
|
"registerSlogan": "Sende Bilder in Echtzeit an Freunde und sei dir sicher, dass nur ihr sie sehen könnt."
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,22 @@
|
||||||
{
|
{
|
||||||
"appTitle": "connect",
|
|
||||||
"@@locale": "en",
|
"@@locale": "en",
|
||||||
"@appTitle": {
|
"registerTitle": "Welcome to twonly!",
|
||||||
"description": "The title of the application"
|
"registerSlogan": "Send pictures to friends in real time and be sure you are the only people who can see them.",
|
||||||
}
|
"registerUsernameSlogan": "Please select a username so others can find you!",
|
||||||
|
"registerUsernameDecoration": "Username",
|
||||||
|
"registerUsernameLimits": "Username must be 4 to 12 characters long, consisting only of letters (a-z) and numbers (0-9).",
|
||||||
|
"registerSubmitButton": "Register now!",
|
||||||
|
"errorUnknown": "An unexpected error has occurred. Please try again later.",
|
||||||
|
"errorBadRequest": "The request could not be understood by the server due to malformed syntax. Please check your input and try again.",
|
||||||
|
"errorTooManyRequests": "You have made too many requests in a short period. Please wait a moment before trying again.",
|
||||||
|
"errorInternalError": "The server encountered an internal error. Please try again later.",
|
||||||
|
"errorInvalidInvitationCode": "The invitation code you provided is invalid. Please check the code and try again.",
|
||||||
|
"errorUsernameAlreadyTaken": "The username you want to use is already taken. Please choose a different username.",
|
||||||
|
"errorSignatureNotValid": "The provided signature is not valid. Please check your credentials and try again.",
|
||||||
|
"errorUsernameNotFound": "The username you entered does not exist. Please check the spelling or create a new account.",
|
||||||
|
"errorUsernameNotValid": "The username you provided does not meet the required criteria. Please choose a valid username.",
|
||||||
|
"errorInvalidPublicKey": "The public key you provided is invalid. Please check the key and try again.",
|
||||||
|
"errorSessionAlreadyAuthenticated": "You are already logged in. Please log out if you want to log in with a different account.",
|
||||||
|
"errorSessionNotAuthenticated": "Your session is not authenticated. Please log in to continue.",
|
||||||
|
"errorOnlyOneSessionAllowed": "Only one active session is allowed per user. Please log out from other devices to continue."
|
||||||
}
|
}
|
||||||
|
|
@ -4,13 +4,27 @@ import 'dart:ffi';
|
||||||
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:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:twonly/src/proto/api/client_to_server.pb.dart';
|
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/server_to_client.pb.dart' as server;
|
import 'package:twonly/src/proto/api/server_to_client.pb.dart' as server;
|
||||||
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:web_socket_channel/web_socket_channel.dart';
|
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||||
|
|
||||||
|
class Result<T, E> {
|
||||||
|
final T? value;
|
||||||
|
final E? error;
|
||||||
|
|
||||||
|
bool get isSuccess => value != null;
|
||||||
|
bool get isError => error != null;
|
||||||
|
|
||||||
|
Result.success(this.value) : error = null;
|
||||||
|
Result.error(this.error) : value = null;
|
||||||
|
}
|
||||||
|
|
||||||
class ApiProvider {
|
class ApiProvider {
|
||||||
ApiProvider({required this.apiUrl});
|
ApiProvider({required this.apiUrl});
|
||||||
|
|
||||||
|
|
@ -77,7 +91,7 @@ class ApiProvider {
|
||||||
log.shout("Timeout for message $seq");
|
log.shout("Timeout for message $seq");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
await Future.delayed(Duration(milliseconds: 1));
|
await Future.delayed(Duration(milliseconds: 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -101,21 +115,6 @@ class ApiProvider {
|
||||||
return await _waitForResponse(seq);
|
return await _waitForResponse(seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
String? _getErrorMsg(server.ServerToClient msg) {
|
|
||||||
// if (msg.containsKey("Ok")) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// if (msg.containsKey("Error")) {
|
|
||||||
// if (msg["Error"] != null) {
|
|
||||||
// if (msg["Error"].containsKey("AlertUser")) {
|
|
||||||
// return msg["Error"]["AlertUser"];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return "There was an unknown error :/";
|
|
||||||
// }
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientToServer createClientToServerFromHandshake(Handshake handshake) {
|
ClientToServer createClientToServerFromHandshake(Handshake handshake) {
|
||||||
// Create the V0 message
|
// Create the V0 message
|
||||||
var v0 = V0()
|
var v0 = V0()
|
||||||
|
|
@ -128,27 +127,63 @@ class ApiProvider {
|
||||||
return clientToServer;
|
return clientToServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> register(
|
static String getLocalizedString(BuildContext context, ErrorCode code) {
|
||||||
String username,
|
switch (code.toString()) {
|
||||||
// Uint8List publicIdentityKey,
|
case "Unknown":
|
||||||
// Uint8List signedPrekey,
|
return AppLocalizations.of(context)!.errorUnknown;
|
||||||
// Uint8List signedPrekeySignature,
|
case "BadRequest":
|
||||||
String? inviteCode) async {
|
return AppLocalizations.of(context)!.errorBadRequest;
|
||||||
|
case "TooManyRequests":
|
||||||
|
return AppLocalizations.of(context)!.errorTooManyRequests;
|
||||||
|
case "InternalError":
|
||||||
|
return AppLocalizations.of(context)!.errorInternalError;
|
||||||
|
case "InvalidInvitationCode":
|
||||||
|
return AppLocalizations.of(context)!.errorInvalidInvitationCode;
|
||||||
|
case "UsernameAlreadyTaken":
|
||||||
|
return AppLocalizations.of(context)!.errorUsernameAlreadyTaken;
|
||||||
|
case "SignatureNotValid":
|
||||||
|
return AppLocalizations.of(context)!.errorSignatureNotValid;
|
||||||
|
case "UsernameNotFound":
|
||||||
|
return AppLocalizations.of(context)!.errorUsernameNotFound;
|
||||||
|
case "UsernameNotValid":
|
||||||
|
return AppLocalizations.of(context)!.errorUsernameNotValid;
|
||||||
|
case "InvalidPublicKey":
|
||||||
|
return AppLocalizations.of(context)!.errorInvalidPublicKey;
|
||||||
|
case "SessionAlreadyAuthenticated":
|
||||||
|
return AppLocalizations.of(context)!.errorSessionAlreadyAuthenticated;
|
||||||
|
case "SessionNotAuthenticated":
|
||||||
|
return AppLocalizations.of(context)!.errorSessionNotAuthenticated;
|
||||||
|
case "OnlyOneSessionAllowed":
|
||||||
|
return AppLocalizations.of(context)!.errorOnlyOneSessionAllowed;
|
||||||
|
default:
|
||||||
|
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();
|
final reqSignal = await SignalHelper.getRegisterData();
|
||||||
|
|
||||||
if (reqSignal == null) {
|
if (reqSignal == null) {
|
||||||
print("NULL");
|
return Result.error(
|
||||||
return null;
|
"There was an fatal error. Try reinstalling the app.");
|
||||||
}
|
}
|
||||||
|
|
||||||
print(reqSignal);
|
|
||||||
var register = Handshake_Register()
|
var register = Handshake_Register()
|
||||||
..username = username
|
..username = username
|
||||||
|
..publicIdentityKey = reqSignal["identityKey"]
|
||||||
..signedPrekey = reqSignal["signedPreKey"]?["key"]
|
..signedPrekey = reqSignal["signedPreKey"]?["key"]
|
||||||
..signedPrekeySignature = reqSignal["signedPreKey"]?["signature"]
|
..signedPrekeySignature = reqSignal["signedPreKey"]?["signature"]
|
||||||
..signedPrekeyId = Int64(reqSignal["signedPreKey"]?["id"]);
|
..signedPrekeyId = Int64(reqSignal["signedPreKey"]?["id"]);
|
||||||
|
|
||||||
if (inviteCode != null) {
|
if (inviteCode != null && inviteCode != "") {
|
||||||
register.inviteCode = inviteCode;
|
register.inviteCode = inviteCode;
|
||||||
}
|
}
|
||||||
// Create the Handshake message
|
// Create the Handshake message
|
||||||
|
|
@ -157,8 +192,8 @@ class ApiProvider {
|
||||||
|
|
||||||
final resp = await _sendRequestV0(req);
|
final resp = await _sendRequestV0(req);
|
||||||
if (resp == null) {
|
if (resp == null) {
|
||||||
return "Server is not reachable!";
|
return Result.error("Server is not reachable!");
|
||||||
}
|
}
|
||||||
return _getErrorMsg(resp);
|
return _asResult(resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
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:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'model/signal_identity_json.dart';
|
|
||||||
import 'model/user_data_json.dart';
|
import 'model/user_data_json.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
// Just a helper function to get the secure storage
|
// Just a helper function to get the secure storage
|
||||||
FlutterSecureStorage getSecureStorage() {
|
FlutterSecureStorage getSecureStorage() {
|
||||||
|
|
@ -38,24 +39,25 @@ Future<UserData?> getUser() async {
|
||||||
|
|
||||||
Future<bool> deleteLocalUserData() async {
|
Future<bool> deleteLocalUserData() async {
|
||||||
final storage = getSecureStorage();
|
final storage = getSecureStorage();
|
||||||
await storage.delete(key: "user");
|
await storage.delete(key: "user_data");
|
||||||
|
await storage.delete(key: "signal_identity");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> createNewUser(String username, String inviteCode) async {
|
Future<Result> createNewUser(String username, String inviteCode) async {
|
||||||
final storage = getSecureStorage();
|
final storage = getSecureStorage();
|
||||||
|
|
||||||
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 check = await apiProvider.register(username, inviteCode);
|
final res = await apiProvider.register(username, inviteCode);
|
||||||
if (check != null) {
|
|
||||||
return check;
|
if (res.isSuccess) {
|
||||||
|
print("Got user_id ${res.value}");
|
||||||
|
final userData = UserData(
|
||||||
|
userId: res.value.userid, username: username, displayName: username);
|
||||||
|
storage.write(key: "user_data", value: jsonEncode(userData));
|
||||||
}
|
}
|
||||||
|
|
||||||
print(check);
|
return res;
|
||||||
|
|
||||||
// await storage.write(key: "user_data", value: jsonEncode(userData));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
|
import 'package:twonly/src/providers/api_provider.dart';
|
||||||
|
|
||||||
import '../utils.dart';
|
import '../utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
|
||||||
class RegisterView extends StatefulWidget {
|
class RegisterView extends StatefulWidget {
|
||||||
const RegisterView({super.key, required this.callbackOnSuccess});
|
const RegisterView({super.key, required this.callbackOnSuccess});
|
||||||
|
|
@ -10,36 +13,12 @@ class RegisterView extends StatefulWidget {
|
||||||
State<RegisterView> createState() => _RegisterViewState();
|
State<RegisterView> createState() => _RegisterViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyButton extends StatelessWidget {
|
|
||||||
final void Function()? onTap;
|
|
||||||
final String text;
|
|
||||||
const MyButton({super.key, required this.onTap, required this.text});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: onTap,
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
borderRadius: BorderRadius.circular(9),
|
|
||||||
),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
text,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _RegisterViewState extends State<RegisterView> {
|
class _RegisterViewState extends State<RegisterView> {
|
||||||
final TextEditingController usernameController = TextEditingController();
|
final TextEditingController usernameController = TextEditingController();
|
||||||
final TextEditingController inviteCodeController = TextEditingController();
|
final TextEditingController inviteCodeController = TextEditingController();
|
||||||
|
|
||||||
|
bool _isTryingToRegister = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
InputDecoration getInputDecoration(hintText) {
|
InputDecoration getInputDecoration(hintText) {
|
||||||
|
|
@ -48,77 +27,136 @@ class _RegisterViewState extends State<RegisterView> {
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text("Welcome to Connect!"),
|
title: Text(""),
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: EdgeInsets.all(10),
|
padding: EdgeInsets.all(10),
|
||||||
child: ListView(
|
child: Padding(
|
||||||
children: [
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
const SizedBox(height: 20),
|
child: ListView(
|
||||||
Center(
|
children: [
|
||||||
child: Text(
|
const SizedBox(height: 50),
|
||||||
"You made the right decision using Connect which is like SnXpchat but encrypted using the Signal protocol.",
|
Text(
|
||||||
|
AppLocalizations.of(context)!.registerTitle,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 15),
|
style: TextStyle(fontSize: 30),
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
const SizedBox(height: 40),
|
padding: EdgeInsets.symmetric(horizontal: 30),
|
||||||
Center(
|
child: Text(
|
||||||
child: Text(
|
AppLocalizations.of(context)!.registerSlogan,
|
||||||
"Choice wisely, this username can't be changed. Only lowercase and numbers are allowed!",
|
textAlign: TextAlign.center,
|
||||||
textAlign: TextAlign.center,
|
style: TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 60),
|
||||||
const SizedBox(height: 10),
|
Center(
|
||||||
TextField(
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)!.registerUsernameSlogan,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(fontSize: 15),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 15),
|
||||||
|
TextField(
|
||||||
controller: usernameController,
|
controller: usernameController,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
LengthLimitingTextInputFormatter(
|
LengthLimitingTextInputFormatter(12),
|
||||||
12), // Limit to 12 characters
|
FilteringTextInputFormatter.allow(RegExp(r'[a-z0-9]')),
|
||||||
FilteringTextInputFormatter.allow(RegExp(
|
|
||||||
r'[a-z0-9]')), // Allow only lowercase letters and numbers
|
|
||||||
],
|
],
|
||||||
decoration: getInputDecoration("Username")),
|
style: TextStyle(fontSize: 17),
|
||||||
const SizedBox(height: 15),
|
decoration: getInputDecoration(
|
||||||
Center(
|
AppLocalizations.of(context)!.registerUsernameDecoration,
|
||||||
child: Text(
|
),
|
||||||
"To protect this small experimental project you need an invitation code! To get one just ask the right person!",
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 5),
|
||||||
const SizedBox(height: 10),
|
Center(
|
||||||
TextField(
|
child: Padding(
|
||||||
controller: inviteCodeController,
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
decoration: getInputDecoration("Invitation code")),
|
child: Text(
|
||||||
const SizedBox(height: 25),
|
AppLocalizations.of(context)!.registerUsernameLimits,
|
||||||
Center(
|
textAlign: TextAlign.center,
|
||||||
child: Text(
|
style: TextStyle(fontSize: 7),
|
||||||
"Where is the password? There is none! So make a backup of your Connect identity in the settings or you will lose your access if you lose your device!",
|
),
|
||||||
textAlign: TextAlign.center,
|
),
|
||||||
),
|
),
|
||||||
),
|
// const SizedBox(height: 15),
|
||||||
const SizedBox(height: 30),
|
// Center(
|
||||||
FilledButton.icon(
|
// child: Text(
|
||||||
icon: Icon(Icons.group),
|
// "To protect this small experimental project you need an invitation code! To get one just ask the right person!",
|
||||||
onPressed: () async {
|
// textAlign: TextAlign.center,
|
||||||
final success = await createNewUser(
|
// ),
|
||||||
usernameController.text, inviteCodeController.text);
|
// ),
|
||||||
if (success == null) {
|
// const SizedBox(height: 10),
|
||||||
widget.callbackOnSuccess();
|
// TextField(
|
||||||
return;
|
// controller: inviteCodeController,
|
||||||
}
|
// decoration: getInputDecoration("Voucher code")),
|
||||||
showAlertDialog(context, "Oh no!", success);
|
// const SizedBox(height: 25),
|
||||||
},
|
// Center(
|
||||||
label: Text("Komm in die Gruppe!"),
|
// child: Text(
|
||||||
),
|
// "Please ",
|
||||||
OutlinedButton.icon(
|
// textAlign: TextAlign.center,
|
||||||
onPressed: () {
|
// ),
|
||||||
showAlertDialog(context, "Coming soon",
|
// ),
|
||||||
"This feature is not yet implemented! Just create a new account :/");
|
const SizedBox(height: 50),
|
||||||
},
|
// Padding(
|
||||||
label: Text("Restore identity")),
|
// padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
// MyButton(onTap: () {}, text: "Komm in die Gruppe!")
|
Column(children: [
|
||||||
],
|
FilledButton.icon(
|
||||||
|
icon: _isTryingToRegister
|
||||||
|
? SizedBox(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Colors.black,
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Icon(Icons.group),
|
||||||
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
_isTryingToRegister = true;
|
||||||
|
});
|
||||||
|
final res = await createNewUser(
|
||||||
|
usernameController.text, inviteCodeController.text);
|
||||||
|
setState(() {
|
||||||
|
_isTryingToRegister = false;
|
||||||
|
});
|
||||||
|
if (res.isSuccess) {
|
||||||
|
widget.callbackOnSuccess();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final errMsg =
|
||||||
|
ApiProvider.getLocalizedString(context, res.error);
|
||||||
|
showAlertDialog(context, "Oh no!", errMsg);
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
padding: WidgetStateProperty.all<EdgeInsets>(
|
||||||
|
EdgeInsets.symmetric(vertical: 10, horizontal: 30),
|
||||||
|
),
|
||||||
|
backgroundColor: _isTryingToRegister
|
||||||
|
? WidgetStateProperty.all<MaterialColor>(
|
||||||
|
Colors.grey)
|
||||||
|
: null),
|
||||||
|
label: Text(
|
||||||
|
AppLocalizations.of(context)!.registerSubmitButton,
|
||||||
|
style: TextStyle(fontSize: 17),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
OutlinedButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
showAlertDialog(context, "Coming soon",
|
||||||
|
"This feature is not yet implemented! Just create a new account :/");
|
||||||
|
},
|
||||||
|
label: Text("Restore identity")),
|
||||||
|
]),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -475,7 +475,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.5.2"
|
version: "4.5.2"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ dependencies:
|
||||||
flutter_secure_storage: ^9.2.2
|
flutter_secure_storage: ^9.2.2
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.2.1
|
||||||
image: ^4.3.0
|
image: ^4.3.0
|
||||||
|
intl: any
|
||||||
json_annotation: ^4.9.0
|
json_annotation: ^4.9.0
|
||||||
libsignal_protocol_dart: ^0.7.1
|
libsignal_protocol_dart: ^0.7.1
|
||||||
logging: ^1.3.0
|
logging: ^1.3.0
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue