diff --git a/packages/devtools_app/lib/src/screens/logging/_log_details.dart b/packages/devtools_app/lib/src/screens/logging/_log_details.dart index 977af418050..7895b2eed28 100644 --- a/packages/devtools_app/lib/src/screens/logging/_log_details.dart +++ b/packages/devtools_app/lib/src/screens/logging/_log_details.dart @@ -11,12 +11,15 @@ import 'package:flutter/material.dart'; import '../../shared/globals.dart'; import '../../shared/preferences/preferences.dart'; import '../../shared/ui/common_widgets.dart'; +import '../../shared/ui/search.dart'; +import 'log_details_controller.dart'; import 'logging_controller.dart'; class LogDetails extends StatefulWidget { - const LogDetails({super.key, required this.log}); + const LogDetails({super.key, required this.log, required this.controller}); final LogData? log; + final LogDetailsController controller; @override State createState() => _LogDetailsState(); @@ -45,6 +48,10 @@ class _LogDetailsState extends State if (widget.log != oldWidget.log) { unawaited(_computeLogDetails()); } + if (widget.controller != oldWidget.controller) { + cancelListeners(); + addAutoDisposeListener(preferences.logging.detailsFormat); + } } Future _computeLogDetails() async { @@ -81,6 +88,7 @@ class _LogDetailsState extends State header: _LogDetailsHeader( log: log, format: preferences.logging.detailsFormat.value, + controller: widget.controller, ), child: Scrollbar( controller: scrollController, @@ -93,9 +101,9 @@ class _LogDetailsState extends State ? Padding( padding: const EdgeInsets.all(denseSpacing), child: SelectionArea( - child: Text( - log?.prettyPrinted() ?? '', - textAlign: TextAlign.left, + child: _SearchableLogDetailsText( + text: log?.prettyPrinted() ?? '', + controller: widget.controller, ), ), ) @@ -107,10 +115,15 @@ class _LogDetailsState extends State } class _LogDetailsHeader extends StatelessWidget { - const _LogDetailsHeader({required this.log, required this.format}); + const _LogDetailsHeader({ + required this.log, + required this.format, + required this.controller, + }); final LogData? log; final LoggingDetailsFormat format; + final LogDetailsController controller; @override Widget build(BuildContext context) { @@ -122,7 +135,13 @@ class _LogDetailsHeader extends StatelessWidget { title: const Text('Details'), includeTopBorder: false, roundedTopBorder: false, + tall: true, actions: [ + // Only supporting search for the text format now since supporting this + // for the expandable JSON viewer would require a more complicated + // refactor of that shared component. + if (format == LoggingDetailsFormat.text) + _LogDetailsSearchField(controller: controller, log: log), LogDetailsFormatButton(format: format), const SizedBox(width: densePadding), CopyToClipboardControl( @@ -134,6 +153,140 @@ class _LogDetailsHeader extends StatelessWidget { } } +/// An animated search field for the log details view that toggles between an icon +/// and a full [SearchField]. +class _LogDetailsSearchField extends StatefulWidget { + const _LogDetailsSearchField({required this.controller, required this.log}); + + final LogDetailsController controller; + final LogData? log; + + @override + State<_LogDetailsSearchField> createState() => _LogDetailsSearchFieldState(); +} + +class _LogDetailsSearchFieldState extends State<_LogDetailsSearchField> + with AutoDisposeMixin { + late bool _isExpanded; + + @override + void initState() { + super.initState(); + _isExpanded = widget.controller.search.isNotEmpty; + addAutoDisposeListener(widget.controller.searchFieldFocusNode, () { + final hasFocus = + widget.controller.searchFieldFocusNode?.hasFocus ?? false; + if (hasFocus != _isExpanded) { + setState(() { + _isExpanded = hasFocus; + }); + } + }); + } + + @override + Widget build(BuildContext context) { + return AnimatedContainer( + duration: defaultDuration, + curve: defaultCurve, + width: _isExpanded ? mediumSearchFieldWidth : defaultButtonHeight, + child: OverflowBox( + minWidth: 0.0, + maxWidth: mediumSearchFieldWidth, + child: _isExpanded + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: densePadding), + child: SearchField( + searchController: widget.controller, + searchFieldEnabled: + widget.log != null && widget.log!.details != null, + shouldRequestFocus: true, + searchFieldWidth: mediumSearchFieldWidth, + ), + ) + : ToolbarAction( + icon: Icons.search, + tooltip: 'Search details', + size: defaultIconSize, + onPressed: () { + setState(() { + _isExpanded = true; + }); + widget.controller.searchFieldFocusNode?.requestFocus(); + }, + ), + ), + ); + } +} + +/// A text widget for the log details view that highlights search matches. +class _SearchableLogDetailsText extends StatelessWidget { + const _SearchableLogDetailsText({ + required this.text, + required this.controller, + }); + + final String text; + final LogDetailsController controller; + + @override + Widget build(BuildContext context) { + return MultiValueListenableBuilder( + listenables: [controller.searchMatches, controller.activeSearchMatch], + builder: (context, values, _) { + final theme = Theme.of(context); + + final matches = values[0] as List; + final activeMatch = values[1] as LogDetailsMatch?; + if (matches.isEmpty) { + return Text( + text, + textAlign: TextAlign.left, + style: theme.regularTextStyle, + ); + } + + final spans = []; + int previousEnd = 0; + for (final match in matches) { + if (match.range.begin > previousEnd) { + spans.add( + TextSpan( + text: text.substring(previousEnd, match.range.begin as int), + ), + ); + } + final isActive = match == activeMatch; + spans.add( + TextSpan( + text: text.substring( + match.range.begin as int, + match.range.end as int, + ), + style: theme.regularTextStyle.copyWith( + backgroundColor: isActive + ? activeSearchMatchColor + : searchMatchColor, + color: Colors.black, + ), + ), + ); + previousEnd = match.range.end as int; + } + + if (previousEnd < text.length) { + spans.add(TextSpan(text: text.substring(previousEnd))); + } + + return Text.rich( + TextSpan(style: theme.regularTextStyle, children: spans), + ); + }, + ); + } +} + @visibleForTesting class LogDetailsFormatButton extends StatelessWidget { const LogDetailsFormatButton({super.key, required this.format}); diff --git a/packages/devtools_app/lib/src/screens/logging/_logs_table.dart b/packages/devtools_app/lib/src/screens/logging/_logs_table.dart index 0475919955a..c406a428d45 100644 --- a/packages/devtools_app/lib/src/screens/logging/_logs_table.dart +++ b/packages/devtools_app/lib/src/screens/logging/_logs_table.dart @@ -48,6 +48,7 @@ class LogsTable extends StatelessWidget { defaultSortDirection: SortDirection.ascending, secondarySortColumn: messageColumn, rowHeight: _logRowHeight, + tallHeaders: true, ); } } diff --git a/packages/devtools_app/lib/src/screens/logging/log_details_controller.dart b/packages/devtools_app/lib/src/screens/logging/log_details_controller.dart new file mode 100644 index 00000000000..33eec934c63 --- /dev/null +++ b/packages/devtools_app/lib/src/screens/logging/log_details_controller.dart @@ -0,0 +1,62 @@ +// Copyright 2024 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. + +import 'package:devtools_app_shared/utils.dart'; +import 'package:flutter/foundation.dart'; + +import '../../shared/primitives/utils.dart'; +import '../../shared/ui/search.dart'; +import 'logging_controller.dart'; + +/// A controller for the log details view that provides search functionality. +class LogDetailsController extends DisposableController + with SearchControllerMixin, AutoDisposeControllerMixin { + LogDetailsController({required ValueListenable selectedLog}) { + init(); + addAutoDisposeListener(selectedLog, () { + _selectedLog = selectedLog.value; + refreshSearchMatches(); + }); + } + + LogData? _selectedLog; + + @override + List matchesForSearch( + String search, { + bool searchPreviousMatches = false, + }) { + if (search.isEmpty || _selectedLog == null) return []; + final matches = []; + + final text = _selectedLog!.prettyPrinted(); + if (text == null) return []; + + final regex = RegExp(search, caseSensitive: false); + final allMatches = regex.allMatches(text); + for (final match in allMatches) { + matches.add(LogDetailsMatch(match.start, match.end)); + } + return matches; + } + + @override + void dispose() { + _selectedLog = null; + super.dispose(); + } +} + +/// A search match in the log details view. +class LogDetailsMatch with SearchableDataMixin { + LogDetailsMatch(this.start, this.end); + + final int start; + final int end; + + Range get range => Range(start, end); + + @override + bool matchesSearchToken(RegExp regExpSearch) => false; +} diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart index 8f9818c584a..fa93986930c 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -28,6 +28,7 @@ import '../../shared/primitives/utils.dart'; import '../../shared/ui/filter.dart'; import '../../shared/ui/search.dart'; import '../inspector/inspector_tree_controller.dart'; +import 'log_details_controller.dart'; import 'logging_screen.dart'; import 'metadata.dart'; @@ -110,6 +111,8 @@ class LoggingController extends DevToolsScreenController @override void init() { super.init(); + logDetailsController = LogDetailsController(selectedLog: selectedLog) + ..init(); addAutoDisposeListener(serviceConnection.serviceManager.connectedState, () { if (serviceConnection.serviceManager.connectedState.value.connected) { _handleConnectionStart(serviceConnection.serviceManager.service!); @@ -138,6 +141,7 @@ class LoggingController extends DevToolsScreenController @override void dispose() { + logDetailsController.dispose(); selectedLog.dispose(); unawaited(_logStatusController.close()); super.dispose(); @@ -234,6 +238,8 @@ class LoggingController extends DevToolsScreenController final _logStatusController = StreamController.broadcast(); + late final LogDetailsController logDetailsController; + List data = []; final selectedLog = ValueNotifier(null); diff --git a/packages/devtools_app/lib/src/screens/logging/logging_screen.dart b/packages/devtools_app/lib/src/screens/logging/logging_screen.dart index 2b68a9dc1fe..79d2c7cfbe2 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_screen.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_screen.dart @@ -87,7 +87,10 @@ class _LoggingScreenState extends State ValueListenableBuilder( valueListenable: controller.selectedLog, builder: (context, selected, _) { - return LogDetails(log: selected); + return LogDetails( + log: selected, + controller: controller.logDetailsController, + ); }, ), ], diff --git a/packages/devtools_app/lib/src/shared/table/_flat_table.dart b/packages/devtools_app/lib/src/shared/table/_flat_table.dart index 79bb3e7d15d..154868a0026 100644 --- a/packages/devtools_app/lib/src/shared/table/_flat_table.dart +++ b/packages/devtools_app/lib/src/shared/table/_flat_table.dart @@ -33,6 +33,7 @@ class SearchableFlatTable extends FlatTable { super.sizeColumnsToFit = true, super.rowHeight, super.selectionNotifier, + super.tallHeaders, }) : super( searchMatchesNotifier: searchController.searchMatches, activeSearchMatchNotifier: searchController.activeSearchMatch, diff --git a/packages/devtools_app/lib/src/shared/table/_table_row.dart b/packages/devtools_app/lib/src/shared/table/_table_row.dart index b7c6a010b92..afecd702bc7 100644 --- a/packages/devtools_app/lib/src/shared/table/_table_row.dart +++ b/packages/devtools_app/lib/src/shared/table/_table_row.dart @@ -263,7 +263,7 @@ class _TableRowState extends State> final box = SizedBox( height: widget._rowType == _TableRowType.data ? defaultRowHeight - : defaultHeaderHeight + (widget.tall ? densePadding : 0.0), + : defaultHeaderHeight + (widget.tall ? 2 * densePadding : 0.0), child: Material( color: _searchAwareBackgroundColor(), child: onPressed != null diff --git a/packages/devtools_app/macos/Runner.xcodeproj/project.pbxproj b/packages/devtools_app/macos/Runner.xcodeproj/project.pbxproj index 59aa8f360ec..ce7a071de3b 100644 --- a/packages/devtools_app/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/devtools_app/macos/Runner.xcodeproj/project.pbxproj @@ -21,14 +21,13 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 11595299B00138FF6A219878 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46084CB9F244837191E61B73 /* Pods_RunnerTests.framework */; }; 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; - E678665441E5C0F7F629BAD5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -62,8 +61,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 11BB555C0F1767B9B5CB7CE0 /* 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 = ""; }; - 13053082F27293B7166BCBED /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; @@ -80,14 +77,9 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 46084CB9F244837191E61B73 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 68C587FFA5A0B8F46A0C5150 /* 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 = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A7CE48BF63861DD9F3A9FA2F /* 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 = ""; }; - BDEB23F5F07C7F498EB77EA2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - E11974409F5281249C10F0E1 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -95,7 +87,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 11595299B00138FF6A219878 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -103,7 +94,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E678665441E5C0F7F629BAD5 /* Pods_Runner.framework in Frameworks */, + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -136,8 +127,6 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, - 618DD25D42BF0C167E4D5128 /* Pods */, ); sourceTree = ""; }; @@ -164,6 +153,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -185,29 +175,6 @@ path = Runner; sourceTree = ""; }; - 618DD25D42BF0C167E4D5128 /* Pods */ = { - isa = PBXGroup; - children = ( - 11BB555C0F1767B9B5CB7CE0 /* Pods-Runner.debug.xcconfig */, - 68C587FFA5A0B8F46A0C5150 /* Pods-Runner.release.xcconfig */, - A7CE48BF63861DD9F3A9FA2F /* Pods-Runner.profile.xcconfig */, - E11974409F5281249C10F0E1 /* Pods-RunnerTests.debug.xcconfig */, - BDEB23F5F07C7F498EB77EA2 /* Pods-RunnerTests.release.xcconfig */, - 13053082F27293B7166BCBED /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 5062035DDDD18FB35E98D5B6 /* Pods_Runner.framework */, - 46084CB9F244837191E61B73 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -215,7 +182,6 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 3E485AF46E5EF6A810E8A04C /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -234,13 +200,11 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - DC1C8B6797A659BE5B59B986 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - E765EEB3239836D35A4D4672 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -248,6 +212,9 @@ 33CC11202044C79F0003C045 /* PBXTargetDependency */, ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 33CC10ED2044A3C60003C045 /* devtools_app.app */; productType = "com.apple.product-type.application"; @@ -291,6 +258,9 @@ Base, ); mainGroup = 33CC10E42044A3C60003C045; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -360,67 +330,6 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - 3E485AF46E5EF6A810E8A04C /* [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-RunnerTests-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; - }; - DC1C8B6797A659BE5B59B986 /* [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; - }; - E765EEB3239836D35A4D4672 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -472,7 +381,6 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E11974409F5281249C10F0E1 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -487,7 +395,6 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BDEB23F5F07C7F498EB77EA2 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -502,7 +409,6 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 13053082F27293B7166BCBED /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -786,6 +692,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/packages/devtools_app/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/devtools_app/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000000..919434a6254 --- /dev/null +++ b/packages/devtools_app/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/devtools_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/devtools_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index cadfa603a2e..559bf4e57a2 100644 --- a/packages/devtools_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/devtools_app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + +