From d0aa77bf3ffe33da684d691b6747e39de9deb62d Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sat, 16 May 2020 12:49:17 +0200 Subject: [PATCH 01/10] Fix logger dependency to 0.7.0. --- example/ios/Flutter/Debug.xcconfig | 1 + example/ios/Flutter/Release.xcconfig | 1 + pubspec.yaml | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig index 592ceee..e8efba1 100644 --- a/example/ios/Flutter/Debug.xcconfig +++ b/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig index 592ceee..399e934 100644 --- a/example/ios/Flutter/Release.xcconfig +++ b/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/pubspec.yaml b/pubspec.yaml index f0026e5..362f03f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,6 +10,5 @@ environment: dependencies: flutter: sdk: flutter - - logger: ">=0.7.0" + logger: 0.7.0 sensors: ^0.4.0+1 \ No newline at end of file From cad0fa24ece888aad872f9d92f72ae0560a5784b Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sat, 16 May 2020 14:44:13 +0200 Subject: [PATCH 02/10] Update example pods. --- example/ios/Runner.xcodeproj/project.pbxproj | 84 +++++++++++++++---- .../contents.xcworkspacedata | 3 + 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index d931fa5..6df3890 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,10 +9,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 4972FB3E8B14D121E11007CE /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 97D6080AEF307F8A78B30C8F /* libPods-Runner.a */; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; @@ -28,8 +25,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -40,19 +35,21 @@ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 97D6080AEF307F8A78B30C8F /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + B963DB357FF4BD90C9D1E6F0 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + EEF019F7FCAFA798F08A1A47 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + F5FCFA760C736AE76D3428FB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -60,20 +57,36 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + 4972FB3E8B14D121E11007CE /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 303C28C9A67591B7A5D01986 /* Pods */ = { + isa = PBXGroup; + children = ( + B963DB357FF4BD90C9D1E6F0 /* Pods-Runner.debug.xcconfig */, + F5FCFA760C736AE76D3428FB /* Pods-Runner.release.xcconfig */, + EEF019F7FCAFA798F08A1A47 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 87D3272E488140F45151E871 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 97D6080AEF307F8A78B30C8F /* libPods-Runner.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -87,7 +100,8 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, + 303C28C9A67591B7A5D01986 /* Pods */, + 87D3272E488140F45151E871 /* Frameworks */, ); sourceTree = ""; }; @@ -130,12 +144,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 3A50015EB72F4971AF799F0F /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 8F5047CB6113A089406925D8 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -194,6 +210,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 3A50015EB72F4971AF799F0F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -206,7 +244,25 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 8F5047CB6113A089406925D8 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${PODS_ROOT}/../Flutter/Flutter.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a1..21a3cc1 100644 --- a/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + From b979ffa9289d2dd22e8e474f4db13bde387df50b Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sat, 16 May 2020 14:49:36 +0200 Subject: [PATCH 03/10] Update LogConsole to accept levelsToFilter and defaultLevel. --- lib/src/log_console.dart | 57 ++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/lib/src/log_console.dart b/lib/src/log_console.dart index fdf5b77..c46ab1f 100644 --- a/lib/src/log_console.dart +++ b/lib/src/log_console.dart @@ -7,9 +7,18 @@ bool _initialized = false; class LogConsole extends StatefulWidget { final bool dark; final bool showCloseButton; - - LogConsole({this.dark = false, this.showCloseButton = false}) - : assert(_initialized, "Please call LogConsole.init() first."); + final List levelsToFilter; + final Level defaultLevel; + + LogConsole({ + this.dark = false, + this.showCloseButton = false, + List levelsToFilter, + Level defaultLevel, + }) : levelsToFilter = + levelsToFilter ?? const [Level.verbose, Level.debug, Level.info, Level.warning, Level.error, Level.wtf], + defaultLevel = defaultLevel ?? Level.verbose, + assert(_initialized, "Please call LogConsole.init() first."); static void init({int bufferSize = 20}) { if (_initialized) return; @@ -46,17 +55,28 @@ class _LogConsoleState extends State { var _scrollController = ScrollController(); var _filterController = TextEditingController(); - Level _filterLevel = Level.verbose; + Level _filterLevel; double _logFontSize = 14; var _currentId = 0; bool _scrollListenerEnabled = true; bool _followBottom = true; + final _mapLevelText = { + Level.verbose: 'VERBOSE', + Level.debug: 'DEBUG', + Level.info: 'INFO', + Level.warning: 'WARNING', + Level.error: 'ERROR', + Level.wtf: 'WTF', + }; + @override void initState() { super.initState(); + _filterLevel = widget.defaultLevel; + _callback = (e) { if (_renderedBuffer.length == _bufferSize) { _renderedBuffer.removeFirst(); @@ -244,30 +264,11 @@ class _LogConsoleState extends State { DropdownButton( value: _filterLevel, items: [ - DropdownMenuItem( - child: Text("VERBOSE"), - value: Level.verbose, - ), - DropdownMenuItem( - child: Text("DEBUG"), - value: Level.debug, - ), - DropdownMenuItem( - child: Text("INFO"), - value: Level.info, - ), - DropdownMenuItem( - child: Text("WARNING"), - value: Level.warning, - ), - DropdownMenuItem( - child: Text("ERROR"), - value: Level.error, - ), - DropdownMenuItem( - child: Text("WTF"), - value: Level.wtf, - ) + for (final level in widget.levelsToFilter) + DropdownMenuItem( + child: Text(_mapLevelText[level]), + value: level, + ), ], onChanged: (value) { _filterLevel = value; From b0bb5a114c6910d0a67ca59666d16ef2737189eb Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sat, 16 May 2020 14:50:15 +0200 Subject: [PATCH 04/10] Update LogConsoleOnShake to accept levelsToFilter, defaultLevel. --- lib/src/log_console_on_shake.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/src/log_console_on_shake.dart b/lib/src/log_console_on_shake.dart index 29477c0..7ab365d 100644 --- a/lib/src/log_console_on_shake.dart +++ b/lib/src/log_console_on_shake.dart @@ -4,11 +4,15 @@ class LogConsoleOnShake extends StatefulWidget { final Widget child; final bool dark; final bool debugOnly; + final List levelsToFilter; + final Level defaultLevel; LogConsoleOnShake({ @required this.child, this.dark, this.debugOnly = true, + this.levelsToFilter, + this.defaultLevel, }); @override @@ -52,6 +56,8 @@ class _LogConsoleOnShakeState extends State { var logConsole = LogConsole( showCloseButton: true, dark: widget.dark ?? Theme.of(context).brightness == Brightness.dark, + levelsToFilter: widget.levelsToFilter, + defaultLevel: widget.defaultLevel, ); PageRoute route; if (Platform.isIOS) { From 69b5256568c6447e66ddfa983f8d55ae0c12d48f Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sat, 16 May 2020 14:55:25 +0200 Subject: [PATCH 05/10] Add LogConsoleOnBoxGesture. --- lib/logger_flutter.dart | 4 +- lib/src/log_console_on_box_gesture.dart | 119 ++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 lib/src/log_console_on_box_gesture.dart diff --git a/lib/logger_flutter.dart b/lib/logger_flutter.dart index 1edd73c..c1df998 100644 --- a/lib/logger_flutter.dart +++ b/lib/logger_flutter.dart @@ -6,6 +6,7 @@ import 'dart:io'; import 'dart:ui'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:logger/logger.dart'; @@ -13,5 +14,6 @@ import 'package:logger/logger.dart'; import 'src/ansi_parser.dart'; import 'src/shake_detector.dart'; -part 'src/log_console_on_shake.dart'; part 'src/log_console.dart'; +part 'src/log_console_on_box_gesture.dart'; +part 'src/log_console_on_shake.dart'; diff --git a/lib/src/log_console_on_box_gesture.dart b/lib/src/log_console_on_box_gesture.dart new file mode 100644 index 0000000..c287b51 --- /dev/null +++ b/lib/src/log_console_on_box_gesture.dart @@ -0,0 +1,119 @@ +part of logger_flutter; + +enum _Direction { + left, + right, + up, + down, +} + +class LogConsoleOnBoxGesture extends StatefulWidget { + final Widget child; + final bool dark; + final bool debugOnly; + final List levelsToFilter; + final Level defaultLevel; + + LogConsoleOnBoxGesture({ + @required this.child, + this.dark, + this.debugOnly = true, + this.levelsToFilter, + this.defaultLevel, + }); + + @override + _LogConsoleOnCircleGestureState createState() => _LogConsoleOnCircleGestureState(); +} + +class _LogConsoleOnCircleGestureState extends State { + bool _open = false; + + @override + void initState() { + super.initState(); + + if (widget.debugOnly) { + assert(() { + _init(); + return true; + }()); + } else { + _init(); + } + } + + List _dragUpdateDetails = []; + static const _patternDirection = {_Direction.down, _Direction.right, _Direction.up, _Direction.left}; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onPanUpdate: (dragUpdateDetails) => _dragUpdateDetails.add(dragUpdateDetails), + onPanEnd: (_) => _checkForPattern(), + child: SizedBox.expand( + child: Container( + color: Colors.transparent, + child: widget.child, + ), + ), + ); + } + + void _checkForPattern() { + const tol = 10; + Offset start = _dragUpdateDetails.first.globalPosition; + List<_Direction> directions = []; + for (final details in _dragUpdateDetails) { + final dx = (details.globalPosition - start).dx; + final dy = (details.globalPosition - start).dy; + + // if one axis delta is sufficiently large, determine direction and set new start reference point + if (dx.abs() > tol || dy.abs() > tol) { + _Direction direction; + if (dy.abs() > dx.abs()) { + direction = dy < 0 ? _Direction.up : _Direction.down; + } else { + direction = dx > 0 ? _Direction.right : _Direction.left; + } + directions.add(direction); + start = details.globalPosition; + } + } + + /// determine if directions match pattern + final filteredDirections = Set.from(directions); + if (setEquals(filteredDirections, _patternDirection)) { + _openLogConsole(); + } + + // reset for next test + _dragUpdateDetails.clear(); + } + + void _init() { + LogConsole.init(); + } + + Future _openLogConsole() async { + if (_open) return; + + _open = true; + + final logConsole = LogConsole( + showCloseButton: true, + dark: widget.dark ?? Theme.of(context).brightness == Brightness.dark, + levelsToFilter: widget.levelsToFilter, + defaultLevel: widget.defaultLevel, + ); + PageRoute route; + if (Platform.isIOS) { + route = CupertinoPageRoute(builder: (_) => logConsole); + } else { + route = MaterialPageRoute(builder: (_) => logConsole); + } + + await Navigator.push(context, route); + _open = false; + } +} From 0dba9d05cdb8ab5209a0edb92820ffb0a983125c Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sat, 16 May 2020 15:36:51 +0200 Subject: [PATCH 06/10] Add lineWidth parameter. --- lib/src/log_console.dart | 46 +++++++++++++++---------- lib/src/log_console_on_box_gesture.dart | 3 ++ lib/src/log_console_on_shake.dart | 3 ++ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/lib/src/log_console.dart b/lib/src/log_console.dart index c46ab1f..8aff289 100644 --- a/lib/src/log_console.dart +++ b/lib/src/log_console.dart @@ -9,12 +9,14 @@ class LogConsole extends StatefulWidget { final bool showCloseButton; final List levelsToFilter; final Level defaultLevel; + final double lineWidth; LogConsole({ this.dark = false, this.showCloseButton = false, List levelsToFilter, Level defaultLevel, + this.lineWidth = 1600, }) : levelsToFilter = levelsToFilter ?? const [Level.verbose, Level.debug, Level.info, Level.warning, Level.error, Level.wtf], defaultLevel = defaultLevel ?? Level.verbose, @@ -177,27 +179,33 @@ class _LogConsoleState extends State { } Widget _buildLogContent() { + final elements = 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, + ); + + final child = widget.lineWidth != null && widget.lineWidth > 0 + ? SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: SizedBox( + width: widget.lineWidth, + child: elements, + ), + ) + : elements; + 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, - ), - ), - ), + child: child, ); } diff --git a/lib/src/log_console_on_box_gesture.dart b/lib/src/log_console_on_box_gesture.dart index c287b51..3ac4840 100644 --- a/lib/src/log_console_on_box_gesture.dart +++ b/lib/src/log_console_on_box_gesture.dart @@ -13,6 +13,7 @@ class LogConsoleOnBoxGesture extends StatefulWidget { final bool debugOnly; final List levelsToFilter; final Level defaultLevel; + final double lineWidth; LogConsoleOnBoxGesture({ @required this.child, @@ -20,6 +21,7 @@ class LogConsoleOnBoxGesture extends StatefulWidget { this.debugOnly = true, this.levelsToFilter, this.defaultLevel, + this.lineWidth, }); @override @@ -105,6 +107,7 @@ class _LogConsoleOnCircleGestureState extends State { dark: widget.dark ?? Theme.of(context).brightness == Brightness.dark, levelsToFilter: widget.levelsToFilter, defaultLevel: widget.defaultLevel, + lineWidth: widget.lineWidth, ); PageRoute route; if (Platform.isIOS) { diff --git a/lib/src/log_console_on_shake.dart b/lib/src/log_console_on_shake.dart index 7ab365d..8b116eb 100644 --- a/lib/src/log_console_on_shake.dart +++ b/lib/src/log_console_on_shake.dart @@ -6,6 +6,7 @@ class LogConsoleOnShake extends StatefulWidget { final bool debugOnly; final List levelsToFilter; final Level defaultLevel; + final double lineWidth; LogConsoleOnShake({ @required this.child, @@ -13,6 +14,7 @@ class LogConsoleOnShake extends StatefulWidget { this.debugOnly = true, this.levelsToFilter, this.defaultLevel, + this.lineWidth, }); @override @@ -58,6 +60,7 @@ class _LogConsoleOnShakeState extends State { dark: widget.dark ?? Theme.of(context).brightness == Brightness.dark, levelsToFilter: widget.levelsToFilter, defaultLevel: widget.defaultLevel, + lineWidth: widget.lineWidth, ); PageRoute route; if (Platform.isIOS) { From 90161ca16990f9176a8cfc0ef13d45dd9b5f7f41 Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sun, 17 May 2020 10:36:09 +0200 Subject: [PATCH 07/10] Add check to ensure there are position updates before calculating direction. --- lib/src/log_console_on_box_gesture.dart | 50 +++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/lib/src/log_console_on_box_gesture.dart b/lib/src/log_console_on_box_gesture.dart index 3ac4840..16d9a43 100644 --- a/lib/src/log_console_on_box_gesture.dart +++ b/lib/src/log_console_on_box_gesture.dart @@ -64,33 +64,37 @@ class _LogConsoleOnCircleGestureState extends State { void _checkForPattern() { const tol = 10; - Offset start = _dragUpdateDetails.first.globalPosition; - List<_Direction> directions = []; - for (final details in _dragUpdateDetails) { - final dx = (details.globalPosition - start).dx; - final dy = (details.globalPosition - start).dy; - - // if one axis delta is sufficiently large, determine direction and set new start reference point - if (dx.abs() > tol || dy.abs() > tol) { - _Direction direction; - if (dy.abs() > dx.abs()) { - direction = dy < 0 ? _Direction.up : _Direction.down; - } else { - direction = dx > 0 ? _Direction.right : _Direction.left; + if (_dragUpdateDetails.length > 0) { + Offset start = _dragUpdateDetails.first.globalPosition; + List<_Direction> directions = []; + for (final details in _dragUpdateDetails) { + final dx = (details.globalPosition - start).dx; + final dy = (details.globalPosition - start).dy; + + // if one axis delta is sufficiently large, determine direction and set new start reference point + if (dx.abs() > tol || dy.abs() > tol) { + _Direction direction; + if (dy.abs() > dx.abs()) { + direction = dy < 0 ? _Direction.up : _Direction.down; + } else { + direction = dx > 0 ? _Direction.right : _Direction.left; + } + directions.add(direction); + start = details.globalPosition; } - directions.add(direction); - start = details.globalPosition; } - } - /// determine if directions match pattern - final filteredDirections = Set.from(directions); - if (setEquals(filteredDirections, _patternDirection)) { - _openLogConsole(); - } + if (directions.length > 0) { + /// determine if directions match pattern + final filteredDirections = Set.from(directions); + if (setEquals(filteredDirections, _patternDirection)) { + _openLogConsole(); + } + } - // reset for next test - _dragUpdateDetails.clear(); + // reset for next test + _dragUpdateDetails.clear(); + } } void _init() { From 1fd784994ba670d0fcb182e1640aab0c1a3299f2 Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sun, 17 May 2020 11:06:25 +0200 Subject: [PATCH 08/10] Merge LogConsoleOnShake and LogConsoleOnBoxGesture into LogConsoleOnGesture. --- example/lib/main.dart | 5 +- lib/logger_flutter.dart | 3 +- ...sture.dart => log_console_on_gesture.dart} | 147 +++++++++++++----- lib/src/log_console_on_shake.dart | 81 ---------- 4 files changed, 113 insertions(+), 123 deletions(-) rename lib/src/{log_console_on_box_gesture.dart => log_console_on_gesture.dart} (60%) delete mode 100644 lib/src/log_console_on_shake.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 14c48d6..dc932e6 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,6 @@ -import 'package:flutter/material.dart'; import 'dart:async'; +import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; import 'package:logger_flutter/logger_flutter.dart'; @@ -37,7 +37,8 @@ class MyApp extends StatelessWidget { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( - body: LogConsoleOnShake( + body: LogConsoleOnGesture( + gesture: Gesture.shake, dark: true, child: Center( child: Text("Shake Phone to open Console."), diff --git a/lib/logger_flutter.dart b/lib/logger_flutter.dart index c1df998..4528f76 100644 --- a/lib/logger_flutter.dart +++ b/lib/logger_flutter.dart @@ -15,5 +15,4 @@ import 'src/ansi_parser.dart'; import 'src/shake_detector.dart'; part 'src/log_console.dart'; -part 'src/log_console_on_box_gesture.dart'; -part 'src/log_console_on_shake.dart'; +part 'src/log_console_on_gesture.dart'; diff --git a/lib/src/log_console_on_box_gesture.dart b/lib/src/log_console_on_gesture.dart similarity index 60% rename from lib/src/log_console_on_box_gesture.dart rename to lib/src/log_console_on_gesture.dart index 16d9a43..4048713 100644 --- a/lib/src/log_console_on_box_gesture.dart +++ b/lib/src/log_console_on_gesture.dart @@ -1,22 +1,22 @@ part of logger_flutter; -enum _Direction { - left, - right, - up, - down, +enum Gesture { + shake, + boxCircle, } -class LogConsoleOnBoxGesture extends StatefulWidget { +class LogConsoleOnGesture extends StatefulWidget { final Widget child; + final Gesture gesture; final bool dark; final bool debugOnly; final List levelsToFilter; final Level defaultLevel; final double lineWidth; - LogConsoleOnBoxGesture({ + LogConsoleOnGesture({ @required this.child, + this.gesture = Gesture.shake, this.dark, this.debugOnly = true, this.levelsToFilter, @@ -25,11 +25,12 @@ class LogConsoleOnBoxGesture extends StatefulWidget { }); @override - _LogConsoleOnCircleGestureState createState() => _LogConsoleOnCircleGestureState(); + _LogConsoleOnGestureState createState() => _LogConsoleOnGestureState(); } -class _LogConsoleOnCircleGestureState extends State { +class _LogConsoleOnGestureState extends State { bool _open = false; + bool _shouldRender = true; @override void initState() { @@ -45,9 +46,106 @@ class _LogConsoleOnCircleGestureState extends State { } } - List _dragUpdateDetails = []; + @override + Widget build(BuildContext context) { + if (_shouldRender) { + return widget.gesture == Gesture.shake + ? _OnShake( + child: widget.child, + onShowConsole: _openLogConsole, + ) + : _OnBoxCircle( + child: widget.child, + onShowConsole: _openLogConsole, + ); + } + + return widget.child; + } + + void _init() => LogConsole.init(); + + Future _openLogConsole() async { + if (_open) return; + + _open = true; + + final logConsole = LogConsole( + showCloseButton: true, + dark: widget.dark ?? Theme.of(context).brightness == Brightness.dark, + levelsToFilter: widget.levelsToFilter, + defaultLevel: widget.defaultLevel, + lineWidth: widget.lineWidth, + ); + PageRoute route; + if (Platform.isIOS) { + route = CupertinoPageRoute(builder: (_) => logConsole); + } else { + route = MaterialPageRoute(builder: (_) => logConsole); + } + + await Navigator.push(context, route); + _open = false; + } +} + +class _OnShake extends StatefulWidget { + final Widget child; + final Future Function() onShowConsole; + + const _OnShake({@required this.child, @required this.onShowConsole, Key key}) : super(key: key); + + @override + __OnShakeState createState() => __OnShakeState(); +} + +class __OnShakeState extends State<_OnShake> { + ShakeDetector _detector; + + @override + void initState() { + super.initState(); + + _detector = ShakeDetector( + onPhoneShake: () async => await widget.onShowConsole(), + ); + _detector.startListening(); + } + + @override + void dispose() { + _detector.stopListening(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return widget.child; + } +} + +enum _Direction { + left, + right, + up, + down, +} + +class _OnBoxCircle extends StatefulWidget { + final Widget child; + final Future Function() onShowConsole; + + const _OnBoxCircle({@required this.child, @required this.onShowConsole, Key key}) : super(key: key); + + @override + __OnBoxCircleState createState() => __OnBoxCircleState(); +} + +class __OnBoxCircleState extends State<_OnBoxCircle> { static const _patternDirection = {_Direction.down, _Direction.right, _Direction.up, _Direction.left}; + List _dragUpdateDetails = []; + @override Widget build(BuildContext context) { return GestureDetector( @@ -88,7 +186,7 @@ class _LogConsoleOnCircleGestureState extends State { /// determine if directions match pattern final filteredDirections = Set.from(directions); if (setEquals(filteredDirections, _patternDirection)) { - _openLogConsole(); + widget.onShowConsole(); } } @@ -96,31 +194,4 @@ class _LogConsoleOnCircleGestureState extends State { _dragUpdateDetails.clear(); } } - - void _init() { - LogConsole.init(); - } - - Future _openLogConsole() async { - if (_open) return; - - _open = true; - - final logConsole = LogConsole( - showCloseButton: true, - dark: widget.dark ?? Theme.of(context).brightness == Brightness.dark, - levelsToFilter: widget.levelsToFilter, - defaultLevel: widget.defaultLevel, - lineWidth: widget.lineWidth, - ); - PageRoute route; - if (Platform.isIOS) { - route = CupertinoPageRoute(builder: (_) => logConsole); - } else { - route = MaterialPageRoute(builder: (_) => logConsole); - } - - await Navigator.push(context, route); - _open = false; - } } diff --git a/lib/src/log_console_on_shake.dart b/lib/src/log_console_on_shake.dart deleted file mode 100644 index 8b116eb..0000000 --- a/lib/src/log_console_on_shake.dart +++ /dev/null @@ -1,81 +0,0 @@ -part of logger_flutter; - -class LogConsoleOnShake extends StatefulWidget { - final Widget child; - final bool dark; - final bool debugOnly; - final List levelsToFilter; - final Level defaultLevel; - final double lineWidth; - - LogConsoleOnShake({ - @required this.child, - this.dark, - this.debugOnly = true, - this.levelsToFilter, - this.defaultLevel, - this.lineWidth, - }); - - @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, - levelsToFilter: widget.levelsToFilter, - defaultLevel: widget.defaultLevel, - lineWidth: widget.lineWidth, - ); - 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(); - } -} From 6d0434ad687eeccfd942c13a33f67ae1ec45ab37 Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sun, 17 May 2020 11:11:34 +0200 Subject: [PATCH 09/10] Fix bug lineWidth not initialized in constructor. --- lib/src/log_console.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/log_console.dart b/lib/src/log_console.dart index 8aff289..4c01634 100644 --- a/lib/src/log_console.dart +++ b/lib/src/log_console.dart @@ -16,10 +16,11 @@ class LogConsole extends StatefulWidget { this.showCloseButton = false, List levelsToFilter, Level defaultLevel, - this.lineWidth = 1600, + double lineWidth, }) : levelsToFilter = levelsToFilter ?? const [Level.verbose, Level.debug, Level.info, Level.warning, Level.error, Level.wtf], defaultLevel = defaultLevel ?? Level.verbose, + lineWidth = lineWidth ?? 1600, assert(_initialized, "Please call LogConsole.init() first."); static void init({int bufferSize = 20}) { From 82fa24d68d9164c4934e39dac2797198ab3c4c38 Mon Sep 17 00:00:00 2001 From: James Leahy Date: Sun, 17 May 2020 11:24:55 +0200 Subject: [PATCH 10/10] Add spaceBetweenElements parameter. --- lib/src/log_console.dart | 14 ++++++++++---- lib/src/log_console_on_gesture.dart | 3 +++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/src/log_console.dart b/lib/src/log_console.dart index 4c01634..9092e50 100644 --- a/lib/src/log_console.dart +++ b/lib/src/log_console.dart @@ -10,6 +10,7 @@ class LogConsole extends StatefulWidget { final List levelsToFilter; final Level defaultLevel; final double lineWidth; + final bool spaceBetweenElements; LogConsole({ this.dark = false, @@ -17,10 +18,12 @@ class LogConsole extends StatefulWidget { List levelsToFilter, Level defaultLevel, double lineWidth, + bool spaceBetweenElements, }) : levelsToFilter = levelsToFilter ?? const [Level.verbose, Level.debug, Level.info, Level.warning, Level.error, Level.wtf], defaultLevel = defaultLevel ?? Level.verbose, lineWidth = lineWidth ?? 1600, + spaceBetweenElements = spaceBetweenElements ?? false, assert(_initialized, "Please call LogConsole.init() first."); static void init({int bufferSize = 20}) { @@ -185,10 +188,13 @@ class _LogConsoleState extends State { controller: _scrollController, itemBuilder: (context, index) { var logEntry = _filteredBuffer[index]; - return Text.rich( - logEntry.span, - key: Key(logEntry.id.toString()), - style: TextStyle(fontSize: _logFontSize), + return Padding( + padding: EdgeInsets.symmetric(vertical: widget.spaceBetweenElements ? 4.0 : 0.0), + child: Text.rich( + logEntry.span, + key: Key(logEntry.id.toString()), + style: TextStyle(fontSize: _logFontSize), + ), ); }, itemCount: _filteredBuffer.length, diff --git a/lib/src/log_console_on_gesture.dart b/lib/src/log_console_on_gesture.dart index 4048713..0d09366 100644 --- a/lib/src/log_console_on_gesture.dart +++ b/lib/src/log_console_on_gesture.dart @@ -13,6 +13,7 @@ class LogConsoleOnGesture extends StatefulWidget { final List levelsToFilter; final Level defaultLevel; final double lineWidth; + final bool spaceBetweenElements; LogConsoleOnGesture({ @required this.child, @@ -22,6 +23,7 @@ class LogConsoleOnGesture extends StatefulWidget { this.levelsToFilter, this.defaultLevel, this.lineWidth, + this.spaceBetweenElements, }); @override @@ -76,6 +78,7 @@ class _LogConsoleOnGestureState extends State { levelsToFilter: widget.levelsToFilter, defaultLevel: widget.defaultLevel, lineWidth: widget.lineWidth, + spaceBetweenElements: widget.spaceBetweenElements, ); PageRoute route; if (Platform.isIOS) {