From bf0a1985e690277f6d0e0c68c1411fe14f868211 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Sun, 26 Dec 2021 12:46:18 +0100 Subject: [PATCH] chore: Clickable links in stories --- lib/pages/add_story/add_story_view.dart | 3 +- lib/pages/story/story_page.dart | 56 ++++++++++++++++++++++++ lib/pages/story/story_view.dart | 57 +++++++++++++++++++------ 3 files changed, 103 insertions(+), 13 deletions(-) diff --git a/lib/pages/add_story/add_story_view.dart b/lib/pages/add_story/add_story_view.dart index 5b2166c7..214a4676 100644 --- a/lib/pages/add_story/add_story_view.dart +++ b/lib/pages/add_story/add_story_view.dart @@ -88,7 +88,8 @@ class AddStoryView extends StatelessWidget { child: TextField( controller: controller.controller, minLines: 1, - maxLines: 20, + maxLines: 15, + maxLength: 500, autofocus: true, textAlign: TextAlign.center, style: TextStyle( diff --git a/lib/pages/story/story_page.dart b/lib/pages/story/story_page.dart index 44bc867b..9e95e73a 100644 --- a/lib/pages/story/story_page.dart +++ b/lib/pages/story/story_page.dart @@ -3,10 +3,12 @@ import 'dart:async'; import 'dart:io'; +import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:flutter/material.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:matrix/matrix.dart'; import 'package:path_provider/path_provider.dart'; import 'package:video_player/video_player.dart'; @@ -227,6 +229,55 @@ class StoryPageController extends State { final Map> _fileCache = {}; + void report(_) async { + _modalOpened = true; + final event = currentEvent; + if (event == null) return; + final score = await showConfirmationDialog( + context: context, + title: L10n.of(context)!.reportMessage, + message: L10n.of(context)!.howOffensiveIsThisContent, + cancelLabel: L10n.of(context)!.cancel, + okLabel: L10n.of(context)!.ok, + actions: [ + AlertDialogAction( + key: -100, + label: L10n.of(context)!.extremeOffensive, + ), + AlertDialogAction( + key: -50, + label: L10n.of(context)!.offensive, + ), + AlertDialogAction( + key: 0, + label: L10n.of(context)!.inoffensive, + ), + ]); + if (score == null) return; + final reason = await showTextInputDialog( + useRootNavigator: false, + context: context, + title: L10n.of(context)!.whyDoYouWantToReportThis, + okLabel: L10n.of(context)!.ok, + cancelLabel: L10n.of(context)!.cancel, + textFields: [DialogTextField(hintText: L10n.of(context)!.reason)]); + if (reason == null || reason.single.isEmpty) return; + final result = await showFutureLoadingDialog( + context: context, + future: () => Matrix.of(context).client.reportContent( + roomId, + event.eventId, + reason: reason.single, + score: score, + ), + ); + _modalOpened = false; + if (result.error != null) return; + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(L10n.of(context)!.contentHasBeenReported)), + ); + } + Future downloadAndDecryptAttachment( Event event, bool getThumbnail) async { return _fileCache[event.eventId] ??= @@ -362,3 +413,8 @@ extension on List { return false; } } + +enum PopupStoryAction { + report, + message, +} diff --git a/lib/pages/story/story_view.dart b/lib/pages/story/story_view.dart index d76606a9..ff29f0eb 100644 --- a/lib/pages/story/story_view.dart +++ b/lib/pages/story/story_view.dart @@ -6,6 +6,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_blurhash/flutter_blurhash.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; +import 'package:matrix_link_text/link_text.dart'; import 'package:video_player/video_player.dart'; import 'package:fluffychat/pages/story/story_page.dart'; @@ -13,6 +14,7 @@ import 'package:fluffychat/utils/date_time_extension.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/utils/string_color.dart'; +import 'package:fluffychat/utils/url_launcher.dart'; import 'package:fluffychat/widgets/avatar.dart'; class StoryView extends StatelessWidget { @@ -69,6 +71,20 @@ class StoryView extends StatelessWidget { ), ), ), + actions: [ + AnimatedOpacity( + duration: const Duration(seconds: 1), + opacity: controller.isHold ? 0 : 1, + child: PopupMenuButton( + onSelected: controller.report, + itemBuilder: (context) => [ + PopupMenuItem( + value: true, + child: Text(L10n.of(context)!.reportMessage), + ), + ], + )), + ], systemOverlayStyle: SystemUiOverlayStyle.light, iconTheme: const IconThemeData(color: Colors.white), elevation: 0, @@ -189,18 +205,35 @@ class StoryView extends StatelessWidget { : null, ), alignment: Alignment.center, - child: Text( - controller.loadingMode - ? L10n.of(context)!.loadingPleaseWait - : event.content.tryGet('body') ?? '', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 24, - color: Colors.white, - backgroundColor: event.messageType == MessageTypes.Text - ? null - : Colors.black, - ), + child: ListView( + shrinkWrap: true, + children: [ + LinkText( + text: controller.loadingMode + ? L10n.of(context)!.loadingPleaseWait + : event.content.tryGet('body') ?? '', + textAlign: TextAlign.center, + onLinkTap: (url) => + UrlLauncher(context, url).launchUrl(), + linkStyle: TextStyle( + fontSize: 24, + color: Colors.blue.shade50, + decoration: TextDecoration.underline, + backgroundColor: + event.messageType == MessageTypes.Text + ? null + : Colors.black, + ), + textStyle: TextStyle( + fontSize: 24, + color: Colors.white, + backgroundColor: + event.messageType == MessageTypes.Text + ? null + : Colors.black, + ), + ), + ], ), ), Positioned(