@bdayadev/flutter-ultra-mcp 1.11.6 → 1.12.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +2 -1
- package/dart/ultra_flutter/pubspec.yaml +1 -1
- package/dart/ultra_flutter_devtools/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/skills/UPSTREAM-LICENSES +75 -0
- package/skills/add-integration-test/SKILL.md +127 -0
- package/skills/add-unit-test/SKILL.md +140 -0
- package/skills/add-widget-preview/SKILL.md +117 -0
- package/skills/add-widget-test/SKILL.md +142 -0
- package/skills/apply-architecture-best-practices/SKILL.md +156 -0
- package/skills/build-cli-app/SKILL.md +173 -0
- package/skills/build-responsive-layout/SKILL.md +126 -0
- package/skills/collect-coverage/SKILL.md +157 -0
- package/skills/fix-layout-issues/SKILL.md +101 -0
- package/skills/fix-runtime-errors/SKILL.md +138 -0
- package/skills/generate-test-mocks/SKILL.md +147 -0
- package/skills/implement-json-serialization/SKILL.md +103 -0
- package/skills/migrate-to-checks-package/SKILL.md +124 -0
- package/skills/resolve-package-conflicts/SKILL.md +111 -0
- package/skills/run-static-analysis/SKILL.md +107 -0
- package/skills/setup-declarative-routing/SKILL.md +157 -0
- package/skills/setup-localization/SKILL.md +177 -0
- package/skills/use-http-package/SKILL.md +151 -0
- package/skills/use-pattern-matching/SKILL.md +132 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: resolve-package-conflicts
|
|
3
|
+
description: Workflow for fixing package version conflicts. Use this when `pub get` fails due to incompatible package versions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Managing Dart Dependencies
|
|
7
|
+
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
10
|
+
- [Core Concepts](#core-concepts)
|
|
11
|
+
- [Version Constraints](#version-constraints)
|
|
12
|
+
- [Workflow: Auditing Dependencies](#workflow-auditing-dependencies)
|
|
13
|
+
- [Workflow: Upgrading Dependencies](#workflow-upgrading-dependencies)
|
|
14
|
+
- [Workflow: Resolving Version Conflicts](#workflow-resolving-version-conflicts)
|
|
15
|
+
- [Examples](#examples)
|
|
16
|
+
|
|
17
|
+
## Core Concepts
|
|
18
|
+
|
|
19
|
+
Dart enforces a strict single-version rule for dependencies: a project and all its transitive dependencies must resolve to a single, shared version of any given package.
|
|
20
|
+
|
|
21
|
+
Understand the output columns of `dart pub outdated`:
|
|
22
|
+
|
|
23
|
+
- **Current:** The version currently recorded in `pubspec.lock`.
|
|
24
|
+
- **Upgradable:** The latest version allowed by the constraints in `pubspec.yaml`. `dart pub upgrade` resolves to this.
|
|
25
|
+
- **Resolvable:** The absolute latest version that can be resolved when factoring in all other dependencies.
|
|
26
|
+
- **Latest:** The latest published version of the package (excluding prereleases).
|
|
27
|
+
|
|
28
|
+
## Version Constraints
|
|
29
|
+
|
|
30
|
+
- **Use Caret Syntax:** Always use caret syntax (e.g., `^1.2.3`) for dependencies.
|
|
31
|
+
- **Tighten Dev Dependencies:** Set the lower bound of `dev_dependencies` to the exact version currently used.
|
|
32
|
+
- **Enforce Lockfiles in CI:** Use `dart pub get --enforce-lockfile` in CI/CD pipelines.
|
|
33
|
+
|
|
34
|
+
## Workflow: Auditing Dependencies
|
|
35
|
+
|
|
36
|
+
**Task Progress:**
|
|
37
|
+
|
|
38
|
+
- [ ] Run `dart pub outdated`.
|
|
39
|
+
- [ ] Review the **Upgradable** column.
|
|
40
|
+
- [ ] Review the **Resolvable** column.
|
|
41
|
+
- [ ] Identify any packages marked as retracted or discontinued.
|
|
42
|
+
|
|
43
|
+
## Workflow: Upgrading Dependencies
|
|
44
|
+
|
|
45
|
+
**Task Progress:**
|
|
46
|
+
|
|
47
|
+
- [ ] **If updating to "Upgradable" versions:**
|
|
48
|
+
- [ ] Run `dart pub upgrade`.
|
|
49
|
+
- [ ] Run `dart pub upgrade --tighten` to update lower bounds.
|
|
50
|
+
- [ ] **If updating to "Resolvable" versions (Major updates):**
|
|
51
|
+
- [ ] Manually edit `pubspec.yaml` to bump the version constraint.
|
|
52
|
+
- [ ] Run `dart pub upgrade` to resolve the new constraints.
|
|
53
|
+
- [ ] **Feedback Loop:**
|
|
54
|
+
- [ ] Run `dart analyze` -> review errors -> fix breaking API changes.
|
|
55
|
+
- [ ] Run `dart test` -> review failures -> fix regressions.
|
|
56
|
+
|
|
57
|
+
## Workflow: Resolving Version Conflicts
|
|
58
|
+
|
|
59
|
+
**NEVER** delete the entire `pubspec.lock` file and run `dart pub get`. This causes uncontrolled upgrades across the entire dependency graph.
|
|
60
|
+
|
|
61
|
+
**Task Progress:**
|
|
62
|
+
|
|
63
|
+
- [ ] Open `pubspec.lock`.
|
|
64
|
+
- [ ] Locate the specific YAML block for the conflicting or retracted package.
|
|
65
|
+
- [ ] Delete ONLY that package's entry from the lockfile.
|
|
66
|
+
- [ ] Run `dart pub get` to fetch the newest compatible version.
|
|
67
|
+
- [ ] **Feedback Loop:**
|
|
68
|
+
- [ ] Run `dart pub deps` -> verify the dependency graph resolves correctly.
|
|
69
|
+
- [ ] If resolution fails, identify the transitive dependency causing the lock, update its constraint in `pubspec.yaml`, and retry.
|
|
70
|
+
|
|
71
|
+
## Examples
|
|
72
|
+
|
|
73
|
+
### Tightening Constraints
|
|
74
|
+
|
|
75
|
+
**Input (`pubspec.yaml`):**
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
dependencies:
|
|
79
|
+
http: ^0.13.0
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Command:**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
dart pub upgrade --tighten http
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Output (`pubspec.yaml`):**
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
dependencies:
|
|
92
|
+
http: ^0.13.5
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Surgical Lockfile Removal
|
|
96
|
+
|
|
97
|
+
If `package_a` is retracted or locked in a conflict, remove only its block from `pubspec.lock`. Leave all other entries untouched. Run `dart pub get`.
|
|
98
|
+
|
|
99
|
+
## Flutter Ultra Integration
|
|
100
|
+
|
|
101
|
+
Investigate and resolve dependency conflicts:
|
|
102
|
+
|
|
103
|
+
- `mcp__plugin_flutter_flutter-ultra-build__pub_get` — Run pub get to see the current resolution state
|
|
104
|
+
- `mcp__plugin_flutter_flutter-ultra-build__pub_deps` — View the full dependency tree
|
|
105
|
+
- `mcp__plugin_flutter_flutter-ultra-build__pub_outdated` — Check which packages are outdated
|
|
106
|
+
- `mcp__plugin_flutter_flutter-ultra-build__pub_upgrade` — Attempt upgrade to resolve conflicts
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
> **Attribution:** This skill is vendored from [dart-lang/skills](https://github.com/dart-lang/skills) (BSD-3-Clause).
|
|
111
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run-static-analysis
|
|
3
|
+
description: Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Analyzing and Fixing Dart Code
|
|
7
|
+
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
10
|
+
- [Analysis Configuration](#analysis-configuration)
|
|
11
|
+
- [Diagnostic Suppression](#diagnostic-suppression)
|
|
12
|
+
- [Workflow: Executing Static Analysis](#workflow-executing-static-analysis)
|
|
13
|
+
- [Workflow: Applying Automated Fixes](#workflow-applying-automated-fixes)
|
|
14
|
+
- [Examples](#examples)
|
|
15
|
+
|
|
16
|
+
## Analysis Configuration
|
|
17
|
+
|
|
18
|
+
Configure the Dart analyzer using the `analysis_options.yaml` file at the package root.
|
|
19
|
+
|
|
20
|
+
- **Base Configuration:** Include a standard rule set (e.g., `package:lints/recommended.yaml` or `package:flutter_lints/flutter.yaml`).
|
|
21
|
+
- **Strict Type Checks:** Enable `strict-casts: true`, `strict-inference: true`, and `strict-raw-types: true` under `analyzer: language:`.
|
|
22
|
+
- **Linter Rules:** Enable or disable specific rules under `linter: rules:`. Do not mix list and map syntax in the same `rules` block.
|
|
23
|
+
- **Formatter Configuration:** Configure `dart format` behavior under the `formatter:` node. Set `page_width` and `trailing_commas`.
|
|
24
|
+
|
|
25
|
+
## Diagnostic Suppression
|
|
26
|
+
|
|
27
|
+
- **File-level Exclusion:** Use `analyzer: exclude:` with glob patterns (e.g., `**/*.g.dart`).
|
|
28
|
+
- **File-level Suppression:** Add `// ignore_for_file: <diagnostic_code>` at the top of a file.
|
|
29
|
+
- **Line-level Suppression:** Add `// ignore: <diagnostic_code>` on the line above.
|
|
30
|
+
|
|
31
|
+
## Workflow: Executing Static Analysis
|
|
32
|
+
|
|
33
|
+
**Task Progress:**
|
|
34
|
+
|
|
35
|
+
- [ ] 1. Verify `analysis_options.yaml` exists at the project root.
|
|
36
|
+
- [ ] 2. Run the analyzer: `dart analyze <target_directory>`.
|
|
37
|
+
- [ ] 3. Review the diagnostic output.
|
|
38
|
+
- [ ] 4. If info-level issues must be treated as failures, append `--fatal-infos`.
|
|
39
|
+
- [ ] 5. Resolve reported errors manually or proceed to Automated Fixes.
|
|
40
|
+
|
|
41
|
+
## Workflow: Applying Automated Fixes
|
|
42
|
+
|
|
43
|
+
**Task Progress:**
|
|
44
|
+
|
|
45
|
+
- [ ] 1. Preview proposed changes: `dart fix --dry-run`.
|
|
46
|
+
- [ ] 2. Review the proposed fixes.
|
|
47
|
+
- [ ] 3. Apply the fixes: `dart fix --apply`.
|
|
48
|
+
- [ ] 4. Format the modified code: `dart format .`.
|
|
49
|
+
- [ ] 5. Run static analysis again to verify all diagnostics are resolved.
|
|
50
|
+
|
|
51
|
+
## Examples
|
|
52
|
+
|
|
53
|
+
### Comprehensive `analysis_options.yaml`
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
include: package:flutter_lints/recommended.yaml
|
|
57
|
+
|
|
58
|
+
analyzer:
|
|
59
|
+
exclude:
|
|
60
|
+
- '**/*.g.dart'
|
|
61
|
+
- 'lib/generated/**'
|
|
62
|
+
language:
|
|
63
|
+
strict-casts: true
|
|
64
|
+
strict-inference: true
|
|
65
|
+
strict-raw-types: true
|
|
66
|
+
errors:
|
|
67
|
+
todo: ignore
|
|
68
|
+
invalid_assignment: warning
|
|
69
|
+
missing_return: error
|
|
70
|
+
|
|
71
|
+
linter:
|
|
72
|
+
rules:
|
|
73
|
+
avoid_shadowing_type_parameters: false
|
|
74
|
+
await_only_futures: true
|
|
75
|
+
use_super_parameters: true
|
|
76
|
+
|
|
77
|
+
formatter:
|
|
78
|
+
page_width: 100
|
|
79
|
+
trailing_commas: preserve
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Inline Diagnostic Suppression
|
|
83
|
+
|
|
84
|
+
```dart
|
|
85
|
+
// ignore_for_file: unused_local_variable, dead_code
|
|
86
|
+
|
|
87
|
+
void processData() {
|
|
88
|
+
// ignore: invalid_assignment
|
|
89
|
+
int x = '';
|
|
90
|
+
|
|
91
|
+
const y = 10; // ignore: constant_identifier_names
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Flutter Ultra Integration
|
|
96
|
+
|
|
97
|
+
Run analysis and auto-fix via flutter-ultra tools:
|
|
98
|
+
|
|
99
|
+
- `mcp__plugin_flutter_flutter-ultra-build__analyze` — Run dart analyze with full diagnostics
|
|
100
|
+
- `mcp__plugin_flutter_flutter-ultra-build__fix` — Apply dart fix --apply for automated lint fixes
|
|
101
|
+
- `mcp__plugin_flutter_flutter-ultra-build__fix_preview` — Preview fixes before applying
|
|
102
|
+
- `mcp__plugin_flutter_flutter-ultra-build__format` — Format code after fixes
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
> **Attribution:** This skill is vendored from [dart-lang/skills](https://github.com/dart-lang/skills) (BSD-3-Clause).
|
|
107
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-declarative-routing
|
|
3
|
+
description: Configure `MaterialApp.router` using a package like `go_router` for advanced URL-based navigation. Use when developing web applications or mobile apps that require specific deep linking and browser history support.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implementing Routing and Deep Linking
|
|
7
|
+
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
10
|
+
- [Core Concepts](#core-concepts)
|
|
11
|
+
- [Workflow: Initializing the Application and Router](#workflow-initializing-the-application-and-router)
|
|
12
|
+
- [Workflow: Configuring Platform Deep Linking](#workflow-configuring-platform-deep-linking)
|
|
13
|
+
- [Workflow: Implementing Nested Navigation](#workflow-implementing-nested-navigation)
|
|
14
|
+
- [Examples](#examples)
|
|
15
|
+
|
|
16
|
+
## Core Concepts
|
|
17
|
+
|
|
18
|
+
Use the `go_router` package for declarative routing in Flutter.
|
|
19
|
+
|
|
20
|
+
- **GoRouter**: Central configuration object defining the route tree.
|
|
21
|
+
- **GoRoute**: Maps a URL path to a Flutter screen.
|
|
22
|
+
- **ShellRoute / StatefulShellRoute**: Wraps child routes in a persistent UI shell (e.g., `BottomNavigationBar`). `StatefulShellRoute` maintains state of parallel branches.
|
|
23
|
+
- **Path URL Strategy**: Removes the default `#` from web URLs.
|
|
24
|
+
|
|
25
|
+
## Workflow: Initializing the Application and Router
|
|
26
|
+
|
|
27
|
+
### Task Progress
|
|
28
|
+
|
|
29
|
+
- [ ] Create the Flutter application.
|
|
30
|
+
- [ ] Add `go_router`: `flutter pub add go_router`.
|
|
31
|
+
- [ ] Configure URL strategy with `usePathUrlStrategy()`.
|
|
32
|
+
- [ ] Implement the `GoRouter` configuration.
|
|
33
|
+
- [ ] Bind the router to `MaterialApp.router`.
|
|
34
|
+
|
|
35
|
+
```dart
|
|
36
|
+
import 'package:flutter/material.dart';
|
|
37
|
+
import 'package:go_router/go_router.dart';
|
|
38
|
+
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
39
|
+
|
|
40
|
+
void main() {
|
|
41
|
+
usePathUrlStrategy();
|
|
42
|
+
runApp(const MyApp());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
final GoRouter _router = GoRouter(
|
|
46
|
+
initialLocation: '/',
|
|
47
|
+
routes: [
|
|
48
|
+
GoRoute(
|
|
49
|
+
path: '/',
|
|
50
|
+
builder: (context, state) => const HomeScreen(),
|
|
51
|
+
routes: [
|
|
52
|
+
GoRoute(
|
|
53
|
+
path: 'details/:id',
|
|
54
|
+
builder: (context, state) => DetailsScreen(id: state.pathParameters['id']!),
|
|
55
|
+
),
|
|
56
|
+
],
|
|
57
|
+
),
|
|
58
|
+
],
|
|
59
|
+
errorBuilder: (context, state) => ErrorScreen(error: state.error),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
class MyApp extends StatelessWidget {
|
|
63
|
+
const MyApp({super.key});
|
|
64
|
+
@override
|
|
65
|
+
Widget build(BuildContext context) {
|
|
66
|
+
return MaterialApp.router(routerConfig: _router, title: 'Routing App');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Workflow: Configuring Platform Deep Linking
|
|
72
|
+
|
|
73
|
+
### Task Progress
|
|
74
|
+
|
|
75
|
+
- [ ] Determine target platforms (iOS, Android, or both).
|
|
76
|
+
- [ ] **Android:** Add intent filter to `AndroidManifest.xml` + host `assetlinks.json`.
|
|
77
|
+
- [ ] **iOS:** Set `FlutterDeepLinkingEnabled` in `Info.plist` + add associated domain in entitlements + host `apple-app-site-association`.
|
|
78
|
+
- [ ] Test via ADB (Android) or `xcrun simctl openurl` (iOS).
|
|
79
|
+
|
|
80
|
+
## Workflow: Implementing Nested Navigation
|
|
81
|
+
|
|
82
|
+
Use `StatefulShellRoute.indexedStack` to implement persistent shells with tab navigation.
|
|
83
|
+
|
|
84
|
+
```dart
|
|
85
|
+
final GoRouter _router = GoRouter(
|
|
86
|
+
initialLocation: '/home',
|
|
87
|
+
routes: [
|
|
88
|
+
StatefulShellRoute.indexedStack(
|
|
89
|
+
builder: (context, state, navigationShell) {
|
|
90
|
+
return ScaffoldWithNavBar(navigationShell: navigationShell);
|
|
91
|
+
},
|
|
92
|
+
branches: [
|
|
93
|
+
StatefulShellBranch(routes: [
|
|
94
|
+
GoRoute(path: '/home', builder: (context, state) => const HomeScreen()),
|
|
95
|
+
]),
|
|
96
|
+
StatefulShellBranch(routes: [
|
|
97
|
+
GoRoute(path: '/settings', builder: (context, state) => const SettingsScreen()),
|
|
98
|
+
]),
|
|
99
|
+
],
|
|
100
|
+
),
|
|
101
|
+
],
|
|
102
|
+
);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Examples
|
|
106
|
+
|
|
107
|
+
### Programmatic Navigation
|
|
108
|
+
|
|
109
|
+
```dart
|
|
110
|
+
context.go('/details/123'); // Replace current stack
|
|
111
|
+
context.push('/details/123'); // Push onto stack
|
|
112
|
+
context.goNamed('details', pathParameters: {'id': '123'});
|
|
113
|
+
context.pop();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Shell Widget Implementation
|
|
117
|
+
|
|
118
|
+
```dart
|
|
119
|
+
class ScaffoldWithNavBar extends StatelessWidget {
|
|
120
|
+
const ScaffoldWithNavBar({required this.navigationShell, super.key});
|
|
121
|
+
final StatefulNavigationShell navigationShell;
|
|
122
|
+
|
|
123
|
+
void _goBranch(int index) {
|
|
124
|
+
navigationShell.goBranch(index,
|
|
125
|
+
initialLocation: index == navigationShell.currentIndex);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@override
|
|
129
|
+
Widget build(BuildContext context) {
|
|
130
|
+
return Scaffold(
|
|
131
|
+
body: navigationShell,
|
|
132
|
+
bottomNavigationBar: NavigationBar(
|
|
133
|
+
selectedIndex: navigationShell.currentIndex,
|
|
134
|
+
onDestinationSelected: _goBranch,
|
|
135
|
+
destinations: const [
|
|
136
|
+
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
|
|
137
|
+
NavigationDestination(icon: Icon(Icons.settings), label: 'Settings'),
|
|
138
|
+
],
|
|
139
|
+
),
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Flutter Ultra Integration
|
|
146
|
+
|
|
147
|
+
After configuring routes, test navigation in the running app:
|
|
148
|
+
|
|
149
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__launch_app` — Launch the app to test routing
|
|
150
|
+
- `mcp__plugin_flutter_flutter-ultra-browser__navigate` — Navigate to specific routes in the browser (web targets)
|
|
151
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__screenshot` — Capture each route for visual verification
|
|
152
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__get_runtime_errors` — Check for routing errors (missing routes, redirect loops)
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
> **Attribution:** This skill is vendored from [flutter/skills](https://github.com/flutter/skills) (BSD-3-Clause).
|
|
157
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-localization
|
|
3
|
+
description: Add `flutter_localizations` and `intl` dependencies, enable "generate true" in `pubspec.yaml`, and create an `l10n.yaml` configuration file. Use when initializing localization support for a new Flutter project.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Internationalizing Flutter Applications
|
|
7
|
+
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
10
|
+
- [Core Concepts](#core-concepts)
|
|
11
|
+
- [Setup Workflow](#setup-workflow)
|
|
12
|
+
- [Implementation Workflow](#implementation-workflow)
|
|
13
|
+
- [Advanced Formatting](#advanced-formatting)
|
|
14
|
+
- [Examples](#examples)
|
|
15
|
+
|
|
16
|
+
## Core Concepts
|
|
17
|
+
|
|
18
|
+
Flutter handles i18n/l10n via `flutter_localizations` and `intl`. Uses App Resource Bundle (`.arb`) files compiled into a generated `AppLocalizations` class for type-safe access.
|
|
19
|
+
|
|
20
|
+
## Setup Workflow
|
|
21
|
+
|
|
22
|
+
- [ ] 1. Add dependencies to `pubspec.yaml`.
|
|
23
|
+
- [ ] 2. Enable the `generate` flag.
|
|
24
|
+
- [ ] 3. Create the `l10n.yaml` configuration file.
|
|
25
|
+
- [ ] 4. Configure `MaterialApp` or `CupertinoApp`.
|
|
26
|
+
|
|
27
|
+
### 1. Add Dependencies
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
flutter pub add flutter_localizations --sdk=flutter
|
|
31
|
+
flutter pub add intl:any
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Enable Code Generation
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
# pubspec.yaml
|
|
38
|
+
flutter:
|
|
39
|
+
generate: true
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Create Configuration File
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
# l10n.yaml
|
|
46
|
+
arb-dir: lib/l10n
|
|
47
|
+
template-arb-file: app_en.arb
|
|
48
|
+
output-localization-file: app_localizations.dart
|
|
49
|
+
synthetic-package: true
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 4. Configure App Entry Point
|
|
53
|
+
|
|
54
|
+
```dart
|
|
55
|
+
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
56
|
+
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
57
|
+
|
|
58
|
+
return MaterialApp(
|
|
59
|
+
localizationsDelegates: const [
|
|
60
|
+
AppLocalizations.delegate,
|
|
61
|
+
GlobalMaterialLocalizations.delegate,
|
|
62
|
+
GlobalWidgetsLocalizations.delegate,
|
|
63
|
+
GlobalCupertinoLocalizations.delegate,
|
|
64
|
+
],
|
|
65
|
+
supportedLocales: const [Locale('en'), Locale('es')],
|
|
66
|
+
home: const MyHomePage(),
|
|
67
|
+
);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Implementation Workflow
|
|
71
|
+
|
|
72
|
+
### 1. Define ARB Files
|
|
73
|
+
|
|
74
|
+
**Template (`lib/l10n/app_en.arb`):**
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"helloWorld": "Hello World!",
|
|
79
|
+
"@helloWorld": {
|
|
80
|
+
"description": "The conventional newborn programmer greeting"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Other locales (`lib/l10n/app_es.arb`):**
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"helloWorld": "!Hola Mundo!"
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 2. Generate Localization Classes
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
flutter pub get
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 3. Consume Localized Strings
|
|
100
|
+
|
|
101
|
+
```dart
|
|
102
|
+
Text(AppLocalizations.of(context)!.helloWorld)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Advanced Formatting
|
|
106
|
+
|
|
107
|
+
### Placeholders
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
"hello": "Hello {userName}",
|
|
111
|
+
"@hello": {
|
|
112
|
+
"placeholders": {
|
|
113
|
+
"userName": { "type": "String", "example": "Bob" }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Plurals
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
"nWombats": "{count, plural, =0{no wombats} =1{1 wombat} other{{count} wombats}}",
|
|
122
|
+
"@nWombats": {
|
|
123
|
+
"placeholders": { "count": { "type": "num", "format": "compact" } }
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Selects
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
"pronoun": "{gender, select, male{he} female{she} other{they}}",
|
|
131
|
+
"@pronoun": {
|
|
132
|
+
"placeholders": { "gender": { "type": "String" } }
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Examples
|
|
137
|
+
|
|
138
|
+
### Complete Widget Implementation
|
|
139
|
+
|
|
140
|
+
```dart
|
|
141
|
+
import 'package:flutter/material.dart';
|
|
142
|
+
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
143
|
+
|
|
144
|
+
class GreetingWidget extends StatelessWidget {
|
|
145
|
+
final String userName;
|
|
146
|
+
final int notificationCount;
|
|
147
|
+
|
|
148
|
+
const GreetingWidget({
|
|
149
|
+
super.key,
|
|
150
|
+
required this.userName,
|
|
151
|
+
required this.notificationCount,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
@override
|
|
155
|
+
Widget build(BuildContext context) {
|
|
156
|
+
final l10n = AppLocalizations.of(context)!;
|
|
157
|
+
return Column(children: [
|
|
158
|
+
Text(l10n.hello(userName)),
|
|
159
|
+
Text(l10n.nWombats(notificationCount)),
|
|
160
|
+
]);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Flutter Ultra Integration
|
|
166
|
+
|
|
167
|
+
Generate and validate localization files with these tools:
|
|
168
|
+
|
|
169
|
+
- `mcp__plugin_flutter_flutter-ultra-build__flutter_gen_l10n` — Generate localization Dart code from ARB files
|
|
170
|
+
- `mcp__plugin_flutter_flutter-ultra-build__list_missing_translations` — Find missing translation keys across locales
|
|
171
|
+
- `mcp__plugin_flutter_flutter-ultra-build__arb_add_key` — Add a new translation key to all ARB files
|
|
172
|
+
- `mcp__plugin_flutter_flutter-ultra-build__arb_diff` — Compare ARB files to find drift between locales
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
> **Attribution:** This skill is vendored from [flutter/skills](https://github.com/flutter/skills) (BSD-3-Clause).
|
|
177
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: use-http-package
|
|
3
|
+
description: Use the `http` package to execute GET, POST, PUT, or DELETE requests. Use when you need to fetch from or send data to a REST API.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Implementing Flutter Networking
|
|
7
|
+
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
10
|
+
- [Configuration & Permissions](#configuration--permissions)
|
|
11
|
+
- [Request Execution & Response Handling](#request-execution--response-handling)
|
|
12
|
+
- [Background Parsing](#background-parsing)
|
|
13
|
+
- [Workflow: Executing Network Operations](#workflow-executing-network-operations)
|
|
14
|
+
- [Examples](#examples)
|
|
15
|
+
|
|
16
|
+
## Configuration & Permissions
|
|
17
|
+
|
|
18
|
+
1. Add the `http` package: `flutter pub add http`
|
|
19
|
+
2. Import: `import 'package:http/http.dart' as http;`
|
|
20
|
+
3. **Android**: Add `<uses-permission android:name="android.permission.INTERNET" />` to `AndroidManifest.xml`.
|
|
21
|
+
4. **macOS**: Add `com.apple.security.network.client` = `true` to both entitlements files.
|
|
22
|
+
|
|
23
|
+
## Request Execution & Response Handling
|
|
24
|
+
|
|
25
|
+
- **URIs:** Always use `Uri.parse('your_url')`.
|
|
26
|
+
- **Headers:** Inject via the `headers` parameter map.
|
|
27
|
+
- **Payloads:** For POST/PUT, encode body with `jsonEncode()`.
|
|
28
|
+
- **Status Validation:** Treat `200 OK` (GET/PUT/DELETE) and `201 CREATED` (POST) as success.
|
|
29
|
+
- **Error Handling:** Throw explicit exceptions on non-success codes. Never return `null`.
|
|
30
|
+
- **Deserialization:** `jsonDecode(response.body)` then map to model's `fromJson`.
|
|
31
|
+
|
|
32
|
+
## Background Parsing
|
|
33
|
+
|
|
34
|
+
For large payloads (>16ms parse time), use `compute()` from `package:flutter/foundation.dart` to parse in a background isolate. The parsing function must be top-level or static.
|
|
35
|
+
|
|
36
|
+
## Workflow: Executing Network Operations
|
|
37
|
+
|
|
38
|
+
**Task Progress:**
|
|
39
|
+
|
|
40
|
+
- [ ] 1. Define strongly typed Dart model with `fromJson`.
|
|
41
|
+
- [ ] 2. Implement network request method returning `Future<Model>`.
|
|
42
|
+
- [ ] 3. Apply conditional logic:
|
|
43
|
+
- **GET**: Append query parameters to URI.
|
|
44
|
+
- **POST/PUT**: Set `Content-Type: application/json; charset=UTF-8`, attach `jsonEncode` body.
|
|
45
|
+
- **DELETE**: Return empty model instance on success.
|
|
46
|
+
- [ ] 4. Validate `statusCode` and throw `Exception` on failure.
|
|
47
|
+
- [ ] 5. Integrate into UI using `FutureBuilder`.
|
|
48
|
+
- [ ] 6. Handle `snapshot.hasData`, `snapshot.hasError`, default to `CircularProgressIndicator`.
|
|
49
|
+
- [ ] 7. Run app -> trigger request -> review console for exceptions -> fix.
|
|
50
|
+
|
|
51
|
+
## Examples
|
|
52
|
+
|
|
53
|
+
### Fetching and Parsing in the Background
|
|
54
|
+
|
|
55
|
+
```dart
|
|
56
|
+
import 'dart:convert';
|
|
57
|
+
import 'dart:io';
|
|
58
|
+
import 'package:flutter/foundation.dart';
|
|
59
|
+
import 'package:flutter/material.dart';
|
|
60
|
+
import 'package:http/http.dart' as http;
|
|
61
|
+
|
|
62
|
+
List<Photo> parsePhotos(String responseBody) {
|
|
63
|
+
final parsed = (jsonDecode(responseBody) as List<Object?>)
|
|
64
|
+
.cast<Map<String, Object?>>();
|
|
65
|
+
return parsed.map<Photo>(Photo.fromJson).toList();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
Future<List<Photo>> fetchPhotos() async {
|
|
69
|
+
final response = await http.get(
|
|
70
|
+
Uri.parse('https://jsonplaceholder.typicode.com/photos'),
|
|
71
|
+
headers: {
|
|
72
|
+
HttpHeaders.authorizationHeader: 'Bearer your_token_here',
|
|
73
|
+
HttpHeaders.acceptHeader: 'application/json',
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
if (response.statusCode == 200) {
|
|
78
|
+
return compute(parsePhotos, response.body);
|
|
79
|
+
} else {
|
|
80
|
+
throw Exception('Failed to load photos. Status: ${response.statusCode}');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
class Photo {
|
|
85
|
+
final int id;
|
|
86
|
+
final String title;
|
|
87
|
+
final String thumbnailUrl;
|
|
88
|
+
|
|
89
|
+
const Photo({required this.id, required this.title, required this.thumbnailUrl});
|
|
90
|
+
|
|
91
|
+
factory Photo.fromJson(Map<String, dynamic> json) {
|
|
92
|
+
return Photo(
|
|
93
|
+
id: json['id'] as int,
|
|
94
|
+
title: json['title'] as String,
|
|
95
|
+
thumbnailUrl: json['thumbnailUrl'] as String,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
class PhotoGallery extends StatefulWidget {
|
|
101
|
+
const PhotoGallery({super.key});
|
|
102
|
+
@override
|
|
103
|
+
State<PhotoGallery> createState() => _PhotoGalleryState();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
class _PhotoGalleryState extends State<PhotoGallery> {
|
|
107
|
+
late Future<List<Photo>> _futurePhotos;
|
|
108
|
+
|
|
109
|
+
@override
|
|
110
|
+
void initState() {
|
|
111
|
+
super.initState();
|
|
112
|
+
_futurePhotos = fetchPhotos();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@override
|
|
116
|
+
Widget build(BuildContext context) {
|
|
117
|
+
return FutureBuilder<List<Photo>>(
|
|
118
|
+
future: _futurePhotos,
|
|
119
|
+
builder: (context, snapshot) {
|
|
120
|
+
if (snapshot.hasData) {
|
|
121
|
+
final photos = snapshot.data!;
|
|
122
|
+
return ListView.builder(
|
|
123
|
+
itemCount: photos.length,
|
|
124
|
+
itemBuilder: (context, index) => ListTile(
|
|
125
|
+
leading: Image.network(photos[index].thumbnailUrl),
|
|
126
|
+
title: Text(photos[index].title),
|
|
127
|
+
),
|
|
128
|
+
);
|
|
129
|
+
} else if (snapshot.hasError) {
|
|
130
|
+
return Center(child: Text('Error: ${snapshot.error}'));
|
|
131
|
+
}
|
|
132
|
+
return const Center(child: CircularProgressIndicator());
|
|
133
|
+
},
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Flutter Ultra Integration
|
|
140
|
+
|
|
141
|
+
Monitor and debug HTTP calls in the running app:
|
|
142
|
+
|
|
143
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__start_http_capture` — Start capturing HTTP traffic
|
|
144
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__get_http_events` — View captured HTTP requests and responses
|
|
145
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__stop_http_capture` — Stop HTTP capture
|
|
146
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__get_runtime_errors` — Check for unhandled HTTP exceptions
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
> **Attribution:** This skill is vendored from [flutter/skills](https://github.com/flutter/skills) (BSD-3-Clause).
|
|
151
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|