I want to add my electron app to mac's ,share menu extension when any folder is clicked

huangapple go评论59阅读模式
英文:

I want to add my electron app to mac's ,share menu extension when any folder is clicked

问题

"mac": {
    "icon": "static/xxx.png",
    "category": "public.app-category.utilities",
    "target": "dmg",
    "hardenedRuntime": true,
    "gatekeeperAssess": true,
    "extendInfo": {
        "NSAppleEventsUsageDescription": "让我使用苹果事件。",
        "NSCameraUsageDescription": "让我使用相机。",
        "NSScreenCaptureDescription": "让我截屏。",
        "NSServices": [
            {
                "NSMenuItem": {
                    "default": "与我的应用共享"
                },
                "NSMessage": "shareWithMyApp:",
                "NSSendTypes": [
                    "NSStringPboardType"
                ],
                "NSReturnTypes": [
                    "NSStringPboardType"
                ]
            }
        ]
    }
}
英文:

enter image description here shown code is piece of build.config.json file , I tried to rebuild it using chat gpt's idea but I don't think it is practical solution, is it how it is done ? or is there any way to add my app to share menu extension , can anyone has reference to how i can solve my problem. thank you in advance

"mac": {
		"icon": "static/xxx.png", 
		"category": "public.app-category.utilities",
		"target": "dmg",
		"hardenedRuntime": true,
		"gatekeeperAssess": true,
		"extendInfo": {
		  "NSAppleEventsUsageDescription": "Let me use Apple Events.",
		  "NSCameraUsageDescription": "Let me use the camera.",
		  "NSScreenCaptureDescription": "Let me take screenshots.",
		  "NSServices": [
          {
            "NSMenuItem": {
              "default": "Share with My App"
            },
            "NSMessage": "shareWithMyApp:",
            "NSSendTypes": [
              "NSStringPboardType"
            ],
            "NSReturnTypes": [
              "NSStringPboardType"
            ]
          }
        ]
		}
	  }

答案1

得分: 0

你需要做的是编写一个**共享扩展**并将其包含在您的捆绑应用程序中。根据我的经验(可能不是最佳方法),我在xCode中构建了一个简化的共享扩展,然后将生成的“.appex”包含在我的构建应用程序中。我仍在努力解决我的尝试中的一些小问题,这绝对比仅仅向Info.plist添加一些值要复杂得多。

您需要能够使用Swift或Obj-C编写一些代码,并且正确的设计是让用户验证所选文件,然后在扩展中“分享它们”,最好是独立于父应用程序。

我相信在iOS版本的共享扩展中,扩展受到严格的沙盒限制,只能访问某些共享资源。您应该能够访问共享的密钥链资源和应用程序组文件。

接下来是我在MacOS上包含共享扩展的不太正规的方法。我知道其他人也这样做了,但这是我通过试验想出来的方法。

我发现我可以共享文件到一个应用程序组文件夹,扩展和父应用程序都可以访问。与iOS不同,MacOS允许子应用程序启动父应用程序,尽管没有参数。有了这些资源,我使用xCode提供的模板编写了一个最小的共享扩展。

我的扩展会关闭共享对话框,就像用户按下发送按钮一样,并将接收到的URL写入应用程序组文件夹中的文件中。我相信这不会被允许出现在App Store中,因为他们会强制执行某些模式。

我的扩展只是将URL写入以UUIDv1值命名的文件中,这样我可以按接收顺序保留它们。在我将这些文件写出之后,我启动我的应用程序,它会在launchsecond-instance时查找相同的文件,并使用我已经编写好以处理命令行参数的电子代码处理这些文件。

除了编写代码,您还需要编写Info.plist值,以帮助操作系统管理您的扩展。这是我的扩展Info.plist中的相关部分。

<key>NSExtension</key>
<dict>
    <key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsAttachmentsWithMinCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsText</key>
            <false/>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>0</integer>
        </dict>
    </dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.share-services</string>
    <key>NSExtensionPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
</dict>

扩展还应该有一个包标识符,表示它与您的父应用程序有关

您还可能想要在xCode中配置扩展的名称和图标,以使其在菜单中显示所需的样式。

一旦xCode项目构建完成,我将生成的“.appex”复制到我的电子项目中(在这种情况下,路径为includes/mac/universal/PlugIns/Share.appex),并将其作为我的electron-builder mac构建配置的一部分。在我的electron-builder.json中,相关条目如下所示。

{
  ...
  "mac": {
    ...
    "extraFiles": [
      {
        "from": "./includes/${os}/universal/PlugIns",
        "to": "PlugIns"
      }
    ]
  }
}

目前,我仍在努力解决一些小问题,阻止我的扩展在系统上自动启用。

  1. 在扩展被操作系统识别之前,必须先运行构建的应用程序。
  2. 第一次使其工作时,需要在“系统偏好设置 > 扩展 > 已添加的扩展”和“系统偏好设置 > 扩展 > 共享菜单”中启用它。之后,系统会记住这些设置。
  3. 尽管其他应用程序在执行此操作后在其菜单中有扩展,但我必须重新启动Finder(重新启动或注销/登录)才能在Finder菜单中看到它。

