Created
February 12, 2026 07:41
-
-
Save ZiuChen/0eb0fa14e6f6c6414990cfc4b56f3148 to your computer and use it in GitHub Desktop.
AirDrop - uTools: Share specified files, images, or text directly to nearby devices via macOS AirDrop on uTools quickcommand plugin.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "program": "quickcommand", | |
| "features": { | |
| "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAAXNSR0IArs4c6QAAA7BJREFUeF7t278vc1EYB/BvdSDEgMGPhgEdJCQmJj82bST+hRoMYkLSTSJhNBCDGAz+BRM2PyYWA0MTLKRFIhKR+DFQeeRt8l6uOu3T45687/eOnOfccz597nnObe8NAciCR9ECIQIWbfcRSECdHwGVfgQkoFZAGc81kIBKAWU4M5CASgFlODOQgEoBZTgzkIBKAWU4M/BfBSwvL8f29vbH9IaGhvDy8qKcqp1wZzPw9PQUbW1tH7M+Pz9HNBq1I6Ds1UnAzc1NxGIxz9S2trYQj8eV0y19uFOActmenJygvb3dd6ZnZ2fo7Ox06nJ2CnBnZwf9/f0IhWRYX49sNou9vT0MDg6WPpWK7NEJwFzBGBgYMJrG7u6uM4XFCcBcwfgu8z6rSia6UlgCB/QrGEZpCMCFwhIYoGTb/v6+b8GorKxEdXW1x/Hh4QGPj49fbKWw9PX1QbIyiCNQwIqKCt+CMTExgYWFBY9HMpnEysqKr5Fssl9fX4Pwc/NHpcnJSSwuLnpApqamsLS0FAhSvpMGloH5BkVAZZ4Q8A+gFIq6ujpIUaivr0dZWZkv7cHBgefvpoC9vb2+/b29veHm5gZPT0+4vb21WmCsXsLr6+sYGRlBTU1N3pz8vP8zBfyp8t7f32NjYwOJREJ5TXwfbg1wfn4eMzMzRgO3BZg7+ezsLObm5ozGUmgja4By+cg2xeSwDSj7x6qqKpOhFNzGCqDc2z4/PxsPxjagDEQ+TBtfyloBbG5uxsXFhQcwEokgk8kYoZqugd911tTUhHQ67fl3S0sLLi8vjc5fSCMCFqLl05aABPwqwEtYeS9MQAKyCquWVm5jVHwAAQloLMB9oDGVf0MnAbu6utDT0+MZ8eHhIY6Pj42m+99vY4yU8jQioFKQgATUbaSVfmAGKgUJSEBewqoc0N7KqU4OcA0koPJHJQISUJcDXAN1furvA5WnZxEhINdAXQ40NDTg6urK08no6Cju7u50HRtG19bWQh6t+/tobGzE9fW1YQ/mzax8oSoPC8lDji4d8nDnT88TFjNeK4AykKOjI3R3dxczppLHpFIpdHR0lLxf6dAa4NjYGFZXVxEOh60M3LRTef1hfHwca2trpiEFtbMGKKMYHh7G8vIyWltbCxpUqRpL5k1PT0PehrJ1WAXMDVqyUBZ203fhtJOVtU4K1m+8fPMrgFoQl+MJqPx0CEhApYAynBlIQKWAMpwZSEClgDKcGUhApYAynBlIQKWAMpwZSEClgDL8HZ4Zzx+VzykmAAAAAElFTkSuQmCC", | |
| "explain": "Airdrop", | |
| "platform": [ | |
| "darwin" | |
| ], | |
| "mainPush": false, | |
| "cmds": [ | |
| { | |
| "type": "over", | |
| "label": "Airdrop" | |
| }, | |
| { | |
| "type": "img", | |
| "label": "Airdrop" | |
| }, | |
| { | |
| "type": "files", | |
| "label": "Airdrop" | |
| } | |
| ], | |
| "mainHide": true, | |
| "code": "professional_350a013f" | |
| }, | |
| "output": "ignore", | |
| "tags": [ | |
| "实用工具" | |
| ], | |
| "cmd": "const { spawn } = require('child_process')\nconst { writeFile } = require('fs/promises')\nconst { join } = require('path')\nconst { tmpdir } = require('os')\n\n ; (async () => {\n try {\n const args = await toAriDropArgs(quickcommand.enterData)\n\n if (!args || args.length === 0) {\n throw new Error('参数无效')\n }\n\n // 执行 Swift 桥接逻辑\n await callSwiftAirDrop(args)\n } catch (error) {\n console.error('AirDrop 出错:', error)\n utools.showNotification(`AirDrop 出错: ${error.message}`)\n }\n })()\n\n/**\n * 将不同类型的数据转换为可供 Swift 消费的参数\n */\nasync function toAriDropArgs({ type, payload }) {\n try {\n switch (type) {\n case 'files': {\n // payload 为文件对象数组\n return payload.map((f) => f.path)\n }\n\n case 'img': {\n // payload 为 base64,存为临时文件以供 AirDrop 识别为图片\n const tempImgPath = join(tmpdir(), `airdrop_temp_img_${Date.now()}.png`)\n const base64Data = payload.replace(/^data:image\\/\\w+;base64,/, '')\n await writeFile(tempImgPath, base64Data, 'base64')\n return [tempImgPath]\n }\n\n case 'text':\n case 'over':\n case 'regex': {\n // 处理文本或划词\n if (typeof payload === 'string') {\n return [payload]\n }\n }\n\n default: {\n throw new Error('不支持的数据类型')\n }\n }\n } catch (err) {\n console.error('AirDrop 脚本运行报错:', err)\n return []\n }\n}\n\n/**\n * 唤起 Swift 解释器执行 Native 逻辑\n */\nfunction callSwiftAirDrop(args) {\n const swiftCode = `\nimport AppKit\n\n// AirDrop 分享服务的 Delegate\nclass AirDropDelegate: NSObject, NSSharingServiceDelegate {\n var didComplete = false\n \n func sharingService(_ sharingService: NSSharingService, didShareItems items: [Any]) {\n print(\"✅ AirDrop 分享成功\")\n didComplete = true\n NSApp.stop(nil)\n }\n \n func sharingService(_ sharingService: NSSharingService, didFailToShareItems items: [Any], error: Error) {\n print(\"❌ AirDrop 分享失败: \\\\(error.localizedDescription)\")\n didComplete = true\n NSApp.stop(nil)\n }\n \n func sharingService(_ sharingService: NSSharingService, sourceWindowForShareItems items: [Any], \n sharingContentScope: UnsafeMutablePointer<NSSharingService.SharingContentScope>) -> NSWindow? {\n let window = NSWindow(\n contentRect: NSRect(x: 0, y: 0, width: 1, height: 1),\n styleMask: [.closable],\n backing: .buffered,\n defer: false\n )\n window.center()\n window.level = .popUpMenu\n window.makeKeyAndOrderFront(nil)\n return window\n }\n}\n\n// 1. 设置为 accessory 模式以避免在 Dock 显示\nlet app = NSApplication.shared\napp.setActivationPolicy(.accessory)\n\nlet arguments = CommandLine.arguments.dropFirst()\nvar items: [Any] = []\n\n// 2. 解析参数为可分享的项目\nfor arg in arguments {\n if arg.hasPrefix(\"http://\") || arg.hasPrefix(\"https://\") {\n if let url = URL(string: arg) { items.append(url) }\n } else if FileManager.default.fileExists(atPath: (arg as NSString).expandingTildeInPath) {\n items.append(URL(fileURLWithPath: (arg as NSString).expandingTildeInPath))\n } else {\n items.append(arg) // 纯文本\n }\n}\n\nguard !items.isEmpty else {\n print(\"❌ 没有可分享的内容\")\n exit(1)\n}\n\n// 3. 创建 AirDrop 分享服务(关键:直接使用 .sendViaAirDrop 而不是 Picker)\nguard let service = NSSharingService(named: .sendViaAirDrop) else {\n print(\"❌ 无法创建 AirDrop 服务\")\n exit(2)\n}\n\n// 4. 检查是否可以分享\nguard service.canPerform(withItems: items) else {\n print(\"❌ 无法通过 AirDrop 分享这些内容\")\n exit(3)\n}\n\n// 5. 设置 delegate 并执行分享\nlet delegate = AirDropDelegate()\nservice.delegate = delegate\n\n// 6. 激活应用并执行分享\nNSApp.activate(ignoringOtherApps: true)\nservice.perform(withItems: items)\n\n// 7. 运行主循环直到分享完成\napp.run()\n`\n\n return new Promise((resolve, reject) => {\n const child = spawn('swift', ['-', ...args], {\n stdio: ['pipe', 'inherit', 'inherit']\n })\n\n child.stdin.write(swiftCode)\n child.stdin.end()\n\n child.on('exit', (code) => {\n code === 0 ? resolve() : reject(new Error(`Exit code ${code}`))\n })\n })\n}\n", | |
| "scptarg": "", | |
| "charset": { | |
| "scriptCode": "", | |
| "outputCode": "" | |
| }, | |
| "customOptions": { | |
| "bin": "", | |
| "argv": "", | |
| "ext": "" | |
| }, | |
| "cursorPosition": { | |
| "lineNumber": 158, | |
| "column": 1 | |
| }, | |
| "order": 7 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment