@bdayadev/flutter-ultra-mcp 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +41 -13
  4. package/dart/ultra_flutter/pubspec.yaml +1 -1
  5. package/dart/ultra_flutter_devtools/pubspec.yaml +1 -1
  6. package/package.json +1 -1
  7. package/packages/flutter-ultra-native-desktop/package.json +2 -0
  8. package/packages/flutter-ultra-native-mobile/package.json +2 -0
  9. package/skills/add-integration-test/SKILL.md +72 -20
  10. package/skills/add-unit-test/SKILL.md +1 -0
  11. package/skills/add-widget-preview/SKILL.md +75 -26
  12. package/skills/add-widget-test/SKILL.md +51 -22
  13. package/skills/apply-architecture-best-practices/SKILL.md +55 -29
  14. package/skills/build-cli-app/SKILL.md +36 -9
  15. package/skills/build-responsive-layout/SKILL.md +65 -31
  16. package/skills/collect-coverage/SKILL.md +12 -1
  17. package/skills/debug/SKILL.md +19 -2
  18. package/skills/drive/SKILL.md +30 -15
  19. package/skills/fix-layout-issues/SKILL.md +71 -20
  20. package/skills/fix-runtime-errors/SKILL.md +79 -20
  21. package/skills/generate-test-mocks/SKILL.md +43 -13
  22. package/skills/implement-json-serialization/SKILL.md +82 -17
  23. package/skills/migrate-to-checks-package/SKILL.md +46 -14
  24. package/skills/record-demo/SKILL.md +20 -0
  25. package/skills/resolve-package-conflicts/SKILL.md +41 -12
  26. package/skills/run-static-analysis/SKILL.md +29 -16
  27. package/skills/setup/SKILL.md +1 -0
  28. package/skills/setup-declarative-routing/SKILL.md +166 -30
  29. package/skills/setup-localization/SKILL.md +90 -20
  30. package/skills/test/SKILL.md +2 -1
  31. package/skills/tour/SKILL.md +31 -22
  32. package/skills/use-http-package/SKILL.md +61 -23
  33. package/skills/use-pattern-matching/SKILL.md +63 -26
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: apply-architecture-best-practices
3
3
  description: Architects a Flutter application using the recommended layered approach (UI, Logic, Data). Use when structuring a new project or refactoring for scalability.
4
+ last_modified: Tue, 21 Apr 2026 20:11:20 GMT
4
5
  ---
5
6
 
6
7
  # Architecting Flutter Applications
@@ -14,28 +15,30 @@ description: Architects a Flutter application using the recommended layered appr
14
15
 
15
16
  ## Architectural Layers
16
17
 
17
- Enforce strict Separation of Concerns by dividing the application into distinct layers.
18
+ Enforce strict Separation of Concerns by dividing the application into distinct layers. Never mix UI rendering with business logic or data fetching.
18
19
 
19
20
  ### UI Layer (Presentation)
20
21
 
21
- Implement the MVVM (Model-View-ViewModel) pattern.
22
+ Implement the MVVM (Model-View-ViewModel) pattern to manage UI state and logic.
22
23
 
23
- - **Views:** Reusable, lean widgets. Restrict logic to UI-specific operations.
24
- - **ViewModels:** Manage UI state. Extend `ChangeNotifier`. Expose immutable state snapshots. Inject Repositories via constructor.
24
+ - **Views:** Write reusable, lean widgets. Restrict logic in Views to UI-specific operations (e.g., animations, layout constraints, simple routing). Pass all required data from the ViewModel.
25
+ - **ViewModels:** Manage UI state and handle user interactions. Extend `ChangeNotifier` (or use `Listenable`) to expose state. Expose immutable state snapshots to the View. Inject Repositories into ViewModels via the constructor.
25
26
 
26
27
  ### Data Layer
27
28
 
28
- Implement the Repository pattern for a single source of truth.
29
+ Implement the Repository pattern to isolate data access logic and create a single source of truth.
29
30
 
30
- - **Services:** Stateless classes wrapping external APIs. Return raw API models or `Result` wrappers.
31
- - **Repositories:** Consume Services. Transform raw models into Domain Models. Handle caching and retry logic.
31
+ - **Services:** Create stateless classes to wrap external APIs (HTTP clients, local databases, platform plugins). Return raw API models or `Result` wrappers.
32
+ - **Repositories:** Consume one or more Services. Transform raw API models into clean Domain Models. Handle caching, offline synchronization, and retry logic. Expose Domain Models to ViewModels.
32
33
 
33
34
  ### Logic Layer (Domain - Optional)
34
35
 
35
- - **Use Cases:** Only if complex business logic clutters the ViewModel, or logic must be reused across ViewModels.
36
+ - **Use Cases:** Implement this layer only if the application contains complex business logic that clutters the ViewModel, or if logic must be reused across multiple ViewModels. Extract this logic into dedicated Use Case (interactor) classes that sit between ViewModels and Repositories.
36
37
 
37
38
  ## Project Structure
38
39
 
40
+ Organize the codebase using a hybrid approach: group UI components by feature, and group Data/Domain components by type.
41
+
39
42
  ```text
40
43
  lib/
41
44
  ├── data/
@@ -55,37 +58,46 @@ lib/
55
58
 
56
59
  ## Workflow: Implementing a New Feature
57
60
 
61
+ Follow this sequential workflow when adding a new feature to the application. Copy the checklist to track progress.
62
+
58
63
  ### Task Progress
59
64
 
60
- - [ ] **Step 1:** Define Domain Models (immutable data classes).
61
- - [ ] **Step 2:** Implement Services (external API communication).
62
- - [ ] **Step 3:** Implement Repositories (consume Services, return Domain Models).
63
- - [ ] **Step 4:** Apply Conditional Logic:
64
- - Complex data transformation or cross-repository logic: Create a Use Case.
65
- - Simple CRUD: Skip to Step 5.
66
- - [ ] **Step 5:** Implement the ViewModel (extend `ChangeNotifier`, inject Repositories).
67
- - [ ] **Step 6:** Implement the View (use `ListenableBuilder` to listen to ViewModel).
68
- - [ ] **Step 7:** Inject Dependencies (register in DI container).
69
- - [ ] **Step 8:** Run tests. Feedback Loop: Run -> Review -> Fix -> Re-run.
65
+ - [ ] **Step 1: Define Domain Models.** Create immutable data classes for the feature using `freezed` or `built_value`.
66
+ - [ ] **Step 2: Implement Services.** Create or update Service classes to handle external API communication.
67
+ - [ ] **Step 3: Implement Repositories.** Create the Repository to consume Services and return Domain Models.
68
+ - [ ] **Step 4: Apply Conditional Logic (Domain Layer).**
69
+ - _If the feature requires complex data transformation or cross-repository logic:_ Create a Use Case class.
70
+ - _If the feature is a simple CRUD operation:_ Skip to Step 5.
71
+ - [ ] **Step 5: Implement the ViewModel.** Create the ViewModel extending `ChangeNotifier`. Inject required Repositories/Use Cases. Expose immutable state and command methods.
72
+ - [ ] **Step 6: Implement the View.** Create the UI widget. Use `ListenableBuilder` or `AnimatedBuilder` to listen to ViewModel changes.
73
+ - [ ] **Step 7: Inject Dependencies.** Register the new Service, Repository, and ViewModel in the dependency injection container (e.g., `provider` or `get_it`).
74
+ - [ ] **Step 8: Run Validator.** Execute unit tests for the ViewModel and Repository.
75
+ - _Feedback Loop:_ Run tests -> Review failures -> Fix logic -> Re-run until passing.
70
76
 
71
77
  ## Examples
72
78
 
73
79
  ### Data Layer: Service and Repository
74
80
 
75
81
  ```dart
82
+ // 1. Service (Raw API interaction)
76
83
  class ApiClient {
77
- Future<UserApiModel> fetchUser(String id) async { /* ... */ }
84
+ Future<UserApiModel> fetchUser(String id) async {
85
+ // HTTP GET implementation...
86
+ }
78
87
  }
79
88
 
89
+ // 2. Repository (Single source of truth, returns Domain Model)
80
90
  class UserRepository {
81
91
  UserRepository({required ApiClient apiClient}) : _apiClient = apiClient;
92
+
82
93
  final ApiClient _apiClient;
83
94
  User? _cachedUser;
84
95
 
85
96
  Future<User> getUser(String id) async {
86
97
  if (_cachedUser != null) return _cachedUser!;
98
+
87
99
  final apiModel = await _apiClient.fetchUser(id);
88
- _cachedUser = User(id: apiModel.id, name: apiModel.fullName);
100
+ _cachedUser = User(id: apiModel.id, name: apiModel.fullName); // Transform to Domain Model
89
101
  return _cachedUser!;
90
102
  }
91
103
  }
