Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
# FlutterGuard CI gate — reject commits that introduce high-severity issues
set -euo pipefail

echo "🔍 Running FlutterGuard static scan..."
dart run flutterguard_cli:flutterguard scan --path . --fail-on high

if [ $? -ne 0 ]; then
echo ""
echo "❌ FlutterGuard 检测到高优问题,提交被阻止。"
echo " 运行 'dart run flutterguard_cli:flutterguard scan' 查看详情。"
exit 1
fi

echo "✅ FlutterGuard 扫描通过。"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@
**/linux/flutter/generated_plugin_registrant.cc
**/linux/flutter/generated_plugin_registrant.h
**/linux/flutter/generated_plugins.cmake

# FlutterGuard scan output
.flutterguard/
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@
```bash
dart format .
flutter analyze
dart run flutterguard_cli:flutterguard scan --path . --fail-on high
```

- `flutter analyze` 必须通过,不允许有 error 级别问题
- `flutterguard scan --fail-on high` 必须通过,不允许引入高优问题
- 涉及逻辑代码时补充测试(如有测试框架)
- 涉及 UI 教学页时进行人工验收或截图说明

Expand All @@ -60,6 +62,14 @@ flutter analyze
5. 标记低质量模块的 `status` 为 `ModuleStatus.pending`
6. 检查 `flutter analyze` 和 `dart format` 是否通过

## 启用预提交钩子

```bash
git config core.hooksPath .githooks
```

这会在每次 `git commit` 前自动执行 FlutterGuard 扫描,阻止引入高优问题的提交。

## 模块分类枚举

```dart
Expand Down
42 changes: 42 additions & 0 deletions flutterguard.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
include:
- lib/**
- test/**

exclude:
- lib/**.g.dart
- lib/**.freezed.dart
- lib/**.mocks.dart

rules:
large_file:
enabled: true
maxLines: 500
large_class:
enabled: true
maxLines: 300
large_build_method:
enabled: true
maxLines: 80
lifecycle_resource:
enabled: true

boundaries:
# 模块禁止反向依赖 app 层
- name: no_module_to_app
from: lib/modules/**
forbidden:
- lib/app/**

# shared 层禁止反向依赖模块或 app
- name: shared_purity
from: lib/shared/**
forbidden:
- lib/modules/**
- lib/app/**

# shared 层必须纯净,不能反向依赖模块或 app
- name: shared_purity
from: lib/shared/**
forbidden:
- lib/modules/**
- lib/app/**
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class _PaintAnimationPageState extends State<PaintAnimationPage>
@override
void dispose() {
for (var item in _flyingItems) {
item.controller.dispose();
item.dispose();
}
super.dispose();
}
Expand Down Expand Up @@ -445,6 +445,10 @@ class FlyingPaintItem {
required this.endPosition,
required this.controller,
});

void dispose() {
controller.dispose();
}
}

/// 自定义 Painter 绘制飞行动画
Expand Down
11 changes: 5 additions & 6 deletions lib/modules/ui/gcode_visualizer/pages/gcode_visualizer_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,29 @@ class GcodeVisualizerPage extends StatefulWidget {
class _GcodeVisualizerPageState extends State<GcodeVisualizerPage>
with TickerProviderStateMixin {
late final GcodePlayerController _controller;
late final TextEditingController _editorController;
final _editorKey = GlobalKey<GcodeEditorPanelState>();

@override
void initState() {
super.initState();
_controller = GcodePlayerController(vsync: this);
_editorController = TextEditingController(text: _controller.source);
_controller.parse();
}

@override
void dispose() {
_editorController.dispose();
_controller.dispose();
super.dispose();
}

void _onParse() {
_controller.updateSource(_editorController.text);
_controller.updateSource(_editorKey.currentState!.text);
_controller.parse();
}

void _onResetSample() {
_controller.loadSample();
_editorController.text = _controller.source;
_editorKey.currentState!.text = _controller.source;
_controller.parse();
}

Expand Down Expand Up @@ -124,7 +122,8 @@ class _GcodeVisualizerPageState extends State<GcodeVisualizerPage>
return Column(
children: [
GcodeEditorPanel(
controller: _editorController,
key: _editorKey,
initialText: _controller.source,
onParse: _onParse,
onResetSample: _onResetSample,
errorCount: _controller.errorCount,
Expand Down
26 changes: 21 additions & 5 deletions lib/modules/ui/gcode_visualizer/widgets/gcode_editor_panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,47 @@ import 'package:flutter/material.dart';
class GcodeEditorPanel extends StatefulWidget {
const GcodeEditorPanel({
super.key,
required this.controller,
required this.initialText,
required this.onParse,
required this.onResetSample,
required this.errorCount,
required this.commandCount,
required this.hasParsed,
});

final TextEditingController controller;
final String initialText;
final VoidCallback onParse;
final VoidCallback onResetSample;
final int errorCount;
final int commandCount;
final bool hasParsed;

@override
State<GcodeEditorPanel> createState() => _GcodeEditorPanelState();
State<GcodeEditorPanel> createState() => GcodeEditorPanelState();
}

class _GcodeEditorPanelState extends State<GcodeEditorPanel> {
class GcodeEditorPanelState extends State<GcodeEditorPanel> {
late final TextEditingController _controller;
bool _resetPressed = false;
bool _parsePressed = false;
bool _resetHovered = false;
bool _parseHovered = false;

String get text => _controller.text;
set text(String value) => _controller.text = value;

@override
void initState() {
super.initState();
_controller = TextEditingController(text: widget.initialText);
}

@override
void dispose() {
_controller.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
Expand Down Expand Up @@ -104,7 +120,7 @@ class _GcodeEditorPanelState extends State<GcodeEditorPanel> {
Padding(
padding: const EdgeInsets.all(8),
child: TextField(
controller: widget.controller,
controller: _controller,
maxLines: 8,
style: const TextStyle(
fontFamily: 'monospace',
Expand Down
86 changes: 86 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f
url: "https://pub.flutter-io.cn"
source: hosted
version: "85.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d"
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.7.1"
args:
dependency: transitive
description:
Expand Down Expand Up @@ -57,6 +73,22 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.19.1"
convert:
dependency: transitive
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.2"
crypto:
dependency: transitive
description:
name: crypto
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.7"
device_info_plus:
dependency: "direct main"
description:
Expand Down Expand Up @@ -168,6 +200,28 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutterguard_cli:
dependency: "direct dev"
description:
path: "../flutterguard/packages/flutterguard_cli"
relative: true
source: path
version: "0.1.0"
flutterguard_core:
dependency: transitive
description:
path: "../flutterguard/packages/flutterguard_core"
relative: true
source: path
version: "0.1.0"
glob:
dependency: transitive
description:
name: glob
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.3"
go_router:
dependency: "direct main"
description:
Expand Down Expand Up @@ -272,6 +326,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
package_config:
dependency: transitive
description:
name: package_config
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
path:
dependency: transitive
description:
Expand Down Expand Up @@ -312,6 +374,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.1.5+1"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
riverpod:
dependency: transitive
description:
Expand Down Expand Up @@ -445,6 +515,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "15.2.0"
watcher:
dependency: transitive
description:
name: watcher
sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.1"
web:
dependency: transitive
description:
Expand Down Expand Up @@ -477,6 +555,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.6.1"
yaml:
dependency: transitive
description:
name: yaml
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.9.0 <4.0.0"
flutter: ">=3.35.0"
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^4.0.0
flutterguard_cli:
path: ../flutterguard/packages/flutterguard_cli

flutter:
uses-material-design: true