From 9dc2e057b271cf2a1ca082fc33f37c0aa664a8d8 Mon Sep 17 00:00:00 2001 From: Chen Asraf Date: Thu, 21 Sep 2023 15:34:13 +0300 Subject: [PATCH] feat: strip colors from output --- lib/core/color_utils.dart | 22 ++++++++++++++++++++ lib/core/consts.dart | 4 +++- lib/core/store.dart | 30 ++++++++++++++++++++++----- lib/main.dart | 7 +++++-- lib/pages/home_page.dart | 43 ++++++++++++++++++++++++++------------- 5 files changed, 84 insertions(+), 22 deletions(-) create mode 100644 lib/core/color_utils.dart diff --git a/lib/core/color_utils.dart b/lib/core/color_utils.dart new file mode 100644 index 0000000..dbfc077 --- /dev/null +++ b/lib/core/color_utils.dart @@ -0,0 +1,22 @@ +import 'package:flutter/foundation.dart'; +import 'package:mudblock/core/consts.dart'; + +class ColorUtils { + static stripColor(String text) { + return text + // esc + // .replaceAll(esc, '') + // .replaceAll(r'^[', '') + // color + .replaceAll(RegExp(esc + r'\[\d*m'), '') + + // color + // .replaceAll(RegExp(r'\[\d+m'), '') + // esc + // .replaceAll(String.fromCharCode(0xff), ''); + + // + ; + } +} + diff --git a/lib/core/consts.dart b/lib/core/consts.dart index c5320be..abe7c45 100644 --- a/lib/core/consts.dart +++ b/lib/core/consts.dart @@ -1,2 +1,4 @@ const newline = '\n'; -const ansiEscapePattern = r'\x1B\[[0-?]*[ -/]*[@-~]'; +// const ansiEscapePattern = r'\x1B\[[0-?]*[ -/]*[@-~]'; +// final esc = String.fromCharCodes([0xff]); +const esc = '\x1B'; diff --git a/lib/core/store.dart b/lib/core/store.dart index eb3cfa2..8cd1fc6 100644 --- a/lib/core/store.dart +++ b/lib/core/store.dart @@ -4,6 +4,7 @@ import 'package:ctelnet/ctelnet.dart'; import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; +import 'color_utils.dart'; import 'consts.dart'; const maxLines = 2000; @@ -12,6 +13,8 @@ class GameStore extends ChangeNotifier { final List _lines = []; late final CTelnetClient _client; late final ScrollController scrollController; + final TextEditingController input = TextEditingController(); + final FocusNode inputFocus = FocusNode(); GameStore init() { addLine('Connecting...'); @@ -37,7 +40,8 @@ class GameStore extends ChangeNotifier { } void onData(String data) { - debugPrint('onData: $data'); + debugPrint('onData: $data'); + debugPrint('stripped: ${ColorUtils.stripColor(data)}'); // final pattern = RegExp("$newline|$ansiEscapePattern"); // ignore: unnecessary_string_interpolations final pattern = RegExp("$newline"); @@ -59,6 +63,7 @@ class GameStore extends ChangeNotifier { void addLine(String line) { _lines.add(line); notifyListeners(); + scrollToEnd(); } void send(String line) { @@ -69,11 +74,26 @@ class GameStore extends ChangeNotifier { void submitInput(String text) { addLine(text); send(text); - scrollController.animateTo( - scrollController.offset, - duration: const Duration(milliseconds: 300), - curve: Curves.easeOut, + scrollToEnd(); + selectInput(); + } + + void scrollToEnd() { + Future.delayed(const Duration(milliseconds: 10), () { + scrollController.animateTo( + scrollController.position.maxScrollExtent, + duration: const Duration(milliseconds: 50), + curve: Curves.easeIn, + ); + }); + } + + void selectInput() { + input.selection = TextSelection( + baseOffset: 0, + extentOffset: input.text.length, ); + inputFocus.requestFocus(); } } diff --git a/lib/main.dart b/lib/main.dart index 41572b8..7f76c78 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,17 +15,20 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'Flutter Demo', + title: 'Mudblock', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: Scaffold( + appBar: AppBar( + title: const Text('Mudblock'), + ), body: ChangeNotifierProvider( create: (_) => GameStore().init(), builder: (context, snapshot) { return const HomePage(); - } + }, ), ), ); diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index b62932e..41400cf 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:mudblock/core/color_utils.dart'; import 'package:provider/provider.dart'; import '../core/store.dart'; @@ -11,15 +12,20 @@ class HomePage extends StatefulWidget { } class _HomePageState extends State with GameStoreMixin { - final TextEditingController _input = TextEditingController(); @override Widget build(BuildContext context) { - const textStyle = TextStyle(color: Colors.white); - return Material( - color: Colors.black, - child: Column( - children: [ - Expanded( + const consoleStyle = TextStyle( + color: Colors.white, + fontFamily: 'Courier New', + fontSize: 16, + ); + final inputStyle = consoleStyle.copyWith(color: Colors.grey); + + return Column( + children: [ + Expanded( + child: Material( + color: Colors.black, child: Consumer( builder: (context, store, child) { final lines = store.lines; @@ -30,7 +36,10 @@ class _HomePageState extends State with GameStoreMixin { return RichText( text: TextSpan( children: [ - TextSpan(text: lines[index], style: textStyle), + TextSpan( + text: ColorUtils.stripColor(lines[index]), + style: consoleStyle, + ), ], ), ); @@ -40,19 +49,25 @@ class _HomePageState extends State with GameStoreMixin { }, ), ), - TextField( - controller: _input, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + focusNode: store.inputFocus, + controller: store.input, onSubmitted: (text) { store.submitInput(text); }, - style: textStyle, + onTap: store.selectInput, + style: consoleStyle.copyWith(color: Colors.black), decoration: InputDecoration( hintText: 'Enter command', - hintStyle: textStyle.copyWith(color: Colors.grey), + border: const OutlineInputBorder(), + hintStyle: inputStyle, ), ), - ], - ), + ), + ], ); } }