Skip to content

Commit 7a0d0df

Browse files
committed
Add UserActivityModifier
1 parent 99614ef commit 7a0d0df

File tree

2 files changed

+77
-7
lines changed

2 files changed

+77
-7
lines changed

Sources/OpenSwiftUI/App/Scene/SceneBridge.swift

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// OpenSwiftUI
44
//
55
// Audited for 6.5.4
6-
// Status: Complete - UserActivityModifier WIP
6+
// Status: Complete
77
// ID: A9714FE7FB47B9EE521B92A735A59E38 (SwiftUI)
88

99
#if canImport(Darwin)
@@ -20,11 +20,13 @@ import Combine
2020
@_spi(Private)
2121
import OpenSwiftUICore
2222

23-
// MARK: - UserActivityTrackingInfo
23+
// MARK: - Logging
2424

2525
@available(OpenSwiftUI_v2_0, *)
2626
public var _defaultOpenSwiftUIActivityEnvironmentLoggingEnabled = false
2727

28+
// MARK: - UserActivityTrackingInfo
29+
2830
class UserActivityTrackingInfo: NSObject, NSUserActivityDelegate {
2931
var userActivity: NSUserActivity?
3032
var handlers: [ViewIdentity: (NSUserActivity) -> Bool] = [:]
@@ -488,7 +490,7 @@ private struct SceneBridgeReader<V>: View where V: View {
488490
}
489491
}
490492

491-
// MARK: - UserActivityModifier [WIP]
493+
// MARK: - UserActivityModifier
492494

493495
struct UserActivityModifier: ViewModifier {
494496
let activityType: String
@@ -512,15 +514,72 @@ struct UserActivityModifier: ViewModifier {
512514
}
513515

514516
func body(content: Content) -> some View {
515-
// TODO:
516-
// macOS: ScrapeableAttachmentViewModifier
517-
// iOS: IdentifiedPreferenceTransformModifier
518-
_openSwiftUIUnimplementedFailure()
517+
SceneBridgeReader { bridge in
518+
content
519+
.advertiseUserActivity(activityType, isActive: isActive, sceneBridge: bridge) { activity in
520+
guard isActive else {
521+
if _defaultOpenSwiftUIActivityEnvironmentLoggingEnabled {
522+
Log.log("Skipping inactive advertiseUserActivity handler")
523+
}
524+
return false
525+
}
526+
update(activity)
527+
return true
528+
}
529+
.onReceive(
530+
SceneBridge.sceneBridgePublisher(
531+
UserActivityTrackingInfo?.self,
532+
identifier: "UserActivityTrackingInfo",
533+
sceneBridge: bridge
534+
)
535+
) { output in
536+
guard let output = output as? UserActivityTrackingInfo? else {
537+
return
538+
}
539+
info = output
540+
}
541+
.scrapeableAttachment(scrapeableAttachment)
542+
}
519543
}
520544
}
521545

522546
@available(OpenSwiftUI_v2_0, *)
523547
extension View {
548+
fileprivate func advertiseUserActivity(
549+
_ activityType: String,
550+
isActive: Bool,
551+
sceneBridge: SceneBridge?,
552+
handler: @escaping (NSUserActivity) -> Bool
553+
) -> some View {
554+
transformIdentifiedPreference(SceneBridge.UserActivityPreferenceKey.self) { value, identity in
555+
if _defaultOpenSwiftUIActivityEnvironmentLoggingEnabled {
556+
Log.log(
557+
"TransformIdentifiedPreference closure for UserActivity " +
558+
"called with value \(String(describing: value))"
559+
)
560+
}
561+
guard isActive, let sceneBridge else {
562+
if _defaultOpenSwiftUIActivityEnvironmentLoggingEnabled {
563+
Log.log("TransformIdentifiedPreference closure for UserActivity: inactive, leaving value alone")
564+
}
565+
return
566+
}
567+
var handlers: [ViewIdentity: (NSUserActivity) -> Bool]
568+
if let value, value.activityType == activityType {
569+
handlers = value.handlers
570+
handlers[identity] = handler
571+
} else {
572+
handlers = [identity: handler]
573+
}
574+
value = .init((activityType: activityType, handlers: handlers))
575+
if _defaultOpenSwiftUIActivityEnvironmentLoggingEnabled {
576+
Log.log(
577+
"TransformIdentifiedPreference for UserActivity setting value " +
578+
"to \(String(describing: value))"
579+
)
580+
}
581+
}
582+
}
524583

525584
/// Advertises a user activity type.
526585
///

Sources/OpenSwiftUI/Modifier/ViewModifier/IdentifiedPreference.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,17 @@
99
import OpenAttributeGraphShims
1010
import OpenSwiftUICore
1111

12+
// MARK: - View + transformIdentityPreference
13+
14+
extension View {
15+
func transformIdentifiedPreference<K>(
16+
_ key: K.Type = K.self,
17+
_ callback: @escaping (inout K.Value, ViewIdentity) -> Void
18+
) -> some View where K: PreferenceKey {
19+
modifier(IdentifiedPreferenceTransformModifier<K>(transform: callback))
20+
}
21+
}
22+
1223
// MARK: - IdentifiedPreferenceTransformModifier
1324

1425
struct IdentifiedPreferenceTransformModifier<Key>: ViewModifier, MultiViewModifier, PrimitiveViewModifier where Key: PreferenceKey {

0 commit comments

Comments
 (0)