关于您有关专门定位文件夹的问题,我没有答案。苹果文档中的此页面描述了配置激活规则,尽管我没有看到任何有助的信息。您可以在从菜单中选择应用程序后进行过滤,但它仍然会出现在非文件夹对象的菜单中。

希望这些信息对您或其他人有所帮助。黄色框告诉我不要这样做,但如果有人愿意教我们更好、不那么“hacky”的方法来实现电子应用程序的共享扩展,我将非常有兴趣听听。

英文:

What you need to do is write a Share Extension and include it in your bundled app. In my experience (which may not be the best way to do it) I built a minimal Share extension in xCode and the I included the generated ".appex" package in my built app. I'm still trying to work out the quirks on my attempt, and it's definitely a much more involved process than just adding some values to the Info.plist.

You'll need to be able to write some code in Swift or Obj-C and the proper design is to have the user validate the selected files and then "share them" with a cloud service in the extension, preferably, independent of the the parent app.

I believe in the iOS version of share extensions the extension is heavily sandboxed with only certain shared resources being available. You should be able to access shared keychain resources and application group files.

What follows is my dirty method of including a share extension in and electron project on MacOS. I know others have done it, but this is what I figured out by hacking away at the idea.

I've found that I can share files to an application group folder reachable by both the extension and the parent app. Unlike iOS, MacOS allows the child app to launch the parent app, although with no arguments. Having these resources available, I wrote a minimal share extension using the template provided by xCode.

My extension closes the share dialog as if the user had pressed the send button and writes the received URLs out to files in the application group folder. I believe that this will not be allowed in the App Store, as they'll enforce certain patterns.

My extension simply writes the URLS into files named with UUIDv1 values, allowing me to keep them in the order they were received. After I write those files out, I launch my app which looks for those same files (on launch or second-instance) and processes the files using my electron code which I've already written to handle command line arguments.

In addition to writing the code, you'll need to write Info.plist values which help the OS manage your extension. This is the relevant portion in my extensions Info.plist.

&lt;key&gt;NSExtension&lt;/key&gt;
&lt;dict&gt;
	&lt;key&gt;NSExtensionAttributes&lt;/key&gt;
	&lt;dict&gt;
		&lt;key&gt;NSExtensionActivationRule&lt;/key&gt;
		&lt;dict&gt;
			&lt;key&gt;NSExtensionActivationSupportsAttachmentsWithMinCount&lt;/key&gt;
			&lt;integer&gt;1&lt;/integer&gt;
			&lt;key&gt;NSExtensionActivationSupportsText&lt;/key&gt;
			&lt;false/&gt;
			&lt;key&gt;NSExtensionActivationSupportsWebURLWithMaxCount&lt;/key&gt;
			&lt;integer&gt;0&lt;/integer&gt;
		&lt;/dict&gt;
	&lt;/dict&gt;
	&lt;key&gt;NSExtensionPointIdentifier&lt;/key&gt;
	&lt;string&gt;com.apple.share-services&lt;/string&gt;
	&lt;key&gt;NSExtensionPrincipalClass&lt;/key&gt;
	&lt;string&gt;$(PRODUCT_MODULE_NAME).ShareViewController&lt;/string&gt;
&lt;/dict&gt;

The extension should also have a bundle identifier signifying it's a relation to your parent app.

You'll also likely want to configure the name and icon for your extension in xCode so that it appears as desired in the menu.

Once the xCode project is built, I copy the generated ".appex" into my electron project (in this case, at the path includes/mac/universal/PlugIns/Share.appex and it's part of my electron-builder mac build configuration. In my electron-builder.json, the relevant entries looks like this.

{
  ...
  &quot;mac&quot;: {
    ...
    &quot;extraFiles&quot;: [
      {
        &quot;from&quot;: &quot;./includes/${os}/universal/PlugIns&quot;,
        &quot;to&quot;: &quot;PlugIns&quot;
      }
    ]
  }
}

At the moment, I'm still trying to get past a few quirky things that prevent my extension from being automatically enabled on the system.

  1. The built app has to be run before the extension is recognized by the operating system.
  2. The first time I got it to work, it needed to be enabled in System Preferences &gt; Extensions &gt; Added Extensions and System Preferences &gt; Extensions &gt; Share Menu. After the first time, these were remembered by the system.
  3. While other applications have the extension in their menus after doing this, I had to restart Finder (restart or log out/in) to have it show up in the finder menu.

In regards to your question about specifically targeting folders, I don't have an answer. This page in apple's documentation describes configuring the activation rules, although I don't see anything that would help. You could filter after your app is selected from the menu, but it would still appear in the menu for non-folder objects.

I hope this made sense and helps you or someone in some way. The yellow box tells me not to do this, but if someone would be nice enough to teach us a better, less hacky method of implementing a share extension for an Electron app, I would be very interested in hearing all about it.

huangapple
  • 本文由 发表于 2023年6月5日 17:09:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76404963.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定