LinkFive - Successful Subscriptions

Flutter BLoC Plugin Example

Flutter BLoC Plugin Example

Let's get right into the bloc example.

We also have a Flutter bloc plugin (which is coming soon)

Initialize and Fetch your Subscriptions

In this example, we use Cubits that emits the state to their listeners.

Please initialize before you provide the Cubits (Maybe in your main-method)

LinkFivePurchases.init("API_KEY");

And to fetch all available subscriptions (maybe when the user enters your paywall), call the fetchSubscriptions method.

LinkFivePurchases.fetchSubscriptions();

Create a new State Class

The state class will hold the data and notify all consumer that something has changed with a given state. There are 2 states:

  • Init State: LinkFiveProductsInitState - when the plugin is not yet initialized or has no data yet.
  • Loaded State: LinkFiveProductsLoadedState - when data arrived and your app can show subscription purchase buttons.
abstract class LinkFiveProductsState extends Equatable{
@override
List<Object> get props => [];
}
class LinkFiveProductsInitState extends LinkFiveProductsState {}
class LinkFiveProductsLoadedState extends LinkFiveProductsState {
final LinkFiveSubscriptionData products;
LinkFiveProductsLoadedState(this.products);
@override
List<Object> get props => products.linkFiveSkuData;
}

Create a new Cubit class

We're using a Cubit to notify all listeners that something has changed with the state we've just created.

class LinkFiveProductsCubit extends Cubit<LinkFiveProductsState> {
}

Listen for subscription changes in it's constructor.

LinkFiveProductsCubit() : super(LinkFiveProductsInitState()){
_stream = LinkFivePurchases
.products
.listen(_subscriptionDataUpdate);
}

In it's listener method, we save all available subscriptions and emit the new state to all listeners

void _subscriptionDataUpdate(LinkFiveSubscriptionData? data) async {
if(data != null) {
emit(LinkFiveProductsLoadedState(data));
}
}

Please cancel the stream when the cubit is closed:

@override
Future<void> close() {
_stream?.cancel();
return super.close();
}

Add the Cubit to your other BlocProviders

In your main method or wherever you want to add the cubit to the widget tree, add the cubit like any other bloc or cubit.

MultiBlocProvider(providers: [
BlocProvider<LinkFiveProductsCubit>(
create: (context) => LinkFiveProductsCubit()),
// ...
], child: YourAppWidgets());

Consume the Cubit

In your build method, right before you want to offer the subscriptions, you can consume the cubit using a BlocBuilder< LinkFiveProductsCubit, LinkFiveProductsState>

BlocBuilder<LinkFiveProductsCubit, LinkFiveProductsState>(
builder: (context, state) {
if (state is LinkFiveProductsLoadedState) {
if (state.products.linkFiveSkuData.length > 0) {
return Container(
child: Column(
children: state.products.linkFiveSkuData
.map((e) => ElevatedButton(
onPressed: () => LinkFivePurchases.purchase(e.productDetails),
child: Text(e.productDetails.title)))
.toList()),
);
}
}
return Text("No products");
}),

When the user presses the button, LinkFivePurchases.purchase(...) will be called and handles the whole purchase flow.

The verified receipt will be passed to the activeSubscription stream.

Active Subscription Cubit

You can now also do the same for an Active Subscriptions Cubit.

class LinkFiveActiveProductsCubit extends Cubit<LinkFiveActiveProductsState>{
/// LinkFive client
final LinkFivePurchasesMain linkFivePurchases = LinkFivePurchasesMain();
/// Stream that will be cleaned on close
StreamSubscription? _stream;
LinkFiveActiveProductsCubit() : super(LinkFiveActiveProductsInitState()){
_stream = linkFivePurchases
.activeProducts
.listen(_activeSubscriptionDataUpdate);
}
/// Saves active Subscriptions and notifies all listeners
void _activeSubscriptionDataUpdate(LinkFiveActiveSubscriptionData? data) {
if(data != null) {
emit(LinkFiveActiveProductsLoadedState(data));
}
}
@override
Future<void> close() {
_stream?.cancel();
return super.close();
}
}
abstract class LinkFiveActiveProductsState extends Equatable{
@override
List<Object> get props => [];
}
class LinkFiveActiveProductsInitState extends LinkFiveActiveProductsState {}
class LinkFiveActiveProductsLoadedState extends LinkFiveActiveProductsState {
final LinkFiveActiveSubscriptionData activeProducts;
LinkFiveActiveProductsLoadedState(this.activeProducts);
@override
List<Object> get props => activeProducts.subscriptionList;
}