From 7d33899aba90121ede883dc02eaa7d5925e84470 Mon Sep 17 00:00:00 2001 From: ManhNTX Date: Tue, 2 Aug 2022 10:59:04 +0700 Subject: [PATCH] open composer view when selected share file --- android/app/src/main/AndroidManifest.xml | 21 ------ ...-app-group-id-in-receive-sharing-intent.md | 19 +++++ ios/Runner.xcodeproj/project.pbxproj | 3 + ios/Runner/Info.plist | 2 + ios/TeamMailShareExtension/Info.plist | 5 -- .../ShareViewController.swift | 70 ++----------------- .../presentation/composer_controller.dart | 35 ++++++++++ .../model/composer_arguments.dart | 4 ++ .../home/presentation/home_controller.dart | 9 ++- .../mailbox_dashboard_controller.dart | 19 +++++ lib/l10n/intl_messages.arb | 2 +- lib/main/utils/email_receive_manager.dart | 22 +++++- pubspec.yaml | 2 +- 13 files changed, 115 insertions(+), 98 deletions(-) create mode 100644 docs/adr/0012-change-app-group-id-in-receive-sharing-intent.md diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 5d83e634d..0ec5994e3 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -82,27 +82,6 @@ - - - - - - - - - - - - - - - - - - - - - + AppGroupId + ${APP_GROUP_ID} CADisableMinimumFrameDurationOnPhone CFBundleDevelopmentRegion diff --git a/ios/TeamMailShareExtension/Info.plist b/ios/TeamMailShareExtension/Info.plist index 02caa4087..37dc2904a 100644 --- a/ios/TeamMailShareExtension/Info.plist +++ b/ios/TeamMailShareExtension/Info.plist @@ -26,12 +26,8 @@ NSExtensionActivationRule - NSExtensionActivationSupportsFileWithMaxCount - 15 NSExtensionActivationSupportsImageWithMaxCount 15 - NSExtensionActivationSupportsMovieWithMaxCount - 15 NSExtensionActivationSupportsText NSExtensionActivationSupportsWebURLWithMaxCount @@ -39,7 +35,6 @@ PHSupportedMediaTypes - Video Image diff --git a/ios/TeamMailShareExtension/ShareViewController.swift b/ios/TeamMailShareExtension/ShareViewController.swift index 776386a35..a2ae24021 100644 --- a/ios/TeamMailShareExtension/ShareViewController.swift +++ b/ios/TeamMailShareExtension/ShareViewController.swift @@ -5,15 +5,13 @@ import Photos class ShareViewController: SLComposeServiceViewController { var hostAppBundleIdentifier = "" - let appGroupId = "group.com.linagora.teammail" + var appGroupId = "" let sharedKey = "ShareKey" var sharedMedia: [SharedMediaFile] = [] var sharedText: [String] = [] let imageContentType = kUTTypeImage as String - let videoContentType = kUTTypeMovie as String let textContentType = kUTTypeText as String let urlContentType = kUTTypeURL as String - let fileURLType = kUTTypeFileURL as String; override func isContentValid() -> Bool { return true @@ -29,6 +27,9 @@ class ShareViewController: SLComposeServiceViewController { // For example: com.test.ShareExtension -> com.test let lastIndexOfPoint = shareExtensionAppBundleIdentifier.lastIndex(of: "."); hostAppBundleIdentifier = String(shareExtensionAppBundleIdentifier[.. + appGroupId = (Bundle.main.object(forInfoDictionaryKey: "AppGroupId") as? String) ?? "group.\(hostAppBundleIdentifier)"; } @@ -50,12 +51,8 @@ class ShareViewController: SLComposeServiceViewController { handleImages(content: content, attachment: attachment, index: index) } else if attachment.hasItemConformingToTypeIdentifier(textContentType) { handleText(content: content, attachment: attachment, index: index) - } else if attachment.hasItemConformingToTypeIdentifier(fileURLType) { - handleFiles(content: content, attachment: attachment, index: index) } else if attachment.hasItemConformingToTypeIdentifier(urlContentType) { handleUrl(content: content, attachment: attachment, index: index) - } else if attachment.hasItemConformingToTypeIdentifier(videoContentType) { - handleVideos(content: content, attachment: attachment, index: index) } } } @@ -142,65 +139,6 @@ class ShareViewController: SLComposeServiceViewController { } } - private func handleVideos (content: NSExtensionItem, attachment: NSItemProvider, index: Int) { - attachment.loadItem(forTypeIdentifier: videoContentType, options: nil) { [weak self] data, error in - - if error == nil, let url = data as? URL, let this = self { - - // Always copy - let fileName = this.getFileName(from: url, type: .video) - let newPath = FileManager.default - .containerURL(forSecurityApplicationGroupIdentifier: this.appGroupId)! - .appendingPathComponent(fileName) - let copied = this.copyFile(at: url, to: newPath) - if(copied) { - guard let sharedFile = this.getSharedMediaFile(forVideo: newPath) else { - return - } - this.sharedMedia.append(sharedFile) - } - - // If this is the last item, save imagesData in userDefaults and redirect to host app - if index == (content.attachments?.count)! - 1 { - let userDefaults = UserDefaults(suiteName: this.appGroupId) - userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey) - userDefaults?.synchronize() - this.redirectToHostApp(type: .media) - } - - } else { - self?.dismissWithError() - } - } - } - - private func handleFiles (content: NSExtensionItem, attachment: NSItemProvider, index: Int) { - attachment.loadItem(forTypeIdentifier: fileURLType, options: nil) { [weak self] data, error in - - if error == nil, let url = data as? URL, let this = self { - - // Always copy - let fileName = this.getFileName(from :url, type: .file) - let newPath = FileManager.default - .containerURL(forSecurityApplicationGroupIdentifier: this.appGroupId)! - .appendingPathComponent(fileName) - let copied = this.copyFile(at: url, to: newPath) - if (copied) { - this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .file)) - } - - if index == (content.attachments?.count)! - 1 { - let userDefaults = UserDefaults(suiteName: this.appGroupId) - userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey) - userDefaults?.synchronize() - this.redirectToHostApp(type: .file) - } - - } else { - self?.dismissWithError() - } - } - } private func dismissWithError() { print("[ERROR] Error loading data!") diff --git a/lib/features/composer/presentation/composer_controller.dart b/lib/features/composer/presentation/composer_controller.dart index d688ee2db..3048710a5 100644 --- a/lib/features/composer/presentation/composer_controller.dart +++ b/lib/features/composer/presentation/composer_controller.dart @@ -25,6 +25,7 @@ import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart'; import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart'; @@ -317,6 +318,7 @@ class ComposerController extends BaseController { if (arguments.emailActionType == EmailActionType.edit) { _getEmailContentAction(arguments); } + _initEmailAddress(arguments); _initSubjectEmail(arguments); _initAttachments(arguments); @@ -902,7 +904,40 @@ class ComposerController extends BaseController { } } + List covertListSharedMediaFileToFile(List value) { + List newFiles = List.empty(growable: true); + if (value.isNotEmpty) { + for (var element in value) { + newFiles.add(File( + Platform.isIOS + ? element.type == SharedMediaType.FILE + ? element.path.toString().replaceAll('file:/', '') + : element.path + : element.path, + )); + } + } + + final List listInlineImage = newFiles.map( + (e) => InlineImage( + ImageSource.local, + fileInfo: FileInfo( + e.path.split('/').last, + e.path, + e.existsSync() ? e.lengthSync() : 0, + ) + ) + ).toList(); + return listInlineImage; + } + void _getEmailContentAction(ComposerArguments arguments) async { + if(arguments.listSharedMediaFile != null && arguments.listSharedMediaFile!.isNotEmpty){ + final listInlineImage = covertListSharedMediaFileToFile(arguments.listSharedMediaFile!); + for (var e in listInlineImage) { + _uploadInlineAttachmentsAction(e.fileInfo!); + } + } if(arguments.emailContents != null && arguments.emailContents!.isNotEmpty){ _emailContents = arguments.emailContents; emailContentsViewState.value = Right(GetEmailContentSuccess(_emailContents!,[],[])); diff --git a/lib/features/email/presentation/model/composer_arguments.dart b/lib/features/email/presentation/model/composer_arguments.dart index 2111a73e5..4a0abfd99 100644 --- a/lib/features/email/presentation/model/composer_arguments.dart +++ b/lib/features/email/presentation/model/composer_arguments.dart @@ -1,12 +1,14 @@ import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:model/model.dart'; +import 'package:receive_sharing_intent/receive_sharing_intent.dart'; import 'package:tmail_ui_user/main/routes/router_arguments.dart'; class ComposerArguments extends RouterArguments { final EmailActionType emailActionType; final PresentationEmail? presentationEmail; final List? emailContents; + final List? listSharedMediaFile; final EmailAddress? emailAddress; final List? attachments; final Role? mailboxRole; @@ -18,6 +20,7 @@ class ComposerArguments extends RouterArguments { this.attachments, this.mailboxRole, this.emailAddress, + this.listSharedMediaFile, }); @override @@ -28,5 +31,6 @@ class ComposerArguments extends RouterArguments { attachments, mailboxRole, emailAddress, + listSharedMediaFile, ]; } \ No newline at end of file diff --git a/lib/features/home/presentation/home_controller.dart b/lib/features/home/presentation/home_controller.dart index f5a0170ec..a49cfb099 100644 --- a/lib/features/home/presentation/home_controller.dart +++ b/lib/features/home/presentation/home_controller.dart @@ -3,9 +3,7 @@ import 'package:dartz/dartz.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; -import 'package:model/account/account.dart'; -import 'package:model/oidc/request/oidc_request.dart'; -import 'package:model/oidc/token_oidc.dart'; +import 'package:model/model.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/caching/caching_manager.dart'; import 'package:tmail_ui_user/features/cleanup/domain/model/cleanup_rule.dart'; @@ -100,6 +98,11 @@ class HomeController extends BaseController { _emailReceiveManager.setPendingEmailAddress(EmailAddress(null, uri.path)); } }); + + _emailReceiveManager.receivingFileSharingStream.listen((listFile) { + log('HomeController::onInit(): SharedMediaFile: ${listFile.toString()}'); + _emailReceiveManager.setPendingFileInfo(listFile); + }); } void _goToLogin({LoginArguments? arguments}) { diff --git a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart index 63504cda6..1bd0470d4 100644 --- a/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart +++ b/lib/features/mailbox_dashboard/presentation/controller/mailbox_dashboard_controller.dart @@ -89,6 +89,7 @@ class MailboxDashBoardController extends ReloadableController { RouterArguments? routerArguments; late StreamSubscription _connectivityStreamSubscription; late StreamSubscription _emailReceiveManagerStreamSubscription; + late StreamSubscription _fileReceiveManagerStreamSubscription; final StreamController> _progressStateController = StreamController>.broadcast(); @@ -110,6 +111,7 @@ class MailboxDashBoardController extends ReloadableController { void onInit() { _registerNetworkConnectivityState(); _registerPendingEmailAddress(); + _registerPendingFileInfo(); _initializeIsolateExecutor(); super.onInit(); } @@ -239,6 +241,22 @@ class MailboxDashBoardController extends ReloadableController { }); } + void _registerPendingFileInfo() { + _fileReceiveManagerStreamSubscription = + _emailReceiveManager.pendingFileInfo.stream.listen((listFile) { + log('MailboxDashBoardController::_registerPendingFileInfo(): ${listFile.length}'); + if (listFile.isNotEmpty) { + _emailReceiveManager.clearPendingFileInfo(); + final arguments = ComposerArguments( + emailActionType: EmailActionType.edit, + mailboxRole: selectedMailbox.value?.role, + listSharedMediaFile: listFile, + ); + goToComposer(arguments); + } + }); + } + void _initializeIsolateExecutor() async { await _isolateExecutor.warmUp(log: BuildUtils.isDebugMode); @@ -556,6 +574,7 @@ class MailboxDashBoardController extends ReloadableController { void onClose() { _emailReceiveManager.closeEmailReceiveManagerStream(); _emailReceiveManagerStreamSubscription.cancel(); + _fileReceiveManagerStreamSubscription.cancel(); _connectivityStreamSubscription.cancel(); _progressStateController.close(); _isolateExecutor.dispose(); diff --git a/lib/l10n/intl_messages.arb b/lib/l10n/intl_messages.arb index 4f5f7111a..45a86d27b 100644 --- a/lib/l10n/intl_messages.arb +++ b/lib/l10n/intl_messages.arb @@ -1,5 +1,5 @@ { - "@@last_modified": "2022-07-27T12:01:37.344258", + "@@last_modified": "2022-08-03T00:27:26.944930", "initializing_data": "Initializing data...", "@initializing_data": { "type": "text", diff --git a/lib/main/utils/email_receive_manager.dart b/lib/main/utils/email_receive_manager.dart index 902118d8b..86f32da3e 100644 --- a/lib/main/utils/email_receive_manager.dart +++ b/lib/main/utils/email_receive_manager.dart @@ -8,13 +8,16 @@ class EmailReceiveManager { BehaviorSubject _pendingEmailAddressInfo = BehaviorSubject.seeded(null); BehaviorSubject get pendingEmailAddressInfo => _pendingEmailAddressInfo; + BehaviorSubject> _pendingFileInfo = BehaviorSubject.seeded(List.empty(growable: true)); + BehaviorSubject> get pendingFileInfo => _pendingFileInfo; + Stream get receivingSharingStream { return Rx.merge([ Stream.fromFuture(ReceiveSharingIntent.getInitialTextAsUri()), ReceiveSharingIntent.getTextStreamAsUri() ]); } - Stream> get receivingSharingStream2 { + Stream> get receivingFileSharingStream { return Rx.merge([ Stream.fromFuture(ReceiveSharingIntent.getInitialMedia()), ReceiveSharingIntent.getMediaStream() @@ -37,4 +40,21 @@ class EmailReceiveManager { void closeEmailReceiveManagerStream() { _pendingEmailAddressInfo.close(); } + + void setPendingFileInfo(List list) async { + clearPendingFileInfo(); + _pendingFileInfo.add(list); + } + + void clearPendingFileInfo() { + if(_pendingFileInfo.isClosed) { + _pendingFileInfo = BehaviorSubject.seeded(List.empty(growable: true)); + } else { + _pendingFileInfo.add(List.empty(growable: true)); + } + } + + void closeFileSharingStream() { + _pendingFileInfo.close(); + } } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 7b9716028..989dee1e9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -146,7 +146,7 @@ dependencies: receive_sharing_intent: git: - url: https://github.com/ManhNTX/receive_sharing_intent.git + url: https://github.com/KasemJaffer/receive_sharing_intent.git ref: master dropdown_button2: 1.4.0