Skip to content

paramountKit 4.0.33.325

Choose a tag to compare

@lessthan3-private-actions-checkout lessthan3-private-actions-checkout released this 26 Aug 21:36
· 307 commits to main since this release
c74d042

paramountKit

Kotlin Multiplatform framework for the Maestro Paramount SDK — exposes Stats (live MMA/UFC data), Key Plays (Key Moments), and animated Overlays to tvOS and iOS apps via Swift Package Manager.

Installation

Add the distribution repo as a package and link the paramountKit product. Track main — each
publish updates the manifest there to the newest build:

dependencies: [
    .package(url: "https://github.com/lessthan3/MaestroKit.android", branch: "main")
]

In Xcode: File → Add Package Dependencies → paste that url → Dependency Rule "Branch: main" → add
paramountKit to your target. The repo has no semver tags, so a from: / version rule resolves
nothing.

To pin one build instead, point a binaryTarget at that release's asset — its url and checksum are
in the release notes:

.binaryTarget(
    name: "paramountKit",
    url: "https://github.com/lessthan3/MaestroKit.android/releases/download/paramountKit-<version>/paramountKit-<version>.zip",
    checksum: "<checksum from the release notes>"
)

Releases: https://github.com/lessthan3/MaestroKit.android/releases?q=paramountKit

Use one or the other. Two packages declaring the same paramountKit product makes SwiftPM drop one
of them from the graph, which Xcode reports as "unexpectedly did not find the new dependency in the
package graph".

Platforms

  • tvOS 16+
  • iOS 16+

Quick Start

import paramountKit

// 1. Configure the SDK once per session.
let instance = ParamountMaestroSDK.shared.configure(
    context: PlatformContext(),
    delegate: MyParamountDelegate(),
    params: ParamountSDKParameters(
        siteId: "your-site-id",
        pageId: nil,
        metadataValue: "event-metadata-value",
        appPackageVersion: "1.0.0",
        isProduction: true,
        userAgent: "ATV"
    ),
    buildConfigInfo: ParamountBuildConfigInfo(
        versionName: "1.0.0",
        isDebug: false
    )
)

// 2. Observe available panels (Stats, Key Plays, Builder) from the config.
Task {
    for await panels in instance.repo.enabledPanels {
        print("Panels: \((panels as? [SharedPanelData])?.map { $0.name } ?? [])")
    }
}

// 3. Tell the SDK which panel is currently shown (for analytics + gating).
instance.didShowPanel(panelTypeId: ParamountPanelTypes.shared.STATS)

// 4. Detach when done.
instance.detach()

Delegate

ParamountEventDelegate is how the SDK talks back to the host app:

class MyParamountDelegate: ParamountEventDelegate {
    func shouldShowPanel() { /* host should surface the panel UI */ }
    func shouldHidePanel() { /* host should hide it */ }
    func trackAction(analytics: [String: String]) { /* forward to your analytics */ }
    func trackImpression(analytics: [String: String]) { /* forward to your analytics */ }
    func onKeyMomentSelected(contentId: String) { /* play the clip */ }
}

Features

Stats panel (MMA/UFC)

Fetches live fight data from the Helios supergraph, polls every 10s, retries with backoff.

let stats = instance.createStatsPresenter()
stats.start()

Task {
    for await state in stats.state {
        switch onEnum(of: state) {
        case .loading:
            print("Loading fights…")
        case .error(let e):
            print("Error: \(e.message)")
        case .success(let s):
            let event = s.event
            print("\(event.name) at \(event.venue)")
            for fight in event.fights {
                print("  \(fight.redFighter.lastName) vs \(fight.blueFighter.lastName)")
            }
        }
    }
}

stats.destroy()

Key Plays panel (Key Moments)

Host app pushes key-moment data into the SDK; the presenter handles sort order + playback progress.

let keyPlays = instance.createKeyPlaysPresenter()
keyPlays.start()

// Push moments from your backend.
instance.updateKeyMomentsData(data: [
    ParamountKeyMoment(contentId: "clip-1", title: "Round 1 KO", ...)
])

// Update playback progress as the user watches.
instance.updateKeyMomentsProgress(contentId: "clip-1", progress: 0.42)

// Change sort order.
instance.setKeyMomentsSortOrder(sortOrder: KeyMomentsSortOrder.newestFirst)

Task {
    for await state in keyPlays.state {
        print("\(state.moments.count) moments, active=\(state.activeContentId ?? "none")")
    }
}

keyPlays.destroy()

Animated Overlays

Rive-based broadcast overlays driven by the SDK's overlay queue.

let overlays = instance.createOverlayPresenter()
overlays.start()

Task {
    for await event in overlays.events {
        // event carries the Rive file URL + duration.
    }
}

overlays.destroy()

Type mapping

Kotlin Swift
StateFlow<T> AsyncSequence — consume with for await
sealed interface / sealed class Use switch onEnum(of:) for exhaustive matching
data object Foo FooType.shared singleton
List<T> Array<T>
Long Int64

Sealed state pattern

switch onEnum(of: state) {
case .loading:
    ProgressView()
case .error(let e):
    Text(e.message)
case .success(let s):
    ContentView(event: s.event)
}

Working example

A complete SwiftUI demo lives in demos/demo-tvos-paramount/ in this repo. It wires up Stats, Key Plays, Overlays, and the panel-visibility bridge.

License

Copyright (c) LessThan3


Installation

.binaryTarget(
    name: "paramountKit",
    url: "https://github.com/lessthan3/MaestroKit.android/releases/download/paramountKit-4.0.33.325/paramountKit-4.0.33.325.zip",
    checksum: "4ef9a590f7c5b7bae9b9c8df279018030d0af8bee1031b172af4f7ead3776471"
)