From 76b617e63ad80fe646a1925b833113994413f204 Mon Sep 17 00:00:00 2001 From: otsmr Date: Sun, 7 Dec 2025 16:02:08 +0100 Subject: [PATCH] add barcode scanner and remove tutorial --- .gitmodules | 0 android/app/src/debug/AndroidManifest.xml | 12 +- android/app/src/main/AndroidManifest.xml | 8 +- android/app/src/profile/AndroidManifest.xml | 1 + ios/Runner/Info.plist | 4 + .../painters/barcode_detector_painter.dart | 55 +++++---- .../painters/coordinates_translator.dart | 1 + lib/src/views/chats/chat_list.view.dart | 13 -- lib/src/views/chats/chat_messages.view.dart | 9 -- lib/src/views/home.view.dart | 2 +- lib/src/views/settings/help/help.view.dart | 40 +++--- lib/src/views/tutorial/show_tutorial.dart | 114 ------------------ lib/src/views/tutorial/tutorials.dart | 91 -------------- 13 files changed, 73 insertions(+), 277 deletions(-) create mode 100644 .gitmodules delete mode 100644 lib/src/views/tutorial/show_tutorial.dart delete mode 100644 lib/src/views/tutorial/tutorials.dart diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index 02e134f..1fcfe70 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -1,9 +1,15 @@ - + - - + + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b75efda..c5964e9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + + + + + + firebase_performance_collection_deactivated + + diff --git a/lib/src/views/camera/painters/barcode_detector_painter.dart b/lib/src/views/camera/painters/barcode_detector_painter.dart index 7cc1e51..f525142 100644 --- a/lib/src/views/camera/painters/barcode_detector_painter.dart +++ b/lib/src/views/camera/painters/barcode_detector_painter.dart @@ -23,24 +23,26 @@ class BarcodeDetectorPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { - final Paint paint = Paint() + final paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 3.0 ..color = Colors.lightGreenAccent; - final Paint background = Paint()..color = Color(0x99000000); + final background = Paint()..color = const Color(0x99000000); - for (final Barcode barcode in barcodes) { - final ParagraphBuilder builder = ParagraphBuilder( + for (final barcode in barcodes) { + final builder = ParagraphBuilder( ParagraphStyle( - textAlign: TextAlign.left, - fontSize: 16, - textDirection: TextDirection.ltr), - ); - builder.pushStyle( - ui.TextStyle(color: Colors.lightGreenAccent, background: background)); - builder.addText('${barcode.displayValue}'); - builder.pop(); + textAlign: TextAlign.left, + fontSize: 16, + textDirection: TextDirection.ltr, + ), + ) + ..pushStyle( + ui.TextStyle(color: Colors.lightGreenAccent, background: background), + ) + ..addText('${barcode.displayValue}') + ..pop(); final left = translateX( barcode.boundingBox.left, @@ -77,16 +79,16 @@ class BarcodeDetectorPainter extends CustomPainter { // paint, // ); - final List cornerPoints = []; + final cornerPoints = []; for (final point in barcode.cornerPoints) { - final double x = translateX( + final x = translateX( point.x.toDouble(), size, imageSize, rotation, cameraLensDirection, ); - final double y = translateY( + final y = translateY( point.y.toDouble(), size, imageSize, @@ -99,20 +101,23 @@ class BarcodeDetectorPainter extends CustomPainter { // Add the first point to close the polygon cornerPoints.add(cornerPoints.first); - canvas.drawPoints(PointMode.polygon, cornerPoints, paint); - - canvas.drawParagraph( - builder.build() - ..layout(ParagraphConstraints( - width: (right - left).abs(), - )), - Offset( + canvas + ..drawPoints(PointMode.polygon, cornerPoints, paint) + ..drawParagraph( + builder.build() + ..layout( + ParagraphConstraints( + width: (right - left).abs(), + ), + ), + Offset( Platform.isAndroid && cameraLensDirection == CameraLensDirection.front ? right : left, - top), - ); + top, + ), + ); } } diff --git a/lib/src/views/camera/painters/coordinates_translator.dart b/lib/src/views/camera/painters/coordinates_translator.dart index 36feed1..4e95655 100644 --- a/lib/src/views/camera/painters/coordinates_translator.dart +++ b/lib/src/views/camera/painters/coordinates_translator.dart @@ -26,6 +26,7 @@ double translateX( switch (cameraLensDirection) { case CameraLensDirection.back: return x * canvasSize.width / imageSize.width; + // ignore: no_default_cases default: return canvasSize.width - x * canvasSize.width / imageSize.width; } diff --git a/lib/src/views/chats/chat_list.view.dart b/lib/src/views/chats/chat_list.view.dart index c1956c9..f5e05a0 100644 --- a/lib/src/views/chats/chat_list.view.dart +++ b/lib/src/views/chats/chat_list.view.dart @@ -23,7 +23,6 @@ import 'package:twonly/src/views/settings/help/changelog.view.dart'; import 'package:twonly/src/views/settings/profile/profile.view.dart'; import 'package:twonly/src/views/settings/settings_main.view.dart'; import 'package:twonly/src/views/settings/subscription/subscription.view.dart'; -import 'package:twonly/src/views/tutorial/tutorials.dart'; class ChatListView extends StatefulWidget { const ChatListView({super.key}); @@ -38,7 +37,6 @@ class _ChatListViewState extends State { List _groupsArchived = []; GlobalKey searchForOtherUsers = GlobalKey(); - Timer? tutorial; bool showFeedbackShortcut = false; @override @@ -58,16 +56,6 @@ class _ChatListViewState extends State { }); }); - tutorial = Timer(const Duration(seconds: 1), () async { - tutorial = null; - if (!mounted) return; - await showChatListTutorialSearchOtherUsers(context, searchForOtherUsers); - if (!mounted) return; - // if (_groupsNotPinned.isNotEmpty) { - // await showChatListTutorialContextMenu(context, firstUserListItemKey); - // } - }); - final changeLog = await rootBundle.loadString('CHANGELOG.md'); final changeLogHash = (await compute(Sha256().hash, changeLog.codeUnits)).bytes; @@ -97,7 +85,6 @@ class _ChatListViewState extends State { @override void dispose() { - tutorial?.cancel(); _contactsSub.cancel(); super.dispose(); } diff --git a/lib/src/views/chats/chat_messages.view.dart b/lib/src/views/chats/chat_messages.view.dart index f4dbc51..4ba73e2 100644 --- a/lib/src/views/chats/chat_messages.view.dart +++ b/lib/src/views/chats/chat_messages.view.dart @@ -22,7 +22,6 @@ import 'package:twonly/src/views/components/flame.dart'; import 'package:twonly/src/views/components/verified_shield.dart'; import 'package:twonly/src/views/contact/contact.view.dart'; import 'package:twonly/src/views/groups/group.view.dart'; -import 'package:twonly/src/views/tutorial/tutorials.dart'; Color getMessageColor(Message message) { return (message.senderId == null) @@ -89,7 +88,6 @@ class _ChatMessagesViewState extends State { Message? quotesMessage; GlobalKey verifyShieldKey = GlobalKey(); late FocusNode textFieldFocus; - Timer? tutorial; final ItemScrollController itemScrollController = ItemScrollController(); int? focusedScrollItem; @@ -99,12 +97,6 @@ class _ChatMessagesViewState extends State { group = widget.group; textFieldFocus = FocusNode(); initStreams(); - - tutorial = Timer(const Duration(seconds: 1), () async { - tutorial = null; - if (!mounted) return; - await showVerifyShieldTutorial(context, verifyShieldKey); - }); } @override @@ -114,7 +106,6 @@ class _ChatMessagesViewState extends State { contactSub?.cancel(); groupActionsSub?.cancel(); lastOpenedMessageByContactSub?.cancel(); - tutorial?.cancel(); super.dispose(); } diff --git a/lib/src/views/home.view.dart b/lib/src/views/home.view.dart index 7c7c893..330dbb5 100644 --- a/lib/src/views/home.view.dart +++ b/lib/src/views/home.view.dart @@ -156,7 +156,7 @@ class HomeViewState extends State { CustomPaint? _customPaint; String? _text; - final _orientations = { + final Map _orientations = { DeviceOrientation.portraitUp: 0, DeviceOrientation.landscapeLeft: 90, DeviceOrientation.portraitDown: 180, diff --git a/lib/src/views/settings/help/help.view.dart b/lib/src/views/settings/help/help.view.dart index cbffd12..5dee0ff 100644 --- a/lib/src/views/settings/help/help.view.dart +++ b/lib/src/views/settings/help/help.view.dart @@ -62,26 +62,26 @@ class _HelpViewState extends State { ); }, ), - ListTile( - title: Text(context.lang.settingsResetTutorials), - subtitle: Text( - context.lang.settingsResetTutorialsDesc, - style: const TextStyle(fontSize: 12), - ), - onTap: () async { - await updateUserdata((user) { - user.tutorialDisplayed = []; - return user; - }); - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(context.lang.settingsResetTutorialsSuccess), - duration: const Duration(seconds: 3), - ), - ); - }, - ), + // ListTile( + // title: Text(context.lang.settingsResetTutorials), + // subtitle: Text( + // context.lang.settingsResetTutorialsDesc, + // style: const TextStyle(fontSize: 12), + // ), + // onTap: () async { + // await updateUserdata((user) { + // user.tutorialDisplayed = []; + // return user; + // }); + // if (!context.mounted) return; + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text(context.lang.settingsResetTutorialsSuccess), + // duration: const Duration(seconds: 3), + // ), + // ); + // }, + // ), const Divider(), ListTile( title: Text(context.lang.allowErrorTracking), diff --git a/lib/src/views/tutorial/show_tutorial.dart b/lib/src/views/tutorial/show_tutorial.dart deleted file mode 100644 index 61f548e..0000000 --- a/lib/src/views/tutorial/show_tutorial.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'dart:async'; -import 'package:flutter/material.dart'; -import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; -import 'package:twonly/src/utils/misc.dart'; -import 'package:twonly/src/utils/storage.dart'; - -Future showTutorial( - BuildContext context, - List targets, -) async { - final completer = Completer(); - TutorialCoachMark( - targets: targets, - colorShadow: context.color.primary, - textSkip: context.lang.ok, - alignSkip: Alignment.bottomCenter, - textStyleSkip: const TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 20, - ), - onSkip: () { - completer.complete(); - return true; - }, - onFinish: () { - completer.complete(); - }, - ).show(context: context); - - await completer.future; -} - -Future checkIfTutorialAlreadyShown(String tutorialId) async { - final user = await getUser(); - if (user == null) return true; - user.tutorialDisplayed ??= []; - if (user.tutorialDisplayed!.contains(tutorialId)) { - return true; - } - user.tutorialDisplayed!.add(tutorialId); - - await updateUserdata((u) { - u.tutorialDisplayed = user.tutorialDisplayed; - return u; - }); - - return false; -} - -TargetFocus getTargetFocus( - BuildContext context, - GlobalKey key, - String title, - String body, -) { - final renderBox = key.currentContext!.findRenderObject()! as RenderBox; - final position = renderBox.localToGlobal(Offset.zero); - final screenHeight = MediaQuery.of(context).size.height; - final centerY = screenHeight / 2; - - double top = 0; - double bottom = 0; - - if (position.dy < centerY) { - bottom = 0; - top = position.dy; - } else { - bottom = centerY; - top = 0; - } - - return TargetFocus( - identify: title, - keyTarget: key, - contents: [ - TargetContent( - align: ContentAlign.custom, - customPosition: CustomTargetContentPosition( - left: 0, - right: 0, - top: top, - bottom: bottom, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - title, - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.bold, - color: Colors.black, - fontSize: 20, - ), - ), - Padding( - padding: const EdgeInsets.only(top: 10), - child: Text( - body, - textAlign: TextAlign.center, - style: const TextStyle( - color: Colors.black, - fontSize: 16, - ), - ), - ), - ], - ), - ), - ], - ); -} diff --git a/lib/src/views/tutorial/tutorials.dart b/lib/src/views/tutorial/tutorials.dart deleted file mode 100644 index 77af385..0000000 --- a/lib/src/views/tutorial/tutorials.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mutex/mutex.dart'; -import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; -import 'package:twonly/src/utils/misc.dart'; -import 'package:twonly/src/views/tutorial/show_tutorial.dart'; - -final lockDisplayTutorial = Mutex(); - -Future showChatListTutorialSearchOtherUsers( - BuildContext context, - GlobalKey searchForOtherUsers, -) async { - await lockDisplayTutorial.protect(() async { - if (await checkIfTutorialAlreadyShown('chat_list:search_users')) { - return; - } - if (!context.mounted) return; - final targets = [ - getTargetFocus( - context, - searchForOtherUsers, - context.lang.tutorialChatListSearchUsersTitle, - context.lang.tutorialChatListSearchUsersDesc, - ), - ]; - await showTutorial(context, targets); - }); -} - -Future showChatListTutorialContextMenu( - BuildContext context, - GlobalKey firstUserListItemKey, -) async { - await lockDisplayTutorial.protect(() async { - if (await checkIfTutorialAlreadyShown('chat_list:context_menu')) { - return; - } - if (!context.mounted) return; - final targets = [ - getTargetFocus( - context, - firstUserListItemKey, - context.lang.tutorialChatListContextMenuTitle, - context.lang.tutorialChatListContextMenuDesc, - ), - ]; - await showTutorial(context, targets); - }); -} - -Future showVerifyShieldTutorial( - BuildContext context, - GlobalKey firstUserListItemKey, -) async { - await lockDisplayTutorial.protect(() async { - if (await checkIfTutorialAlreadyShown('chat_messages:verify_shield')) { - return; - } - if (!context.mounted) return; - final targets = [ - getTargetFocus( - context, - firstUserListItemKey, - context.lang.tutorialChatMessagesVerifyShieldTitle, - context.lang.tutorialChatMessagesVerifyShieldDesc, - ), - ]; - await showTutorial(context, targets); - }); -} - -Future showReopenMediaFilesTutorial( - BuildContext context, - GlobalKey firstUserListItemKey, -) async { - await lockDisplayTutorial.protect(() async { - if (await checkIfTutorialAlreadyShown('chat_messages:reopen_message')) { - return; - } - if (!context.mounted) return; - final targets = [ - getTargetFocus( - context, - firstUserListItemKey, - context.lang.tutorialChatMessagesReopenMessageTitle, - context.lang.tutorialChatMessagesReopenMessageDesc, - ), - ]; - await showTutorial(context, targets); - }); -}