From 1ba9f89d44b5f2dfc5d57ee247d9d67f66484cdd Mon Sep 17 00:00:00 2001 From: fuwa Date: Thu, 25 Jul 2019 01:48:26 +0000 Subject: [PATCH] add exiting state --- cyberwow/lib/main.dart | 15 ++++++- cyberwow/lib/state.dart | 42 ++++++++++++++----- cyberwow/lib/widget/exiting.dart | 71 ++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 cyberwow/lib/widget/exiting.dart diff --git a/cyberwow/lib/main.dart b/cyberwow/lib/main.dart index e3759c6..3e2838a 100644 --- a/cyberwow/lib/main.dart +++ b/cyberwow/lib/main.dart @@ -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 with WidgetsBindingObserver { - int _counter = 0; // AppState _state = LoadingState("init..."); AppState _state; @@ -80,6 +80,8 @@ class _CyberWOW_PageState extends State with WidgetsBindingObserv initialPage: 0, ); + bool _exiting = false; + final StreamController inputStreamController = StreamController(); @override @@ -105,6 +107,10 @@ class _CyberWOW_PageState extends State with WidgetsBindingObserv return _notification; } + bool _isExiting() { + return _exiting; + } + AppState _getState() { return _state; } @@ -127,7 +133,7 @@ class _CyberWOW_PageState extends State 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 with WidgetsBindingObserv (s) => () => validState = false, (s) => s.next(), (s) => s.next(), + (s) => s.wait(), ); } @@ -164,7 +171,10 @@ class _CyberWOW_PageState extends State with WidgetsBindingObserv Future _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 with WidgetsBindingObserv (s) => buildSyncing(context, s), (s) => buildSynced(context, s, syncedPageController), (s) => buildReSyncing(context, s), + (s) => buildExiting(context, s), ), ); } diff --git a/cyberwow/lib/state.dart b/cyberwow/lib/state.dart index a43357b..cf42fbe 100644 --- a/cyberwow/lib/state.dart +++ b/cyberwow/lib/state.dart @@ -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 next(StreamSink processInput, Stream processOutput) async { + Future next + ( + StreamSink processInput, Stream processOutput, IsExitingFunc isExiting + ) async { log.fine("Syncing next"); Future 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 stdout; int height; @@ -212,8 +219,9 @@ class SyncedState extends HookedState { String syncInfo = 'syncInfo'; List getConnections = []; List 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 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 processInput; Stream 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 printStdout() async { await for (final line in processOutput) { - if (synced) break; log.finest('exiting: print stdout loop'); append(line); diff --git a/cyberwow/lib/widget/exiting.dart b/cyberwow/lib/widget/exiting.dart new file mode 100644 index 0000000..31b58ca --- /dev/null +++ b/cyberwow/lib/widget/exiting.dart @@ -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 . + +*/ + +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: + [ + 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, + ), + ) + ) + ) + ], + ), + ), + ), + ); +}