mirror of
https://github.com/wownero/cyberwow.git
synced 2026-10-24 10:48:53 +02:00
269 lines
7.8 KiB
Dart
269 lines
7.8 KiB
Dart
/*
|
||
|
||
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 'package:flutter/services.dart';
|
||
|
||
import '../state.dart';
|
||
import '../logging.dart';
|
||
|
||
Widget summary(BuildContext context, SyncedState state) {
|
||
final height = state.height.toString();
|
||
final onFire = state.getTransactionPool.length >= 10;
|
||
final onFireNotice = onFire ? ' 🔥' : '';
|
||
final poolLength = state.getTransactionPool.length;
|
||
final poolLengthNotice = poolLength > 1 ? '[$poolLength] ' : '';
|
||
final txNotice = state.getTransactionPool.isEmpty
|
||
? ''
|
||
: poolLengthNotice +
|
||
state.getTransactionPool.first['id_hash'].substring(0, 6) +
|
||
' ...';
|
||
|
||
return Container(
|
||
padding: EdgeInsets.only(bottom: 10.0),
|
||
child: Align(
|
||
alignment: Alignment.center,
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: <Widget>[
|
||
Spacer(
|
||
flex: 17,
|
||
),
|
||
Image.asset(
|
||
'assets/lolnode_icon.png',
|
||
height: 220,
|
||
),
|
||
Spacer(
|
||
flex: 7,
|
||
),
|
||
Expanded(
|
||
flex: 15,
|
||
child: Row(children: <Widget>[
|
||
Spacer(),
|
||
AnimatedSwitcher(
|
||
duration: Duration(milliseconds: 500),
|
||
child: Text(
|
||
height,
|
||
style: Theme.of(context).textTheme.headline4,
|
||
key: ValueKey<int>(state.height),
|
||
),
|
||
),
|
||
AnimatedSwitcher(
|
||
duration: Duration(milliseconds: 500),
|
||
child: Text(
|
||
onFireNotice,
|
||
style: TextStyle(
|
||
fontSize: 25,
|
||
),
|
||
key: ValueKey<int>(onFire ? 0 : 1),
|
||
),
|
||
),
|
||
Spacer(),
|
||
])),
|
||
AnimatedSwitcher(
|
||
duration: Duration(milliseconds: 500),
|
||
child: Text(
|
||
txNotice,
|
||
style: Theme.of(context).textTheme.bodyText1,
|
||
key: ValueKey<int>(poolLength),
|
||
),
|
||
),
|
||
Spacer(
|
||
flex: 1,
|
||
),
|
||
SizedBox(
|
||
height: 20.0,
|
||
width: 20.0,
|
||
child: (state.connected)
|
||
? Container()
|
||
: CircularProgressIndicator(
|
||
strokeWidth: 2,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget rpcView(BuildContext context, String headline6, String body) {
|
||
return Container(
|
||
padding: const EdgeInsets.all(10.0),
|
||
child: Align(
|
||
alignment: Alignment.topLeft,
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: <Widget>[
|
||
Expanded(
|
||
flex: 1,
|
||
child: SingleChildScrollView(
|
||
scrollDirection: Axis.vertical,
|
||
child: Column(
|
||
children: <Widget>[
|
||
Container(
|
||
height: 0,
|
||
margin: const EdgeInsets.only(bottom: 15),
|
||
),
|
||
Text(
|
||
headline6,
|
||
style: Theme.of(context).textTheme.headline4,
|
||
),
|
||
Container(
|
||
height: 1,
|
||
color: Theme.of(context).primaryColor,
|
||
margin: const EdgeInsets.only(bottom: 20, top: 20),
|
||
),
|
||
Text(
|
||
body,
|
||
style: Theme.of(context).textTheme.bodyText1,
|
||
)
|
||
],
|
||
)))
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget getInfo(BuildContext context, SyncedState state) =>
|
||
rpcView(context, 'info', state.getInfoCache);
|
||
|
||
Widget getTransactionPool(BuildContext context, SyncedState state) {
|
||
final pool = state.getTransactionPool;
|
||
const minimalLength = 6;
|
||
final subTitle = pool.length < minimalLength ? '' : ' ‹${pool.length}›';
|
||
return rpcView(context, 'tx pool' + subTitle, state.getTransactionPoolCache);
|
||
}
|
||
|
||
Widget getConnections(BuildContext context, SyncedState state) {
|
||
final peers = state.getConnections;
|
||
const minimalLength = 6;
|
||
final subTitle = peers.length < minimalLength ? '' : ' ‹${peers.length}›';
|
||
return rpcView(context, 'peers' + subTitle, state.getConnectionsCache);
|
||
}
|
||
|
||
Widget terminalView(BuildContext context, String headline6, SyncedState state) {
|
||
final input = TextFormField(
|
||
controller: state.textController,
|
||
// textInputAction: TextInputAction.next,
|
||
// autofocus: true,
|
||
autocorrect: false,
|
||
enableSuggestions: false,
|
||
keyboardType: TextInputType.visiblePassword,
|
||
decoration: InputDecoration(
|
||
// border: UnderlineInputBorder // OutlineInputBorder
|
||
// (
|
||
// ),
|
||
// hintText: 'WOW',
|
||
enabledBorder: UnderlineInputBorder(
|
||
borderSide: BorderSide(
|
||
color: Theme.of(context).primaryColor,
|
||
),
|
||
),
|
||
border: InputBorder.none,
|
||
),
|
||
onFieldSubmitted: (v) {
|
||
String autoReplace(final String x) {
|
||
final words = x.split(' ');
|
||
|
||
if (words.length == 0) {
|
||
return x;
|
||
}
|
||
|
||
final head = words.first;
|
||
final tail = words.sublist(1);
|
||
final guessHead = head.replaceAll('-', '_');
|
||
|
||
return [guessHead, ...tail].join(' ');
|
||
}
|
||
|
||
final _text = state.textController.text.trim();
|
||
final line = autoReplace(_text);
|
||
|
||
log.info('textController: $state.controller');
|
||
|
||
if (line.isNotEmpty) {
|
||
log.finer('terminal input: $line');
|
||
state.appendInput(line);
|
||
}
|
||
|
||
state.textController.clear();
|
||
},
|
||
);
|
||
|
||
return Container(
|
||
// padding: const EdgeInsets.all(10.0),
|
||
child: Align(
|
||
alignment: Alignment.topLeft,
|
||
child: Column(
|
||
mainAxisAlignment: MainAxisAlignment.center,
|
||
children: <Widget>[
|
||
Expanded(
|
||
flex: 1,
|
||
child: SingleChildScrollView(
|
||
scrollDirection: Axis.vertical,
|
||
reverse: true,
|
||
child: Column(
|
||
children: <Widget>[
|
||
Text(
|
||
state.appHook.stdoutCache,
|
||
style: Theme.of(context).textTheme.bodyText1,
|
||
)
|
||
],
|
||
))),
|
||
Container(
|
||
margin: const EdgeInsets.all(10.0),
|
||
child: input,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
Widget terminal(BuildContext context, SyncedState state) =>
|
||
terminalView(context, 'terminal', state);
|
||
|
||
Widget pageView(BuildContext context, SyncedState state) {
|
||
void _onPageChanged(int pageIndex) {
|
||
if (pageIndex != 0) {
|
||
SystemChannels.textInput.invokeMethod('TextInput.hide');
|
||
}
|
||
state.onPageChanged(pageIndex);
|
||
}
|
||
|
||
return PageView(
|
||
controller: state.pageController,
|
||
onPageChanged: _onPageChanged,
|
||
children: [
|
||
terminal(context, state),
|
||
summary(context, state),
|
||
getTransactionPool(context, state),
|
||
getConnections(context, state),
|
||
getInfo(context, state),
|
||
],
|
||
);
|
||
}
|
||
|
||
Widget build(BuildContext context, SyncedState state) {
|
||
return Scaffold(body: pageView(context, state));
|
||
}
|