# Story Block (Flutter)

{% hint style="danger" %}
For android:

StoryBlock is a heavy object containing multiple instances of the player, Heavy-lifting UI elements, and intensive background tasks, Beware that the recommended number of the StoryBlock being used in a single screen is 1. However, in a wide range of new Android devices, 2 instances might work alright. Any number of StoryBlock above this limitation is not recommended by the Firework team and is not supported.
{% endhint %}

Currently, there are eight source types of the story block:

* Discover
* Channel
* Playlist
* Dynamic Content
* Hashtag Playlist
* SKU
* Single Content

### Integration

<pre class="language-dart"><code class="lang-dart">import 'package:fw_flutter_sdk/fw_flutter_sdk.dart';
import 'package:visibility_detector/visibility_detector.dart';

StoryBlockController? _storyBlockController;

/// discover
StoryBlock(
  height: 400,
  source: StoryBlockSource.discover,
)

/// channel
StoryBlock(
  height: 400,
  source: StoryBlockSource.channel,
  channel: "your encoded channel id",
)

/// playlist
<strong>StoryBlock(
</strong>  height: 400,
  source: StoryBlockSource.playlist,
  channel: "your encoded channel id",
  playlist: "your encoded playlist id",
)

/// dynamic content
StoryBlock(
  height: 400,
  source: StoryBlockSource.dynamicContent,
  dynamicContentParameters: const {
    '&#x3C;cohort key>': ['&#x3C;cohort value1>', '&#x3C;cohort value2>']
  },
)

/// hashtag playlist
StoryBlock(
  height: 400,
  source: StoryBlockSource.hashtagPlaylist,
  channel: "your encoded channel id",
  hashtagFilterExpression: "&#x3C;hashtag filter expression>",
)

/// sku
StoryBlock(
  height: 400,
  source: StoryBlockSource.sku,
  channel: "your encoded channel id",
  productIds: ["prodct_id_1", "prodct_id_2"],
)

/// single content
StoryBlock(
  height: 400,
  source: StoryBlockSource.singleContent,
  contentId: "your encoded video or live stream id"
);
</code></pre>

### Configure corner radius

```dart
StoryBlock(
  height: 400,
  source: StoryBlockSource.discover,
  cornerRadius: 20,
);
```

### Story block loading result callback

`StoryBlock` widget provides `onStoryBlockLoadFinished` property for setting story block loading result callback.

```dart
StoryBlock(
  height: 400,
  source: StoryBlockSource.discover,
);
```

### Empty callback

`StoryBlock` widget provides `onStoryBlockEmpty` property for setting story block empty callback. The callback is triggered when there are no items in the story block. For example, you could hide the widget when the callback is triggered. The callback is triggered in the following scenarios:

1. Load successfully but the back end returns an empty list
2. The load failed and the list is empty

```dart
StoryBlock(
  source: StoryBlock.discover,
  onStoryBlockEmpty: (error) {
    // Hide the widget
  },
);
```

### Play or pause story block programmatically

```dart
StoryBlockController? _storyBlockController;

StoryBlock(
  height: 400,
  source: StoryBlockSource.discover,
  onStoryBlockCreated: (controller) {
    _storyBlockController = controller;
  },
);

// Play story block
_storyBlockController?.play();
// Pause story block
_storyBlockController?.pause();
```

### Open fullscreen story block programmatically (Android)

```dart
StoryBlockController? _storyBlockController;

StoryBlock(
  height: 400,
  source: StoryBlockSource.discover,
  onStoryBlockCreated: (controller) {
    _storyBlockController = controller;
  },
);

// Open fullscreen story block
// Only supported on iOS
_storyBlockController?.openFullscreen();
```

### Enable PiP(Picture in Picture)

#### Set up the iOS project

To enable PiP outside the iOS app, you also need to add "Audio, Airplay, and Picture in Picture" background mode via Signing & Capabilities in your iOS project settings(as shown in the following screenshot). More information about this can be found here: [Apple Documentation](https://developer.apple.com/documentation/avfoundation/media_playback/configuring_the_audio_playback_of_ios_and_tvos_apps)

<figure><img src="https://688917408-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MLoGG8m6bokS9YTmS7m%2Fuploads%2Fgit-blob-05dd638be25f054783c9fb71674ffa926d1634bc%2Fimage%20(42)%20(1).png?alt=media" alt=""><figcaption></figcaption></figure>

#### Set enablePictureInPicture to true on Dart side

```dart
// Enable PiP for StoryBlock widget
StoryBlock(
  height: 400,
  source: StoryBlockSource.discover,
  enablePictureInPicture: true,
);
```

### Keep alive when scrolling the widget out of the view box

Generally, if you put the story block widget as the child of ListView, it will be rebuilt when scrolling the widget out of the view box. You could set `wantKeepAlive` as `true` to make the story block widget keep alive when scrolling the widget out of the view box.

```dart
StoryBlock(
  height: 400,
  source: StoryBlockSource.discover,
  // Keep the widget alive when scrolling the widget out of the view box
  wantKeepAlive: true,
);
```

### Player configurations

Please refer to [Player configurations (Flutter)](https://docs.firework.com/firework-for-developers/flutter-sdk/integration-guide-v2/customization/player-configurations-flutter).

## Reference

[StoryBlock](https://eng.firework.com/fw_flutter_sdk/v2/fw_flutter_sdk/StoryBlock-class.html)
