Skip to content

v4.0.0

Latest

Choose a tag to compare

@zeyadsadaqa zeyadsadaqa released this 05 Oct 09:50

v4.0.0

Hub-configured layouts come to Android: a single composable, GetAppearanceView, renders a whole collection of shoppable videos as a grid, row, story or floating button using the appearance you configure in Bam Hub, with paging, autoplay, fullscreen and product hydration handled by the SDK.

This is a major release because of one breaking change: videoScaleMode is now nullable and no longer defaults to FIT. Most integrations need no code changes; see the migration note below to be sure.

Upgrade

// gradle/libs.versions.toml
bambuserCommerceSDK = "4.0.0"
implementation("com.bambuser:commerce-sdk:4.0.0")

⚠️ Breaking change

videoScaleMode on BambuserVideoConfiguration is now BambuserVideoScaleMode? and defaults to null (previously FIT).

  • A value you set always wins, exactly as before.
  • When left null, the video follows the scale mode requested by the player's own resize events, falling back to FIT until the first one arrives. This lets a player switch between fit and fill as it moves between its preview and full UI.

Do I need to change anything?

Your code today Action
Passes videoScaleMode = FIT or FILL explicitly Nothing. Behavior is unchanged.
Omits videoScaleMode and wants the player to decide Nothing. This is the new default.
Omits videoScaleMode and relies on always-letterboxed video Pass videoScaleMode = BambuserVideoScaleMode.FIT explicitly.
Reads configuration.videoScaleMode as non-null, e.g. an exhaustive when Add a null branch.

✨ New

Appearance view

BambuserSDK.GetAppearanceView renders a collection of shoppable videos with the appearance configured in Bam Hub. The SDK fetches the collection, picks the layout from the appearance's mode (grid, row, story or fab), applies its sizing, spacing, autoplay and tap behavior, and loads further pages as the user scrolls.

val appearanceState = rememberBambuserAppearanceViewState()

bambuserSdk.GetAppearanceView(
    videoConfiguration = BambuserVideoConfiguration(
        videoType = BambuserCollectionInfo.Playlist(
            orgId = "<orgId>",
            componentId = "<placement id from Bam Hub>",
        ),
        configuration = mapOf(
            "playerConfig" to mapOf(
                "softLimit" to "6",   // appearance override, same keys as the hub
                "currency" to "USD",  // anything else goes to the web player as-is
            ),
            "thumbnail" to mapOf("showPlayButton" to false), // optional
            "preload" to true,                               // optional, the default
        ),
        events = listOf("*"),
        videoScaleMode = BambuserVideoScaleMode.FILL,        // optional, applies to every player
    ),
    pageSize = 15,
    state = appearanceState,
    appearanceDelegate = object : BambuserAppearanceViewDelegate {
        override fun onPlayerSelected(item: BambuserAppearanceItem) { /* ... */ }
    },
    videoPlayerDelegate = myPlayerDelegate,  // per-player events, same delegate as a single video
    modifier = Modifier.fillMaxWidth(),
)

What to render. videoType must be a BambuserCollectionInfo, otherwise the composable throws IllegalArgumentException:

  • Playlist(orgId, componentId) renders a placement with the appearance configured for it in Bam Hub.
  • SKU(orgId, sku) and GroupId(orgId, groupId) render the videos attached to a product or a product group.

Overriding the appearance. configuration["playerConfig"] accepts the keys the hub uses (mode, focusMode, autoplay, cornerRadius, playerWidth, playlistGap, softLimit, ...). Precedence, lowest first: the collection's player config, the default appearance, the app appearance, then your map. Null and blank values are ignored. Entries that are not appearance keys, such as currency, locale or buttons, are forwarded unchanged to every player's web configuration. Any other top-level key in configuration is copied into every player as well.

Every player, one config. events and videoScaleMode apply to every player in the collection, inline and fullscreen. configuration["thumbnail"] tunes every preview thumbnail with the keys a single shoppable player accepts (enabled, showPlayButton, showLoadingIndicator, preview, contentMode). configuration["preload"] (default true) controls whether players boot the web player behind their thumbnail; set it to false on long collections to defer loading until a player is tapped or played.

Observing the collection. rememberBambuserAppearanceViewState() returns a BambuserAppearanceViewState the SDK keeps up to date as Compose state: the resolved mode (BambuserAppearanceMode.GRID, ROW, STORY, FAB or UNKNOWN), the loaded videoIds, and the current pagination. Use it to size or decorate the container per layout.

Collection-level callbacks. BambuserAppearanceViewDelegate has eight methods, all with empty defaults, all on the main thread:

override fun onWillLoadPage(page: Int) {}
override fun onPageLoaded(page: Int, totalPages: Int?) {}
override fun onPageFailedToLoad(page: Int, error: Exception) {}
override fun onPlayerSelected(item: BambuserAppearanceItem) {}
override fun onEnterFullscreen(item: BambuserAppearanceItem) {}
override fun onExitFullscreen(item: BambuserAppearanceItem) {}
override fun onCurrentChanged(item: BambuserAppearanceItem) {}
override fun onDismiss() {}

Item callbacks carry a BambuserAppearanceItem with the video's index, its playerId and its VideoMetadata. Per-player events still arrive through the BambuserVideoPlayerDelegate you pass to the same composable, so product hydration works exactly as it does for a single shoppable video.

Lifecycle. The collection lives as long as the composable is in the composition. Leaving the composition cancels any fetch in flight and releases the players; there is nothing to clean up.

Note on the FAB layout: the floating button behaves and looks different from the other layouts. Create a separate appearance in Bam Hub for it, on its own placement, instead of reusing the one for grid, row or story.

Supporting API

  • BambuserCollectionInfo now implements BambuserVideoType, so a Playlist, SKU or GroupId can be the videoType of a BambuserVideoConfiguration.
  • New public types: BambuserAppearanceViewDelegate, BambuserAppearanceViewState, rememberBambuserAppearanceViewState(), BambuserAppearanceMode, BambuserAppearancePagination and BambuserAppearanceItem.

🐛 Fixed

  • Resize events from the web player that carry no dimensions are now ignored. They are sent while the player switches between its preview and full UI and previously collapsed the video view for a moment, which showed as a flash when a player expanded to fullscreen.

Requirements

Unchanged: minSdk 26, compileSdk 36, Compose BOM 2025.02.00.

Full changelog: v3.7.0...v4.0.0