Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update on share menu icon #2

Open
rkscodes opened this issue Sep 19, 2022 · 7 comments
Open

Update on share menu icon #2

rkscodes opened this issue Sep 19, 2022 · 7 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@rkscodes
Copy link

Any plans on including that share icon ?

@agungrbudiman agungrbudiman closed this as not planned Won't fix, can't repro, duplicate, stale Nov 25, 2022
@agungrbudiman agungrbudiman reopened this Nov 28, 2022
@agungrbudiman agungrbudiman added enhancement New feature or request planned help wanted Extra attention is needed and removed planned labels Nov 29, 2022
@sannidhyaroy
Copy link

sannidhyaroy commented Dec 5, 2022

I did try to add the share menu and I think I made quite some progress, although there are some minor bugs. The two major problems I'm facing now is that I'm not able to retrieve the file URL from the NSItemProvider and also for some reason, I'm unable to get the data packet of the file for sharing, if I put a sample file URL in my code. Any idea how this can be sorted out @agungrbudiman? I'm really new to Swift & macOS development, so I apologize in advance if this is a trivial issue that I just don't understand.

This is the code for the send button method in the share menu:

`@IBAction func send(_ sender: AnyObject?) {

   var contentType: String
    if let content = extensionContext!.inputItems[0] as? NSExtensionItem {
        if #available(macOSApplicationExtension 11.0, *) {
            contentType = UTType.png.identifier // Just testing with PNGs for now to detect where the problem lies
        } else {
            // Fallback on earlier versions
            contentType = kUTTypePNG as String
        }
        
        if let contents = content.attachments {
            let pressedBtnTag = sender?.tag
            sharedUserDefaults?.set(pressedBtnTag, forKey: SharedUserDefaults.Keys.buttonTag) // Saves the buttonTag to the UserDefaults which will help us identify the device to send later
            // look for content files
            for attachment in contents {
                if attachment.hasItemConformingToTypeIdentifier(contentType) {
                    attachment.loadItem(forTypeIdentifier: contentType, options: nil) { (data, error) in
                        if let url = data as? URL {
                            sharedUserDefaults?.set(url, forKey: SharedUserDefaults.Keys.fileurl)
                            self.uploadFile() // Will send a notification to the Darwin Notification System which will be picked up by the observer in the main app and it will load the button tag & url from User Defaults and request the data packet to upload it
                        }
                    }
                }
            }
        }
    }
    self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
}`

UPDATE: Change it to UTType.url.identifier fixed the issue! The only issue remaining is the get the selected Device. It would be great if we could store custom data types in User Defaults. I need to pass the selected Device to the main app which will then initiate the send packet command.

@agungrbudiman agungrbudiman pinned this issue Dec 5, 2022
@sannidhyaroy
Copy link

sannidhyaroy commented Dec 5, 2022

[EDIT]:

I got the issue fixed and the share extension is working. You can check it out in the nightly branch of my Soduto repository. It has quite a few bugs, so do let me know if you'd like in case anyone tries it out. Also, remember to enable the extension from System Preferences (for macOS Ventura: System Preferences > Privacy & Security > Extensions > Added Extensions > enable Soduto). I've been struggling to get this working for quite a few days and lost all hope in between to get this to work, so I'm at least glad that I pulled it off.

[ORIGINAL COMMENT]:

@agungrbudiman This is probably going to be a long comment so I apologize beforehand. You can reply me later if you're busy right now.

Can you give me some info about the public var validDevices: [Device] { return self.devices.values.filter { $0.isReachable && $0.pairingStatus == .Paired } } inside ShareService.swift? I'm new to Swift so I'm not sure if this is a trivial issue which I don't understand. All I know that is self.validDevices is a [Device] array of "Device" data type which contains the list of devices which are paired to Soduto and reachable. The ShareService makes use of this variable to know how many devices are connected and reachable and if the array is empty, then it wouldn't show any device to share, else it would show the name of the reachable devices for the user to select among any one of them.

Onto the issue:

I create a variable in AppDelegate with var validDevices: [Device] = deviceManager.pairedDevices and can now successfully make use of this array to get the list of devices and show the names in the share extension which I'm currently working on. Since, the app can't directly communicate with an app extension, I used User Defaults to store the list of paired device names to a [String] array which is then retrieved by the share extension when it launches and it displays those names in a sequential order (e.g.: first device name from array goes to first row then second device name to second row which means index 0 of array is shown in row index 0 and so on...)!

