Skip to content

Commit abd7f56

Browse files
authored
feat: improve bootstrap and keyverification (#14)
* fix: bt rework * fix: bootstrap and keyverification * remove bootstrap null * osss
1 parent 6325a09 commit abd7f56

File tree

10 files changed

+89
-116
lines changed

10 files changed

+89
-116
lines changed

lib/chat/authentication/chat_login_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class _ChatLoginPageState extends State<ChatLoginPage> {
5050
homeServer: _homeServerController.text.trim(),
5151
username: _usernameController.text,
5252
password: _passwordController.text,
53-
onSuccess: () async => Navigator.of(context).pushAndRemoveUntil(
53+
onSuccess: () => Navigator.of(context).pushAndRemoveUntil(
5454
MaterialPageRoute(
5555
builder: (_) => const ChatMasterDetailPage(),
5656
),

lib/chat/bootstrap/bootstrap_model.dart

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import 'dart:io';
22

3-
import 'package:flutter/foundation.dart';
43
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
54
import 'package:matrix/encryption.dart';
65
import 'package:matrix/matrix.dart';
@@ -18,11 +17,11 @@ class BootstrapModel extends SafeChangeNotifier {
1817
final Client _client;
1918
final FlutterSecureStorage _secureStorage;
2019

21-
Future<bool> isBootrapNeeded() async =>
22-
_client.isUnknownSession && _client.encryption!.crossSigning.enabled;
20+
Future<bool> checkBootstrap() async {
21+
if (!_client.encryptionEnabled) {
22+
return true;
23+
}
2324

24-
Future<bool> isBootrapNeededFull() async {
25-
if (!_client.encryptionEnabled) return true;
2625
await _client.accountDataLoading;
2726
await _client.userDeviceKeysLoading;
2827
if (_client.prevBatch == null) {
@@ -112,12 +111,10 @@ class BootstrapModel extends SafeChangeNotifier {
112111
_bootstrap =
113112
_client.encryption?.bootstrap(onUpdate: (v) => _setBootsTrap(v));
114113
final theKey = await _loadKeyFromSecureStorage();
115-
if (key == null) {
116-
notifyListeners();
117-
return;
114+
if (key != null) {
115+
_key = theKey;
118116
}
119117

120-
_key = theKey;
121118
notifyListeners();
122119
}
123120

@@ -131,8 +128,6 @@ class BootstrapModel extends SafeChangeNotifier {
131128
}
132129
}
133130

134-
bool get supportsSecureStorage => !kIsWeb;
135-
136131
String getSecureStorageLocalizedName(AppLocalizations l10n) {
137132
if (Platform.isAndroid) {
138133
return l10n.storeInAndroidKeystore;

lib/chat/bootstrap/view/bootstrap_page.dart

Lines changed: 19 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@ import '../bootstrap_model.dart';
1717
import 'key_verification_dialog.dart';
1818

1919
class BootstrapPage extends StatelessWidget with WatchItMixin {
20-
const BootstrapPage({
21-
super.key,
22-
});
20+
const BootstrapPage({super.key});
2321

2422
@override
2523
Widget build(BuildContext context) {
@@ -46,7 +44,9 @@ class BootstrapPage extends StatelessWidget with WatchItMixin {
4644

4745
if (key != null && recoveryKeyStored == false) {
4846
return Scaffold(
49-
appBar: AppBar(
47+
appBar: YaruWindowTitleBar(
48+
border: BorderSide.none,
49+
backgroundColor: Colors.transparent,
5050
centerTitle: true,
5151
leading: IconButton(
5252
icon: const Icon(YaruIcons.window_close),
@@ -87,15 +87,14 @@ class BootstrapPage extends StatelessWidget with WatchItMixin {
8787
),
8888
),
8989
const SizedBox(height: 16),
90-
if (model.supportsSecureStorage)
91-
YaruCheckboxListTile(
92-
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
93-
value: storeInSecureStorage,
94-
onChanged: (v) => model.setStoreInSecureStorage(v ?? false),
95-
title:
96-
Text(model.getSecureStorageLocalizedName(context.l10n)),
97-
subtitle: Text(l10n.storeInSecureStorageDescription),
98-
),
90+
YaruCheckboxListTile(
91+
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
92+
value: storeInSecureStorage,
93+
onChanged: (v) => model.setStoreInSecureStorage(v ?? false),
94+
title:
95+
Text(model.getSecureStorageLocalizedName(context.l10n)),
96+
subtitle: Text(l10n.storeInSecureStorageDescription),
97+
),
9998
const SizedBox(height: 16),
10099
YaruCheckboxListTile(
101100
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
@@ -213,8 +212,10 @@ class BootstrapPage extends StatelessWidget with WatchItMixin {
213212
}
214213

215214
return Scaffold(
216-
appBar: YaruDialogTitleBar(
215+
appBar: YaruWindowTitleBar(
217216
title: Text(titleText),
217+
border: BorderSide.none,
218+
backgroundColor: Colors.transparent,
218219
),
219220
body: Center(
220221
child: Column(
@@ -230,34 +231,6 @@ class BootstrapPage extends StatelessWidget with WatchItMixin {
230231
}
231232
}
232233

233-
Future<T?> showAdaptiveBottomSheet<T>({
234-
required BuildContext context,
235-
required Widget Function(BuildContext) builder,
236-
bool isDismissible = true,
237-
bool isScrollControlled = true,
238-
double maxHeight = 512,
239-
bool useRootNavigator = true,
240-
}) =>
241-
showModalBottomSheet(
242-
context: context,
243-
builder: builder,
244-
// this sadly is ugly on desktops but otherwise breaks `.of(context)` calls
245-
useRootNavigator: useRootNavigator,
246-
isDismissible: isDismissible,
247-
isScrollControlled: isScrollControlled,
248-
constraints: BoxConstraints(
249-
maxHeight: maxHeight,
250-
maxWidth: 400,
251-
),
252-
clipBehavior: Clip.hardEdge,
253-
shape: const RoundedRectangleBorder(
254-
borderRadius: BorderRadius.only(
255-
topLeft: Radius.circular(10),
256-
topRight: Radius.circular(10),
257-
),
258-
),
259-
);
260-
261234
class OpenExistingSSSSPage extends StatefulWidget
262235
with WatchItStatefulWidgetMixin {
263236
const OpenExistingSSSSPage({super.key});
@@ -289,6 +262,10 @@ class _OpenExistingSSSSPageState extends State<OpenExistingSSSSPage> {
289262
watchPropertyValue((BootstrapModel m) => m.recoveryKeyInputError);
290263

291264
return Scaffold(
265+
appBar: const YaruWindowTitleBar(
266+
border: BorderSide.none,
267+
backgroundColor: Colors.transparent,
268+
),
292269
body: Center(
293270
child: SizedBox(
294271
width: 400,

lib/chat/bootstrap/view/key_verification_dialog.dart

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ import 'package:flutter/services.dart';
77
import 'package:future_loading_dialog/future_loading_dialog.dart';
88
import 'package:matrix/encryption.dart';
99
import 'package:matrix/matrix.dart';
10+
import 'package:yaru/yaru.dart';
1011

1112
import '../../../common/view/build_context_x.dart';
1213
import '../../../l10n/l10n.dart';
1314
import '../../view/chat_avatar.dart';
15+
import '../../view/chat_master/chat_master_detail_page.dart';
1416

15-
// TODO: code by fluffy-chat, replace
17+
// Credit: this code has been initially copied from https://github.com/krille-chan/fluffychat
18+
// Thank you @krille-chan
1619
class KeyVerificationDialog extends StatefulWidget {
1720
Future<void> show(BuildContext context) => showAdaptiveDialog(
1821
context: context,
@@ -21,14 +24,10 @@ class KeyVerificationDialog extends StatefulWidget {
2124
);
2225

2326
final KeyVerification request;
24-
final Function()? onCancel;
25-
final Function()? onDone;
2627

2728
const KeyVerificationDialog({
2829
super.key,
2930
required this.request,
30-
this.onCancel,
31-
this.onDone,
3231
});
3332

3433
@override
@@ -188,7 +187,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
188187
);
189188
buttons.add(
190189
TextButton.icon(
191-
icon: const Icon(Icons.close),
190+
icon: const Icon(YaruIcons.window_close),
192191
style: TextButton.styleFrom(foregroundColor: Colors.red),
193192
label: Text(l10n.reject),
194193
onPressed: () => widget.request.rejectVerification().then((_) {
@@ -200,7 +199,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
200199
);
201200
buttons.add(
202201
TextButton.icon(
203-
icon: const Icon(Icons.check),
202+
icon: const Icon(YaruIcons.checkmark),
204203
label: Text(l10n.accept),
205204
onPressed: () => widget.request.acceptVerification(),
206205
),
@@ -233,7 +232,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
233232
);
234233
buttons.add(
235234
TextButton.icon(
236-
icon: const Icon(Icons.close),
235+
icon: const Icon(YaruIcons.window_close),
237236
label: Text(l10n.cancel),
238237
onPressed: () => widget.request.cancel(),
239238
),
@@ -273,7 +272,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
273272
);
274273
buttons.add(
275274
TextButton.icon(
276-
icon: const Icon(Icons.close),
275+
icon: const Icon(YaruIcons.window_close),
277276
style: TextButton.styleFrom(
278277
foregroundColor: Colors.red,
279278
),
@@ -283,7 +282,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
283282
);
284283
buttons.add(
285284
TextButton.icon(
286-
icon: const Icon(Icons.check_outlined),
285+
icon: const Icon(YaruIcons.checkmark),
287286
label: Text(l10n.theyMatch),
288287
onPressed: () => widget.request.acceptSas(),
289288
),
@@ -308,7 +307,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
308307
mainAxisSize: MainAxisSize.min,
309308
children: <Widget>[
310309
const Icon(
311-
Icons.check_circle_outlined,
310+
YaruIcons.ok,
312311
color: Colors.green,
313312
size: 128.0,
314313
),
@@ -325,12 +324,17 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
325324
l10n.close,
326325
),
327326
onPressed: () {
328-
widget.onDone?.call();
329327
if (context.mounted) {
330328
Navigator.of(
331329
context,
332330
rootNavigator: false,
333331
).pop();
332+
Navigator.of(context).pushAndRemoveUntil(
333+
MaterialPageRoute(
334+
builder: (_) => const ChatMasterDetailPage(),
335+
),
336+
(route) => false,
337+
);
334338
}
335339
},
336340
),
@@ -340,7 +344,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
340344
body = Column(
341345
mainAxisSize: MainAxisSize.min,
342346
children: <Widget>[
343-
const Icon(Icons.cancel, color: Colors.red, size: 128.0),
347+
const Icon(YaruIcons.edit_clear, color: Colors.red, size: 128.0),
344348
const SizedBox(height: 16),
345349
Text(
346350
'Error ${widget.request.canceledCode}: ${widget.request.canceledReason}',

lib/chat/chat_download_service.dart

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import 'dart:io';
44
import 'package:file_picker/file_picker.dart';
55
import 'package:matrix/matrix.dart';
66
import 'package:shared_preferences/shared_preferences.dart';
7-
8-
import '../app_config.dart';
7+
import 'package:yaru/yaru.dart';
98

109
class ChatDownloadService {
1110
ChatDownloadService({
@@ -34,7 +33,7 @@ class ChatDownloadService {
3433
}
3534
MatrixFile? file;
3635
String? path;
37-
if (isMobilePlatform) {
36+
if (isMobile) {
3837
file = await event.downloadAndDecryptAttachment();
3938
path = await FilePicker.platform.saveFile(
4039
fileName: file.name,

lib/chat/draft_model.dart

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import 'package:matrix/matrix.dart';
66
import 'package:mime/mime.dart';
77
import 'package:safe_change_notifier/safe_change_notifier.dart';
88
import 'package:video_compress/video_compress.dart';
9+
import 'package:yaru/yaru.dart';
910

10-
import '../app_config.dart';
1111
import '../common/logging.dart';
1212
import 'local_image_service.dart';
1313

@@ -79,11 +79,12 @@ class DraftModel extends SafeChangeNotifier {
7979
}
8080
}
8181

82-
final draft = '${getDraft(room.id)}';
83-
removeDraft(room.id);
84-
if (draft.isNotEmpty) {
82+
if (getDraft(room.id)?.isNotEmpty == true) {
83+
final draft = '${getDraft(room.id)}';
84+
removeDraft(room.id);
85+
String? eventId;
8586
try {
86-
await room.sendTextEvent(
87+
eventId = await room.sendTextEvent(
8788
draft.trim(),
8889
inReplyTo: replyEvent,
8990
editEventId: _editEvents[room.id]?.eventId,
@@ -92,6 +93,9 @@ class DraftModel extends SafeChangeNotifier {
9293
onFail(e.toString());
9394
printMessageInDebugMode(e, s);
9495
}
96+
if (eventId == null) {
97+
setDraft(roomId: room.id, draft: draft, notify: true);
98+
}
9599
}
96100

97101
_sending = false;
@@ -237,7 +241,7 @@ class DraftModel extends SafeChangeNotifier {
237241
Future<MatrixVideoFile> resizeVideo(XFile xFile) async {
238242
MediaInfo? mediaInfo;
239243
try {
240-
if (isMobilePlatform) {
244+
if (isMobile) {
241245
// will throw an error e.g. on Android SDK < 18
242246
mediaInfo = await VideoCompress.compressVideo(xFile.path);
243247
}
@@ -258,7 +262,7 @@ class DraftModel extends SafeChangeNotifier {
258262
// final Map<MatrixVideoFile, XFile> _fileMap = {};
259263

260264
Future<MatrixImageFile?> getVideoThumbnail(XFile xFile) async {
261-
if (!isMobilePlatform) return null;
265+
if (!isMobile) return null;
262266

263267
try {
264268
final bytes = await VideoCompress.getByteThumbnail(xFile.path);

lib/chat/view/chat_master/chat_master_detail_page.dart

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,25 @@ class _ChatMasterDetailPageState extends State<ChatMasterDetailPage> {
2828
@override
2929
void initState() {
3030
super.initState();
31-
di<BootstrapModel>().isBootrapNeeded().then(
32-
(isNeeded) {
31+
WidgetsBinding.instance.addPostFrameCallback((_) {
32+
final bootstrapModel = di<BootstrapModel>();
33+
bootstrapModel.checkBootstrap().then((isNeeded) {
3334
if (isNeeded) {
34-
di<BootstrapModel>().startBootstrap(wipe: false).then((value) {
35-
if (mounted) {
36-
showDialog(
37-
context: context,
38-
builder: (context) => const SizedBox(
39-
height: 500,
40-
width: 400,
41-
child: BootstrapPage(),
42-
),
43-
);
44-
}
45-
});
35+
bootstrapModel.startBootstrap(wipe: false).then(
36+
(_) {
37+
if (mounted) {
38+
Navigator.of(context).pushAndRemoveUntil(
39+
MaterialPageRoute(
40+
builder: (_) => const BootstrapPage(),
41+
),
42+
(route) => false,
43+
);
44+
}
45+
},
46+
);
4647
}
47-
},
48-
);
48+
});
49+
});
4950
}
5051

5152
@override

lib/chat/view/events/chat_html_message.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import '../../../common/view/confirm.dart';
1515
import '../../../l10n/l10n.dart';
1616
import '../mxc_image.dart';
1717

18-
// Credit: this code has been copied and from https://github.com/krille-chan/fluffychat
19-
// and then modified
18+
// Credit: this code has been initially copied from https://github.com/krille-chan/fluffychat
2019
// Thank you @krille-chan
2120
class HtmlMessage extends StatelessWidget {
2221
final String html;

0 commit comments

Comments
 (0)