diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b7171e7245..355548bf6c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -79,25 +79,10 @@ - - - - - - - - - - - - - - - - + diff --git a/ios/FluffyChat Share/ShareViewController.swift b/ios/FluffyChat Share/ShareViewController.swift index 96d921432f..e56ab17539 100644 --- a/ios/FluffyChat Share/ShareViewController.swift +++ b/ios/FluffyChat Share/ShareViewController.swift @@ -5,7 +5,7 @@ import Photos class ShareViewController: SLComposeServiceViewController { // TODO: IMPORTANT: This should be your host app bundle identifier - let hostAppBundleIdentifier = "im.fluffychat.app" + let hostAppBundleIdentifier = "com.linagora.ios.twake" let sharedKey = "ShareKey" var sharedMedia: [SharedMediaFile] = [] var sharedText: [String] = [] @@ -200,7 +200,7 @@ class ShareViewController: SLComposeServiceViewController { } private func redirectToHostApp(type: RedirectType) { - let url = URL(string: "ShareMedia://dataUrl=\(sharedKey)#\(type)") + let url = URL(string: "ShareMedia-\(hostAppBundleIdentifier)://dataUrl=\(sharedKey)#\(type)") var responder = self as UIResponder? let selectorOpenURL = sel_registerName("openURL:") diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index af4e85702e..c34a50fe35 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -35,7 +35,7 @@ im.fluffychat.app.uris CFBundleURLSchemes - ShareMedia + ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER) twake.chat matrix diff --git a/lib/config/go_routes/go_router.dart b/lib/config/go_routes/go_router.dart index 53c495790d..715cbdb8f4 100644 --- a/lib/config/go_routes/go_router.dart +++ b/lib/config/go_routes/go_router.dart @@ -8,6 +8,7 @@ import 'package:fluffychat/pages/chat_details/chat_details.dart'; import 'package:fluffychat/pages/chat_draft/draft_chat.dart'; import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart'; +import 'package:fluffychat/pages/share/share.dart'; import 'package:fluffychat/pages/story/story_page.dart'; import 'package:fluffychat/presentation/model/forward/forward_argument.dart'; import 'package:fluffychat/utils/responsive/responsive_utils.dart'; @@ -37,6 +38,7 @@ import 'package:fluffychat/widgets/log_view.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/cupertino.dart'; import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart'; abstract class AppRoutes { static FutureOr loggedInRedirect( @@ -161,12 +163,14 @@ abstract class AppRoutes { routes: [ GoRoute( path: ':roomid', - pageBuilder: (context, state) => defaultPageBuilder( - context, - Chat( - roomId: state.pathParameters['roomid']!, - ), - ), + pageBuilder: (context, state) { + return defaultPageBuilder( + context, + Chat( + roomId: state.pathParameters['roomid']!, + ), + ); + }, redirect: loggedOutRedirect, ), ], @@ -352,13 +356,17 @@ abstract class AppRoutes { ), GoRoute( path: ':roomid', - pageBuilder: (context, state) => defaultPageBuilder( - context, - Chat( - roomId: state.pathParameters['roomid']!, - key: Key(state.pathParameters['roomid']!), - ), - ), + pageBuilder: (context, state) { + final shareFile = state.extra as MatrixFile?; + return defaultPageBuilder( + context, + Chat( + roomId: state.pathParameters['roomid']!, + key: Key(state.pathParameters['roomid']!), + shareFile: shareFile, + ), + ); + }, redirect: loggedOutRedirect, routes: [ GoRoute( @@ -437,6 +445,14 @@ abstract class AppRoutes { ), ], ), + GoRoute( + path: '/share', + pageBuilder: (context, state) => defaultPageBuilder( + context, + const Share(), + ), + redirect: loggedOutRedirect, + ), ], ), ]; diff --git a/lib/pages/share/share.dart b/lib/pages/share/share.dart new file mode 100644 index 0000000000..7fc97df475 --- /dev/null +++ b/lib/pages/share/share.dart @@ -0,0 +1,66 @@ +import 'package:collection/collection.dart'; +import 'package:fluffychat/di/global/get_it_initializer.dart'; +import 'package:fluffychat/domain/usecase/send_file_interactor.dart'; +import 'package:fluffychat/pages/share/share_view.dart'; +import 'package:fluffychat/presentation/mixins/send_files_mixin.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:matrix/matrix.dart'; +import 'package:scroll_to_index/scroll_to_index.dart'; + +class Share extends StatefulWidget { + const Share({super.key}); + + @override + State createState() => ShareController(); +} + +class ShareController extends State with SendFilesMixin { + final sendFileInteractor = getIt.get(); + + final isShowRecentlyChatsNotifier = ValueNotifier(true); + + final AutoScrollController recentChatScrollController = + AutoScrollController(); + + final selectedRoomsNotifier = ValueNotifier([]); + + void onSelectChat(String id) { + if (selectedRoomsNotifier.value.contains(id)) { + selectedRoomsNotifier.value.remove(id); + } else { + selectedRoomsNotifier.value.add(id); + } + selectedRoomsNotifier.value = selectedRoomsNotifier.value.sorted( + (current, next) => current.compareTo(next), + ); + } + + void toggleRecentlyChats() { + isShowRecentlyChatsNotifier.value = !isShowRecentlyChatsNotifier.value; + } + + void shareTo(String roomId) async { + final room = Room( + id: selectedRoomsNotifier.value.first, + client: Matrix.of(context).client, + ); + final shareContent = Matrix.of(context).shareContent; + if (shareContent != null) { + final shareFile = shareContent.tryGet('file'); + if (shareContent.tryGet('msgtype') == 'chat.fluffy.shared_file') { + context.go('/rooms/${room.id}', extra: shareFile); + } else { + room.sendEvent(shareContent); + context.go('/rooms/${room.id}'); + } + Matrix.of(context).shareContent = null; + } + } + + @override + Widget build(BuildContext context) { + return ShareView(this); + } +} diff --git a/lib/pages/share/share_view.dart b/lib/pages/share/share_view.dart new file mode 100644 index 0000000000..ea982049b4 --- /dev/null +++ b/lib/pages/share/share_view.dart @@ -0,0 +1,80 @@ +import 'package:fluffychat/pages/forward/recent_chat_list.dart'; +import 'package:fluffychat/pages/forward/recent_chat_title.dart'; +import 'package:fluffychat/pages/share/share.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:fluffychat/widgets/twake_components/twake_fab.dart'; +import 'package:fluffychat/widgets/twake_components/twake_icon_button.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:go_router/go_router.dart'; + +class ShareView extends StatelessWidget { + const ShareView(this.controller, {super.key}); + + final ShareController controller; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + L10n.of(context)!.share, + style: Theme.of(context).textTheme.headlineLarge, + ), + leading: TwakeIconButton( + tooltip: L10n.of(context)!.cancel, + icon: Icons.close, + onPressed: () => context.pop(), + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: SingleChildScrollView( + child: Column( + children: [ + RecentChatsTitle( + isShowRecentlyChats: + controller.isShowRecentlyChatsNotifier.value, + toggleRecentChat: controller.toggleRecentlyChats, + ), + ValueListenableBuilder( + valueListenable: controller.isShowRecentlyChatsNotifier, + builder: (context, isShowRecentlyChat, child) { + if (isShowRecentlyChat) { + return RecentChatList( + rooms: Matrix.of(context).client.rooms, + selectedEventsNotifier: controller.selectedRoomsNotifier, + onSelectedChat: (roomId) => + controller.onSelectChat(roomId), + recentChatScrollController: + controller.recentChatScrollController, + ); + } + + return const SizedBox.shrink(); + }, + ), + ], + ), + ), + ), + floatingActionButtonLocation: FloatingActionButtonLocation.endFloat, + floatingActionButton: ValueListenableBuilder>( + valueListenable: controller.selectedRoomsNotifier, + builder: ((context, selectedChats, child) { + if (selectedChats.length != 1) { + return const SizedBox.shrink(); + } + return TwakeFloatingActionButton( + icon: Icons.send, + size: 18.0, + onTap: () => controller.shareTo( + controller.selectedRoomsNotifier.value.first, + ), + ); + }), + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index d9a093dbb3..4527c95b9f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1965,10 +1965,11 @@ packages: receive_sharing_intent: dependency: "direct main" description: - name: receive_sharing_intent - sha256: "912bebb551bce75a14098891fd750305b30d53eba0d61cc70cd9973be9866e8d" - url: "https://pub.dev" - source: hosted + path: "." + ref: "receive-.txt-v2" + resolved-ref: "7ac2cccb3e1ac4bddce7e287adcb69726f368b89" + url: "git@github.com:krabbenprgr/receive_sharing_intent.git" + source: git version: "1.4.5" record: dependency: "direct main" diff --git a/pubspec.yaml b/pubspec.yaml index beff3853e4..2dc5c2e400 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -77,7 +77,10 @@ dependencies: punycode: ^1.0.0 qr_code_scanner: ^1.0.0 qr_flutter: ^4.0.0 - receive_sharing_intent: ^1.4.5 + receive_sharing_intent: + git: + url: git@github.com:krabbenprgr/receive_sharing_intent.git + ref: receive-.txt-v2 record: ^4.4.4 scroll_to_index: ^3.0.1 share_plus: ^4.0.10+1