After the user selects a device from the table, the code checks for the row number which was selected and stores it in User Defaults. Futthermore, it retrieves the file url of the content, which was selected to be shared (e.g.: images, videos, text files) and stores the file url to User Defaults. Now the extension sends a notification to the Darwin Notification System and closes the share extension window. The Darwin Notification is picked up by the observer in the main app inside the applicationDidFinishLaunching function of AppDelegate which then loads up the file url and row number from the user defaults. Now, what I was expecting is that I'll be able to get the "Device" data type (cuz the share extension needs this parameter to send files) using self.validDevices[row] but this is where the problems start and the build will fail as you can't use "self" in the closure block of the Darwin notification observer. I tried to get the validDevices array inside ShareService but the surprising part is that it is an empty array. (NOTE: I was using validDevices array defined in AppDelegate all this time which worked but can't use it in this case as I can't access it in the closure block.)

I can still send files from "Send Files" option in the menu bar of Soduto or by dragging a file to the menu bar icon which means the validDevices array inside ShareService.swift isn't empty. The uploadFile method checks if self.validDevices.count isn't zero and then it sends the file to the other device, which means that it's only when I try to check the array size, I find that it's empty.

Sorry for reading this long comment. If you know where I'm going wrong, it'd be of great help if you tell me the reason. Pardon me if my code logic is flawed, this is the first swift project I tried, so my expectations aren't huge either. Critics are welcomed!

@agungrbudiman
Copy link
Owner

Thank you for your hard work. I tried to add share extension before but then I realize I can't use any code from the main app. It's like building new app rather than just adding new interface. So I thought to rewrite all the logic from the main app into the share extension but it will be redundant. I thought another approach is to connect share extension and the main app just like Soduto Browser and the Soduto interacts, but I still can't figure it out how to connect it after several days of fiddling with the code. After that I thought maybe it's a good idea to learn basic swift before jumping out into this project, hence I added help wanted label. I tried clone your fork and it build successfully on my mac running Monterey 12.6.1.

@sannidhyaroy
Copy link

Yeah, the main app and the extension are sandboxed which is the main issue here, hence they can't communicate with each other. It's a major challenge to pass data among them and I tried to use App Groups, User Defaults and the Darwin Notification Center to fill those gaps. The share extension works but there are a lot of bugs. Selecting multiple files and sending it, sends the same file over and over again. And the share extension works successfully only for files in the Downloads folder because macOS doesn't allow access to other directories. If I turn off app sandbox, then it works in other folders too. However, I don't know if there's any downside in disabling sandboxing, so I'm trying to find another workaround.

Anyways, hail Stack Overflow! Nothing is possible without them 😂🙌

@sannidhyaroy
Copy link

[UPDATE]:

The share extension works almost fine now. I fixed the read access issues and the device availability issues. I can create a pull request if you (@agungrbudiman) want to but I'd prefer not to merge it with your beta branch as this yet isn't as stable as a beta version is supposed to. Multiple file sharing at once still doesn't work yet. If you have an alpha or nightly branch, I can create a pull request to merge it there.

I loved this project and tried to contribute as much as I could to it, even though I don't know the basics of Swift. Even though the project is official not in development, the open-source community is extremely helpful which is why Soduto lives till this day :)

@agungrbudiman
Copy link
Owner

I've created alpha branch, you can open a PR there. Yeah this project also my bridge to learning swift because I'm using mac and android, there is no other apps that could sync these two devices, especially sync notification. Regarding file sync/sharing I'm using syncthing, maybe you could give it a try. Sadly Soduto isn't get much traction like mentioned here, maybe because majority of mac person are using iPhone. I'm glad there are people still care about this project and continue giedrius-stanevicius work.

@sannidhyaroy
Copy link

sannidhyaroy commented Dec 18, 2022

I thought another approach is to connect share extension and the main app just like Soduto Browser

@agungrbudiman Hey, just curious, do you know how the Soduto Browser interacts with the main app, despite being a different target build? Like, does it use XPC or User Defaults or something else?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants