sdui 0.1.32 sdui: ^0.1.32 copied to clipboard
*SDUI* make it easy to implement Server Driven UI pattern on flutter. - The server decides what to render by describing in a JSON the widgets to render. - The Flutter screen parse the JSON and build t [...]
import 'package:flutter/material.dart';
import 'package:sdui/sdui.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
Http.getInstance().interceptors = [
HttpJsonInterceptor(),
HttpAuthorizationInterceptor()
];
DynamicRouteState.statusCodeRoutes[401] = '/401';
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo',
initialRoute: '/',
routes: _routes(),
debugShowCheckedModeBanner: false,
navigatorObservers: [sduiRouteObserver],
);
}
Map<String, WidgetBuilder> _routes() => {
'/': (context) => const HomeScreen(),
'/remote': (context) => const DynamicRoute(
provider: HttpRouteContentProvider('http://10.0.2.2:8080')),
'/static': (context) =>
DynamicRoute(provider: StaticRouteContentProvider(json)),
'/401': (context) => const Error401()
};
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => HomeScreenState();
}
class HomeScreenState extends State<HomeScreen> with RouteAware {
int state = 0;
@override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
sduiRouteObserver.subscribe(this, ModalRoute.of(context)!);
});
super.initState();
}
@override
void dispose() {
sduiRouteObserver.unsubscribe(this);
super.dispose();
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Column(children: [
Text(state.toString()),
ElevatedButton(
child: const Text('Remote'),
onPressed: () => Navigator.pushNamed(context, '/remote')),
const Spacer(),
ElevatedButton(
child: const Text('Static'),
onPressed: () => Navigator.pushNamed(context, '/static')),
]),
);
@override
void didPopNext() {
setState(() {
state++;
});
}
@override
void didPush() {
setState(() {
state++;
});
}
}
class Error401 extends StatelessWidget {
const Error401({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) => const Center(child: Text('401'));
}
var json = '''
{
"type": "Screen",
"attributes": {
"safe": false
},
"children": [
{
"type": "column",
"children":[
{
"type": "qrview",
"attributes": {
}
}
]
}
],
"appBar": {
"type": "AppBar",
"attributes": {
"title": "Add Cash",
"elevation": 0.0,
"backgroundColor": "#FFFFFF",
"foregroundColor": "#000000"
},
"children": []
}
}
''';
/// HTTP interceptor that adds Authorization header
class HttpAuthorizationInterceptor extends HttpInterceptor {
@override
void onRequest(RequestTemplate request) async {
String token =
'eyJraWQiOiIxIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJ0ZW5hbnRfaWQiOjEsInN1YiI6IjE2Iiwic3ViX3R5cGUiOiJVU0VSIiwic2NvcGUiOlsiY2FydC1tYW5hZ2UiLCJjYXJ0LXJlYWQiLCJjYXRhbG9nLW1hbmFnZSIsImNhdGFsb2ctcmVhZCIsImNvbnRhY3QtbWFuYWdlIiwiY29udGFjdC1yZWFkIiwibWFpbC1zZW5kIiwib3JkZXItbWFuYWdlIiwib3JkZXItcmVhZCIsInBheW1lbnQtbWFuYWdlIiwicGF5bWVudC1tYW5hZ2UiLCJwYXltZW50LW1ldGhvZC1tYW5hZ2UiLCJwYXltZW50LW1ldGhvZC1yZWFkIiwicGF5bWVudC1yZWFkIiwicGF5bWVudC1yZWFkIiwicXItbWFuYWdlIiwicXItcmVhZCIsInNtcy1zZW5kIiwic21zLXZlcmlmeSIsInRlbmFudC1yZWFkIiwidXNlci1tYW5hZ2UiLCJ1c2VyLXJlYWQiXSwiaXNzIjoid3V0c2kuY29tIiwibmFtZSI6IkhlcnZlIFRjaGVwYW5ub3UiLCJhZG1pbiI6ZmFsc2UsInBob25lX251bWJlciI6IisxNTE0NzU4MDE5MSIsImV4cCI6MTY0NTU1NTI2OSwiaWF0IjoxNjQ1NDcwNjY5LCJqdGkiOiIxIn0.du2nLpJdvWWgJNrsdLckG2rvb2nIb9wcKolE2spIM1ESdCOOlGpuIoB5iFj08d_VUjRoQbP7XNrNt5EcALs7EYj-9wqVkw33BKzHQNq_aGcOU5LOcWiqCow-F29irFAO3GLe9r0w1xFS7u1_K-NAVUXRP7ot3EZCrC0nIUkRsB9-flcR2VqO5c0R6b1XfDzW';
request.headers['Authorization'] = 'Bearer $token';
request.headers['X-Tenant-ID'] = '1';
request.headers['X-Environment'] = 'dev';
}
@override
void onResponse(ResponseTemplate response) {
// TODO: implement onResponse
}
}