dbrij_ship_rfw 0.1.1
dbrij_ship_rfw: ^0.1.1 copied to clipboard
Server driven Flutter screens for Dbrij Ship: Remote Flutter Widgets delivered on the release rail, staged and rolled back like any other release.
example/main.dart
// Server driven screens with Dbrij Ship, end to end.
//
// The app below has a checkout screen built locally. If a release on the Ship
// dashboard carries an asset pack with `ui/checkout.rfw` in it, that remote screen
// replaces the local one; if there is none (first launch, offline, the kill switch,
// a pack rolled back) the local screen is shown. Nothing downloaded ever executes: a
// blob only composes widgets this app registered, and its events land in Dart below.
import 'dart:io';
import 'package:dbrij_ship/dbrij_ship.dart';
import 'package:dbrij_ship_rfw/dbrij_ship_rfw.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final ship = Ship(
appKey: 'shp_your_app_key', // from the Setup card on the Ship dashboard
binaryVersion: '1.4.0',
platform: Platform.isIOS ? 'ios' : 'android',
// In a real app pass a ShipStorage over shared_preferences here. Without one the
// device id is remade every launch (see the dbrij_ship README).
);
// Where packs are kept. A real app uses its support directory (path_provider).
final assets = ShipAssets(
ship: ship,
directory: Directory('${Directory.systemTemp.path}/dbrij_ship_packs'),
);
final ui = ShipRemoteUi(
assets: assets,
widgets:
createMaterialWidgets(), // plus your own widgets, if blobs should use them
);
// Start from the pack already on disk, so the first frame needs no network.
await assets.restore();
await ui.loadAll(<String>['checkout']);
try {
await ship.checkIn();
} on ShipException {
// Offline is normal. The app runs on what it has.
}
ui.publishShipValues(ship); // flags and config, where a blob can read them
runApp(ExampleApp(ui: ui));
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key, required this.ui});
final ShipRemoteUi ui;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Checkout')),
body: ShipRemoteWidget(
ui: ui,
name: 'checkout',
// Required, and the most important line here: the local screen IS the app,
// and the remote one is an override that may not be there.
fallback: (context) => const LocalCheckout(),
// A blob names an event; what it DOES is decided here, in the store build.
onEvent: (name, args) {
if (name == 'checkout.begin') debugPrint('Begin checkout: $args');
},
),
),
);
}
}
class LocalCheckout extends StatelessWidget {
const LocalCheckout({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: FilledButton(
onPressed: () => debugPrint('Begin checkout'),
child: const Text('Pay now'),
),
);
}
}