From da8109894224abae1b8d1e9702e6478fb5ba2fdc Mon Sep 17 00:00:00 2001 From: Simon Joecks Date: Tue, 13 Jul 2021 10:54:25 +0200 Subject: [PATCH 1/4] Upgrade to logger 1.0.0 - Nullsafty - Logger does not contain the addObserver method thus it is neccessary to wrap the LogOutput - removed sensors and shake functionality - dropped the Ansis Parser and the listview in favor for copyable text - update logs when opening the console --- example/.flutter-plugins-dependencies | 1 + .../android/app/src/main/AndroidManifest.xml | 1 - example/ios/Flutter/Debug.xcconfig | 1 + example/ios/Flutter/Release.xcconfig | 1 + example/lib/main.dart | 27 ++- lib/logger_flutter.dart | 6 +- lib/src/ansi_parser.dart | 126 ------------- lib/src/log_console.dart | 173 +++++++++++------- lib/src/log_console_on_shake.dart | 72 -------- lib/src/shake_detector.dart | 68 ------- pubspec.yaml | 8 +- 11 files changed, 136 insertions(+), 348 deletions(-) create mode 100644 example/.flutter-plugins-dependencies delete mode 100644 lib/src/ansi_parser.dart delete mode 100644 lib/src/log_console_on_shake.dart delete mode 100644 lib/src/shake_detector.dart diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies new file mode 100644 index 0000000..5b55ece --- /dev/null +++ b/example/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"sensors","path":"/Users/joecks/Library/flutter/.pub-cache/hosted/pub.dartlang.org/sensors-0.4.2+6/","dependencies":[]}],"android":[{"name":"sensors","path":"/Users/joecks/Library/flutter/.pub-cache/hosted/pub.dartlang.org/sensors-0.4.2+6/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"sensors","dependencies":[]}],"date_created":"2021-07-13 10:49:37.042300","version":"2.2.3"} \ No newline at end of file diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 9ce586c..be27031 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ spans; - - void parse(String s) { - spans = []; - var state = TEXT; - StringBuffer buffer; - var text = StringBuffer(); - var code = 0; - List codes; - - for (var i = 0, n = s.length; i < n; i++) { - var c = s[i]; - - switch (state) { - case TEXT: - if (c == '\u001b') { - state = BRACKET; - buffer = StringBuffer(c); - code = 0; - codes = []; - } else { - text.write(c); - } - break; - - case BRACKET: - buffer.write(c); - if (c == '[') { - state = CODE; - } else { - state = TEXT; - text.write(buffer); - } - break; - - case CODE: - buffer.write(c); - var codeUnit = c.codeUnitAt(0); - if (codeUnit >= 48 && codeUnit <= 57) { - code = code * 10 + codeUnit - 48; - continue; - } else if (c == ';') { - codes.add(code); - code = 0; - continue; - } else { - if (text.isNotEmpty) { - spans.add(createSpan(text.toString())); - text.clear(); - } - state = TEXT; - if (c == 'm') { - codes.add(code); - handleCodes(codes); - } else { - text.write(buffer); - } - } - - break; - } - } - - spans.add(createSpan(text.toString())); - } - - void handleCodes(List codes) { - if (codes.isEmpty) { - codes.add(0); - } - - switch (codes[0]) { - case 0: - foreground = getColor(0, true); - background = getColor(0, false); - break; - case 38: - foreground = getColor(codes[2], true); - break; - case 39: - foreground = getColor(0, true); - break; - case 48: - background = getColor(codes[2], false); - break; - case 49: - background = getColor(0, false); - } - } - - Color getColor(int colorCode, bool foreground) { - switch (colorCode) { - case 0: - return foreground ? Colors.black : Colors.transparent; - case 12: - return dark ? Colors.lightBlue[300] : Colors.indigo[700]; - case 208: - return dark ? Colors.orange[300] : Colors.orange[700]; - case 196: - return dark ? Colors.red[300] : Colors.red[700]; - case 199: - return dark ? Colors.pink[300] : Colors.pink[700]; - } - } - - TextSpan createSpan(String text) { - return TextSpan( - text: text, - style: TextStyle( - color: foreground, - backgroundColor: background, - ), - ); - } -} diff --git a/lib/src/log_console.dart b/lib/src/log_console.dart index fdf5b77..5c7fcfa 100644 --- a/lib/src/log_console.dart +++ b/lib/src/log_console.dart @@ -1,50 +1,98 @@ part of logger_flutter; -ListQueue _outputEventBuffer = ListQueue(); -int _bufferSize = 20; -bool _initialized = false; +class _WrappedOutput implements LogOutput { + final Function(OutputEvent e) outputListener; + final LogOutput innerLogOutput; + + _WrappedOutput(this.outputListener, this.innerLogOutput); + + @override + void output(OutputEvent event) { + innerLogOutput.output(event); + outputListener(event); + } + + @override + void destroy() { + innerLogOutput.destroy(); + } + + @override + void init() { + innerLogOutput.init(); + } +} class LogConsole extends StatefulWidget { final bool dark; final bool showCloseButton; + static ListQueue _outputEventBuffer = ListQueue(); + static bool _initialized = false; + static final _newLogs = ChangeNotifier(); + LogConsole({this.dark = false, this.showCloseButton = false}) - : assert(_initialized, "Please call LogConsole.init() first."); + : assert(_initialized, 'Please call LogConsole.init() first.'); + + /// Attach this LogOutput to your logger instance: + /// ` + /// Logger( + /// printer: PrettyPrinter( + /// printTime: true, + /// printEmojis: true, + /// colors: true, + /// methodCount: methodCount, + /// errorMethodCount: errMethodCount, + /// ), + /// level: level, + /// output: LogConsole.wrap(output), + /// filter: ProductionFiler(), + /// ); + /// ` + static LogOutput wrap({int bufferSize = 1000, LogOutput? innerOutput}) { + _initialized = true; - static void init({int bufferSize = 20}) { - if (_initialized) return; + final output = innerOutput ?? ConsoleOutput(); - _bufferSize = bufferSize; - _initialized = true; - Logger.addOutputListener((e) { + return _WrappedOutput((e) { if (_outputEventBuffer.length == bufferSize) { _outputEventBuffer.removeFirst(); } _outputEventBuffer.add(e); - }); + // ignore: invalid_use_of_visible_for_testing_member, invalid_use_of_protected_member + _newLogs.notifyListeners(); + }, output); } @override _LogConsoleState createState() => _LogConsoleState(); + + static void openLogConsole(BuildContext context) async { + var logConsole = LogConsole( + showCloseButton: true, + dark: Theme.of(context).brightness == Brightness.dark, + ); + PageRoute route; + route = MaterialPageRoute(builder: (_) => logConsole); + + await Navigator.push(context, route); + } } class RenderedEvent { final int id; final Level level; - final TextSpan span; - final String lowerCaseText; + final String text; - RenderedEvent(this.id, this.level, this.span, this.lowerCaseText); + RenderedEvent(this.id, this.level, this.text); } class _LogConsoleState extends State { - OutputCallback _callback; - - ListQueue _renderedBuffer = ListQueue(); + final ListQueue _renderedBuffer = ListQueue(); List _filteredBuffer = []; - var _scrollController = ScrollController(); - var _filterController = TextEditingController(); + final _scrollController = ScrollController(); + final _filterController = TextEditingController(); Level _filterLevel = Level.verbose; double _logFontSize = 14; @@ -57,17 +105,6 @@ class _LogConsoleState extends State { void initState() { super.initState(); - _callback = (e) { - if (_renderedBuffer.length == _bufferSize) { - _renderedBuffer.removeFirst(); - } - - _renderedBuffer.add(_renderEvent(e)); - _refreshFilter(); - }; - - Logger.addOutputListener(_callback); - _scrollController.addListener(() { if (!_scrollListenerEnabled) return; var scrolledToBottom = _scrollController.offset >= @@ -76,14 +113,26 @@ class _LogConsoleState extends State { _followBottom = scrolledToBottom; }); }); + + LogConsole._newLogs.addListener(_onNewLogs); + } + + void _onNewLogs() { + setState(() { + _reloadContent(); + }); } @override void didChangeDependencies() { super.didChangeDependencies(); + _reloadContent(); + } + + void _reloadContent() { _renderedBuffer.clear(); - for (var event in _outputEventBuffer) { + for (var event in LogConsole._outputEventBuffer) { _renderedBuffer.add(_renderEvent(event)); } _refreshFilter(); @@ -96,7 +145,7 @@ class _LogConsoleState extends State { return false; } else if (_filterController.text.isNotEmpty) { var filterText = _filterController.text.toLowerCase(); - return it.lowerCaseText.contains(filterText); + return it.text.toLowerCase().contains(filterText); } else { return true; } @@ -157,24 +206,25 @@ class _LogConsoleState extends State { } Widget _buildLogContent() { + final text = StringBuffer(); + _filteredBuffer.forEach((e) { + text.write(e.text); + text.write('\n'); + }); + return Container( color: widget.dark ? Colors.black : Colors.grey[150], child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SizedBox( - width: 1600, - child: ListView.builder( - shrinkWrap: true, - controller: _scrollController, - itemBuilder: (context, index) { - var logEntry = _filteredBuffer[index]; - return Text.rich( - logEntry.span, - key: Key(logEntry.id.toString()), - style: TextStyle(fontSize: _logFontSize), - ); - }, - itemCount: _filteredBuffer.length, + scrollDirection: Axis.vertical, + controller: _scrollController, + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SizedBox( + width: 1600, + child: SelectableText( + text.toString(), + style: TextStyle(fontSize: _logFontSize), + ), ), ), ), @@ -188,7 +238,7 @@ class _LogConsoleState extends State { mainAxisSize: MainAxisSize.max, children: [ Text( - "Log Console", + 'Log Console', style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, @@ -235,7 +285,7 @@ class _LogConsoleState extends State { controller: _filterController, onChanged: (s) => _refreshFilter(), decoration: InputDecoration( - labelText: "Filter log output", + labelText: 'Filter log output', border: OutlineInputBorder(), ), ), @@ -245,32 +295,32 @@ class _LogConsoleState extends State { value: _filterLevel, items: [ DropdownMenuItem( - child: Text("VERBOSE"), + child: Text('VERBOSE'), value: Level.verbose, ), DropdownMenuItem( - child: Text("DEBUG"), + child: Text('DEBUG'), value: Level.debug, ), DropdownMenuItem( - child: Text("INFO"), + child: Text('INFO'), value: Level.info, ), DropdownMenuItem( - child: Text("WARNING"), + child: Text('WARNING'), value: Level.warning, ), DropdownMenuItem( - child: Text("ERROR"), + child: Text('ERROR'), value: Level.error, ), DropdownMenuItem( - child: Text("WTF"), + child: Text('WTF'), value: Level.wtf, ) ], onChanged: (value) { - _filterLevel = value; + _filterLevel = value as Level; _refreshFilter(); }, ) @@ -289,7 +339,7 @@ class _LogConsoleState extends State { var scrollPosition = _scrollController.position; await _scrollController.animateTo( scrollPosition.maxScrollExtent, - duration: new Duration(milliseconds: 400), + duration: Duration(milliseconds: 400), curve: Curves.easeOut, ); @@ -297,20 +347,17 @@ class _LogConsoleState extends State { } RenderedEvent _renderEvent(OutputEvent event) { - var parser = AnsiParser(widget.dark); var text = event.lines.join('\n'); - parser.parse(text); return RenderedEvent( _currentId++, event.level, - TextSpan(children: parser.spans), - text.toLowerCase(), + text, ); } @override void dispose() { - Logger.removeOutputListener(_callback); + LogConsole._newLogs.removeListener(_onNewLogs); super.dispose(); } } @@ -319,7 +366,7 @@ class LogBar extends StatelessWidget { final bool dark; final Widget child; - LogBar({this.dark, this.child}); + LogBar({this.dark = false, required this.child}); @override Widget build(BuildContext context) { @@ -330,7 +377,7 @@ class LogBar extends StatelessWidget { boxShadow: [ if (!dark) BoxShadow( - color: Colors.grey[400], + color: Colors.grey[400]!, blurRadius: 3, ), ], diff --git a/lib/src/log_console_on_shake.dart b/lib/src/log_console_on_shake.dart deleted file mode 100644 index 29477c0..0000000 --- a/lib/src/log_console_on_shake.dart +++ /dev/null @@ -1,72 +0,0 @@ -part of logger_flutter; - -class LogConsoleOnShake extends StatefulWidget { - final Widget child; - final bool dark; - final bool debugOnly; - - LogConsoleOnShake({ - @required this.child, - this.dark, - this.debugOnly = true, - }); - - @override - _LogConsoleOnShakeState createState() => _LogConsoleOnShakeState(); -} - -class _LogConsoleOnShakeState extends State { - ShakeDetector _detector; - bool _open = false; - - @override - void initState() { - super.initState(); - - if (widget.debugOnly) { - assert(() { - _init(); - return true; - }()); - } else { - _init(); - } - } - - @override - Widget build(BuildContext context) { - return widget.child; - } - - _init() { - LogConsole.init(); - _detector = ShakeDetector(onPhoneShake: _openLogConsole); - _detector.startListening(); - } - - _openLogConsole() async { - if (_open) return; - - _open = true; - - var logConsole = LogConsole( - showCloseButton: true, - dark: widget.dark ?? Theme.of(context).brightness == Brightness.dark, - ); - PageRoute route; - if (Platform.isIOS) { - route = CupertinoPageRoute(builder: (_) => logConsole); - } else { - route = MaterialPageRoute(builder: (_) => logConsole); - } - - await Navigator.push(context, route); - _open = false; - } - - @override - void dispose() { - _detector.stopListening(); - super.dispose(); - } -} diff --git a/lib/src/shake_detector.dart b/lib/src/shake_detector.dart deleted file mode 100644 index 86e24b0..0000000 --- a/lib/src/shake_detector.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'dart:async'; -import 'dart:math'; - -import 'package:flutter/material.dart'; -import 'package:sensors/sensors.dart'; - -class ShakeDetector { - final VoidCallback onPhoneShake; - - final double shakeThresholdGravity; - - final int minTimeBetweenShakes; - - final int shakeCountResetTime; - - final int minShakeCount; - - int shakeCount = 0; - - int lastShakeTimestamp = DateTime.now().millisecondsSinceEpoch; - - StreamSubscription streamSubscription; - - ShakeDetector({ - this.onPhoneShake, - this.shakeThresholdGravity = 1.25, - this.minTimeBetweenShakes = 160, - this.shakeCountResetTime = 1500, - this.minShakeCount = 2, - }); - - /// Starts listening to accerelometer events - void startListening() { - streamSubscription = accelerometerEvents.listen((event) { - var gX = event.x / 9.81; - var gY = event.y / 9.81; - var gZ = event.z / 9.81; - - // gForce will be close to 1 when there is no movement. - var gForce = sqrt(gX * gX + gY * gY + gZ * gZ); - if (gForce > shakeThresholdGravity) { - var now = DateTime.now().millisecondsSinceEpoch; - // ignore shake events too close to each other - if (lastShakeTimestamp + minTimeBetweenShakes > now) { - return; - } - - // reset the shake count after 1.5 seconds of no shakes - if (lastShakeTimestamp + shakeCountResetTime < now) { - shakeCount = 0; - } - - lastShakeTimestamp = now; - if (++shakeCount >= minShakeCount) { - shakeCount = 0; - onPhoneShake(); - } - } - }); - } - - /// Stops listening to accelerometer events - void stopListening() { - if (streamSubscription != null) { - streamSubscription.cancel(); - } - } -} diff --git a/pubspec.yaml b/pubspec.yaml index f0026e5..8f8e8fa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,15 +1,15 @@ name: logger_flutter description: Flutter extension for logger. Please go there for documentation. -version: 0.7.1 +version: 1.0.0 author: Simon Leier homepage: https://github.com/leisim/logger_flutter environment: - sdk: ">=2.2.2 <3.0.0" + sdk: '>=2.13.0-0 <3.0.0' dependencies: flutter: sdk: flutter - logger: ">=0.7.0" - sensors: ^0.4.0+1 \ No newline at end of file + logger: ">=1.0.0" + async: 2.6.1 \ No newline at end of file From 1cff973061b9515e6ff95f923acbd1a5981dfa1a Mon Sep 17 00:00:00 2001 From: Simon Joecks Date: Tue, 13 Jul 2021 11:28:58 +0200 Subject: [PATCH 2/4] Remove .flutter-plugins-dependencies from repo --- example/.flutter-plugins-dependencies | 1 - example/.gitignore | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 example/.flutter-plugins-dependencies diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies deleted file mode 100644 index 5b55ece..0000000 --- a/example/.flutter-plugins-dependencies +++ /dev/null @@ -1 +0,0 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"sensors","path":"/Users/joecks/Library/flutter/.pub-cache/hosted/pub.dartlang.org/sensors-0.4.2+6/","dependencies":[]}],"android":[{"name":"sensors","path":"/Users/joecks/Library/flutter/.pub-cache/hosted/pub.dartlang.org/sensors-0.4.2+6/","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"sensors","dependencies":[]}],"date_created":"2021-07-13 10:49:37.042300","version":"2.2.3"} \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore index b142d3f..40838b4 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -25,6 +25,7 @@ .pub-cache/ .pub/ /build/ +.flutter-plugins-dependencies # Android related **/android/**/gradle-wrapper.jar From f92ba30c5fefee621e1feaa65c5b08c0e03adc6e Mon Sep 17 00:00:00 2001 From: "DESKTOP-68EULOT\\Igindo-Frank" Date: Mon, 13 Sep 2021 08:31:32 +0200 Subject: [PATCH 3/4] update deps --- pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 8f8e8fa..b51a8bb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,11 +5,11 @@ author: Simon Leier homepage: https://github.com/leisim/logger_flutter environment: - sdk: '>=2.13.0-0 <3.0.0' + sdk: '>=2.14.0 <3.0.0' dependencies: flutter: sdk: flutter - logger: ">=1.0.0" - async: 2.6.1 \ No newline at end of file + logger: 1.1.0 + async: 2.8.1 \ No newline at end of file From 33d08ef0122d905543806ae13e19e49b0658c347 Mon Sep 17 00:00:00 2001 From: Peter Stojanowski Date: Wed, 15 Dec 2021 15:24:08 +0000 Subject: [PATCH 4/4] Flutter 2.8.0 upgrade --- lib/logger_flutter.dart | 3 --- pubspec.yaml | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/logger_flutter.dart b/lib/logger_flutter.dart index 0a20206..5e50030 100644 --- a/lib/logger_flutter.dart +++ b/lib/logger_flutter.dart @@ -3,11 +3,8 @@ library logger_flutter; import 'dart:async'; import 'dart:collection'; -import 'dart:ui'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:logger/logger.dart'; part 'src/log_console.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index b51a8bb..1fe00e6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,6 @@ name: logger_flutter description: Flutter extension for logger. Please go there for documentation. version: 1.0.0 -author: Simon Leier homepage: https://github.com/leisim/logger_flutter environment: @@ -12,4 +11,4 @@ dependencies: sdk: flutter logger: 1.1.0 - async: 2.8.1 \ No newline at end of file + async: 2.8.2