@@ -94,19 +106,23 @@ class UserRepository {
94
106
  ### UI Layer: ViewModel and View
95
107
 
96
108
  ```dart
109
+ // 3. ViewModel (State management and presentation logic)
97
110
  class ProfileViewModel extends ChangeNotifier {
98
111
  ProfileViewModel({required UserRepository userRepository})
99
112
  : _userRepository = userRepository;
113
+
100
114
  final UserRepository _userRepository;
101
115
 
102
116
  User? _user;
103
117
  User? get user => _user;
118
+
104
119
  bool _isLoading = false;
105
120
  bool get isLoading => _isLoading;
106
121
 
107
122
  Future<void> loadProfile(String id) async {
108
123
  _isLoading = true;
109
124
  notifyListeners();
125
+
110
126
  try {
111
127
  _user = await _userRepository.getUser(id);
112
128
  } finally {
@@ -116,8 +132,10 @@ class ProfileViewModel extends ChangeNotifier {
116
132
  }
117
133
  }
118
134
 
135
+ // 4. View (Dumb UI component)
119
136
  class ProfileView extends StatelessWidget {
120
137
  const ProfileView({super.key, required this.viewModel});
138
+
121
139
  final ProfileViewModel viewModel;
122
140
 
123
141
  @override
@@ -125,16 +143,24 @@ class ProfileView extends StatelessWidget {
125
143
  return ListenableBuilder(
126
144
  listenable: viewModel,
127
145
  builder: (context, _) {
128
- if (viewModel.isLoading) return const Center(child: CircularProgressIndicator());
146
+ if (viewModel.isLoading) {
147
+ return const Center(child: CircularProgressIndicator());
148
+ }
149
+
129
150
  final user = viewModel.user;
130
- if (user == null) return const Center(child: Text('User not found'));
131
- return Column(children: [
132
- Text(user.name),
133
- ElevatedButton(
134
- onPressed: () => viewModel.loadProfile(user.id),
135
- child: const Text('Refresh'),
136
- ),
137
- ]);
151
+ if (user == null) {
152
+ return const Center(child: Text('User not found'));
153
+ }
154
+
155
+ return Column(
156
+ children: [
157
+ Text(user.name),
158
+ ElevatedButton(
159
+ onPressed: () => viewModel.loadProfile(user.id),
160
+ child: const Text('Refresh'),
161
+ ),
162
+ ],
163
+ );
138
164
  },
139
165
  );
140
166
  }
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: build-cli-app
3
3
  description: Entrypoint structure, exit codes, cross-platform scripts. Use when building command line utilities, scripts, or applications.
4
+ last_modified: Fri, 04 May 2026 17:41:00 GMT
4
5
  ---
5
6
 
6
7
  # Building Dart CLI Applications
@@ -32,7 +33,7 @@ Import the `args` package to manage command-line arguments, flags, and subcomman
32
33
  - If building a complex, multi-command CLI (like `git`): Implement `CommandRunner` and extend `Command` for each subcommand.
33
34
  - Define global arguments on the `CommandRunner.argParser` and command-specific arguments on the individual `Command.argParser`.
34
35
  - Catch `UsageException` to gracefully handle invalid arguments and display the automatically generated help text.
35
- - **Validate Help Text Accuracy**: Ensure the help text provides all necessary information to run the tool.
36
+ - **Validate Help Text Accuracy**: Ensure the help text provides all necessary information to run the tool. If the help text references a compiled executable name, and the user needs to add it to their PATH to run it that way, provide clear instructions on how to do so in the help text or description.
36
37
 
37
38
  ## Execution & Error Handling
38
39
 
@@ -42,11 +43,14 @@ Leverage the `io` and `stack_trace` packages to build robust, production-ready C
42
43
  - Use `sharedStdIn` from the `io` package if multiple asynchronous listeners need sequential access to standard input.
43
44
  - Wrap the application execution in `Chain.capture()` from the `stack_trace` package to track asynchronous stack chains.
44
45
  - Format output stack traces using `Trace.terse` or `Chain.terse` to strip noisy core library frames and present readable errors to the user.
45
- - **Do not swallow exceptions** in lower-level logic unless recovery is possible. Let them bubble up.
46
- - **Fail fast and with non-zero exit codes**: Ensure operation failures result in descriptive error messages to `stderr` and appropriate non-zero exit codes.
46
+ - **Do not swallow exceptions** in lower-level logic or storage classes unless recovery is possible. Let them bubble up or rethrow them so higher-level commands know operations failed.
47
+ - **Fail fast and with non-zero exit codes**: Ensure operation failures result in descriptive error messages to `stderr` and appropriate non-zero exit codes (e.g., using `exit(1)` or triggering a 64 exit code after a caught `UsageException`).
47
48
 
48
49
  ## Testing CLI Applications
49
50
 
51
+ > [!IMPORTANT]
52
+ > **All new commands and significant features must be covered by automated tests.** Manual verification is not sufficient for testing logic. However, manual verification of help text and user experience (UX) is still required to ensure the interface is intuitive and correct.
53
+
50
54
  Use `test_process` and `test_descriptor` to write high-fidelity integration tests for your CLI.
51
55
 
52
56
  - Define expected filesystem states using `test_descriptor` (`d.dir`, `d.file`).
@@ -61,9 +65,25 @@ Use `test_process` and `test_descriptor` to write high-fidelity integration test
61
65
  Select the appropriate compilation target based on your distribution requirements.
62
66
 
63
67
  - **If testing locally during development:** Use `dart run bin/cli.dart`. This uses the JIT compiler for rapid iteration.
64
- - **If bundling code assets and dynamic libraries:** Use `dart build cli`.
65
- - **If distributing a standalone native executable:** Use `dart compile exe bin/cli.dart -o <output_path>`.
66
- - **If distributing multiple apps with strict disk space limits:** Use `dart compile aot-snapshot bin/cli.dart`.
68
+ - **If bundling code assets and dynamic libraries:** Use `dart build cli`. This runs build hooks and outputs to `build/cli/_/bundle/`.
69
+ - **If distributing a standalone native executable:** Use `dart compile exe bin/cli.dart -o <output_path>`. This bundles the Dart runtime and machine code into a single file.
70
+ - **If distributing multiple apps with strict disk space limits:** Use `dart compile aot-snapshot bin/cli.dart`. Run the resulting `.aot` file using `dartaotruntime`.
71
+
72
+ <details>
73
+ <summary>Cross-Compilation Targets (Linux Only)</summary>
74
+
75
+ Dart supports cross-compiling to Linux from macOS, Windows, or Linux hosts.
76
+ Use the `--target-os` and `--target-arch` flags with `dart compile exe` or `dart compile aot-snapshot`.
77
+
78
+ - `--target-os=linux` (Only Linux is currently supported as a cross-compilation target)
79
+ - `--target-arch=arm64` (64-bit ARM)
80
+ - `--target-arch=x64` (x86-64)
81
+ - `--target-arch=arm` (32-bit ARM)
82
+ - `--target-arch=riscv64` (64-bit RISC-V)
83
+
84
+ Example: `dart compile exe --target-os=linux --target-arch=arm64 bin/cli.dart`
85
+
86
+ </details>
67
87
 
68
88
  ## Workflows
69
89
 
@@ -74,9 +94,9 @@ Select the appropriate compilation target based on your distribution requirement
74
94
  - [ ] Register command-specific flags in the constructor using `argParser.addFlag()` or `argParser.addOption()`.
75
95
  - [ ] Implement the `run()` method with the core logic.
76
96
  - [ ] Register the new command in the `CommandRunner` instance in `bin/cli.dart` using `addCommand()`.
77
- - [ ] Create tests for the new command in the `test/` directory.
97
+ - [ ] Create tests for the new command in the `test/` directory using `test_process` or standard tests.
78
98
  - [ ] Run validator -> Execute `dart run bin/cli.dart help <command_name>` to verify help text generation.
79
- - [ ] Verify final UX: Compile the application using `dart compile exe` and run the resulting executable.
99
+ - [ ] Verify final UX: Compile the application using `dart compile exe` and run the resulting executable to verify the target user experience (e.g., `./bin/cli <command>`).
80
100
 
81
101
  ### Task Progress: Compile and Release Native Executable
82
102
 
@@ -84,6 +104,7 @@ Select the appropriate compilation target based on your distribution requirement
84
104
  - [ ] Run validator -> Execute `dart analyze` to ensure no static analysis errors.
85
105
  - [ ] Run validator -> Execute `dart test` to pass all integration tests.
86
106
  - [ ] Compile for host OS: `dart compile exe bin/cli.dart -o build/cli-host`
107
+ - [ ] Compile for Linux (if host is macOS/Windows): `dart compile exe --target-os=linux --target-arch=x64 bin/cli.dart -o build/cli-linux-x64`
87
108
 
88
109
  ## Examples
89
110
 
@@ -121,7 +142,7 @@ void main(List<String> args) {
121
142
  if (error is UsageException) {
122
143
  stderr.writeln(error.message);
123
144
  stderr.writeln(error.usage);
124
- exit(64);
145
+ exit(64); // ExitCode.usage.code
125
146
  } else {
126
147
  stderr.writeln('Fatal error: $error');
127
148
  stderr.writeln(chain.terse);
@@ -140,18 +161,24 @@ import 'package:test_descriptor/test_descriptor.dart' as d;
140
161
 
141
162
  void main() {
142
163
  test('CLI formats output correctly and modifies filesystem', () async {
164
+ // 1. Setup mock filesystem
143
165
  await d.dir('project', [
144
166
  d.file('config.json', '{"key": "value"}')
145
167
  ]).create();
146
168
 
169
+ // 2. Spawn the CLI process
147
170
  final process = await TestProcess.start(
148
171
  'dart',
149
172
  ['run', 'bin/cli.dart', 'process', '--path', '${d.sandbox}/project']
150
173
  );
151
174
 
175
+ // 3. Validate stdout stream
152
176
  await expectLater(process.stdout, emitsThrough('Processing complete.'));
177
+
178
+ // 4. Validate exit code
153
179
  await process.shouldExit(0);
154
180
 
181
+ // 5. Validate filesystem mutations
155
182
  await d.dir('project', [
156
183
  d.file('config.json', '{"key": "value"}'),
157
184
  d.file('output.log', 'Success')
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: build-responsive-layout
3
3
  description: Use `LayoutBuilder`, `MediaQuery`, or `Expanded/Flexible` to create a layout that adapts to different screen sizes. Use when you need the UI to look good on both mobile and tablet/desktop form factors.
4
+ last_modified: Tue, 21 Apr 2026 20:17:40 GMT
4
5
  ---
5
6
 
6
7
  # Implementing Adaptive Layouts
@@ -16,49 +17,64 @@ description: Use `LayoutBuilder`, `MediaQuery`, or `Expanded/Flexible` to create
16
17
 
17
18
  ## Space Measurement Guidelines
18
19
 
20
+ Determine the available space accurately to ensure layouts adapt to the app window, not just the physical device.
21
+
19
22
  - **Use `MediaQuery.sizeOf(context)`** to get the size of the entire app window.
20
- - **Use `LayoutBuilder`** to make layout decisions based on the parent widget's allocated space.
21
- - **Do not use `MediaQuery.orientationOf` or `OrientationBuilder`** near the top of the widget tree. Device orientation does not accurately reflect available space.
22
- - **Do not check for hardware types** ("phone" vs. "tablet"). Base all decisions strictly on available window space.
23
+ - **Use `LayoutBuilder`** to make layout decisions based on the parent widget's allocated space. Evaluate `constraints.maxWidth` to determine the appropriate widget tree to return.
24
+ - **Do not use `MediaQuery.orientationOf` or `OrientationBuilder`** near the top of the widget tree to switch layouts. Device orientation does not accurately reflect the available app window space.
25
+ - **Do not check for hardware types** (e.g., "phone" vs. "tablet"). Flutter apps run in resizable windows, multi-window modes, and picture-in-picture. Base all layout decisions strictly on available window space.
23
26
 
24
27
  ## Widget Sizing and Constraints
25
28
 
26
- - **`Expanded`**: Force a child to fill all remaining available space.
27
- - **`Flexible`**: Allow a child to size itself up to a limit while expanding/contracting. Use `flex` factor for sibling ratios.
28
- - **Constrain Width**: Wrap widgets in `ConstrainedBox` with `maxWidth` on large screens.
29
- - **Lazy Rendering**: Use `ListView.builder` or `GridView.builder` for long/unknown-length lists.
29
+ Understand and apply Flutter's core layout rule: **Constraints go down. Sizes go up. Parent sets position.**
30
+
31
+ - **Distribute Space:** Use `Expanded` and `Flexible` within `Row`, `Column`, or `Flex` widgets.
32
+ - Use `Expanded` to force a child to fill all remaining available space (equivalent to `Flexible` with `fit: FlexFit.tight` and a `flex` factor of 1.0).
33
+ - Use `Flexible` to allow a child to size itself up to a specific limit while still expanding/contracting. Use the `flex` factor to define the ratio of space consumption among siblings.
34
+ - **Constrain Width:** Prevent widgets from consuming all horizontal space on large screens. Wrap widgets like `GridView` or `ListView` in a `ConstrainedBox` or `Container` and define a `maxWidth` in the `BoxConstraints`.
35
+ - **Lazy Rendering:** Always use `ListView.builder` or `GridView.builder` when rendering lists with an unknown or large number of items.
30
36
 
31
37
  ## Device and Orientation Behaviors
32
38
 
33
- - **Do not lock screen orientation.** Causes severe layout issues on foldable devices.
34
- - **Support Multiple Inputs:** Implement support for mice, trackpads, and keyboard shortcuts.
39
+ Ensure the app behaves correctly across all device form factors and input methods.
40
+
41
+ - **Do not lock screen orientation.** Locking orientation causes severe layout issues on foldable devices, often resulting in letterboxing (the app centered with black borders). Android large format tiers require both portrait and landscape support.
42
+ - **Fallback for Locked Orientation:** If business requirements strictly mandate a locked orientation, use the `Display API` to retrieve physical screen dimensions instead of `MediaQuery`. `MediaQuery` fails to receive the larger window size in compatibility modes.
43
+ - **Support Multiple Inputs:** Implement support for basic mice, trackpads, and keyboard shortcuts. Ensure touch targets are appropriately sized and keyboard navigation is accessible.
35
44
 
36
45
  ## Workflow: Constructing an Adaptive Layout
37
46
 
47
+ Follow this workflow to implement a layout that adapts to the available `BoxConstraints`.
48
+
38
49
  **Task Progress:**
39
50
 
40
- - [ ] Identify the target widget.
41
- - [ ] Wrap in a `LayoutBuilder`.
42
- - [ ] Extract `constraints.maxWidth`.
43
- - [ ] Define breakpoint (e.g., `600`).
44
- - [ ] If `maxWidth > breakpoint`: Return large-screen layout (e.g., `Row` with sidebar).
45
- - [ ] If `maxWidth <= breakpoint`: Return small-screen layout.
46
- - [ ] Resize the app window -> review transitions -> fix overflow errors.
51
+ - [ ] Identify the target widget that requires adaptive behavior.
52
+ - [ ] Wrap the widget tree in a `LayoutBuilder`.
53
+ - [ ] Extract the `constraints.maxWidth` from the builder callback.
54
+ - [ ] Define an adaptive breakpoint (e.g., `largeScreenMinWidth = 600`).
55
+ - [ ] **If `maxWidth > largeScreenMinWidth`:** Return a large-screen layout (e.g., a `Row` placing a navigation sidebar and content area side-by-side).
56
+ - [ ] **If `maxWidth <= largeScreenMinWidth`:** Return a small-screen layout (e.g., a `Column` or standard navigation-style approach).
57
+ - [ ] Run validator -> resize the application window -> review layout transitions -> fix overflow errors.
47
58
 
48
59
  ## Workflow: Optimizing for Large Screens
49
60
 
61
+ Follow this workflow to prevent UI elements from stretching unnaturally on large displays.
62
+
50
63
  **Task Progress:**
51
64
 
52
- - [ ] Identify full-width components.
53
- - [ ] **Lists**: Convert `ListView.builder` to `GridView.builder` with `SliverGridDelegateWithMaxCrossAxisExtent`.
54
- - [ ] **Forms/text**: Wrap in `ConstrainedBox` with `BoxConstraints(maxWidth: ...)`.
55
- - [ ] Wrap in `Center` to keep constrained content centered.
56
- - [ ] Test on desktop/tablet -> review horizontal stretching.
65
+ - [ ] Identify full-width components (e.g., `ListView`, text blocks, forms).
66
+ - [ ] **If optimizing a list:** Convert `ListView.builder` to `GridView.builder` using `SliverGridDelegateWithMaxCrossAxisExtent` to automatically adjust column counts based on window size.
67
+ - [ ] **If optimizing a form or text block:** Wrap the component in a `ConstrainedBox`.
68
+ - [ ] Apply `BoxConstraints(maxWidth: [optimal_width])` to the `ConstrainedBox`.
69
+ - [ ] Wrap the `ConstrainedBox` in a `Center` widget to keep the constrained content centered on large screens.
70
+ - [ ] Run validator -> test on desktop/tablet target -> review horizontal stretching -> adjust `maxWidth` or grid extents.
57
71
 
58
72
  ## Examples
59
73
 
60
74
  ### Adaptive Layout using LayoutBuilder
61
75
 
76
+ Demonstrates switching between a mobile and desktop layout based on available width.
77
+
62
78
  ```dart
63
79
  import 'package:flutter/material.dart';
64
80
 
@@ -72,25 +88,37 @@ class AdaptiveLayout extends StatelessWidget {
72
88
  return LayoutBuilder(
73
89
  builder: (context, constraints) {
74
90
  if (constraints.maxWidth > largeScreenMinWidth) {
75
- return Row(
76
- children: [
77
- const SizedBox(width: 250, child: Placeholder(color: Colors.blue)),
78
- const VerticalDivider(width: 1),
79
- Expanded(child: const Placeholder(color: Colors.green)),
80
- ],
81
- );
91
+ return _buildLargeScreenLayout();
82
92
  } else {
83
- return const Placeholder(color: Colors.green);
93
+ return _buildSmallScreenLayout();
84
94
  }
85
95
  },
86
96
  );
87
97
  }
98
+
99
+ Widget _buildLargeScreenLayout() {
100
+ return Row(
101
+ children: [
102
+ const SizedBox(width: 250, child: Placeholder(color: Colors.blue)),
103
+ const VerticalDivider(width: 1),
104
+ Expanded(child: const Placeholder(color: Colors.green)),
105
+ ],
106
+ );
107
+ }
108
+
109
+ Widget _buildSmallScreenLayout() {
110
+ return const Placeholder(color: Colors.green);
111
+ }
88
112
  }
