mirror of
				https://gitlab.com/famedly/fluffychat.git
				synced 2025-11-04 06:17:26 +01:00 
			
		
		
		
	feat: add bootstrapping
This commit is contained in:
		
							parent
							
								
									d89512e495
								
							
						
					
					
						commit
						b6a48b92a0
					
				
							
								
								
									
										121
									
								
								lib/components/dialogs/uia_dialog.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								lib/components/dialogs/uia_dialog.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,121 @@
 | 
			
		||||
import 'package:famedlysdk/famedlysdk.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
 | 
			
		||||
import '../matrix.dart';
 | 
			
		||||
 | 
			
		||||
class UiaDialog extends StatefulWidget {
 | 
			
		||||
  final UiaRequest uia;
 | 
			
		||||
 | 
			
		||||
  UiaDialog({this.uia});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  _UiaDialogState createState() => _UiaDialogState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _UiaDialogState extends State<UiaDialog> {
 | 
			
		||||
  bool loading = true;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    loading = widget.uia.nextStages.isEmpty; // initial test if the first reply returned
 | 
			
		||||
    widget.uia.onUpdate = () {
 | 
			
		||||
      loading = false;
 | 
			
		||||
      setState(() => null);
 | 
			
		||||
    };
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    if (loading) {
 | 
			
		||||
      return AlertDialog(
 | 
			
		||||
        title: Text(L10n.of(context).loadingPleaseWait),
 | 
			
		||||
        content: LinearProgressIndicator(),
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    if (widget.uia.fail) {
 | 
			
		||||
      return AlertDialog(
 | 
			
		||||
        title: Text('UIA fail'),
 | 
			
		||||
        actions: <Widget>[
 | 
			
		||||
          FlatButton(
 | 
			
		||||
            child: Text('Close'),
 | 
			
		||||
            onPressed: () => Navigator.of(context).pop(),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    if (widget.uia.done) {
 | 
			
		||||
      return AlertDialog(
 | 
			
		||||
        title: Text('UIA done'),
 | 
			
		||||
        actions: <Widget>[
 | 
			
		||||
          FlatButton(
 | 
			
		||||
            child: Text('Close'),
 | 
			
		||||
            onPressed: () => Navigator.of(context).pop(),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    if (widget.uia.nextStages.isEmpty) {
 | 
			
		||||
      return AlertDialog(
 | 
			
		||||
        title: Text('UIA error'),
 | 
			
		||||
        actions: <Widget>[
 | 
			
		||||
          FlatButton(
 | 
			
		||||
            child: Text('Close'),
 | 
			
		||||
            onPressed: () => Navigator.of(context).pop(),
 | 
			
		||||
          ),
 | 
			
		||||
        ],
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    // TODO: pick next stage
 | 
			
		||||
    final nextStage = widget.uia.nextStages.first;
 | 
			
		||||
    switch (nextStage) {
 | 
			
		||||
      case 'm.login.password':
 | 
			
		||||
        final controller = TextEditingController();
 | 
			
		||||
        String input;
 | 
			
		||||
        final submit = () {
 | 
			
		||||
          final client = Matrix.of(context).client;
 | 
			
		||||
          final auth = <String, dynamic>{
 | 
			
		||||
            'password': input,
 | 
			
		||||
            'user': client.userID,
 | 
			
		||||
            'identifier': <String, dynamic>{
 | 
			
		||||
              'type': 'm.id.user',
 | 
			
		||||
              'user': client.userID,
 | 
			
		||||
            },
 | 
			
		||||
          };
 | 
			
		||||
          widget.uia.completeStage('m.login.password', auth);
 | 
			
		||||
          setState(() => loading = true);
 | 
			
		||||
        };
 | 
			
		||||
        return AlertDialog(
 | 
			
		||||
          title: Text('Ender password'),
 | 
			
		||||
          content: TextField(
 | 
			
		||||
            controller: controller,
 | 
			
		||||
            autofocus: true,
 | 
			
		||||
            autocorrect: false,
 | 
			
		||||
            onSubmitted: (s) {
 | 
			
		||||
              input = s;
 | 
			
		||||
              submit();
 | 
			
		||||
            },
 | 
			
		||||
            minLines: 1,
 | 
			
		||||
            maxLines: 1,
 | 
			
		||||
            obscureText: true,
 | 
			
		||||
            decoration: InputDecoration(
 | 
			
		||||
              border: OutlineInputBorder(),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
          actions: <Widget>[
 | 
			
		||||
            FlatButton(
 | 
			
		||||
              child: Text('Submit'),
 | 
			
		||||
              onPressed: () {
 | 
			
		||||
                input = controller.text;
 | 
			
		||||
                submit();
 | 
			
		||||
              },
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        );
 | 
			
		||||
      default:
 | 
			
		||||
        return AlertDialog(
 | 
			
		||||
          title: Text('Unknown UIA stage ' + nextStage),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -24,6 +24,7 @@ import '../utils/famedlysdk_store.dart';
 | 
			
		||||
import '../views/key_verification.dart';
 | 
			
		||||
import '../utils/platform_infos.dart';
 | 
			
		||||
import 'avatar.dart';
 | 
			
		||||
import 'dialogs/uia_dialog.dart';
 | 
			
		||||
 | 
			
		||||
class Matrix extends StatefulWidget {
 | 
			
		||||
  static const String callNamespace = 'chat.fluffy.jitsi_call';
 | 
			
		||||
@ -118,6 +119,7 @@ class MatrixState extends State<Matrix> {
 | 
			
		||||
  StreamSubscription onKeyVerificationRequestSub;
 | 
			
		||||
  StreamSubscription onJitsiCallSub;
 | 
			
		||||
  StreamSubscription onNotification;
 | 
			
		||||
  StreamSubscription onUiaRequestSub;
 | 
			
		||||
  StreamSubscription<html.Event> onFocusSub;
 | 
			
		||||
  StreamSubscription<html.Event> onBlurSub;
 | 
			
		||||
 | 
			
		||||
@ -297,6 +299,12 @@ class MatrixState extends State<Matrix> {
 | 
			
		||||
          await request.rejectVerification();
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      onUiaRequestSub ??= client.onUiaRequest.stream.listen((UiaRequest uia) {
 | 
			
		||||
        showDialog(
 | 
			
		||||
          context: context,
 | 
			
		||||
          builder: (c) => UiaDialog(uia: uia),
 | 
			
		||||
        );
 | 
			
		||||
      });
 | 
			
		||||
      _initWithStore();
 | 
			
		||||
    } else {
 | 
			
		||||
      client = widget.client;
 | 
			
		||||
@ -342,6 +350,7 @@ class MatrixState extends State<Matrix> {
 | 
			
		||||
    onKeyVerificationRequestSub?.cancel();
 | 
			
		||||
    onJitsiCallSub?.cancel();
 | 
			
		||||
    onNotification?.cancel();
 | 
			
		||||
    onUiaRequestSub?.cancel();
 | 
			
		||||
    onFocusSub?.cancel();
 | 
			
		||||
    onBlurSub?.cancel();
 | 
			
		||||
    super.dispose();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										344
									
								
								lib/views/bootstrap.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										344
									
								
								lib/views/bootstrap.dart
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,344 @@
 | 
			
		||||
import 'package:famedlysdk/famedlysdk.dart';
 | 
			
		||||
import 'package:famedlysdk/encryption.dart';
 | 
			
		||||
import 'package:famedlysdk/matrix_api.dart';
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
 | 
			
		||||
 | 
			
		||||
import '../components/adaptive_page_layout.dart';
 | 
			
		||||
import '../components/avatar.dart';
 | 
			
		||||
import '../components/dialogs/simple_dialogs.dart';
 | 
			
		||||
import '../components/matrix.dart';
 | 
			
		||||
import 'chat_list.dart';
 | 
			
		||||
 | 
			
		||||
class BootstrapView extends StatelessWidget {
 | 
			
		||||
  BootstrapView();
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
 | 
			
		||||
    return AdaptivePageLayout(
 | 
			
		||||
      primaryPage: FocusPage.SECOND,
 | 
			
		||||
      firstScaffold: ChatList(),
 | 
			
		||||
      secondScaffold: BootstrapPage(Matrix.of(context).client),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class BootstrapPage extends StatefulWidget {
 | 
			
		||||
  final Client client;
 | 
			
		||||
  BootstrapPage(this.client);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  _BootstrapPageState createState() => _BootstrapPageState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _BootstrapPageState extends State<BootstrapPage> {
 | 
			
		||||
  Bootstrap bootstrap;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  void initState() {
 | 
			
		||||
    bootstrap = widget.client.encryption.bootstrap(onUpdate: () => setState(() => null));
 | 
			
		||||
    super.initState();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    Widget body;
 | 
			
		||||
    final buttons = <Widget>[];
 | 
			
		||||
    switch (bootstrap.state) {
 | 
			
		||||
      case BootstrapState.loading:
 | 
			
		||||
        body = CircularProgressIndicator();
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askWipeSsss:
 | 
			
		||||
        body = Text('Wipe SSSS?');
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text('Yes'),
 | 
			
		||||
          onPressed: () => bootstrap.wipeSsss(true),
 | 
			
		||||
        ));
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('No'),
 | 
			
		||||
          onPressed: () => bootstrap.wipeSsss(false),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askUseExistingSsss:
 | 
			
		||||
        body = Text('Use existing SSSS?');
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text('Yes'),
 | 
			
		||||
          onPressed: () => bootstrap.useExistingSsss(true),
 | 
			
		||||
        ));
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('No'),
 | 
			
		||||
          onPressed: () => bootstrap.useExistingSsss(false),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askBadSsss:
 | 
			
		||||
        body = Text('SSSS bad - continue nevertheless? DATALOSS!!!');
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text('Yes'),
 | 
			
		||||
          onPressed: () => bootstrap.ignoreBadSecrets(true),
 | 
			
		||||
        ));
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('No'),
 | 
			
		||||
          onPressed: () => bootstrap.ignoreBadSecrets(false),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askUnlockSsss:
 | 
			
		||||
        final widgets = <Widget>[Text('Unlock old SSSS')];
 | 
			
		||||
        for (final entry in bootstrap.oldSsssKeys.entries) {
 | 
			
		||||
          final keyId = entry.key;
 | 
			
		||||
          final key = entry.value;
 | 
			
		||||
          widgets.add(Flexible(child: _AskUnlockOldSsss(keyId, key)));
 | 
			
		||||
        }
 | 
			
		||||
        body = Column(
 | 
			
		||||
          children: widgets,
 | 
			
		||||
          mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        );
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('Done'),
 | 
			
		||||
          onPressed: () => bootstrap.unlockedSsss(),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askNewSsss:
 | 
			
		||||
        String passphrase;
 | 
			
		||||
        body = Column(
 | 
			
		||||
          children: <Widget>[
 | 
			
		||||
            Text('New SSSS passphrase'),
 | 
			
		||||
            Flexible(
 | 
			
		||||
              child: TextField(
 | 
			
		||||
                autofocus: false,
 | 
			
		||||
                autocorrect: false,
 | 
			
		||||
                onChanged: (s) {
 | 
			
		||||
                  passphrase = s;
 | 
			
		||||
                },
 | 
			
		||||
                minLines: 1,
 | 
			
		||||
                maxLines: 1,
 | 
			
		||||
                obscureText: true,
 | 
			
		||||
                decoration: InputDecoration(
 | 
			
		||||
                  hintText: 'New passphrase',
 | 
			
		||||
                  prefixStyle: TextStyle(color: Theme.of(context).primaryColor),
 | 
			
		||||
                  suffixStyle: TextStyle(color: Theme.of(context).primaryColor),
 | 
			
		||||
                  border: OutlineInputBorder(),
 | 
			
		||||
                ),
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
          mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        );
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('Done'),
 | 
			
		||||
          onPressed: () => bootstrap.newSsss(passphrase?.isNotEmpty ?? false ? passphrase : null),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.openExistingSsss:
 | 
			
		||||
        body = Column(
 | 
			
		||||
          children: <Widget>[
 | 
			
		||||
            Text('Existing SSSS passphrase'),
 | 
			
		||||
            Flexible(child: _AskUnlockOldSsss('existing', bootstrap.newSsssKey)),
 | 
			
		||||
          ],
 | 
			
		||||
          mainAxisSize: MainAxisSize.min,
 | 
			
		||||
        );
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('Done'),
 | 
			
		||||
          onPressed: () => bootstrap.openExistingSsss(),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askWipeCrossSigning:
 | 
			
		||||
        body = Text('Wipe cross-signing?');
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text('Yes'),
 | 
			
		||||
          onPressed: () => bootstrap.wipeCrossSigning(true),
 | 
			
		||||
        ));
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('No'),
 | 
			
		||||
          onPressed: () => bootstrap.wipeCrossSigning(false),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askSetupCrossSigning:
 | 
			
		||||
        body = Text('Set up cross-signing?');
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text('Yes'),
 | 
			
		||||
          onPressed: () => bootstrap.askSetupCrossSigning(
 | 
			
		||||
            setupMasterKey: true,
 | 
			
		||||
            setupSelfSigningKey: true,
 | 
			
		||||
            setupUserSigningKey: true,
 | 
			
		||||
          ),
 | 
			
		||||
        ));
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('No'),
 | 
			
		||||
          onPressed: () => bootstrap.askSetupCrossSigning(),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askWipeOnlineKeyBackup:
 | 
			
		||||
        body = Text('Wipe online key backup?');
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text('Yes'),
 | 
			
		||||
          onPressed: () => bootstrap.wipeOnlineKeyBackup(true),
 | 
			
		||||
        ));
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('No'),
 | 
			
		||||
          onPressed: () => bootstrap.wipeOnlineKeyBackup(false),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.askSetupOnlineKeyBackup:
 | 
			
		||||
        body = Text('Set up online key backup?');
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text('Yes'),
 | 
			
		||||
          onPressed: () => bootstrap.askSetupOnlineKeyBackup(true),
 | 
			
		||||
        ));
 | 
			
		||||
        buttons.add(RaisedButton(
 | 
			
		||||
          textColor: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          color: Colors.white,
 | 
			
		||||
          child: Text('No'),
 | 
			
		||||
          onPressed: () => bootstrap.askSetupOnlineKeyBackup(false),
 | 
			
		||||
        ));
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.error:
 | 
			
		||||
        body = Icon(Icons.cancel, color: Colors.red, size: 200.0);
 | 
			
		||||
        break;
 | 
			
		||||
      case BootstrapState.done:
 | 
			
		||||
        body = Icon(Icons.check_circle, color: Colors.green, size: 200.0);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    body ??= Text('ERROR: Unknown state ' + bootstrap.state.toString());
 | 
			
		||||
    return Scaffold(
 | 
			
		||||
      appBar: AppBar(
 | 
			
		||||
        title: Text('Bootstrapping'),
 | 
			
		||||
      ),
 | 
			
		||||
      extendBody: true,
 | 
			
		||||
      extendBodyBehindAppBar: true,
 | 
			
		||||
      body: Center(
 | 
			
		||||
        child: body,
 | 
			
		||||
      ),
 | 
			
		||||
      persistentFooterButtons: buttons.isEmpty ? null : buttons,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _AskUnlockOldSsss extends StatefulWidget {
 | 
			
		||||
  final String keyId;
 | 
			
		||||
  final OpenSSSS ssssKey;
 | 
			
		||||
  _AskUnlockOldSsss(this.keyId, this.ssssKey);
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  _AskUnlockOldSsssState createState() => _AskUnlockOldSsssState();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class _AskUnlockOldSsssState extends State<_AskUnlockOldSsss> {
 | 
			
		||||
  bool valid = false;
 | 
			
		||||
  TextEditingController textEditingController = TextEditingController();
 | 
			
		||||
  String input;
 | 
			
		||||
 | 
			
		||||
  void checkInput(BuildContext context) async {
 | 
			
		||||
    if (input == null) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    SimpleDialogs(context).showLoadingDialog(context);
 | 
			
		||||
    valid = false;
 | 
			
		||||
    try {
 | 
			
		||||
      await widget.ssssKey.unlock(keyOrPassphrase: input);
 | 
			
		||||
      valid = true;
 | 
			
		||||
    } catch (_) {
 | 
			
		||||
      valid = false;
 | 
			
		||||
    }
 | 
			
		||||
    await Navigator.of(context)?.pop();
 | 
			
		||||
    setState(() => null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext build) {
 | 
			
		||||
    if (valid) {
 | 
			
		||||
      return Row(
 | 
			
		||||
        children: <Widget>[
 | 
			
		||||
          Text(widget.keyId),
 | 
			
		||||
          Text('unlocked'),
 | 
			
		||||
        ],
 | 
			
		||||
        mainAxisSize: MainAxisSize.min,
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    return Row(
 | 
			
		||||
      children: <Widget>[
 | 
			
		||||
        Text(widget.keyId),
 | 
			
		||||
        Flexible(
 | 
			
		||||
          child: TextField(
 | 
			
		||||
            controller: textEditingController,
 | 
			
		||||
            autofocus: false,
 | 
			
		||||
            autocorrect: false,
 | 
			
		||||
            onSubmitted: (s) {
 | 
			
		||||
              input = s;
 | 
			
		||||
              checkInput(context);
 | 
			
		||||
            },
 | 
			
		||||
            minLines: 1,
 | 
			
		||||
            maxLines: 1,
 | 
			
		||||
            obscureText: true,
 | 
			
		||||
            decoration: InputDecoration(
 | 
			
		||||
              hintText: L10n.of(context).passphraseOrKey,
 | 
			
		||||
              prefixStyle: TextStyle(color: Theme.of(context).primaryColor),
 | 
			
		||||
              suffixStyle: TextStyle(color: Theme.of(context).primaryColor),
 | 
			
		||||
              border: OutlineInputBorder(),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
        RaisedButton(
 | 
			
		||||
          color: Theme.of(context).primaryColor,
 | 
			
		||||
          elevation: 5,
 | 
			
		||||
          textColor: Colors.white,
 | 
			
		||||
          child: Text(L10n.of(context).submit),
 | 
			
		||||
          onPressed: () {
 | 
			
		||||
            input = textEditingController.text;
 | 
			
		||||
            checkInput(context);
 | 
			
		||||
          },
 | 
			
		||||
        ),
 | 
			
		||||
      ],
 | 
			
		||||
      mainAxisSize: MainAxisSize.min,
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -27,9 +27,9 @@ class HomeserverPicker extends StatelessWidget {
 | 
			
		||||
      await SentryController.toggleSentryAction(context);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!homeserver.startsWith('https://')) {
 | 
			
		||||
      homeserver = 'https://$homeserver';
 | 
			
		||||
    }
 | 
			
		||||
//    if (!homeserver.startsWith('https://')) {
 | 
			
		||||
//      homeserver = 'https://$homeserver';
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
    final success = await SimpleDialogs(context).tryRequestWithLoadingDialog(
 | 
			
		||||
        checkHomeserver(homeserver, Matrix.of(context).client));
 | 
			
		||||
 | 
			
		||||
@ -78,19 +78,12 @@ class _KeyVerificationPageState extends State<KeyVerificationPage> {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          SimpleDialogs(context).showLoadingDialog(context);
 | 
			
		||||
          // make sure the loading spinner shows before we test the keys
 | 
			
		||||
          await Future.delayed(Duration(milliseconds: 100));
 | 
			
		||||
          var valid = false;
 | 
			
		||||
          try {
 | 
			
		||||
            await widget.request.openSSSS(recoveryKey: input);
 | 
			
		||||
            await widget.request.openSSSS(keyOrPassphrase: input);
 | 
			
		||||
            valid = true;
 | 
			
		||||
          } catch (_) {
 | 
			
		||||
            try {
 | 
			
		||||
              await widget.request.openSSSS(passphrase: input);
 | 
			
		||||
              valid = true;
 | 
			
		||||
            } catch (_) {
 | 
			
		||||
              valid = false;
 | 
			
		||||
            }
 | 
			
		||||
            valid = false;
 | 
			
		||||
          }
 | 
			
		||||
          await Navigator.of(context)?.pop();
 | 
			
		||||
          if (!valid) {
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,7 @@ import '../utils/app_route.dart';
 | 
			
		||||
import 'app_info.dart';
 | 
			
		||||
import 'chat_list.dart';
 | 
			
		||||
import 'settings_emotes.dart';
 | 
			
		||||
import 'bootstrap.dart';
 | 
			
		||||
 | 
			
		||||
class SettingsView extends StatelessWidget {
 | 
			
		||||
  @override
 | 
			
		||||
@ -198,23 +199,12 @@ class _SettingsState extends State<Settings> {
 | 
			
		||||
    );
 | 
			
		||||
    if (str != null) {
 | 
			
		||||
      SimpleDialogs(context).showLoadingDialog(context);
 | 
			
		||||
      // make sure the loading spinner shows before we test the keys
 | 
			
		||||
      await Future.delayed(Duration(milliseconds: 100));
 | 
			
		||||
      var valid = false;
 | 
			
		||||
      try {
 | 
			
		||||
        handle.unlock(recoveryKey: str);
 | 
			
		||||
        await handle.unlock(keyOrPassphrase: str);
 | 
			
		||||
        valid = true;
 | 
			
		||||
      } catch (e, s) {
 | 
			
		||||
        debugPrint('Couldn\'t use recovery key: ' + e.toString());
 | 
			
		||||
        debugPrint(s.toString());
 | 
			
		||||
        try {
 | 
			
		||||
          handle.unlock(passphrase: str);
 | 
			
		||||
          valid = true;
 | 
			
		||||
        } catch (e, s) {
 | 
			
		||||
          debugPrint('Couldn\'t use recovery passphrase: ' + e.toString());
 | 
			
		||||
          debugPrint(s.toString());
 | 
			
		||||
          valid = false;
 | 
			
		||||
        }
 | 
			
		||||
        valid = false;
 | 
			
		||||
      }
 | 
			
		||||
      await Navigator.of(context)?.pop();
 | 
			
		||||
      if (valid) {
 | 
			
		||||
@ -466,10 +456,16 @@ class _SettingsState extends State<Settings> {
 | 
			
		||||
                                  : L10n.of(context).keysMissing)))
 | 
			
		||||
                  : null,
 | 
			
		||||
              onTap: () async {
 | 
			
		||||
                if (!client.encryption.crossSigning.enabled) {
 | 
			
		||||
                  await SimpleDialogs(context).inform(
 | 
			
		||||
                    contentText: L10n.of(context).noCrossSignBootstrap,
 | 
			
		||||
                if (true || !client.encryption.crossSigning.enabled) {
 | 
			
		||||
                  await Navigator.of(context).push(
 | 
			
		||||
                    AppRoute.defaultRoute(
 | 
			
		||||
                      context,
 | 
			
		||||
                      BootstrapView(),
 | 
			
		||||
                    ),
 | 
			
		||||
                  );
 | 
			
		||||
                  /*await SimpleDialogs(context).inform(
 | 
			
		||||
                    contentText: L10n.of(context).noCrossSignBootstrap,
 | 
			
		||||
                  );*/
 | 
			
		||||
                  return;
 | 
			
		||||
                }
 | 
			
		||||
                if (client.isUnknownSession) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user