Initial commit
Some checks failed
Main Deploy Workflow / deploy_web (push) Has been cancelled
Main Deploy Workflow / deploy_playstore_internal (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
2026-09-11 15:59:56 -03:00
commit 0037b0b9cf
651 changed files with 199705 additions and 0 deletions

View File

@@ -0,0 +1,163 @@
// SPDX-FileCopyrightText: 2019-Present Christian Kußowski
// SPDX-FileCopyrightText: 2019-Present Contributors to FluffyChat
//
// SPDX-License-Identifier: AGPL-3.0-or-later
import 'package:tatchat/l10n/l10n.dart';
import 'package:tatchat/pages/key_verification/key_verification_dialog.dart';
import 'package:tatchat/utils/beautify_string_extension.dart';
import 'package:tatchat/widgets/adaptive_dialogs/adaptive_dialog_action.dart';
import 'package:tatchat/widgets/adaptive_dialogs/dialog_text_field.dart';
import 'package:tatchat/widgets/avatar.dart';
import 'package:material_ui/material_ui.dart';
import 'package:matrix/matrix.dart';
Future<bool> showTrustUserInRoomDialog(BuildContext context, Room room) async {
if (!room.encrypted) return true;
final users = await room.requestParticipants();
if (!context.mounted) return false;
users.removeWhere((user) {
if (user.id == room.client.userID) return true;
final keys = room.client.userDeviceKeys[user.id];
final masterKey = keys?.masterKey;
if (keys == null ||
masterKey == null ||
masterKey.verified ||
masterKey.trustOnFirstUseSince != null) {
return true;
}
return false;
});
if (users.isEmpty) return true;
final l10n = L10n.of(context);
final theme = Theme.of(context);
final action = await showAdaptiveDialog<_Action>(
context: context,
builder: (context) => AlertDialog.adaptive(
title: Center(
child: Icon(
Icons.lock_outlined,
size: 32,
color: theme.colorScheme.primary,
),
),
content: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 128),
child: SelectionArea(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: .stretch,
mainAxisSize: .min,
children: [
const SizedBox(height: 8),
Center(
child: Text(
users.length == 1
? l10n.messageCanOnlyBeReadByUser
: l10n.messageCanOnlyBeReadByUsers,
style: TextStyle(fontSize: 16),
textAlign: .center,
),
),
const SizedBox(height: 16),
for (final user in users) ...[
Row(
children: [
Avatar(
name: user.calcDisplayname(),
mxContent: user.avatarUrl,
size: 14,
),
const SizedBox(width: 4),
Expanded(
child: Text(
user.calcDisplayname(),
style: theme.textTheme.labelSmall,
maxLines: 1,
textAlign: TextAlign.start,
),
),
],
),
Builder(
builder: (context) {
final controller = TextEditingController(
text: l10n.publicKey(
room
.client
.userDeviceKeys[user.id]
?.masterKey
?.publicKey
?.beautifiedOneLine ??
'???',
),
);
return DialogTextField(
controller: controller,
textStyle: theme.textTheme.labelSmall,
readOnly: true,
maxLines: 3,
);
},
),
],
],
),
),
),
),
actions: [
AdaptiveDialogAction(
autofocus: true,
bigButtons: true,
onPressed: () {
for (final user in users) {
room.client.userDeviceKeys[user.id]?.masterKey?.trustOnFirstUse();
}
Navigator.of(context).pop(_Action.allow);
},
child: Text(L10n.of(context).continueText),
),
if (room.isDirectChat)
AdaptiveDialogAction(
bigButtons: true,
onPressed: () => Navigator.of(context).pop(_Action.verification),
child: Text(L10n.of(context).interactiveVerification),
),
AdaptiveDialogAction(
bigButtons: true,
onPressed: () => Navigator.of(context).pop(_Action.deny),
child: Text(l10n.cancel),
),
],
),
);
if (action == null) return false;
switch (action) {
case _Action.allow:
for (final user in users) {
room.client.userDeviceKeys[user.id]?.masterKey?.trustOnFirstUse();
}
case _Action.deny:
return false;
case _Action.verification:
final req = await room.client.userDeviceKeys[room.directChatMatrixID]
?.startVerification();
if (req == null) return false;
if (!context.mounted) return false;
final success = await KeyVerificationDialog(request: req).show(context);
return success == true;
}
return true;
}
enum _Action { allow, deny, verification }