89
113
  ```
90
114
 
91
115
  ### Constraining Width on Large Screens
92
116
 
117
+ Demonstrates preventing a widget from consuming all horizontal space.
118
+
93
119
  ```dart
120
+ import 'package:flutter/material.dart';
121
+
94
122
  class ConstrainedContent extends StatelessWidget {
95
123
  const ConstrainedContent({super.key});
96
124
 
@@ -99,10 +127,16 @@ class ConstrainedContent extends StatelessWidget {
99
127
  return Scaffold(
100
128
  body: Center(
101
129
  child: ConstrainedBox(
102
- constraints: const BoxConstraints(maxWidth: 800.0),
130
+ constraints: const BoxConstraints(
131
+ maxWidth: 800.0, // Maximum width for readability
132
+ ),
103
133
  child: ListView.builder(
104
134
  itemCount: 50,
105
- itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
135
+ itemBuilder: (context, index) {
136
+ return ListTile(
137
+ title: Text('Item $index'),
138
+ );
139
+ },
106
140
  ),
107
141
  ),
108
142
  ),
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: collect-coverage
3
- description: Collect coverage using the coverage package and create an LCOV report
3
+ description: Collect coverage using the coverage packge and create an LCOV report
4
+ last_modified: Fri, 24 Apr 2026 15:14:32 GMT
4
5
  ---
5
6
 
6
7
  # Implementing Dart and Flutter Test Coverage
@@ -63,8 +64,12 @@ Use the bundled `test_with_coverage` script. This script automatically runs all
63
64
  dart run coverage:test_with_coverage
64
65
  ```
65
66
 
67
+ _Note: If working within a Dart workspace (monorepo), specify the test directories explicitly (e.g., `dart run coverage:test_with_coverage -- pkgs/foo/test pkgs/bar/test`)._
68
+
66
69
  ### 3. Feedback Loop: Validate Output
67
70
 
71
+ **Run validator -> review errors -> fix:**
72
+
68
73
  1. Verify that the `coverage/` directory was created in the project root.
69
74
  2. Ensure `coverage/coverage.json` (raw data) and `coverage/lcov.info` (formatted report) exist.
70
75
  3. If coverage is missing for specific files, ensure they are imported and executed by your test files, or add `// coverage:ignore-file` if they are intentionally excluded.
@@ -95,6 +100,8 @@ Extract the coverage data from the running VM service and output it to a JSON fi
95
100
  dart run coverage:collect_coverage --wait-paused --uri=http://127.0.0.1:8181/ -o coverage/coverage.json --resume-isolates
96
101
  ```
97
102
 
103
+ _Optional: Append `--function-coverage` and `--branch-coverage` to gather deeper metrics (requires Dart VM 2.17.0+)._
104
+
98
105
  ### 3. Format to LCOV
99
106
 
100
107
  Convert the raw JSON data into the standard LCOV format.
@@ -107,6 +114,8 @@ dart run coverage:format_coverage --packages=.dart_tool/package_config.json --lc
107
114
 
108
115
  ### Example: `pubspec.yaml` Configuration
109
116
 
117
+ Ensure your `pubspec.yaml` reflects the `coverage` package strictly under `dev_dependencies`.
118
+
110
119
  ```yaml
111
120
  name: my_dart_app
112
121
  environment:
@@ -122,6 +131,8 @@ dev_dependencies:
122
131
 
123
132
  ### Example: Applying Ignore Directives
124
133
 
134
+ Use ignore directives to prevent generated code or untestable edge cases from lowering coverage scores.
135
+
125
136
  ```dart
126
137
  // coverage:ignore-file
127
138
  import 'package:meta/meta.dart';
@@ -96,7 +96,24 @@ Collect live evidence before diagnosing. Propose code fixes only after inspectin
96
96
  - `mcp__plugin_flutter_flutter-ultra-runtime__count_widget_tree_nodes` to gauge tree complexity.
97
97
  - `mcp__plugin_flutter_flutter-ultra-runtime__start_tail_logs` + `mcp__plugin_flutter_flutter-ultra-runtime__poll_tail_logs` for live log streaming during reproduction.
98
98
 
99
- ### 5. Evaluate in-app expressions
99
+ ### 5. Advanced VM service access
100
+
101
+ For low-level inspection beyond the standard helpers, use `mcp__plugin_flutter_flutter-ultra-runtime__call_vm_service_method` to call raw VM Service protocol methods directly:
102
+
103
+ - `getStack` — full isolate stack frames at any moment (useful when `get_runtime_errors` doesn't capture a synchronous deadlock).
104
+ - `getObject` — inspect any live Dart object by its VM object ID retrieved from `evaluate`.
105
+ - `evaluate` with full params — pass `disableBreakpoints: true` or `scope` overrides that the wrapper `evaluate` tool does not expose.
106
+
107
+ ```
108
+ call_vm_service_method(
109
+ method: "getStack",
110
+ params: { "isolateId": "<id>", "limit": 20 }
111
+ )
112
+ ```
113
+
114
+ Use this when `evaluate` and `get_runtime_errors` are insufficient to explain observed behaviour.
115
+
116
+ ### 6. Evaluate in-app expressions
100
117
 
101
118
  `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` freely to inspect live objects:
102
119
 
@@ -104,7 +121,7 @@ Collect live evidence before diagnosing. Propose code fixes only after inspectin
104
121
  - `context.read<MyBloc>().state.toString()`
105
122
  - `ProviderScope.containerOf(context).read(myProvider).toString()`
106
123
 
107
- ### 6. Test the fix
124
+ ### 7. Test the fix
108
125
 
109
126
  1. Apply the code change.
110
127
  2. `mcp__plugin_flutter_flutter-ultra-runtime__hot_reload` (or `mcp__plugin_flutter_flutter-ultra-runtime__hot_restart` if `initState` changed).
@@ -30,18 +30,22 @@ Break the user's request into discrete, verifiable steps. Announce the plan befo
30
30
 
31
31
  **Perform the action:**
32
32
 
33
- | Action | Tool |
34
- | ------------------------- | ----------------------------------------------------------------- |
35
- | Tap by key/text/coords | `mcp__plugin_flutter_flutter-ultra-gesture__tap` |
36
- | Double tap | `mcp__plugin_flutter_flutter-ultra-gesture__double_tap` |
37
- | Long press | `mcp__plugin_flutter_flutter-ultra-gesture__long_press` |
38
- | Enter text | `mcp__plugin_flutter_flutter-ultra-gesture__enter_text` |
39
- | Clear text field | `mcp__plugin_flutter_flutter-ultra-gesture__clear_text` |
40
- | Scroll to element | `mcp__plugin_flutter_flutter-ultra-gesture__scroll_to` |
41
- | Scroll until visible | `mcp__plugin_flutter_flutter-ultra-gesture__scroll_until_visible` |
42
- | Swipe gesture | `mcp__plugin_flutter_flutter-ultra-gesture__swipe` |
43
- | Pinch zoom | `mcp__plugin_flutter_flutter-ultra-gesture__pinch_zoom` |
44
- | Navigate programmatically | `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` |
33
+ | Action | Tool |
34
+ | ------------------------- | ---------------------------------------------------------------------- |
35
+ | Tap by key/text/coords | `mcp__plugin_flutter_flutter-ultra-gesture__tap` |
36
+ | Double tap | `mcp__plugin_flutter_flutter-ultra-gesture__double_tap` |
37
+ | Long press | `mcp__plugin_flutter_flutter-ultra-gesture__long_press` |
38
+ | Enter text | `mcp__plugin_flutter_flutter-ultra-gesture__enter_text` |
39
+ | Clear text field | `mcp__plugin_flutter_flutter-ultra-gesture__clear_text` |
40
+ | Scroll to element | `mcp__plugin_flutter_flutter-ultra-gesture__scroll_to` |
41
+ | Scroll until visible | `mcp__plugin_flutter_flutter-ultra-gesture__scroll_until_visible` |
42
+ | Swipe gesture | `mcp__plugin_flutter_flutter-ultra-gesture__swipe` |
43
+ | Pinch zoom | `mcp__plugin_flutter_flutter-ultra-gesture__pinch_zoom` |
44
+ | Drag and drop | `mcp__plugin_flutter_flutter-ultra-browser__drag` |
45
+ | Multi-touch gesture | `mcp__plugin_flutter_flutter-ultra-gesture__perform_actions` |
46
+ | Open deep link | `mcp__plugin_flutter_flutter-ultra-native-mobile__dispatch_deep_link` |
47
+ | Set location | `mcp__plugin_flutter_flutter-ultra-native-mobile__set_device_location` |
48
+ | Navigate programmatically | `mcp__plugin_flutter_flutter-ultra-runtime__evaluate` |
45
49
 
46
50
  **Wait for the UI to settle:**
47
51
 
@@ -77,8 +81,19 @@ When a flow involves an external OAuth consent screen:
77
81
  3. `mcp__plugin_flutter_flutter-ultra-browser__fill` for username/password fields.
78
82
  4. `mcp__plugin_flutter_flutter-ultra-browser__click` on the submit button.
79
83
  5. `mcp__plugin_flutter_flutter-ultra-browser__wait_for_url` matching the app's redirect URI.
84
+ 6. Use `mcp__plugin_flutter_flutter-ultra-browser__mock_network_route` to stub API responses during the flow when deterministic data is needed.
85
+ 7. Use `mcp__plugin_flutter_flutter-ultra-browser__network_state_set` to simulate offline/slow-network conditions and verify the app handles connectivity loss gracefully.
80
86
 
81
- ### 6. Native mobile system dialogs (mobile targets)
87
+ ### 6. Native OS interactions (mobile targets)
88
+
89
+ For flows that leave the Flutter layer and interact with the host OS:
90
+
91
+ - **Share sheet**: `mcp__plugin_flutter_flutter-ultra-native-mobile__handle_share_sheet` to detect the OS share sheet after triggering a share action, then select an app or dismiss.
92
+ - **Notification flows**: `mcp__plugin_flutter_flutter-ultra-native-mobile__open_notification_tray` to expand the shade, `mcp__plugin_flutter_flutter-ultra-native-mobile__list_notifications` to find the target notification, `mcp__plugin_flutter_flutter-ultra-native-mobile__tap_notification` to open it and return to the app.
93
+ - **Chrome Custom Tab / SFSafariViewController flows**: `mcp__plugin_flutter_flutter-ultra-native-mobile__detect_in_app_browser` to confirm the CCT/SVC is open, `mcp__plugin_flutter_flutter-ultra-native-mobile__interact_in_app_browser` to type/tap within it (e.g., OAuth consent), then wait for the app to resume.
94
+ - **File picker**: `mcp__plugin_flutter_flutter-ultra-native-mobile__pick_file_native` to select a file from the OS file picker dialog that Flutter cannot drive with gesture tools.
95
+
96
+ ### 7. Native mobile system dialogs (mobile targets)
82
97
 
83
98
  - `mcp__plugin_flutter_flutter-ultra-native-mobile__wait_for_native_element` to detect OS dialogs.
84
99
  - `mcp__plugin_flutter_flutter-ultra-native-mobile__native_permission_grant` or `mcp__plugin_flutter_flutter-ultra-native-mobile__native_permission_deny`.
@@ -87,7 +102,7 @@ When a flow involves an external OAuth consent screen:
87
102
  - `mcp__plugin_flutter_flutter-ultra-native-mobile__native_home` to press Home.
88
103
  - `mcp__plugin_flutter_flutter-ultra-native-mobile__solve_oauth_cct` for Chrome Custom Tab OAuth flows.
89
104
 
90
- ### 7. Native desktop dialogs (desktop targets)
105
+ ### 8. Native desktop dialogs (desktop targets)
91
106
 
92
107
  - `mcp__plugin_flutter_flutter-ultra-native-desktop__wait_for_window` to detect native dialogs.
93
108
  - `mcp__plugin_flutter_flutter-ultra-native-desktop__desktop_click` to interact with dialog buttons.
@@ -95,7 +110,7 @@ When a flow involves an external OAuth consent screen:
95
110
  - `mcp__plugin_flutter_flutter-ultra-native-desktop__select_file_in_dialog` for file picker dialogs.
96
111
  - `mcp__plugin_flutter_flutter-ultra-native-desktop__confirm_dialog` to accept/dismiss confirmation dialogs.
97
112
 
98
- ### 8. Report the flow result
113
+ ### 9. Report the flow result
99
114
 
100
115
  Produce a numbered summary: steps taken, pass/fail status per step, screenshot paths, and any errors from `mcp__plugin_flutter_flutter-ultra-runtime__get_runtime_errors`.
101
116