fst 0.2.8 fst: ^0.2.8 copied to clipboard
State tree interface implementation for Flutter + Flutter specific APIs
import 'package:flutter/material.dart';
import 'package:fst/extensions.dart';
import 'package:fst/fst.dart';
void main() {
runApp(const CounterApp());
}
const $modifier = Context<bool>(#modifier);
const $count = Context<int>(#count);
class CounterImpl extends Impl<int> implements IncrementFABApi, ResetButtonApi {
const CounterImpl(super.n);
@override
void increment() {
final delta = switch (n.read($modifier)) {
true => 10,
false => 1,
};
value += delta;
}
@override
void reset() => value = 0;
}
class CounterApp extends StatelessWidget {
const CounterApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: StateTreeBuilder<bool>(
(context, n, child) {
final incrementBy10 = n.send(false);
final focusNode = n.init(FocusNode.new);
$modifier(n).provide(incrementBy10);
return RawKeyboardListener(
focusNode: focusNode,
autofocus: true,
onKey: (e) {
n.send(e.isShiftPressed);
},
child: child,
);
},
child: StateTreeBuilder<int>(
(context, n, child) {
$count.provide(n, n.send(0));
final api = n.init(() => CounterImpl(n));
IncrementFAB.$api.provide(n, api);
IncrementFAB.$enabled.provide(n, n.receive() < 25);
ResetButton.$api.provide(n, api);
return child;
},
child: StateTreeBuilder(
(context, n, child) {
final c = n.watch($count);
n.call(
(count) {
if (c % 10 != 0 || c == 0) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Count is multiple of 10')),
);
},
c,
mode: InvocationMode.postFrame,
);
return child;
},
child: const Home(),
),
),
),
);
}
}
class Home extends StateTreeWidget<void> {
const Home({super.key});
@override
Widget build(BuildContext context, StateTreeNode n) {
return Scaffold(
appBar: AppBar(
title: const Text('State Tree Example'),
actions: const [
ResetButton(),
],
),
body: Center(
child: StateTreeBuilder((context, n, _) {
final count = n.watch($count);
return Text('Count: $count');
}),
),
floatingActionButton: n.query(
IncrementFAB.$enabled,
(e) => e ? const IncrementFAB() : null,
),
);
}
}
abstract interface class IncrementFABApi {
void increment();
}
class IncrementFAB extends StateTreeWidget {
static const $api = Context<IncrementFABApi>(#increment_fab_api);
static const $enabled = Context<bool>(#increment_fab_enabled);
const IncrementFAB({super.key});
@override
Widget build(BuildContext context, StateTreeNode n) {
return FloatingActionButton(
onPressed: n.read($api).increment,
child: const Icon(Icons.add),
);
}
}
abstract interface class ResetButtonApi {
void reset();
}
class ResetButton extends StateTreeWidget {
static const $api = Context<ResetButtonApi>(#reset_button_api);
const ResetButton({super.key});
@override
Widget build(BuildContext context, StateTreeNode n) {
return IconButton(
onPressed: n.read($api).reset,
icon: const Icon(Icons.refresh),
);
}
}