seaislee1209 066eb8f820 feat: music-creation page + MiniMax API integration + Flutter dev setup
Music Creation Page:
- Vinyl 3D flip to view lyrics, tonearm animation, glow rotation effect
- Circular SVG progress ring, speech bubble feedback, confirm dialog
- Playlist modal, free creation input, lyrics formatting optimization
- MiniMax API real music generation with SSE streaming progress

Backend:
- FastAPI proxy server.py for MiniMax API calls
- Music + lyrics file persistence to Capybara music/ directory
- GET /api/playlist endpoint for auto-building playlist from files

UI/UX Refinements:
- frontend-design skill compliance across all pages
- Glassmorphism effects, modal interactions, scroll tap prevention
- iPhone 12 Pro responsive layout (390x844)

Flutter Development Preparation:
- Installed flutter-expert skill with 6 reference docs
- Added 5 Cursor Rules: official Flutter, clean architecture, UI performance, testing, Dart standards

Assets:
- 9 Capybara music MP3 files + lyrics TXT files
- MiniMax API documentation

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-06 18:23:19 +08:00

124 lines
2.5 KiB
Markdown

# Widget Patterns
## Optimized Widget Pattern
```dart
// Use const constructors
class OptimizedCard extends StatelessWidget {
final String title;
final VoidCallback onTap;
const OptimizedCard({
super.key,
required this.title,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: onTap,
child: Padding(
padding: const EdgeInsets.all(16),
child: Text(title, style: Theme.of(context).textTheme.titleMedium),
),
),
);
}
}
```
## Responsive Layout
```dart
class ResponsiveLayout extends StatelessWidget {
final Widget mobile;
final Widget? tablet;
final Widget desktop;
const ResponsiveLayout({
super.key,
required this.mobile,
this.tablet,
required this.desktop,
});
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth >= 1100) return desktop;
if (constraints.maxWidth >= 650) return tablet ?? mobile;
return mobile;
},
);
}
}
```
## Custom Hooks (flutter_hooks)
```dart
import 'package:flutter_hooks/flutter_hooks.dart';
class CounterWidget extends HookWidget {
@override
Widget build(BuildContext context) {
final counter = useState(0);
final controller = useTextEditingController();
useEffect(() {
// Setup
return () {
// Cleanup
};
}, []);
return Column(
children: [
Text('Count: ${counter.value}'),
ElevatedButton(
onPressed: () => counter.value++,
child: const Text('Increment'),
),
],
);
}
}
```
## Sliver Patterns
```dart
CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 200,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: const Text('Title'),
background: Image.network(imageUrl, fit: BoxFit.cover),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item $index')),
childCount: 100,
),
),
],
)
```
## Key Optimization Patterns
| Pattern | Implementation |
|---------|----------------|
| **const widgets** | Add `const` to static widgets |
| **keys** | Use `Key` for list items |
| **select** | `ref.watch(provider.select(...))` |
| **RepaintBoundary** | Isolate expensive repaints |
| **ListView.builder** | Lazy loading for lists |
| **const constructors** | Always use when possible |