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