add exiting state

pull/2/head
fuwa 5 years ago
parent 038af999f9
commit 1ba9f89d44

@ -37,6 +37,7 @@ import 'widget/blank.dart';
import 'widget/syncing.dart';
import 'widget/synced.dart';
import 'widget/resyncing.dart';
import 'widget/exiting.dart';
void main() {
Logger.root.level = kReleaseMode ? Level.INFO : Level.FINE;
@ -71,7 +72,6 @@ class CyberWOW_Page extends StatefulWidget {
class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserver
{
int _counter = 0;
// AppState _state = LoadingState("init...");
AppState _state;
@ -80,6 +80,8 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
initialPage: 0,
);
bool _exiting = false;
final StreamController<String> inputStreamController = StreamController();
@override
@ -105,6 +107,10 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
return _notification;
}
bool _isExiting() {
return _exiting;
}
AppState _getState() {
return _state;
}
@ -127,7 +133,7 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
final syncing = process.runBinary(binName, input: inputStreamController.stream).asBroadcastStream();
SyncedState _syncedState = await _syncingState.next(inputStreamController.sink, syncing);
SyncedState _syncedState = await _syncingState.next(inputStreamController.sink, syncing, _isExiting);
await _syncedState.next();
var validState = true;
@ -139,6 +145,7 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
(s) => () => validState = false,
(s) => s.next(),
(s) => s.next(),
(s) => s.wait(),
);
}
@ -164,7 +171,10 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
Future<bool> _exitApp(BuildContext context) async {
log.info("CyberWOW_PageState _exitApp");
WidgetsBinding.instance.removeObserver(this);
_exiting = true;
inputStreamController.sink.add('exit');
await Future.delayed(const Duration(seconds: 10), () => null);
// the process controller should call exit(0) for us
@ -184,6 +194,7 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
(s) => buildSyncing(context, s),
(s) => buildSynced(context, s, syncedPageController),
(s) => buildReSyncing(context, s),
(s) => buildExiting(context, s),
),
);
}

@ -45,6 +45,7 @@ abstract class AppState {
T Function(SyncingState) useSyncingState,
T Function(SyncedState) useSyncedState,
T Function(ReSyncingState) useReSyncingState,
T Function(ExitingState) useExitingState,
)
{
if (this is BlankState) {
@ -62,19 +63,20 @@ abstract class AppState {
if (this is ReSyncingState) {
return useReSyncingState(this);
}
if (this is ExitingState) {
return useExitingState(this);
}
throw Exception('Invalid state');
}
}
typedef SetStateFunc = void Function(AppState);
typedef GetNotificationFunc = AppLifecycleState Function();
typedef IsExitingFunc = bool Function();
class HookedState extends AppState {
final SetStateFunc setState;
final GetNotificationFunc getNotification;
final GetExitingFunc isExiting;
HookedState(this.setState, this.getNotification, this.isExiting);
HookedState(this.setState, this.getNotification);
syncState() {
setState(this);
@ -158,7 +160,10 @@ class SyncingState extends HookedState {
syncState();
}
Future<SyncedState> next(StreamSink<String> processInput, Stream<String> processOutput) async {
Future<SyncedState> next
(
StreamSink<String> processInput, Stream<String> processOutput, IsExitingFunc isExiting
) async {
log.fine("Syncing next");
Future<void> printStdout() async {
@ -195,12 +200,14 @@ class SyncingState extends HookedState {
// processInput.add('exit');
final _height = await rpc.height();
SyncedState _next = SyncedState(setState, getNotification, stdout, processInput, processOutput);
SyncedState _next = SyncedState(setState, getNotification, isExiting, stdout, processInput, processOutput);
_next.height = _height;
return moveState(_next);
}
}
typedef IsExitingFunc = bool Function();
class SyncedState extends HookedState {
Queue<String> stdout;
int height;
@ -212,8 +219,9 @@ class SyncedState extends HookedState {
String syncInfo = 'syncInfo';
List<dynamic> getConnections = [];
List<dynamic> getTransactionPool = [];
final IsExitingFunc isExiting;
SyncedState(f, s, this.stdout, this.processInput, this.processOutput) : super (f, s);
SyncedState(f, s, this.isExiting, this.stdout, this.processInput, this.processOutput) : super (f, s);
void appendInput(String line) {
stdout.addLast('> ' + line + '\n');
@ -226,6 +234,14 @@ class SyncedState extends HookedState {
Future<void> logStdout() async {
await for (final line in processOutput) {
if (!synced) break;
if (isExiting()) {
ExitingState _next = ExitingState
(
setState, getNotification, stdout, processOutput
);
return moveState(_next);
}
// print('synced: print stdout loop');
stdout.addLast(line);
log.info(line);
@ -261,7 +277,10 @@ class SyncedState extends HookedState {
log.fine('synced: loop exit');
ReSyncingState _next = ReSyncingState(setState, getNotification, stdout, processInput, processOutput);
ReSyncingState _next = ReSyncingState
(
setState, getNotification, isExiting, stdout, processInput, processOutput
);
return moveState(_next);
}
}
@ -272,8 +291,9 @@ class ReSyncingState extends HookedState {
StreamSink<String> processInput;
Stream<String> processOutput;
bool synced = false;
final IsExitingFunc isExiting;
ReSyncingState(f, s, this.stdout, this.processInput, this.processOutput) : super (f, s);
ReSyncingState(f, s, this.isExiting, this.stdout, this.processInput, this.processOutput) : super (f, s);
void append(String msg) {
stdout.addLast(msg);
@ -310,7 +330,10 @@ class ReSyncingState extends HookedState {
await checkSync();
log.fine('resync: await exit');
SyncedState _next = SyncedState(setState, getNotification, stdout, processInput, processOutput);
SyncedState _next = SyncedState
(
setState, getNotification, isExiting, stdout, processInput, processOutput
);
_next.height = await rpc.height();
return moveState(_next);
}
@ -335,7 +358,6 @@ class ExitingState extends HookedState {
Future<void> printStdout() async {
await for (final line in processOutput) {
if (synced) break;
log.finest('exiting: print stdout loop');
append(line);

@ -0,0 +1,71 @@
/*
Copyright 2019 fuwa
This file is part of CyberWOW.
CyberWOW is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CyberWOW is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CyberWOW. If not, see <https://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import '../state.dart';
import '../config.dart' as config;
Widget buildExiting(BuildContext context, ExitingState state) {
return Scaffold
(
// appBar: AppBar
// (
// // title: Text(widget.title),
// title: Text('CyberWOW'),
// ),
body: Container
(
// padding: const EdgeInsets.all(10.0),
color: config.c.backgroundColor,
child: Align
(
alignment: Alignment.topLeft,
child: Column
(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>
[
Expanded
(
flex: 1,
child: SingleChildScrollView
(
scrollDirection: Axis.vertical,
reverse: true,
child: Text
(
state.stdout.join(),
style: TextStyle
(
fontFamily: 'RobotoMono',
fontSize: 11,
color: config.c.textColor,
),
)
)
)
],
),
),
),
);
}