Page MenuHomePhabricator

[Spike] Investigate implementation of breadcrumbs on iOS
Open, LowPublic

Description

We want to leverage a breadcrumbs-like style of events to be able to capture component interactions and screen hierarchy (referred to in SwiftUI as a navigation stack).

Notes below captured from a conversation between @Seddon and @Tsevener (who provided all of the sensible and informed thoughts)

This spike should examine how such events could be brought into the iOS. It needs to account for the apps architecture where app navigation is in UIKit with SwiftUI views wrapped up in UIHostingControllers and are navigated to via UINavigationControllers.

Article: https://medium.com/@uwaisalqadri/swiftui-view-uikit-navigation-74aa22fc0e0

There's just a single type of HostingController, that could be a good way to have a single place for capturing impression events. Currently we spin up a new HostingController type for each feature

Here's some (nonworking) code of all-SwiftUI breadcrumbing, just the first pattern that came to mind:

// Breadcrumb Components
struct BreadcrumbButton: View {
    
    let action: (() -> Void)
    let label: String
    let metricsClickName: String
    let metricsInterfaceName: String
    
    var body: some View {
        Button(action: {
            AppInteractionFunnel.shared.logEvent(name: metricsClickName, interface: metricsInterfaceName)
            action()
        }, label: {
            Text(label)
        })
    }
}

struct BreadcrumbView<Content: View>: View {
    let metricsImpressionName: String
    let metricsInterfaceName: String
    let content: Content
    
    init(metricsImpressionName: String, metricsInterfaceName: String, @ViewBuilder content: () -> Content) {
        self.content = content()
    }
    
    
    var body: some View {
        content
            .onAppear {
                AppInteractionFunnel.shared.logEvent(name: metricsImpressionName, interface: metricsInterfaceName)
            }
    }
}

// Feature-specific View
struct ImageRecommendationChoiceView: View {
    
    let metricsImpressionName: String = "choice_impression"
    let metricsInterfaceName: String = "image_recommendations"
    
    var body: some View {
        BreadcrumbView(metricsImpressionName: metricsImpressionName, metricsInterfaceName: metricsInterfaceName) {
            HStack {
                BreadcrumbButton(action: {
                    // TODO: Navigate elsewhere
                }, label: "Yes", metricsClickName: "click_yes", metricsInterfaceName: metricsInterfaceName)
                
                BreadcrumbButton(action: {
                    // TODO: Navigate elsewhere
                }, label: "No", metricsClickName: "click_no", metricsInterfaceName: metricsInterfaceName)
                
                BreadcrumbButton(action: {
                    // TODO: Navigate elsewhere
                }, label: "Not Sure", metricsClickName: "click_not_sure", metricsInterfaceName: metricsInterfaceName)
            }
        }
    }
}