use runtimeType to determine state type

pull/4/head
fuwa 4 years ago
parent 6b1353a324
commit c2bf063f81

@ -32,12 +32,7 @@ import 'config.dart' as config;
import 'logging.dart';
import 'controller/process/deploy.dart' as process;
import 'controller/process/run.dart' as process;
import 'widget/loading.dart' as widget;
import 'widget/blank.dart' as widget;
import 'widget/syncing.dart' as widget;
import 'widget/synced.dart' as widget;
import 'widget/resyncing.dart' as widget;
import 'widget/exiting.dart' as widget;
import 'widget.dart' as widget;
void main() {
Logger.root.level = kReleaseMode ? Level.INFO : Level.FINE;
@ -128,7 +123,7 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
.runBinary(binName, input: inputStreamController.stream, shouldExit: _isExiting)
.asBroadcastStream();
HookedState _syncedNextState = await _syncingState.next(inputStreamController.sink, syncing);
AppState _syncedNextState = await _syncingState.next(inputStreamController.sink, syncing);
var exited = false;
@ -143,19 +138,25 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
var validState = true;
while (validState && !exited) {
await _getState().use
(
(s) => validState = false,
(s) => validState = false,
(s) => validState = false,
(s) => s.next(),
(s) => s.next(),
(s) async {
await s.wait();
AppState _state = _getState();
switch (_state.runtimeType) {
case ExitingState: {
await (_state as ExitingState).wait();
log.finer('exit state wait done');
exited = true;
}
);
break;
case SyncedState:
(_state as SyncedState).next();
break;
case ReSyncingState:
(_state as ReSyncingState).next();
break;
default: validState = false;
}
}
log.finer('state machine finished');
@ -203,15 +204,7 @@ class _CyberWOW_PageState extends State<CyberWOW_Page> with WidgetsBindingObserv
return WillPopScope
(
onWillPop: () => _exitApp(context),
child: _state.use
(
(s) => widget.buildBlank(context, s),
(s) => widget.buildLoading(context, s),
(s) => widget.buildSyncing(context, s),
(s) => widget.buildSynced(context, s),
(s) => widget.buildReSyncing(context, s),
(s) => widget.buildExiting(context, s),
),
child: widget.build(context, _state),
);
}
}

