Merge pull request #1503 from krille-chan/krille/update-receive-sharing-intent
refactor: Update to new receive sharing intent package
This commit is contained in:
commit
6286f30b9b
9 changed files with 119 additions and 368 deletions
|
|
@ -49,10 +49,14 @@
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can open on notification action -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
|
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can open https://matrix.to urls -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
@ -61,38 +65,61 @@
|
||||||
android:scheme="https"
|
android:scheme="https"
|
||||||
android:host="matrix.to"/>
|
android:host="matrix.to"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can open matrix: uris -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:scheme="matrix" />
|
<data android:scheme="matrix" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can open im.fluffychat:// uris -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:scheme="im.fluffychat" android:host="chat" />
|
<data android:scheme="im.fluffychat" android:host="chat" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can receive shared files -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data
|
||||||
|
android:mimeType="*/*"
|
||||||
|
android:scheme="content" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can receive shared text -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:mimeType="text/*" />
|
<data android:mimeType="text/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can receive shared documents -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:mimeType="document/*" />
|
<data android:mimeType="document/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can receive shared images -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:mimeType="image/*" />
|
<data android:mimeType="image/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can receive shared videos -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<data android:mimeType="video/*" />
|
<data android:mimeType="video/*" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- App can receive shared audios -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND" />
|
<action android:name="android.intent.action.SEND" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|
|
||||||
|
|
@ -1,335 +1,14 @@
|
||||||
import UIKit
|
// If you get no such module 'receive_sharing_intent' error.
|
||||||
import Social
|
// Go to Build Phases of your Runner target and
|
||||||
import MobileCoreServices
|
// move `Embed Foundation Extension` to the top of `Thin Binary`.
|
||||||
import Photos
|
import receive_sharing_intent
|
||||||
|
|
||||||
class ShareViewController: SLComposeServiceViewController {
|
class ShareViewController: RSIShareViewController {
|
||||||
// TODO: IMPORTANT: This should be your host app bundle identifier
|
|
||||||
let hostAppBundleIdentifier = "im.fluffychat.app"
|
// Use this method to return false if you don't want to redirect to host app automatically.
|
||||||
let sharedKey = "ShareKey"
|
// Default is true
|
||||||
var sharedMedia: [SharedMediaFile] = []
|
override func shouldAutoRedirect() -> Bool {
|
||||||
var sharedText: [String] = []
|
return false
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
|
||||||
super.viewDidLoad();
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
|
||||||
super.viewDidAppear(animated)
|
|
||||||
|
|
||||||
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
|
|
||||||
if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
|
|
||||||
if let contents = content.attachments {
|
|
||||||
for (index, attachment) in (contents).enumerated() {
|
|
||||||
if attachment.hasItemConformingToTypeIdentifier(imageContentType) {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override func didSelectPost() {
|
|
||||||
print("didSelectPost");
|
|
||||||
}
|
|
||||||
|
|
||||||
override func configurationItems() -> [Any]! {
|
|
||||||
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleText (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
|
|
||||||
attachment.loadItem(forTypeIdentifier: textContentType, options: nil) { [weak self] data, error in
|
|
||||||
|
|
||||||
if error == nil, let item = data as? String, let this = self {
|
|
||||||
|
|
||||||
this.sharedText.append(item)
|
|
||||||
|
|
||||||
// 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: "group.\(this.hostAppBundleIdentifier)")
|
|
||||||
userDefaults?.set(this.sharedText, forKey: this.sharedKey)
|
|
||||||
userDefaults?.synchronize()
|
|
||||||
this.redirectToHostApp(type: .text)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
self?.dismissWithError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleUrl (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
|
|
||||||
attachment.loadItem(forTypeIdentifier: urlContentType, options: nil) { [weak self] data, error in
|
|
||||||
|
|
||||||
if error == nil, let item = data as? URL, let this = self {
|
|
||||||
|
|
||||||
this.sharedText.append(item.absoluteString)
|
|
||||||
|
|
||||||
// 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: "group.\(this.hostAppBundleIdentifier)")
|
|
||||||
userDefaults?.set(this.sharedText, forKey: this.sharedKey)
|
|
||||||
userDefaults?.synchronize()
|
|
||||||
this.redirectToHostApp(type: .text)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
self?.dismissWithError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleImages (content: NSExtensionItem, attachment: NSItemProvider, index: Int) {
|
|
||||||
attachment.loadItem(forTypeIdentifier: imageContentType, 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: .image)
|
|
||||||
let newPath = FileManager.default
|
|
||||||
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(this.hostAppBundleIdentifier)")!
|
|
||||||
.appendingPathComponent(fileName)
|
|
||||||
let copied = this.copyFile(at: url, to: newPath)
|
|
||||||
if(copied) {
|
|
||||||
this.sharedMedia.append(SharedMediaFile(path: newPath.absoluteString, thumbnail: nil, duration: nil, type: .image))
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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: "group.\(this.hostAppBundleIdentifier)")
|
|
||||||
userDefaults?.set(this.toData(data: this.sharedMedia), forKey: this.sharedKey)
|
|
||||||
userDefaults?.synchronize()
|
|
||||||
this.redirectToHostApp(type: .media)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
self?.dismissWithError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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: "group.\(this.hostAppBundleIdentifier)")!
|
|
||||||
.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: "group.\(this.hostAppBundleIdentifier)")
|
|
||||||
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: "group.\(this.hostAppBundleIdentifier)")!
|
|
||||||
.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: "group.\(this.hostAppBundleIdentifier)")
|
|
||||||
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!")
|
|
||||||
let alert = UIAlertController(title: "Error", message: "Error loading data", preferredStyle: .alert)
|
|
||||||
|
|
||||||
let action = UIAlertAction(title: "Error", style: .cancel) { _ in
|
|
||||||
self.dismiss(animated: true, completion: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
alert.addAction(action)
|
|
||||||
present(alert, animated: true, completion: nil)
|
|
||||||
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func redirectToHostApp(type: RedirectType) {
|
|
||||||
let url = URL(string: "ShareMedia://dataUrl=\(sharedKey)#\(type)")
|
|
||||||
var responder = self as UIResponder?
|
|
||||||
let selectorOpenURL = sel_registerName("openURL:")
|
|
||||||
|
|
||||||
while (responder != nil) {
|
|
||||||
if (responder?.responds(to: selectorOpenURL))! {
|
|
||||||
let _ = responder?.perform(selectorOpenURL, with: url)
|
|
||||||
}
|
|
||||||
responder = responder!.next
|
|
||||||
}
|
|
||||||
extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum RedirectType {
|
|
||||||
case media
|
|
||||||
case text
|
|
||||||
case file
|
|
||||||
}
|
|
||||||
|
|
||||||
func getExtension(from url: URL, type: SharedMediaType) -> String {
|
|
||||||
let parts = url.lastPathComponent.components(separatedBy: ".")
|
|
||||||
var ex: String? = nil
|
|
||||||
if (parts.count > 1) {
|
|
||||||
ex = parts.last
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ex == nil) {
|
|
||||||
switch type {
|
|
||||||
case .image:
|
|
||||||
ex = "PNG"
|
|
||||||
case .video:
|
|
||||||
ex = "MP4"
|
|
||||||
case .file:
|
|
||||||
ex = "TXT"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ex ?? "Unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFileName(from url: URL, type: SharedMediaType) -> String {
|
|
||||||
var name = url.lastPathComponent
|
|
||||||
|
|
||||||
if (name.isEmpty) {
|
|
||||||
name = UUID().uuidString + "." + getExtension(from: url, type: type)
|
|
||||||
}
|
|
||||||
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyFile(at srcURL: URL, to dstURL: URL) -> Bool {
|
|
||||||
do {
|
|
||||||
if FileManager.default.fileExists(atPath: dstURL.path) {
|
|
||||||
try FileManager.default.removeItem(at: dstURL)
|
|
||||||
}
|
|
||||||
try FileManager.default.copyItem(at: srcURL, to: dstURL)
|
|
||||||
} catch (let error) {
|
|
||||||
print("Cannot copy item at \(srcURL) to \(dstURL): \(error)")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private func getSharedMediaFile(forVideo: URL) -> SharedMediaFile? {
|
|
||||||
let asset = AVAsset(url: forVideo)
|
|
||||||
let duration = (CMTimeGetSeconds(asset.duration) * 1000).rounded()
|
|
||||||
let thumbnailPath = getThumbnailPath(for: forVideo)
|
|
||||||
|
|
||||||
if FileManager.default.fileExists(atPath: thumbnailPath.path) {
|
|
||||||
return SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video)
|
|
||||||
}
|
|
||||||
|
|
||||||
var saved = false
|
|
||||||
let assetImgGenerate = AVAssetImageGenerator(asset: asset)
|
|
||||||
assetImgGenerate.appliesPreferredTrackTransform = true
|
|
||||||
// let scale = UIScreen.main.scale
|
|
||||||
assetImgGenerate.maximumSize = CGSize(width: 360, height: 360)
|
|
||||||
do {
|
|
||||||
let img = try assetImgGenerate.copyCGImage(at: CMTimeMakeWithSeconds(600, preferredTimescale: Int32(1.0)), actualTime: nil)
|
|
||||||
try UIImage.pngData(UIImage(cgImage: img))()?.write(to: thumbnailPath)
|
|
||||||
saved = true
|
|
||||||
} catch {
|
|
||||||
saved = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return saved ? SharedMediaFile(path: forVideo.absoluteString, thumbnail: thumbnailPath.absoluteString, duration: duration, type: .video) : nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private func getThumbnailPath(for url: URL) -> URL {
|
|
||||||
let fileName = Data(url.lastPathComponent.utf8).base64EncodedString().replacingOccurrences(of: "==", with: "")
|
|
||||||
let path = FileManager.default
|
|
||||||
.containerURL(forSecurityApplicationGroupIdentifier: "group.\(hostAppBundleIdentifier)")!
|
|
||||||
.appendingPathComponent("\(fileName).jpg")
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
class SharedMediaFile: Codable {
|
|
||||||
var path: String; // can be image, video or url path. It can also be text content
|
|
||||||
var thumbnail: String?; // video thumbnail
|
|
||||||
var duration: Double?; // video duration in milliseconds
|
|
||||||
var type: SharedMediaType;
|
|
||||||
|
|
||||||
|
|
||||||
init(path: String, thumbnail: String?, duration: Double?, type: SharedMediaType) {
|
|
||||||
self.path = path
|
|
||||||
self.thumbnail = thumbnail
|
|
||||||
self.duration = duration
|
|
||||||
self.type = type
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug method to print out SharedMediaFile details in the console
|
|
||||||
func toString() {
|
|
||||||
print("[SharedMediaFile] \n\tpath: \(self.path)\n\tthumbnail: \(self.thumbnail)\n\tduration: \(self.duration)\n\ttype: \(self.type)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum SharedMediaType: Int, Codable {
|
|
||||||
case image
|
|
||||||
case video
|
|
||||||
case file
|
|
||||||
}
|
|
||||||
|
|
||||||
func toData(data: [SharedMediaFile]) -> Data {
|
|
||||||
let encodedData = try? JSONEncoder().encode(data)
|
|
||||||
return encodedData!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Array {
|
|
||||||
subscript (safe index: UInt) -> Element? {
|
|
||||||
return Int(index) < count ? self[Int(index)] : nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -32,6 +32,11 @@ target 'Runner' do
|
||||||
use_modular_headers!
|
use_modular_headers!
|
||||||
|
|
||||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
|
||||||
|
# From package https://pub.dev/packages/receive_sharing_intent
|
||||||
|
target 'FluffyChat Share' do
|
||||||
|
inherit! :search_paths
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
609046320A2D7D2B0D36583B /* Pods_FluffyChat_Share.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9EB6E6475A19949A37A2634 /* Pods_FluffyChat_Share.framework */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
|
|
@ -56,10 +57,12 @@
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
09545B0C8C397F94966EA956 /* Pods-FluffyChat Share.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FluffyChat Share.debug.xcconfig"; path = "Target Support Files/Pods-FluffyChat Share/Pods-FluffyChat Share.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
50DEFC207B70632D9C56ED78 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
50DEFC207B70632D9C56ED78 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
58F7B95D036AD8E67B27588D /* Pods-FluffyChat Share.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FluffyChat Share.profile.xcconfig"; path = "Target Support Files/Pods-FluffyChat Share/Pods-FluffyChat Share.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
76737C9A857D5FD6D2634A3F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
76737C9A857D5FD6D2634A3F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
|
@ -80,7 +83,9 @@
|
||||||
C137635D2AD1446100A8F905 /* notification.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = notification.caf; sourceTree = "<group>"; };
|
C137635D2AD1446100A8F905 /* notification.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = notification.caf; sourceTree = "<group>"; };
|
||||||
C149567B25C7274F00A16396 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
C149567B25C7274F00A16396 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
C149567D25C7276200A16396 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
C149567D25C7276200A16396 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
|
C9EB6E6475A19949A37A2634 /* Pods_FluffyChat_Share.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FluffyChat_Share.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA246783222E02DD03959891 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
EA246783222E02DD03959891 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
F3778959E67CDA0CDB0D97BC /* Pods-FluffyChat Share.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FluffyChat Share.release.xcconfig"; path = "Target Support Files/Pods-FluffyChat Share/Pods-FluffyChat Share.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -96,6 +101,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
609046320A2D7D2B0D36583B /* Pods_FluffyChat_Share.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -106,6 +112,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
50DEFC207B70632D9C56ED78 /* Pods_Runner.framework */,
|
50DEFC207B70632D9C56ED78 /* Pods_Runner.framework */,
|
||||||
|
C9EB6E6475A19949A37A2634 /* Pods_FluffyChat_Share.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -177,6 +184,9 @@
|
||||||
76737C9A857D5FD6D2634A3F /* Pods-Runner.debug.xcconfig */,
|
76737C9A857D5FD6D2634A3F /* Pods-Runner.debug.xcconfig */,
|
||||||
EA246783222E02DD03959891 /* Pods-Runner.release.xcconfig */,
|
EA246783222E02DD03959891 /* Pods-Runner.release.xcconfig */,
|
||||||
9DB2F3524376810E74C799A8 /* Pods-Runner.profile.xcconfig */,
|
9DB2F3524376810E74C799A8 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
09545B0C8C397F94966EA956 /* Pods-FluffyChat Share.debug.xcconfig */,
|
||||||
|
F3778959E67CDA0CDB0D97BC /* Pods-FluffyChat Share.release.xcconfig */,
|
||||||
|
58F7B95D036AD8E67B27588D /* Pods-FluffyChat Share.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -195,9 +205,9 @@
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
C1005C4D261071B5002F4F32 /* Embed App Extensions */,
|
C1005C4D261071B5002F4F32 /* Embed App Extensions */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
|
||||||
F9C8EE392B9AB471149C306E /* [CP] Embed Pods Frameworks */,
|
F9C8EE392B9AB471149C306E /* [CP] Embed Pods Frameworks */,
|
||||||
064CBD7CE0D4CD6850C6880A /* [CP] Copy Pods Resources */,
|
064CBD7CE0D4CD6850C6880A /* [CP] Copy Pods Resources */,
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
|
@ -213,6 +223,7 @@
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = C1005C51261071B5002F4F32 /* Build configuration list for PBXNativeTarget "FluffyChat Share" */;
|
buildConfigurationList = C1005C51261071B5002F4F32 /* Build configuration list for PBXNativeTarget "FluffyChat Share" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
|
67579C1EA0B5C7B918473158 /* [CP] Check Pods Manifest.lock */,
|
||||||
C1005C3E261071B5002F4F32 /* Sources */,
|
C1005C3E261071B5002F4F32 /* Sources */,
|
||||||
C1005C3F261071B5002F4F32 /* Frameworks */,
|
C1005C3F261071B5002F4F32 /* Frameworks */,
|
||||||
C1005C40261071B5002F4F32 /* Resources */,
|
C1005C40261071B5002F4F32 /* Resources */,
|
||||||
|
|
@ -320,7 +331,29 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
|
||||||
|
};
|
||||||
|
67579C1EA0B5C7B918473158 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-FluffyChat Share-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
8C9CCA7C5C45651F90C7BFDD /* [CP] Check Pods Manifest.lock */ = {
|
8C9CCA7C5C45651F90C7BFDD /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
|
@ -357,7 +390,7 @@
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
|
||||||
};
|
};
|
||||||
F9C8EE392B9AB471149C306E /* [CP] Embed Pods Frameworks */ = {
|
F9C8EE392B9AB471149C306E /* [CP] Embed Pods Frameworks */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
|
@ -693,6 +726,7 @@
|
||||||
};
|
};
|
||||||
C1005C4E261071B5002F4F32 /* Debug */ = {
|
C1005C4E261071B5002F4F32 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 09545B0C8C397F94966EA956 /* Pods-FluffyChat Share.debug.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
|
@ -727,6 +761,7 @@
|
||||||
};
|
};
|
||||||
C1005C4F261071B5002F4F32 /* Release */ = {
|
C1005C4F261071B5002F4F32 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = F3778959E67CDA0CDB0D97BC /* Pods-FluffyChat Share.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
|
@ -758,6 +793,7 @@
|
||||||
};
|
};
|
||||||
C1005C50261071B5002F4F32 /* Profile */ = {
|
C1005C50261071B5002F4F32 /* Profile */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 58F7B95D036AD8E67B27588D /* Pods-FluffyChat Share.profile.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
<string>im.fluffychat.app.uris</string>
|
<string>im.fluffychat.app.uris</string>
|
||||||
<key>CFBundleURLSchemes</key>
|
<key>CFBundleURLSchemes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>ShareMedia</string>
|
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<string>im.fluffychat</string>
|
<string>im.fluffychat</string>
|
||||||
<string>matrix</string>
|
<string>matrix</string>
|
||||||
</array>
|
</array>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
@ -26,7 +25,6 @@ import 'package:fluffychat/widgets/avatar.dart';
|
||||||
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
import 'package:fluffychat/widgets/future_loading_dialog.dart';
|
||||||
import '../../../utils/account_bundles.dart';
|
import '../../../utils/account_bundles.dart';
|
||||||
import '../../config/setting_keys.dart';
|
import '../../config/setting_keys.dart';
|
||||||
import '../../utils/matrix_sdk_extensions/matrix_file_extension.dart';
|
|
||||||
import '../../utils/url_launcher.dart';
|
import '../../utils/url_launcher.dart';
|
||||||
import '../../utils/voip/callkeep_manager.dart';
|
import '../../utils/voip/callkeep_manager.dart';
|
||||||
import '../../widgets/fluffy_chat_app.dart';
|
import '../../widgets/fluffy_chat_app.dart';
|
||||||
|
|
@ -196,20 +194,14 @@ class ChatListController extends State<ChatList>
|
||||||
// Share content into this room
|
// Share content into this room
|
||||||
final shareContent = Matrix.of(context).shareContent;
|
final shareContent = Matrix.of(context).shareContent;
|
||||||
if (shareContent != null) {
|
if (shareContent != null) {
|
||||||
final shareFile = shareContent.tryGet<MatrixFile>('file');
|
final shareFile = shareContent.tryGet<XFile>('file');
|
||||||
if (shareContent.tryGet<String>('msgtype') == 'chat.fluffy.shared_file' &&
|
if (shareContent.tryGet<String>('msgtype') == 'chat.fluffy.shared_file' &&
|
||||||
shareFile != null) {
|
shareFile != null) {
|
||||||
await showDialog(
|
await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
useRootNavigator: false,
|
useRootNavigator: false,
|
||||||
builder: (c) => SendFileDialog(
|
builder: (c) => SendFileDialog(
|
||||||
files: [
|
files: [shareFile],
|
||||||
XFile.fromData(
|
|
||||||
shareFile.bytes,
|
|
||||||
name: shareFile.name,
|
|
||||||
mimeType: shareFile.mimeType,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
room: room,
|
room: room,
|
||||||
outerContext: context,
|
outerContext: context,
|
||||||
),
|
),
|
||||||
|
|
@ -432,16 +424,32 @@ class ChatListController extends State<ChatList>
|
||||||
? SelectMode.share
|
? SelectMode.share
|
||||||
: SelectMode.normal;
|
: SelectMode.normal;
|
||||||
|
|
||||||
void _processIncomingSharedFiles(List<SharedMediaFile> files) {
|
void _processIncomingSharedMedia(List<SharedMediaFile> files) {
|
||||||
if (files.isEmpty) return;
|
if (files.isEmpty) return;
|
||||||
final file = File(files.first.path.replaceFirst('file://', ''));
|
|
||||||
|
if (files.length > 1) {
|
||||||
|
Logs().w(
|
||||||
|
'Received ${files.length} incoming shared media but app can only handle the first one',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only handle the first file currently
|
||||||
|
final sharedMedia = files.first;
|
||||||
|
|
||||||
|
// Handle URIs and Texts, which are also passed in path
|
||||||
|
if (sharedMedia.type case SharedMediaType.text || SharedMediaType.url) {
|
||||||
|
return _processIncomingSharedText(sharedMedia.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
final file = XFile(
|
||||||
|
sharedMedia.path.replaceFirst('file://', ''),
|
||||||
|
mimeType: sharedMedia.mimeType,
|
||||||
|
);
|
||||||
|
|
||||||
Matrix.of(context).shareContent = {
|
Matrix.of(context).shareContent = {
|
||||||
'msgtype': 'chat.fluffy.shared_file',
|
'msgtype': 'chat.fluffy.shared_file',
|
||||||
'file': MatrixFile(
|
'file': file,
|
||||||
bytes: file.readAsBytesSync(),
|
if (sharedMedia.message != null) 'body': sharedMedia.message,
|
||||||
name: file.path,
|
|
||||||
).detectFileType,
|
|
||||||
};
|
};
|
||||||
context.go('/rooms');
|
context.go('/rooms');
|
||||||
}
|
}
|
||||||
|
|
@ -473,18 +481,14 @@ class ChatListController extends State<ChatList>
|
||||||
if (!PlatformInfos.isMobile) return;
|
if (!PlatformInfos.isMobile) return;
|
||||||
|
|
||||||
// For sharing images coming from outside the app while the app is in the memory
|
// For sharing images coming from outside the app while the app is in the memory
|
||||||
_intentFileStreamSubscription = ReceiveSharingIntent.getMediaStream()
|
_intentFileStreamSubscription = ReceiveSharingIntent.instance
|
||||||
.listen(_processIncomingSharedFiles, onError: print);
|
.getMediaStream()
|
||||||
|
.listen(_processIncomingSharedMedia, onError: print);
|
||||||
|
|
||||||
// For sharing images coming from outside the app while the app is closed
|
// For sharing images coming from outside the app while the app is closed
|
||||||
ReceiveSharingIntent.getInitialMedia().then(_processIncomingSharedFiles);
|
ReceiveSharingIntent.instance
|
||||||
|
.getInitialMedia()
|
||||||
// For sharing or opening urls/text coming from outside the app while the app is in the memory
|
.then(_processIncomingSharedMedia);
|
||||||
_intentDataStreamSubscription = ReceiveSharingIntent.getTextStream()
|
|
||||||
.listen(_processIncomingSharedText, onError: print);
|
|
||||||
|
|
||||||
// For sharing or opening urls/text coming from outside the app while the app is closed
|
|
||||||
ReceiveSharingIntent.getInitialText().then(_processIncomingSharedText);
|
|
||||||
|
|
||||||
// For receiving shared Uris
|
// For receiving shared Uris
|
||||||
_intentUriStreamSubscription = linkStream.listen(_processIncomingUris);
|
_intentUriStreamSubscription = linkStream.listen(_processIncomingUris);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:file_selector/file_selector.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:file_selector/file_selector.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
|
|
||||||
|
|
@ -1630,10 +1630,10 @@ packages:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: receive_sharing_intent
|
name: receive_sharing_intent
|
||||||
sha256: "912bebb551bce75a14098891fd750305b30d53eba0d61cc70cd9973be9866e8d"
|
sha256: ec76056e4d258ad708e76d85591d933678625318e411564dcb9059048ca3a593
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.5"
|
version: "1.8.1"
|
||||||
record:
|
record:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ dependencies:
|
||||||
provider: ^6.0.2
|
provider: ^6.0.2
|
||||||
punycode: ^1.0.0
|
punycode: ^1.0.0
|
||||||
qr_code_scanner: ^1.0.1
|
qr_code_scanner: ^1.0.1
|
||||||
receive_sharing_intent: 1.4.5 # Update needs more work
|
receive_sharing_intent: ^1.8.1
|
||||||
record: ^5.1.2
|
record: ^5.1.2
|
||||||
scroll_to_index: ^3.0.1
|
scroll_to_index: ^3.0.1
|
||||||
share_plus: ^10.0.2
|
share_plus: ^10.0.2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue