use runtimeType to determine state type

master
fuwa 4 years ago
parent 6b1353a324
commit c2bf063f81

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

@ -40,39 +40,6 @@ import 'helper.dart';
import 'controller/rpc/rpcView.dart' as rpcView; import 'controller/rpc/rpcView.dart' as rpcView;
import 'controller/rpc/rpc2View.dart' as rpc2View; 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 SetStateFunc = void Function(AppState);
typedef GetNotificationFunc = AppLifecycleState Function(); typedef GetNotificationFunc = AppLifecycleState Function();
typedef IsExitingFunc = bool Function(); typedef IsExitingFunc = bool Function();
@ -84,21 +51,21 @@ class AppHook {
AppHook(this.setState, this.getNotification, this.isExiting); AppHook(this.setState, this.getNotification, this.isExiting);
} }
class HookedState extends AppState { class AppState {
final AppHook appHook; final AppHook appHook;
HookedState(this.appHook); AppState(this.appHook);
syncState() { syncState() {
appHook.setState(this); appHook.setState(this);
} }
HookedState moveState(HookedState _next) { AppState moveState(AppState _next) {
appHook.setState(_next); appHook.setState(_next);
return _next; return _next;
} }
} }
class BlankState extends HookedState { class BlankState extends AppState {
BlankState(appHook) : super (appHook); BlankState(appHook) : super (appHook);
Future<LoadingState> next(String status) async { 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; final String banner;
String status = ''; String status = '';
@ -156,7 +123,7 @@ class LoadingState extends HookedState {
} }
} }
class SyncingState extends HookedState { class SyncingState extends AppState {
final Queue<String> stdout = Queue.from(['']); final Queue<String> stdout = Queue.from(['']);
bool synced = false; bool synced = false;
@ -171,7 +138,7 @@ class SyncingState extends HookedState {
syncState(); syncState();
} }
Future<HookedState> next Future<AppState> next
( (
StreamSink<String> processInput, Stream<String> processOutput StreamSink<String> processInput, Stream<String> processOutput
) async { ) async {
@ -233,7 +200,7 @@ class SyncingState extends HookedState {
} }
} }
class SyncedState extends HookedState { class SyncedState extends AppState {
final Queue<String> stdout; final Queue<String> stdout;
final StreamSink<String> processInput; final StreamSink<String> processInput;
final Stream<String> processOutput; final Stream<String> processOutput;
@ -281,7 +248,7 @@ class SyncedState extends HookedState {
this.pageIndex = value; this.pageIndex = value;
} }
Future<HookedState> next() async { Future<AppState> next() async {
log.fine("Synced next"); log.fine("Synced next");
Future<void> logStdout() async { 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 Queue<String> stdout;
final StreamSink<String> processInput; final StreamSink<String> processInput;
final Stream<String> processOutput; final Stream<String> processOutput;
@ -372,7 +339,7 @@ class ReSyncingState extends HookedState {
syncState(); syncState();
} }
Future<HookedState> next() async { Future<AppState> next() async {
log.fine("ReSyncing next"); log.fine("ReSyncing next");
Future<void> printStdout() async { 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 Queue<String> stdout;
final Stream<String> processOutput; 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 '../state.dart';
import '../config.dart' as config; import '../config.dart' as config;
Widget buildBlank(BuildContext context, BlankState state) { Widget build(BuildContext context, BlankState state) {
return Scaffold( return Scaffold(
body: Container body: Container
( (

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

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

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

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

Loading…
Cancel
Save