MoodCanvas/lib/screens/editor/editor_screen.dart
fengshengxiong 91b7eebbf2 接入TopON
2026-01-22 16:34:55 +08:00

273 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:share_plus/share_plus.dart';
import 'package:aesthetica_wallpaper/models/recipe.dart';
import 'package:aesthetica_wallpaper/providers/editor_provider.dart';
import 'package:aesthetica_wallpaper/providers/recipe_provider.dart';
import 'package:aesthetica_wallpaper/screens/preview/full_screen_preview_dialog.dart';
import 'editor_preview.dart';
import 'editor_controls.dart';
import 'simple_save_dialog.dart';
// ------------------------------------
// --- 1. Editor Screen (EditorScreen) ---
// ------------------------------------
class EditorScreen extends StatelessWidget {
const EditorScreen({super.key});
@override
Widget build(BuildContext context) {
final editorProvider = Provider.of<EditorProvider>(context, listen: false);
final GlobalKey repaintBoundaryKey = GlobalKey();
final GlobalKey pureImageKey = GlobalKey(); // Pure image key
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
title: const Text(
'Workshop',
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
backgroundColor: Colors.transparent,
elevation: 0,
iconTheme: const IconThemeData(color: Colors.white),
actions: [
// Full screen button
Container(
margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
icon: const Icon(Icons.fullscreen, color: Colors.white),
tooltip: 'Full Screen Preview',
onPressed: () => _showFullScreenPreview(context, editorProvider),
),
),
// Save button
Container(
margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.pinkAccent, Colors.purpleAccent],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
icon: const Icon(Icons.download, color: Colors.white),
tooltip: 'Save to Gallery',
onPressed: () => _showSimpleSave(context),
),
),
// Share button
Container(
margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration(
color: Colors.blue.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
icon: const Icon(Icons.share, color: Colors.blue),
tooltip: 'Share Creation',
onPressed: () => _shareCreation(),
),
),
// Favorite button
Consumer<RecipeProvider>(
builder: (context, recipeProvider, child) {
final isFavorited = recipeProvider.recipes.any(
(recipe) =>
recipe.baseImagePath ==
editorProvider.currentRecipe.baseImagePath,
);
return Container(
margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration(
color: isFavorited
? Colors.pinkAccent.withValues(alpha: 0.2)
: Colors.white.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
icon: Icon(
isFavorited ? Icons.favorite : Icons.favorite_border,
color: isFavorited ? Colors.pinkAccent : Colors.white,
),
tooltip: isFavorited
? 'Remove from Favorites'
: 'Add to Favorites',
onPressed: () {
final currentRecipe = editorProvider.currentRecipe;
final existingRecipe = recipeProvider.recipes.firstWhere(
(recipe) =>
recipe.baseImagePath == currentRecipe.baseImagePath,
orElse: () => Recipe(id: '', baseImagePath: ''),
);
if (existingRecipe.id.isEmpty) {
recipeProvider.addRecipe(currentRecipe);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Row(
children: [
Icon(Icons.favorite, color: Colors.white),
SizedBox(width: 8),
Text('Added to favorites!'),
],
),
backgroundColor: Colors.pinkAccent,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
duration: const Duration(seconds: 2),
),
);
} else {
recipeProvider.deleteRecipe(existingRecipe.id);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Row(
children: [
Icon(Icons.heart_broken, color: Colors.white),
SizedBox(width: 8),
Text('Removed from favorites'),
],
),
backgroundColor: Colors.orange,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
duration: const Duration(seconds: 2),
),
);
}
},
),
);
},
),
// Save recipe button
Container(
margin: const EdgeInsets.only(right: 16),
decoration: BoxDecoration(
color: Colors.green.withValues(alpha: 0.2),
borderRadius: BorderRadius.circular(12),
),
child: IconButton(
icon: const Icon(Icons.save, color: Colors.green),
tooltip: 'Save Recipe',
onPressed: () {
final recipe = editorProvider.currentRecipe;
Provider.of<RecipeProvider>(
context,
listen: false,
).addRecipe(recipe);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Row(
children: [
Icon(Icons.check_circle, color: Colors.white),
SizedBox(width: 8),
Text('Recipe Saved!'),
],
),
backgroundColor: Colors.green,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
);
Navigator.of(context).pop();
},
),
),
],
),
body: SafeArea(
child: Column(
children: [
// Preview area (takes available space)
Expanded(
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 16),
child: EditorPreview(
repaintBoundaryKey: repaintBoundaryKey,
pureImageKey: pureImageKey,
),
),
),
// Minimal spacing between preview and controls
const SizedBox(height: 8),
// Control area (fixed height)
Container(
height: 160,
decoration: BoxDecoration(
color: Colors.grey[900],
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.3),
blurRadius: 10,
spreadRadius: 2,
offset: const Offset(0, -2),
),
],
),
child: const EditorControls(),
),
],
),
),
);
}
// Show full screen preview
void _showFullScreenPreview(
BuildContext context,
EditorProvider editorProvider,
) {
showDialog(
context: context,
barrierDismissible: true,
builder: (context) =>
FullScreenPreviewDialog(recipe: editorProvider.currentRecipe),
);
}
// Show simple save dialog
void _showSimpleSave(BuildContext context) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => SimpleSaveDialog(
fileName: 'MoodCanvas_${DateTime.now().millisecondsSinceEpoch}',
),
);
}
// Share creation functionality
void _shareCreation() {
SharePlus.instance.share(
ShareParams(
text:
'Check out my amazing wallpaper creation! 🎨\n\nMade with MoodCanvas:Walls - the ultimate wallpaper creator app. Express your creativity and personalize your device!\n\nDownload MoodCanvas:Walls: https://moodcanvas.app',
subject: 'My MoodCanvas:Walls Creation',
),
);
}
}