Migration Guide: 2.x → 3.x
Migrate from deprecated Flows & Views APIs to the new Components API, and from OWTheme to the new elements customization system
Version 3.0.0 introduces:
OWUIComponents— a unified API that replaces bothOWUIFlowsandOWUIViewsOWCustomizationElements— granular element customization that replacesOWThemeandOWCommentActionsCustomizations- SwiftUI Views —
OpenWebPreConversation,OpenWebConversation,OpenWebConversationCount
SwiftUI Views (Recommended)
Version 3.0.0 adds native SwiftUI Views: OpenWebPreConversation, OpenWebConversation, and OpenWebConversationCount. If your app uses SwiftUI, this is the simplest migration path — especially if you were using OWUIViews to embed views in SwiftUI.
import OpenWebSDK
struct ArticleView: View {
var body: some View {
ScrollView {
articleContent
OpenWebPreConversation(postId: "my-post-id")
.conversationNavigation(.fullScreen)
}
}
}For full documentation, see SwiftUI Views.
UIKit: Accessing the New Components API
// Before
let flows: OWUIFlows = OpenWeb.manager.ui.flows
let views: OWUIViews = OpenWeb.manager.ui.views
// After
let components: OWUIComponents = OpenWeb.manager.ui.componentsUIKit Flows → Components
Quick Reference
| Before (Deprecated) | After (OWUIComponents) |
|---|---|
flows.preConversation( | components.getPreConversation( |
flows.conversation( | components.openConversation(…) |
flows.conversation( | components.getConversation(…) |
flows.commentCreation(…) | components.openConversation( |
flows.commentThread(…) | components.openConversation( |
PreConversation Flow
The presentationalMode parameter is replaced by conversationNavigation, which does not require a view controller reference — the SDK resolves it internally.
let flows = OpenWeb.manager.ui.flows
let view = try await flows.preConversation(
postId: "somePostId",
article: article,
presentationalMode: .present(viewController: self, style: .fullScreen)
)
// Add view as subviewlet components = OpenWeb.manager.ui.components
let view = try await components.getPreConversation(
postId: "somePostId",
article: article,
conversationNavigation: .fullScreen
)
// Add view as subviewNavigation Mode Mapping
Before (OWPresentationalMode) | After (OWConversationNavigationMode) |
|---|---|
.present(viewController: vc, style: .fullScreen) | .fullScreen |
.present(viewController: vc, style: .pageSheet) | .sheet |
.push(navigationController: navController) | .push |
Full Conversation Flow (Full Screen)
let flows = OpenWeb.manager.ui.flows
try await flows.conversation(
postId: "somePostId",
article: article,
presentationalMode: .present(viewController: self, style: .fullScreen)
)let components = OpenWeb.manager.ui.components
try await components.openConversation(
postId: "somePostId",
article: article,
presentationalMode: .present(viewController: self, style: .fullScreen)
)Full Conversation Flow (Partial Screen)
let flows = OpenWeb.manager.ui.flows
let conversationVC = try await flows.conversation(
postId: "somePostId",
article: article
)let components = OpenWeb.manager.ui.components
let conversationVC = try await components.getConversation(
postId: "somePostId",
article: article
)Comment Creation Flow
let flows = OpenWeb.manager.ui.flows
try await flows.commentCreation(
postId: "somePostId",
article: article,
presentationalMode: .present(viewController: self, style: .pageSheet)
)let components = OpenWeb.manager.ui.components
try await components.openConversation(
postId: "somePostId",
article: article,
route: .commentCreation(type: .comment),
presentationalMode: .present(viewController: self, style: .pageSheet)
)Comment Thread Flow
let flows = OpenWeb.manager.ui.flows
try await flows.commentThread(
postId: "somePostId",
article: article,
commentId: "someCommentId",
presentationalMode: .push(navigationController: navController)
)let components = OpenWeb.manager.ui.components
try await components.openConversation(
postId: "somePostId",
article: article,
route: .commentThread(commentId: "someCommentId"),
presentationalMode: .push(navigationController: navController)
)UIKit Views → Components
SwiftUI appsIf you were using
OWUIViewsto embed views in SwiftUI, consider migrating directly to the new SwiftUI Views (OpenWebPreConversation,OpenWebConversation) instead of going throughOWUIComponents.
These migrations are not simple renames. Key differences:
getConversation()returns aUIViewController, not aUIView. Embed it as a child view controller.OWViewActionsCallbacksis removed — the SDK handles navigation internally. If you do need callbacks, useOWActionsCallbacks.views.reportReason(),views.clarityDetails(),views.webTab(),views.commenterAppeal(), andviews.notifications()no longer need to be called — the SDK handles them internally.
Quick Reference
| Before (Deprecated) | After (OWUIComponents) |
|---|---|
views.preConversation(…, | components.getPreConversation(…, |
views.preConversation(…, | components.getPreConversation(…, |
views.conversation(…) | components.getConversation(…) |
views.commentCreation(…) | components.getConversation(…, |
views.commentThread(…) | components.getConversation(…, |
views.reportReason(…) | (removed — handled internally by the SDK) |
PreConversation View with Custom Navigation
let views = OpenWeb.manager.ui.views
let view = try await views.preConversation(
postId: "somePostId",
article: article,
additionalSettings: additionalSettings,
callbacks: { callbackType, postId in
switch callbackType {
case .openConversationFlow(let route):
// Navigate to the full conversation manually
}
}
)
// Add view as subviewlet components = OpenWeb.manager.ui.components
let view = try await components.getPreConversation(
postId: "somePostId",
article: article,
conversationNavigation: .custom(callbacks: { callbackType, postId in
switch callbackType {
case .openConversationFlow(let route):
// Navigate to the full conversation manually
}
}),
additionalSettings: additionalSettings
)
// Add view as subviewConversation View (Embedding Change)
The old API returned a UIView you could add as a subview. The new API returns a UIViewController that must be embedded as a child view controller.
let views = OpenWeb.manager.ui.views
let conversationView = try await views.conversation(
postId: "somePostId",
article: article,
additionalSettings: additionalSettings,
callbacks: viewActionsCallbacks
)
// Add as subview
containerView.addSubview(conversationView)let components = OpenWeb.manager.ui.components
let conversationVC = try await components.getConversation(
postId: "somePostId",
article: article,
additionalSettings: additionalSettings,
callbacks: actionsCallbacks
)
// Embed as child view controller
addChild(conversationVC)
containerView.addSubview(conversationVC.view)
conversationVC.didMove(toParent: self)Comment Creation / Thread Views
Same pattern — replace views.commentCreation(…) and views.commentThread(…) with getConversation(route:…) and embed the returned view controller.
let conversationVC = try await components.getConversation(
postId: "somePostId",
article: article,
route: .commentCreation(type: .comment)
)
// Embed as child view controllerlet conversationVC = try await components.getConversation(
postId: "somePostId",
article: article,
route: .commentThread(commentId: "someCommentId")
)
// Embed as child view controllerCallbacks
OWFlowActionsCallbacks → OWActionsCallbacks
OWFlowActionsCallbacks is now a typealias for OWActionsCallbacks. Your existing code compiles without changes.
public typealias OWActionsCallbacks = (OWActionCallbackType, OWViewSourceType, OWPostId) -> Void
public typealias OWFlowActionsCallbacks = OWActionsCallbacksSimilarly, OWFlowActionCallbackType is a typealias for OWActionCallbackType:
public enum OWActionCallbackType {
case openPublisherProfile(ssoPublisherId: String, type: OWUserProfileType, presentationalMode: OWPresentationalMode)
case conversationDismissed
}OWViewActionsCallbacks — Removed
OWViewActionsCallbacks and its fine-grained OWViewActionCallbackType cases (.articleHeaderPressed, .closeConversationPressed, .communityGuidelinesPressed(url:), .openReportReason(…), etc.) have no direct replacement in OWUIComponents.
Use OWActionsCallbacks for the supported events (.openPublisherProfile, .conversationDismissed), and .custom(callbacks:) on OWConversationNavigationMode for pre-conversation navigation events.
OWConversationNavigationMode
New enum that replaces OWPresentationalMode in the pre-conversation context. The SDK resolves the parent view controller internally — you only specify the presentation style.
public enum OWConversationNavigationMode {
case present(OWModalPresentationStyle)
case push
case custom(callbacks: OWPreConversationActionsCallbacks)
public static let fullScreen = OWConversationNavigationMode.present(.fullScreen)
public static let sheet = OWConversationNavigationMode.present(.pageSheet)
}Customizations: OWTheme → elements
OWTheme is deprecated. Use OWCustomizationElements via OpenWeb.manager.ui.customizations.elements.
Property Mapping
Deprecated OWTheme property | Replacement |
|---|---|
skeletonColor | customizations.elements.skeletonGradientEdge.color |
skeletonShimmeringColor | customizations.elements.skeletonGradientCenter.color |
primarySeparatorColor | customizations.elements.sectionDivider.color |
secondarySeparatorColor | customizations.elements.contentDivider.color |
tertiarySeparatorColor | customizations.elements.divider.color |
primaryTextColor | customizations.elements.commentBody.color |
secondaryTextColor | customizations.elements.subtitle.color |
tertiaryTextColor | customizations.elements.detail.color |
primaryBackgroundColor | customizations.elements.background.color |
secondaryBackgroundColor | customizations.elements.overlayBackground.color |
tertiaryBackgroundColor | customizations.elements.cardBackground.color |
surfaceColor | (removed, no replacement) |
primaryBorderColor | customizations.elements.border.color |
secondaryBorderColor | (removed, no replacement) |
loaderColor | customizations.elements.loader.color |
brandColor | customizations.elements.brand.color |
voteUpUnselectedColor | customizations.elements.voteUpUnselected.color |
voteDownUnselectedColor | customizations.elements.voteDownUnselected.color |
voteUpSelectedColor | customizations.elements.voteUpSelected.color |
voteDownSelectedColor | customizations.elements.voteDownSelected.color |
Example
let customizations = OpenWeb.manager.ui.customizations
customizations.customizedTheme.primaryTextColor = OWColor(lightColor: .black, darkColor: .white)
customizations.customizedTheme.brandColor = OWColor(lightColor: .systemBlue, darkColor: .systemCyan)let customizations = OpenWeb.manager.ui.customizations
customizations.elements.commentBody.color = UIColor(lightColor: .black, darkColor: .white)
customizations.elements.brand.color = UIColor(lightColor: .systemBlue, darkColor: .systemCyan)Customizations: OWCommentActionsCustomizations → elements
| Deprecated | Replacement |
|---|---|
customizations.commentActions.fontStyle | customizations.elements.commentActions.fontWeight |
customizations.commentActions.color | customizations.elements.commentActions.color |
OWCommentActionsFontStyle → UIFont.Weight
fontStyle took an OWCommentActionsFontStyle enum. fontWeight takes UIFont.Weight?:
OWCommentActionsFontStyle | UIFont.Weight? |
|---|---|
.regular | nil (default) |
.semiBold | .semibold |
OWCommentActionsColor → UIColor?
color took an OWCommentActionsColor enum. The new color property takes UIColor?:
OWCommentActionsColor | UIColor? |
|---|---|
.default | nil (default) |
.brandColor | Assign the same color you set on elements.brand.color |
OWColor
OWColor is now a typealias for UIColor. Code using OWColor(lightColor:darkColor:) continues to work — UIColor has the same convenience initializer.
// Both work identically
OWColor(lightColor: .black, darkColor: .white)
UIColor(lightColor: .black, darkColor: .white)Updated 7 days ago
