diff --git a/lib/pages/add_story/add_story.dart b/lib/pages/add_story/add_story.dart index 277b9391..6a58c3de 100644 --- a/lib/pages/add_story/add_story.dart +++ b/lib/pages/add_story/add_story.dart @@ -14,6 +14,7 @@ import 'package:vrouter/vrouter.dart'; import 'package:fluffychat/pages/add_story/add_story_view.dart'; import 'package:fluffychat/pages/add_story/invite_story_page.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_file_extension.dart'; +import 'package:fluffychat/utils/resize_image.dart'; import 'package:fluffychat/utils/room_send_file_extension.dart'; import 'package:fluffychat/utils/string_color.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -81,6 +82,7 @@ class AddStoryController extends State { } void postStory() async { + if (video == null && image == null && controller.text.isEmpty) return; final client = Matrix.of(context).client; var storiesRoom = await client.getStoriesRoom(context); @@ -106,18 +108,20 @@ class AddStoryController extends State { context: context, future: () async { if (storiesRoom == null) throw ('Stories room is null'); - final video = this.video; + var video = this.video?.detectFileType; if (video != null) { + video = await video.resizeVideo(); await storiesRoom.sendFileEventWithThumbnail( - video.detectFileType, + video, extraContent: {'body': controller.text}, ); return; } - final image = this.image; + var image = this.image?.detectFileType; if (image != null) { + image = await image.resizeImage(); await storiesRoom.sendFileEventWithThumbnail( - image.detectFileType, + image, extraContent: {'body': controller.text}, ); return; diff --git a/lib/pages/add_story/add_story_view.dart b/lib/pages/add_story/add_story_view.dart index 84b0f4c8..bb2d7ba3 100644 --- a/lib/pages/add_story/add_story_view.dart +++ b/lib/pages/add_story/add_story_view.dart @@ -59,13 +59,19 @@ class AddStoryView extends StatelessWidget { body: Stack( children: [ if (video != null) - FutureBuilder( - future: video.initialize().then((_) => video.play()), - builder: (_, __) => Center(child: VideoPlayer(video)), + Padding( + padding: const EdgeInsets.symmetric(vertical: 80.0), + child: FutureBuilder( + future: video.initialize().then((_) => video.play()), + builder: (_, __) => Center(child: VideoPlayer(video)), + ), ), AnimatedContainer( duration: const Duration(seconds: 2), - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 80.0, + ), decoration: BoxDecoration( image: controller.image == null ? null @@ -96,7 +102,9 @@ class AddStoryView extends StatelessWidget { style: TextStyle( fontSize: 24, color: Colors.white, - backgroundColor: !controller.hasMedia ? null : Colors.black, + backgroundColor: !controller.hasMedia + ? null + : Colors.black.withOpacity(0.5), ), onEditingComplete: controller.updateColors, decoration: InputDecoration( @@ -117,16 +125,13 @@ class AddStoryView extends StatelessWidget { ), ], ), - floatingActionButton: - controller.controller.text.isEmpty && !controller.hasMedia - ? null - : FloatingActionButton.extended( - onPressed: controller.postStory, - label: Text(L10n.of(context)!.publish), - backgroundColor: Theme.of(context).colorScheme.surface, - foregroundColor: Theme.of(context).colorScheme.onSurface, - icon: const Icon(Icons.send_rounded), - ), + floatingActionButton: FloatingActionButton.extended( + onPressed: controller.postStory, + label: Text(L10n.of(context)!.publish), + backgroundColor: Theme.of(context).colorScheme.surface, + foregroundColor: Theme.of(context).colorScheme.onSurface, + icon: const Icon(Icons.send_rounded), + ), ); } } diff --git a/lib/pages/story/story_view.dart b/lib/pages/story/story_view.dart index 9985ca64..bdeefdb9 100644 --- a/lib/pages/story/story_view.dart +++ b/lib/pages/story/story_view.dart @@ -32,74 +32,63 @@ class StoryView extends StatelessWidget { icon: const Icon(Icons.close), onPressed: Navigator.of(context).pop, ), - title: AnimatedOpacity( - duration: const Duration(seconds: 1), - opacity: controller.isHold ? 0 : 1, - child: ListTile( - contentPadding: EdgeInsets.zero, - title: Text( - controller.title, - style: const TextStyle( - color: Colors.white, - shadows: [ - Shadow( - color: Colors.black, - offset: Offset(0, 0), - blurRadius: 5, + title: ListTile( + contentPadding: EdgeInsets.zero, + title: Text( + controller.title, + style: const TextStyle( + color: Colors.white, + shadows: [ + Shadow( + color: Colors.black, + offset: Offset(0, 0), + blurRadius: 5, + ), + ], + ), + ), + subtitle: currentEvent != null + ? Text( + currentEvent.originServerTs.localizedTime(context), + style: const TextStyle( + color: Colors.white70, + shadows: [ + Shadow( + color: Colors.black, + offset: Offset(0, 0), + blurRadius: 5, + ), + ], ), - ], - ), - ), - subtitle: currentEvent != null - ? Text( - currentEvent.originServerTs.localizedTime(context), - style: const TextStyle( - color: Colors.white70, - shadows: [ - Shadow( - color: Colors.black, - offset: Offset(0, 0), - blurRadius: 5, - ), - ], - ), - ) - : null, - leading: Avatar( - mxContent: controller.avatar, - name: controller.title, - ), + ) + : null, + leading: Avatar( + mxContent: controller.avatar, + name: controller.title, ), ), actions: currentEvent == null ? null : [ if (!controller.isOwnStory) - AnimatedOpacity( - duration: const Duration(seconds: 1), - opacity: controller.isHold ? 0 : 1, - child: IconButton( - icon: Icon(Icons.adaptive.share_outlined), - onPressed: controller.share, - ), + IconButton( + icon: Icon(Icons.adaptive.share_outlined), + onPressed: controller.share, ), - AnimatedOpacity( - duration: const Duration(seconds: 1), - opacity: controller.isHold ? 0 : 1, - child: PopupMenuButton( - onSelected: controller.onPopupStoryAction, - itemBuilder: (context) => [ - if (controller.currentEvent?.canRedact ?? false) - PopupMenuItem( - value: PopupStoryAction.delete, - child: Text(L10n.of(context)!.delete), - ), - PopupMenuItem( - value: PopupStoryAction.report, - child: Text(L10n.of(context)!.reportMessage), - ), - ], - )), + PopupMenuButton( + onSelected: controller.onPopupStoryAction, + itemBuilder: (context) => [ + if (controller.currentEvent?.canRedact ?? false) + PopupMenuItem( + value: PopupStoryAction.delete, + child: Text(L10n.of(context)!.delete), + ), + PopupMenuItem( + value: PopupStoryAction.report, + child: Text(L10n.of(context)!.reportMessage), + ), + ], + ), ], systemOverlayStyle: SystemUiOverlayStyle.light, iconTheme: const IconThemeData(color: Colors.white), @@ -155,32 +144,45 @@ class StoryView extends StatelessWidget { if (event.messageType == MessageTypes.Text) { controller.loadingModeOff(); } + final hash = event.infoMap['xyz.amorgan.blurhash']; return GestureDetector( onTapDown: controller.hold, onTapUp: controller.unhold, child: Stack( children: [ + if (hash is String) + BlurHash( + hash: hash, + imageFit: BoxFit.cover, + ), if (event.messageType == MessageTypes.Video && PlatformInfos.isMobile) - FutureBuilder( - future: controller.loadVideoControllerFuture ??= - controller.loadVideoController(event), - builder: (context, snapshot) { - final videoPlayerController = snapshot.data; - if (videoPlayerController == null) { - controller.loadingModeOn(); - return Container(); - } - controller.loadingModeOff(); - return Center(child: VideoPlayer(videoPlayerController)); - }, + Positioned( + top: 80, + bottom: 64, + left: 0, + right: 0, + child: FutureBuilder( + future: controller.loadVideoControllerFuture ??= + controller.loadVideoController(event), + builder: (context, snapshot) { + final videoPlayerController = snapshot.data; + if (videoPlayerController == null) { + controller.loadingModeOn(); + return Container(); + } + controller.loadingModeOff(); + return Center( + child: VideoPlayer(videoPlayerController)); + }, + ), ), if (event.messageType == MessageTypes.Image || (event.messageType == MessageTypes.Video && !PlatformInfos.isMobile)) Positioned( - top: 0, - bottom: 0, + top: 80, + bottom: 64, left: 0, right: 0, child: FutureBuilder( @@ -190,13 +192,7 @@ class StoryView extends StatelessWidget { final matrixFile = snapshot.data; if (matrixFile == null) { controller.loadingModeOn(); - final hash = event.infoMap['xyz.amorgan.blurhash']; - return hash is String - ? BlurHash( - hash: hash, - imageFit: BoxFit.cover, - ) - : Container(); + return Container(); } controller.loadingModeOff(); return Center( @@ -210,7 +206,10 @@ class StoryView extends StatelessWidget { ), AnimatedContainer( duration: const Duration(milliseconds: 200), - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + vertical: 64, + ), decoration: BoxDecoration( gradient: event.messageType == MessageTypes.Text ? LinearGradient( @@ -259,36 +258,32 @@ class StoryView extends StatelessWidget { top: 4, left: 4, right: 4, - child: AnimatedOpacity( - duration: const Duration(seconds: 1), - opacity: controller.isHold ? 0 : 1, - child: SafeArea( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - for (var i = 0; i < events.length; i++) - Expanded( - child: i == controller.index - ? LinearProgressIndicator( - color: Colors.white, - minHeight: 2, - backgroundColor: Colors.grey.shade600, - value: controller.loadingMode - ? null - : controller.progress.inMilliseconds / - StoryPageController - .maxProgress.inMilliseconds, - ) - : Container( - margin: const EdgeInsets.all(4), - height: 2, - color: i < controller.index - ? Colors.white - : Colors.grey.shade600, - ), - ), - ], - ), + child: SafeArea( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + for (var i = 0; i < events.length; i++) + Expanded( + child: i == controller.index + ? LinearProgressIndicator( + color: Colors.white, + minHeight: 2, + backgroundColor: Colors.grey.shade600, + value: controller.loadingMode + ? null + : controller.progress.inMilliseconds / + StoryPageController + .maxProgress.inMilliseconds, + ) + : Container( + margin: const EdgeInsets.all(4), + height: 2, + color: i < controller.index + ? Colors.white + : Colors.grey.shade600, + ), + ), + ], ), ), ), @@ -297,32 +292,28 @@ class StoryView extends StatelessWidget { bottom: 16, left: 16, right: 16, - child: AnimatedOpacity( - duration: const Duration(seconds: 1), - opacity: controller.isHold ? 0 : 1, - child: SafeArea( - child: TextField( - focusNode: controller.replyFocus, - controller: controller.replyController, - minLines: 1, - maxLines: 7, - onSubmitted: controller.replyAction, - textInputAction: TextInputAction.newline, - readOnly: controller.replyLoading, - decoration: InputDecoration( - hintText: L10n.of(context)!.reply, - prefixIcon: IconButton( - onPressed: controller.replyEmojiAction, - icon: const Icon(Icons.emoji_emotions_outlined), - ), - suffixIcon: controller.replyLoading - ? const CircularProgressIndicator.adaptive( - strokeWidth: 2) - : IconButton( - onPressed: controller.replyAction, - icon: const Icon(Icons.send_outlined), - ), + child: SafeArea( + child: TextField( + focusNode: controller.replyFocus, + controller: controller.replyController, + minLines: 1, + maxLines: 7, + onSubmitted: controller.replyAction, + textInputAction: TextInputAction.newline, + readOnly: controller.replyLoading, + decoration: InputDecoration( + hintText: L10n.of(context)!.reply, + prefixIcon: IconButton( + onPressed: controller.replyEmojiAction, + icon: const Icon(Icons.emoji_emotions_outlined), ), + suffixIcon: controller.replyLoading + ? const CircularProgressIndicator.adaptive( + strokeWidth: 2) + : IconButton( + onPressed: controller.replyAction, + icon: const Icon(Icons.send_outlined), + ), ), ), ), @@ -333,20 +324,16 @@ class StoryView extends StatelessWidget { bottom: 16, left: 16, right: 16, - child: AnimatedOpacity( - duration: const Duration(seconds: 1), - opacity: controller.isHold ? 0 : 1, - child: SafeArea( - child: Center( - child: OutlinedButton.icon( - style: OutlinedButton.styleFrom( - backgroundColor: - Theme.of(context).colorScheme.surface, - ), - onPressed: controller.displaySeenByUsers, - icon: const Icon(Icons.visibility_outlined), - label: Text(controller.seenByUsersTitle), + child: SafeArea( + child: Center( + child: OutlinedButton.icon( + style: OutlinedButton.styleFrom( + backgroundColor: + Theme.of(context).colorScheme.surface, ), + onPressed: controller.displaySeenByUsers, + icon: const Icon(Icons.visibility_outlined), + label: Text(controller.seenByUsersTitle), ), ), ),