@ -1,6 +1,4 @@
import ' package:adaptive_dialog/adaptive_dialog.dart ' ;
import ' package:adaptive_dialog/adaptive_dialog.dart ' ;
import ' package:fluffychat/config/setting_keys.dart ' ;
import ' package:fluffychat/utils/matrix_sdk_extensions.dart/flutter_matrix_hive_database.dart ' ;
import ' package:matrix/encryption.dart ' ;
import ' package:matrix/encryption.dart ' ;
import ' package:matrix/encryption/utils/bootstrap.dart ' ;
import ' package:matrix/encryption/utils/bootstrap.dart ' ;
import ' package:matrix/matrix.dart ' ;
import ' package:matrix/matrix.dart ' ;
@ -67,12 +65,6 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
} ) ;
} ) ;
}
}
void cancelAndDontAskAgain ( ) async {
await ( widget . client . database as FlutterMatrixHiveStore )
. put ( SettingKeys . dontAskForBootstrapKey , true ) ;
Navigator . of ( context , rootNavigator: false ) . pop < bool > ( false ) ;
}
@ override
@ override
Widget build ( BuildContext context ) {
Widget build ( BuildContext context ) {
_wipe ? ? = widget . wipe ;
_wipe ? ? = widget . wipe ;
@ -83,43 +75,58 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
titleText = L10n . of ( context ) . loadingPleaseWait ;
titleText = L10n . of ( context ) . loadingPleaseWait ;
if ( bootstrap = = null ) {
if ( bootstrap = = null ) {
titleText = L10n . of ( context ) . chatBackup ;
titleText = L10n . of ( context ) . setupChatBackup ;
body = Text ( L10n . of ( context ) . chatBackupDescription ) ;
body = Column (
mainAxisSize: MainAxisSize . min ,
children: [
Image . asset ( ' assets/backup.png ' , fit: BoxFit . contain ) ,
Text ( L10n . of ( context ) . setupChatBackupDescription ) ,
] ,
) ;
buttons . add ( AdaptiveFlatButton (
buttons . add ( AdaptiveFlatButton (
label: L10n . of ( context ) . next ,
label: L10n . of ( context ) . next ,
onPressed: ( ) = > _createBootstrap ( false ) ,
onPressed: ( ) = > _createBootstrap ( false ) ,
) ) ;
) ) ;
buttons . add ( AdaptiveFlatButton (
label: L10n . of ( context ) . dontAskAgain ,
onPressed: cancelAndDontAskAgain ,
textColor: Colors . red ,
) ) ;
} else if ( bootstrap . newSsssKey ? . recoveryKey ! = null & &
} else if ( bootstrap . newSsssKey ? . recoveryKey ! = null & &
_recoveryKeyStored = = false ) {
_recoveryKeyStored = = false ) {
final key = bootstrap . newSsssKey . recoveryKey ;
final key = bootstrap . newSsssKey . recoveryKey ;
titleText = L10n . of ( context ) . securityKey ;
titleText = L10n . of ( context ) . securityKey ;
body = Container (
return Scaffold (
alignment: Alignment . center ,
appBar: AppBar (
width: 200 ,
leading: IconButton (
height: 128 ,
icon: Icon ( Icons . close ) ,
child: Text (
onPressed: Navigator . of ( context ) . pop ,
key ,
textAlign: TextAlign . center ,
style: TextStyle (
fontSize: 18 ,
wordSpacing: 38 ,
fontFamily: ' monospace ' ,
) ,
) ,
title: Text ( L10n . of ( context ) . securityKey ) ,
) ,
) ,
) ;
body: ListView (
buttons . add ( AdaptiveFlatButton (
padding: const EdgeInsets . all ( 16.0 ) ,
label: L10n . of ( context ) . copyToClipboard ,
children: [
TextField (
minLines: 4 ,
maxLines: 4 ,
readOnly: true ,
controller: TextEditingController ( text: key ) ,
) ,
const SizedBox ( height: 16 ) ,
ElevatedButton . icon (
icon: Icon ( Icons . copy_outlined ) ,
label: Text ( L10n . of ( context ) . copyToClipboard ) ,
onPressed: ( ) = > Clipboard . setData ( ClipboardData ( text: key ) ) ,
onPressed: ( ) = > Clipboard . setData ( ClipboardData ( text: key ) ) ,
) ) ;
) ,
buttons . add ( AdaptiveFlatButton (
const SizedBox ( height: 16 ) ,
label: L10n . of ( context ) . next ,
ElevatedButton . icon (
style: ElevatedButton . styleFrom (
primary: Theme . of ( context ) . secondaryHeaderColor ,
onPrimary: Theme . of ( context ) . primaryColor ,
) ,
icon: Icon ( Icons . check_outlined ) ,
label: Text ( L10n . of ( context ) . iWroteDownTheKey ) ,
onPressed: ( ) = > setState ( ( ) = > _recoveryKeyStored = true ) ,
onPressed: ( ) = > setState ( ( ) = > _recoveryKeyStored = true ) ,
) ) ;
) ,
] ,
) ,
) ;
} else {
} else {
switch ( bootstrap . state ) {
switch ( bootstrap . state ) {
case BootstrapState . loading:
case BootstrapState . loading:
@ -151,22 +158,20 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
break ;
break ;
case BootstrapState . openExistingSsss:
case BootstrapState . openExistingSsss:
_recoveryKeyStored = true ;
_recoveryKeyStored = true ;
titleText =
return Scaffold (
_recoveryKeyInputError ? ? L10n . of ( context ) . pleaseEnterSecurityKey ;
appBar: AppBar (
body = PlatformInfos . isCupertinoStyle
leading: IconButton (
? CupertinoTextField (
icon: Icon ( Icons . close ) ,
minLines: 1 ,
onPressed: Navigator . of ( context ) . pop ,
maxLines: 1 ,
) ,
autofocus: true ,
title: Text ( L10n . of ( context ) . pleaseEnterSecurityKey ) ,
autocorrect: false ,
) ,
autofillHints: _recoveryKeyInputLoading
body: ListView (
? null
padding: const EdgeInsets . all ( 16.0 ) ,
: [ AutofillHints . password ] ,
children: [
controller: _recoveryKeyTextEditingController ,
TextField (
)
minLines: 4 ,
: TextField (
maxLines: 4 ,
minLines: 1 ,
maxLines: 1 ,
autofocus: true ,
autofocus: true ,
autocorrect: false ,
autocorrect: false ,
autofillHints: _recoveryKeyInputLoading
autofillHints: _recoveryKeyInputLoading
@ -174,13 +179,15 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
: [ AutofillHints . password ] ,
: [ AutofillHints . password ] ,
controller: _recoveryKeyTextEditingController ,
controller: _recoveryKeyTextEditingController ,
decoration: InputDecoration (
decoration: InputDecoration (
border: UnderlineInputBorder ( ) ,
hintText: ' Abc123 Def456 ' ,
filled: false ,
labelText: L10n . of ( context ) . securityKey ,
hintText: L10n . of ( context ) . securityKey ,
errorText: _recoveryKeyInputError ,
) ,
) ,
) ;
) ,
buttons . add ( AdaptiveFlatButton (
const SizedBox ( height: 16 ) ,
label: L10n . of ( context ) . unlockChatBackup ,
ElevatedButton . icon (
icon: Icon ( Icons . lock_open_outlined ) ,
label: Text ( L10n . of ( context ) . unlockChatBackup ) ,
onPressed: ( ) async {
onPressed: ( ) async {
setState ( ( ) {
setState ( ( ) {
_recoveryKeyInputError = null ;
_recoveryKeyInputError = null ;
@ -188,7 +195,8 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
} ) ;
} ) ;
try {
try {
await bootstrap . newSsssKey . unlock (
await bootstrap . newSsssKey . unlock (
keyOrPassphrase: _recoveryKeyTextEditingController . text ,
keyOrPassphrase:
_recoveryKeyTextEditingController . text ,
) ;
) ;
await bootstrap . openExistingSsss ( ) ;
await bootstrap . openExistingSsss ( ) ;
} catch ( e , s ) {
} catch ( e , s ) {
@ -198,23 +206,45 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
} finally {
} finally {
setState ( ( ) = > _recoveryKeyInputLoading = false ) ;
setState ( ( ) = > _recoveryKeyInputLoading = false ) ;
}
}
} ) ) ;
} ) ,
buttons . add ( AdaptiveFlatButton (
const SizedBox ( height: 16 ) ,
label: L10n . of ( context ) . transferFromAnotherDevice ,
Row ( children: [
Expanded ( child: Divider ( ) ) ,
Padding (
padding: const EdgeInsets . all ( 12.0 ) ,
child: Text ( L10n . of ( context ) . or ) ,
) ,
Expanded ( child: Divider ( ) ) ,
] ) ,
const SizedBox ( height: 16 ) ,
ElevatedButton . icon (
style: ElevatedButton . styleFrom (
primary: Theme . of ( context ) . secondaryHeaderColor ,
onPrimary: Theme . of ( context ) . primaryColor ,
) ,
icon: Icon ( Icons . transfer_within_a_station_outlined ) ,
label: Text ( L10n . of ( context ) . transferFromAnotherDevice ) ,
onPressed: ( ) async {
onPressed: ( ) async {
final req = await showFutureLoadingDialog (
final req = await showFutureLoadingDialog (
context: context ,
context: context ,
future: ( ) = > widget . client . userDeviceKeys [ widget . client . userID ]
future: ( ) = > widget
. client . userDeviceKeys [ widget . client . userID ]
. startVerification ( ) ,
. startVerification ( ) ,
) ;
) ;
if ( req . error ! = null ) return ;
if ( req . error ! = null ) return ;
await KeyVerificationDialog ( request: req . result ) . show ( context ) ;
await KeyVerificationDialog ( request: req . result )
. show ( context ) ;
Navigator . of ( context , rootNavigator: false ) . pop ( ) ;
Navigator . of ( context , rootNavigator: false ) . pop ( ) ;
} ,
} ,
) ) ;
) ,
buttons . add ( AdaptiveFlatButton (
const SizedBox ( height: 16 ) ,
textColor: Colors . red ,
ElevatedButton . icon (
label: L10n . of ( context ) . securityKeyLost ,
style: ElevatedButton . styleFrom (
primary: Theme . of ( context ) . secondaryHeaderColor ,
onPrimary: Colors . red ,
) ,
icon: Icon ( Icons . delete_outlined ) ,
label: Text ( L10n . of ( context ) . securityKeyLost ) ,
onPressed: ( ) async {
onPressed: ( ) async {
if ( OkCancelResult . ok = =
if ( OkCancelResult . ok = =
await showOkCancelAlertDialog (
await showOkCancelAlertDialog (
@ -229,8 +259,10 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
_createBootstrap ( true ) ;
_createBootstrap ( true ) ;
}
}
} ,
} ,
) ) ;
)
break ;
] ,
) ,
) ;
case BootstrapState . askWipeCrossSigning:
case BootstrapState . askWipeCrossSigning:
WidgetsBinding . instance . addPostFrameCallback (
WidgetsBinding . instance . addPostFrameCallback (
( _ ) = > bootstrap . wipeCrossSigning ( _wipe ) ,
( _ ) = > bootstrap . wipeCrossSigning ( _wipe ) ,
@ -270,8 +302,8 @@ class _BootstrapDialogState extends State<BootstrapDialog> {
body = Column (
body = Column (
mainAxisSize: MainAxisSize . min ,
mainAxisSize: MainAxisSize . min ,
children: [
children: [
I con( Icons . check_circle , color: Colors . green , size: 40 ) ,
I mage. asset ( ' assets/backup.png ' , fit: BoxFit . contain ) ,
Text ( L10n . of ( context ) . keysCached ) ,
Text ( L10n . of ( context ) . yourChatBackupHasBeenSetUp ) ,
] ,
] ,
) ;
) ;
buttons . add ( AdaptiveFlatButton (
buttons . add ( AdaptiveFlatButton (