a33a668286
- 新增 WidgetsMac(macOS app-extension):与 iOS CommilitiaDropWidgets 同源(Widgets/ + Shared + Resources/i18n),macOS 26 原生支持 ControlWidget——控制中心两控件(上传 / 拉取云剪贴板)+ 交互式小组件(通知中心 / 桌面,按钮直跑 AppIntent)。嵌入 CommilitiaDropMac(Contents/PlugIns) - ClipboardIntents 跨平台:UIPasteboard 读 / 写加 #if os(macOS) NSPasteboard 分支(上传 / 拉取剪贴板 AppIntent,控制中心与小组件按钮共用)。其余控件源(ClipboardControls ControlWidget / CloudClipboardWidget 交互小组件 / ClipboardClient REST + App Group / WidgetFeedback 本地通知)本就 WidgetKit/AppIntents/Foundation 跨平台,无改 - App Group(读主 app 代铸的 widget_session)仅 Release 挂 Support/macOS/WidgetsMac.entitlements(macOS App Group 属受限能力须 provisioning profile,Phase 6 Developer ID 签名再挂);Debug/ad-hoc 无 App Group——控件 / 小组件编过 + 嵌入 + ad-hoc 签过,但读不到共享会话、呈占位。运行期功能待 Phase 6(App Group Release 挂 app + 扩展 + 签名) - 控件 / 小组件 kind 已在 Phase 1 去缩写为 net.commilitia.Commilitia-Drop.control.*/.widget.clipboard - 验证:just mac-build(CommilitiaDropMac.app + WidgetsMac.appex 嵌入、ad-hoc 签过)+ iOS 模拟器(CommilitiaDrop.app)均 BUILD SUCCEEDED
84 lines
2.7 KiB
Swift
84 lines
2.7 KiB
Swift
import AppIntents
|
||
#if canImport(UIKit)
|
||
import UIKit
|
||
#elseif canImport(AppKit)
|
||
import AppKit
|
||
#endif
|
||
|
||
// 「上传剪贴板」动作:读本机剪贴板文本,经控件专用会话推到云剪贴板。控制中心控件与主屏小组件按钮
|
||
// 共用此 intent。App 外触发时经 WidgetFeedback 弹本地通知反馈成功 / 失败(#6)。
|
||
struct UploadClipboardIntent: AppIntent
|
||
{
|
||
static var title: LocalizedStringResource = "上传剪贴板"
|
||
static var description = IntentDescription("把本机剪贴板内容上传到 Commilitia Drop 云剪贴板")
|
||
|
||
func perform() async throws -> some IntentResult
|
||
{
|
||
#if os(macOS)
|
||
let text = await MainActor.run { NSPasteboard.general.string(forType: .string) ?? "" }
|
||
#else
|
||
let text = await MainActor.run { UIPasteboard.general.string ?? "" }
|
||
#endif
|
||
guard !text.isEmpty else
|
||
{
|
||
await WidgetFeedback.post(t("ios.clipboard.empty"))
|
||
return .result()
|
||
}
|
||
do
|
||
{
|
||
try await ClipboardClient.upload(text)
|
||
await WidgetFeedback.post(t("ios.clipboard.uploaded"))
|
||
}
|
||
catch ClipboardClient.ClientError.noSession
|
||
{
|
||
await WidgetFeedback.post(t("ios.widget.needApp"))
|
||
}
|
||
catch
|
||
{
|
||
await WidgetFeedback.post(t("ios.clipboard.failed"))
|
||
}
|
||
return .result()
|
||
}
|
||
}
|
||
|
||
// 「拉取剪贴板」动作:拉云剪贴板内容写入本机剪贴板。同上,App 外触发弹本地通知反馈。
|
||
struct PullClipboardIntent: AppIntent
|
||
{
|
||
static var title: LocalizedStringResource = "拉取剪贴板"
|
||
static var description = IntentDescription("把 Commilitia Drop 云剪贴板内容写入本机剪贴板")
|
||
|
||
func perform() async throws -> some IntentResult
|
||
{
|
||
do
|
||
{
|
||
let text = try await ClipboardClient.pull()
|
||
if text.isEmpty
|
||
{
|
||
await WidgetFeedback.post(t("ios.clipboard.empty"))
|
||
}
|
||
else
|
||
{
|
||
#if os(macOS)
|
||
await MainActor.run
|
||
{
|
||
NSPasteboard.general.clearContents()
|
||
NSPasteboard.general.setString(text, forType: .string)
|
||
}
|
||
#else
|
||
await MainActor.run { UIPasteboard.general.string = text }
|
||
#endif
|
||
await WidgetFeedback.post(t("ios.clipboard.pulled"))
|
||
}
|
||
}
|
||
catch ClipboardClient.ClientError.noSession
|
||
{
|
||
await WidgetFeedback.post(t("ios.widget.needApp"))
|
||
}
|
||
catch
|
||
{
|
||
await WidgetFeedback.post(t("ios.clipboard.failed"))
|
||
}
|
||
return .result()
|
||
}
|
||
}
|