Skip to content

Commit

Permalink
Merge pull request #1690 from matthiasn/feat/incoming_verification_re…
Browse files Browse the repository at this point in the history
…quest

feat: incoming verification request
  • Loading branch information
matthiasn committed Mar 16, 2024
2 parents 3d84018 + 83f8a48 commit 062ca84
Show file tree
Hide file tree
Showing 10 changed files with 518 additions and 238 deletions.
2 changes: 2 additions & 0 deletions lib/beamer/beamer_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import 'package:lotti/widgets/misc/desktop_menu.dart';
import 'package:lotti/widgets/misc/time_recording_indicator.dart';
import 'package:lotti/widgets/nav_bar/nav_bar.dart';
import 'package:lotti/widgets/nav_bar/nav_bar_item.dart';
import 'package:lotti/widgets/sync/matrix/incoming_verification_modal.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';

class AppScreen extends StatefulWidget {
Expand All @@ -49,6 +50,7 @@ class _AppScreenState extends State<AppScreen> {
return Scaffold(
body: Stack(
children: [
const IncomingVerificationWrapper(),
IndexedStack(
index: index,
children: [
Expand Down
3 changes: 3 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,10 @@
"settingsMatrixListUnverifiedLabel": "Unverified devices",
"settingsMatrixNoUnverifiedLabel": "No unverified devices",
"settingsMatrixStartVerificationLabel": "Start Verification",
"settingsMatrixAcceptIncomingVerificationLabel": "Accept Verification",
"settingsMatrixVerifyLabel": "Verify",
"settingsMatrixVerifyConfirm": "Confirm on other device that the emojis below are displayed on both devices, in the same order:",
"settingsMatrixVerifyIncomingConfirm": "Confirm that the emojis below are displayed on both devices, in the same order:",
"settingsMatrixAcceptVerificationLabel": "Other device shows emojis, continue",
"settingsMatrixCancelVerificationLabel": "Cancel Verification",
"settingsMatrixVerificationSuccessConfirm": "Got it",
Expand All @@ -210,6 +212,7 @@
}
},
"settingsMatrixContinueVerificationLabel": "Accept on other device to continue",
"settingsMatrixVerificationCancelledLabel": "Cancelled on other device...",
"settingsMatrixLogoutButtonLabel": "Logout",
"settingsMatrixLoginButtonLabel": "Login",
"settingsMatrixSaveLabel": "Save",
Expand Down
86 changes: 86 additions & 0 deletions lib/sync/matrix/key_verification_runner.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:matrix/encryption/utils/key_verification.dart';
import 'package:matrix/matrix.dart';

class KeyVerificationRunner {
KeyVerificationRunner(
this.keyVerification, {
required this.controller,
}) {
lastStep = keyVerification.lastStep ?? '';
startedVerification = keyVerification.startedVerification;
lastStepHistory.add(lastStep);
publishState();

_timer = Timer.periodic(
const Duration(milliseconds: 100),
(timer) {
final newLastStep = keyVerification.lastStep;
// debugPrint('KeyVerificationRunner newLastStep: $newLastStep ');
if (newLastStep != null && newLastStep != lastStep) {
lastStep = newLastStep;
lastStepHistory.add(newLastStep);
debugPrint('KeyVerificationRunner newLastStep: $newLastStep ');
publishState();

if (lastStep == 'm.key.verification.key') {
//acceptEmojiVerification();
readEmojis();
}

if (lastStep == EventTypes.KeyVerificationDone) {
stopTimer();
}

if (lastStep == 'm.key.verification.mac') {
//keyVerification.acceptVerification();
}

if (lastStep == 'm.key.verification.cancel') {
stopTimer();
}
}
},
);
}

String lastStep = '';
bool? startedVerification;
List<String> lastStepHistory = [];
List<KeyVerificationEmoji>? emojis;
KeyVerification keyVerification;
StreamController<KeyVerificationRunner> controller;
Timer? _timer;

void stopTimer() {
_timer?.cancel();
}

Future<void> acceptVerification() async {
await keyVerification.acceptVerification();
}

Future<List<KeyVerificationEmoji>?> acceptEmojiVerification() async {
await keyVerification.acceptSas();
emojis = keyVerification.sasEmojis;
publishState();
return emojis;
}

Future<List<KeyVerificationEmoji>?> readEmojis() async {
emojis = keyVerification.sasEmojis;
publishState();
return emojis;
}

void publishState() {
controller.add(this);
}

Future<void> cancelVerification() async {
await keyVerification.cancel();
stopTimer();
}
}
74 changes: 50 additions & 24 deletions lib/sync/matrix/matrix_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:lotti/database/database.dart';
import 'package:lotti/database/logging_db.dart';
import 'package:lotti/get_it.dart';
import 'package:lotti/sync/inbox/save_attachments.dart';
import 'package:lotti/sync/matrix/key_verification_runner.dart';
import 'package:lotti/sync/secure_storage.dart';
import 'package:lotti/sync/utils.dart';
import 'package:lotti/utils/audio_utils.dart';
Expand All @@ -37,20 +38,45 @@ class MatrixStats {
}

class MatrixService {
MatrixService() : _client = createClient() {
MatrixService()
: _client = createClient(),
_keyVerificationController =
StreamController<KeyVerificationRunner>.broadcast() {
_incomingKeyVerificationRunnerController =
StreamController<KeyVerificationRunner>.broadcast(
onListen: publishIncomingRunnerState,
);

keyVerificationStream = _keyVerificationController.stream;
incomingKeyVerificationStream =
_incomingKeyVerificationRunnerController.stream;
loginAndListen();
}

void publishIncomingRunnerState() {
incomingKeyVerificationRunner?.publishState();
}

Client _client;
final LoggingDb _loggingDb = getIt<LoggingDb>();
MatrixConfig? _matrixConfig;
LoginResponse? _loginResponse;
KeyVerification? _keyVerification;

final Map<String, int> messageCounts = {};
int sentCount = 0;

final StreamController<MatrixStats> messageCountsController =
StreamController<MatrixStats>.broadcast();
KeyVerificationRunner? keyVerificationRunner;
KeyVerificationRunner? incomingKeyVerificationRunner;
final StreamController<KeyVerificationRunner> _keyVerificationController;
late final StreamController<KeyVerificationRunner>
_incomingKeyVerificationRunnerController;
late final Stream<KeyVerificationRunner> keyVerificationStream;
late final Stream<KeyVerificationRunner> incomingKeyVerificationStream;

final _incomingKeyVerificationController =
StreamController<KeyVerification>.broadcast();

static Client createClient() {
return Client(
Expand Down Expand Up @@ -131,7 +157,9 @@ class MatrixService {
);
}

await loadArchive();
if (isLoggedIn()) {
await loadArchive();
}

final joinRes = await _client.joinRoom(matrixConfig.roomId).onError((
error,
Expand Down Expand Up @@ -177,24 +205,12 @@ class MatrixService {
return unverified;
}

Future<KeyVerification> verifyDevice(DeviceKeys deviceKeys) async {
Future<void> verifyDevice(DeviceKeys deviceKeys) async {
final keyVerification = await deviceKeys.startVerification();
_keyVerification = keyVerification;
return keyVerification;
}

Future<void> continueVerification() async {
await _keyVerification?.continueVerification('m.sas.v1');
}

Future<List<KeyVerificationEmoji>?> acceptEmojiVerification() async {
await _keyVerification?.acceptSas();
final emojis = _keyVerification?.sasEmojis;
return emojis;
}

Future<void> cancelVerification() async {
await _keyVerification?.cancel();
keyVerificationRunner = KeyVerificationRunner(
keyVerification,
controller: _keyVerificationController,
);
}

Future<void> deleteDevice(DeviceKeys deviceKeys) async {
Expand All @@ -212,16 +228,26 @@ class MatrixService {
return _client.deviceName;
}

Stream<KeyVerification> getIncomingKeyVerificationStream() {
return _incomingKeyVerificationController.stream;
}

Future<void> listen() async {
try {
_client.onLoginStateChanged.stream.listen((LoginState loginState) {
debugPrint('LoginState: $loginState');
});

_client.onKeyVerificationRequest.stream
.listen((KeyVerification keyVerification) {
debugPrint('Key Verification Request $keyVerification');
keyVerification.acceptVerification();
_client.onKeyVerificationRequest.stream.listen((
KeyVerification keyVerification,
) {
incomingKeyVerificationRunner = KeyVerificationRunner(
keyVerification,
controller: _incomingKeyVerificationRunnerController,
);

debugPrint('Key Verification Request from ${keyVerification.deviceId}');
_incomingKeyVerificationController.add(keyVerification);
});

final roomId = _matrixConfig?.roomId;
Expand Down
16 changes: 5 additions & 11 deletions lib/sync/secure_storage.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class SecureStorage {
Expand All @@ -23,17 +22,12 @@ class SecureStorage {
}

Future<void> writeValue(String key, String value) async {
await delete(key: key);
_state[key] = value;
EasyDebounce.debounce(
'writeValue-$key',
const Duration(seconds: 1),
() async {
await _storage.write(
key: key,
value: _state[key],
iOptions: IOSOptions.defaultOptions,
);
},
await _storage.write(
key: key,
value: _state[key],
iOptions: IOSOptions.defaultOptions,
);
}

Expand Down
36 changes: 36 additions & 0 deletions lib/widgets/buttons/rounded_filled_button.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:flutter/material.dart';

class RoundedFilledButton extends StatelessWidget {
const RoundedFilledButton({
required this.onPressed,
required this.labelText,
this.backgroundColor = Colors.greenAccent,
this.foregroundColor = Colors.black87,
this.semanticsLabel,
super.key,
});

final Color backgroundColor;
final Color foregroundColor;
final VoidCallback? onPressed;
final String labelText;
final String? semanticsLabel;

@override
Widget build(BuildContext context) {
return FilledButton(
onPressed: onPressed,
style: FilledButton.styleFrom(
backgroundColor: backgroundColor,
foregroundColor: foregroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: Text(
labelText,
semanticsLabel: semanticsLabel,
),
);
}
}
1 change: 1 addition & 0 deletions lib/widgets/sync/matrix/device_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:lotti/get_it.dart';
import 'package:lotti/sync/matrix/matrix_service.dart';
import 'package:lotti/widgets/buttons/rounded_filled_button.dart';
import 'package:lotti/widgets/sync/matrix/verification_modal.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:matrix/matrix.dart';
Expand Down
Loading

0 comments on commit 062ca84

Please sign in to comment.