Links

Story Block

Currently, there are five source types of the story block:
  • Discover
  • Channel
  • Playlist
  • Dynamic Content
  • Hashtag Playlist
  • SKU

Integration

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
StoryBlock(
height: 400,
source: StoryBlockSource.playlist,
playlist: "your encoded playlist id",
channel: "your encoded channel id",
)
/// dynamic content
StoryBlock(
height: 400,
source: StoryBlockSource.dynamicContent,
dynamicContentParameters: const {
'<cohort key>': ['<cohort value1>', '<cohort value2>']
},
)
/// hashtag playlist
StoryBlock(
height: 400,
source: StoryBlockSource.hashtagPlaylist,
channel: "your encoded channel id",
hashtagFilterExpression: "<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"
);

Configure corner radius

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.
StoryBlock(
height: 400,
source: StoryBlockSource.discover,
);

Story block configuration

StoryBlock widget provides storyBlockConfiguration prop for configuring Video Player. The current configurable properties are showShareButton, shareBaseURL, and ctaWidth etc. Please refer to StoryBlockConfiguration for more details.
final storyBlockConfiguration = StoryBlockConfiguration(
showShareButton: true,
ctaWidth: VideoPlayerCTAWidth.compact,
);
StoryBlock(
source: StoryBlockSource.discover,
storyBlockConfiguration: storyBlockConfiguration,
);

Play or pause story block programmatically

StoryBlockController? _storyBlockController;
StoryBlock(
height: 400,
source: StoryBlockSource.discover,
onStoryBlockCreated: (controller) {
_storyBlockController = controller;
},
);
// play story block
_storyBlockController?.play();
// pause story block
_storyBlockController?.pause();

Floating Player(Only supported on iOS)

You could set enablePictureInPicture to true to enable the floating player.
StoryBlock(
height: 400,
source: StoryBlockSource.discover,
enablePictureInPicture: true,
);

OS Picture in Picture(Only supported on iOS)

You also need to set enablePictureInPicture to true to enable the OS Picture in Picture.
StoryBlock(
height: 400,
source: StoryBlockSource.discover,
enablePictureInPicture: true,
);
This feature allows the user to watch media while the application is in a background state. While in background mode a video will display in a floating, resizable window.

Set up the iOS project

To enable PiP functionality, you also need to add Background Modes capability via Signing & Capabilities in your iOS project settings. More information about this can be found here: Apple Documentation
To use Picture in Picture, we configure the app to support background audio playback. See Configuring the Audio Playback of iOS and tvOS Apps for more details.

Keep alive when scrolling the list

Generally, if you put the story block widget as the child of ListView, it will be rebuilt when scrolling the list. You could refer to the following two ways to make the story block widget keep alive when scrolling the list.

Replace ListView with SingleChildScrollView and Column

ListView(
children: [
StoryBlock(
source: StoryBlockSource.discover,
),
],
);
// Replace ListView with SingleChildScrollView and Column
SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
StoryBlock(
source: StoryBlockSource.discover,
),
],
),
);

Use addAutomaticKeepAlives and AutomaticKeepAliveClientMixin

class StoryBlockWrapper extends StatefulWidget {
final Widget child;
const StoryBlockWrapper({
super.key,
required this.child,
});
@override
State<StoryBlockWrapper> createState() => _StoryBlockWrapperState();
}
class _StoryBlockWrapperState extends State<StoryBlockWrapper>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
super.build(context); // This line is required.
return widget.child;
}
@override
bool get wantKeepAlive => true; // Need to return true.
}
ListView(
addAutomaticKeepAlives: true, // Need to be set to true.
children: [
StoryBlockWrapper(
child: StoryBlock(
source: StoryBlockSource.discover,
),
),
],
);

Reference