@ -40,39 +40,6 @@ import 'helper.dart';
import 'controller/rpc/rpcView.dart' as rpcView;
import 'controller/rpc/rpc2View.dart' as rpc2View;
abstract class AppState {
T use<T>
(
T Function(BlankState) useBlankState,
T Function(LoadingState) useLoadingState,
T Function(SyncingState) useSyncingState,
T Function(SyncedState) useSyncedState,
T Function(ReSyncingState) useReSyncingState,
T Function(ExitingState) useExitingState,
)
{
if (this is BlankState) {
return useBlankState(this);
}
if (this is LoadingState) {
return useLoadingState(this);
}
if (this is SyncingState) {
return useSyncingState(this);
}
if (this is SyncedState) {
return useSyncedState(this);
}
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();
@ -84,21 +51,21 @@ class AppHook {
AppHook(this.setState, this.getNotification, this.isExiting);
}
class HookedState extends AppState {
class AppState {
final AppHook appHook;
HookedState(this.appHook);
AppState(this.appHook);
syncState() {
appHook.setState(this);
}
HookedState moveState(HookedState _next) {
AppState moveState(AppState _next) {
appHook.setState(_next);
return _next;
}
}
class BlankState extends HookedState {
class BlankState extends AppState {
BlankState(appHook) : super (appHook);
Future<LoadingState> next(String status) async {
@ -107,7 +74,7 @@ class BlankState extends HookedState {
}
}
class LoadingState extends HookedState {
class LoadingState extends AppState {
final String banner;
String status = '';
@ -156,7 +123,7 @@ class LoadingState extends HookedState {
}
}
class SyncingState extends HookedState {
class SyncingState extends AppState {
final Queue<String> stdout = Queue.from(['']);
bool synced = false;
@ -171,7 +138,7 @@ class SyncingState extends HookedState {
syncState();
}
Future<HookedState> next
Future<AppState> next
(
StreamSink<String> processInput, Stream<String> processOutput
) async {
@ -233,7 +200,7 @@ class SyncingState extends HookedState {
}
}
class SyncedState extends HookedState {
class SyncedState extends AppState {
final Queue<String> stdout;
final StreamSink<String> processInput;
final Stream<String> processOutput;
@ -281,7 +248,7 @@ class SyncedState extends HookedState {
this.pageIndex = value;
}
Future<HookedState> next() async {
Future<AppState> next() async {
log.fine("Synced next");
Future<void> logStdout() async {
@ -353,7 +320,7 @@ class SyncedState extends HookedState {
}
class ReSyncingState extends HookedState {
class ReSyncingState extends AppState {
final Queue<String> stdout;
final StreamSink<String> processInput;
final Stream<String> processOutput;
@ -372,7 +339,7 @@ class ReSyncingState extends HookedState {
syncState();
}
Future<HookedState> next() async {
Future<AppState> next() async {
log.fine("ReSyncing next");
Future<void> printStdout() async {
@ -420,7 +387,7 @@ class ReSyncingState extends HookedState {
}
}
class ExitingState extends HookedState {
class ExitingState extends AppState {
final Queue<String> stdout;
final Stream<String> processOutput;

@ -0,0 +1,42 @@
/*
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 'widget/blank.dart' as blank;
import 'widget/loading.dart' as loading;
import 'widget/syncing.dart' as syncing;
import 'widget/synced.dart' as synced;
import 'widget/resyncing.dart' as resyncing;
import 'widget/exiting.dart' as exiting;
Widget build(final BuildContext context, final AppState state) {
switch (state.runtimeType) {
case BlankState: return blank.build(context, state);
case LoadingState: return loading.build(context, state);
case SyncingState: return syncing.build(context, state);
case SyncedState: return synced.build(context, state);
case ReSyncingState: return resyncing.build(context, state);
case ExitingState: return exiting.build(context, state);
default: Placeholder();
}
}

@ -24,7 +24,7 @@ import 'package:flutter/material.dart';
import '../state.dart';
import '../config.dart' as config;
Widget buildBlank(BuildContext context, BlankState state) {
Widget build(BuildContext context, BlankState state) {
return Scaffold(
body: Container
(

@ -24,7 +24,7 @@ import 'package:flutter/material.dart';
import '../state.dart';
import '../config.dart' as config;
Widget buildExiting(BuildContext context, ExitingState state) {
Widget build(BuildContext context, ExitingState state) {
return Scaffold
(
// appBar: AppBar

@ -24,7 +24,7 @@ import 'package:flutter/material.dart';
import '../state.dart';
import '../config.dart' as config;
Widget buildLoading(BuildContext context, LoadingState state) {
Widget build(BuildContext context, LoadingState state) {
return Scaffold(
// appBar: AppBar(
// // title: Text(widget.title),

@ -24,7 +24,7 @@ import 'package:flutter/material.dart';
import '../state.dart';
import '../config.dart' as config;
Widget buildReSyncing(BuildContext context, ReSyncingState state) {
Widget build(BuildContext context, ReSyncingState state) {
return Scaffold
(
// appBar: AppBar

@ -320,7 +320,7 @@ Widget pageView (BuildContext context, SyncedState state) {
);
}
Widget buildSynced(BuildContext context, SyncedState state) {
Widget build(BuildContext context, SyncedState state) {
return Scaffold
(
body: pageView(context, state)

@ -24,7 +24,7 @@ import 'package:flutter/material.dart';
import '../state.dart';
import '../config.dart' as config;
Widget buildSyncing(BuildContext context, SyncingState state) {
Widget build(BuildContext context, SyncingState state) {
return Scaffold
(
// appBar: AppBar