Files
ReelShort/lib/pages/create/create_view.dart
T

375 lines
11 KiB
Dart

// Author: fruit.com.cn
import 'package:flutter/material.dart';
import '../../core/theme/app_colors.dart';
import '../../core/theme/app_theme.dart';
import '../../core/widgets/plain_page_scaffold.dart';
import '../../l10n/app_localizations.dart';
const double _cardHeight = 196;
const double _cardRadius = 20;
const double _arrowSize = 36;
const double _illustrationWidth = 156;
const double _illustrationHeight = 88;
const double _mottoLineWidth = 96;
const List<Color> _aiGradientStart = [Color(0xFFFFE3D0), Color(0xFFFFC9AC)];
const List<Color> _uploadGradient = [Color(0xFFFFEAD9), Color(0xFFFFD3B3)];
/// 创作页:AI 制作与上传发布两张主卡,底部品牌标语。
class CreatePage extends StatelessWidget {
const CreatePage({super.key});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Theme(
data: AppTheme.light(),
child: SafeArea(
bottom: false,
child: ListView(
key: const Key('create-page'),
padding: const EdgeInsets.fromLTRB(16, 28, 16, 24),
children: [
Text(
l10n.createTab,
style: const TextStyle(
fontFamily: 'Outfit',
color: AppColors.onSurface,
fontSize: 28,
fontWeight: FontWeight.w800,
),
),
const SizedBox(height: 6),
Text(
l10n.createSubtitle,
style: const TextStyle(color: AppColors.muted, fontSize: 13),
),
const SizedBox(height: 24),
_CreateCard(
key: const Key('create-ai'),
title: l10n.createAiTitle,
subtitle: l10n.createAiSubtitle,
illustration: const _AiIllustration(),
onTap: () => _openPlaceholder(context, l10n.createAiTitle),
),
const SizedBox(height: 16),
_CreateCard(
key: const Key('create-upload'),
title: l10n.createUploadTitle,
subtitle: l10n.createUploadSubtitle,
illustration: const _UploadIllustration(),
onTap: () => _openPlaceholder(context, l10n.createUploadTitle),
),
const SizedBox(height: 32),
Text(
l10n.createMottoPrimary,
key: const Key('create-motto-primary'),
textAlign: TextAlign.center,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 18,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 4),
Text(
l10n.createMottoSecondary,
key: const Key('create-motto-secondary'),
textAlign: TextAlign.center,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 18,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 10),
Center(
child: Container(
key: const Key('create-motto-line'),
width: _mottoLineWidth,
height: 2,
decoration: BoxDecoration(
color: AppColors.blue,
borderRadius: BorderRadius.circular(1),
),
),
),
],
),
),
);
}
void _openPlaceholder(BuildContext context, String title) {
Navigator.of(context).push<void>(
MaterialPageRoute(builder: (_) => _CreatePlaceholderPage(title: title)),
);
}
}
class _CreateCard extends StatelessWidget {
const _CreateCard({
super.key,
required this.title,
required this.subtitle,
required this.illustration,
required this.onTap,
});
final String title;
final String subtitle;
final Widget illustration;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: AppColors.card,
borderRadius: BorderRadius.circular(_cardRadius),
boxShadow: const [AppTheme.cardShadow],
),
child: Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(_cardRadius),
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: onTap,
child: SizedBox(
height: _cardHeight,
child: Stack(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(20, 18, 68, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 22,
fontWeight: FontWeight.w900,
),
),
const SizedBox(height: 6),
Text(
subtitle,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: AppColors.muted,
fontSize: 13,
),
),
],
),
),
Positioned(
top: 16,
right: 16,
child: Container(
width: _arrowSize,
height: _arrowSize,
decoration: const BoxDecoration(
color: AppColors.raised,
shape: BoxShape.circle,
),
child: const Icon(
Icons.arrow_forward_rounded,
color: AppColors.blue,
size: 18,
),
),
),
Positioned(right: 14, bottom: 14, child: illustration),
],
),
),
),
),
);
}
}
class _AiIllustration extends StatelessWidget {
const _AiIllustration();
@override
Widget build(BuildContext context) {
return Container(
width: _illustrationWidth,
height: _illustrationHeight,
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: _aiGradientStart,
),
borderRadius: BorderRadius.circular(16),
),
child: Stack(
children: [
const Positioned(
left: 12,
top: 10,
child: Icon(
Icons.auto_awesome_rounded,
color: AppColors.secondary,
size: 30,
),
),
const Positioned(
right: 14,
top: 8,
child: Icon(
Icons.auto_awesome_rounded,
color: AppColors.blue,
size: 12,
),
),
Positioned(
right: 32,
top: 30,
child: Container(
width: 5,
height: 5,
decoration: BoxDecoration(
color: AppColors.blue.withValues(alpha: 0.55),
shape: BoxShape.circle,
),
),
),
const Positioned(
left: 12,
bottom: 10,
child: Text(
'Every Story Matters',
style: TextStyle(
color: AppColors.muted,
fontSize: 10,
fontWeight: FontWeight.w700,
),
),
),
],
),
);
}
}
class _UploadIllustration extends StatelessWidget {
const _UploadIllustration();
@override
Widget build(BuildContext context) {
return Container(
width: _illustrationWidth,
height: _illustrationHeight,
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: _uploadGradient,
),
borderRadius: BorderRadius.circular(16),
),
child: Stack(
children: [
const Positioned(
left: 12,
top: 8,
child: Icon(
Icons.cloud_upload_rounded,
color: AppColors.secondary,
size: 30,
),
),
Positioned(
right: 16,
top: 12,
child: Container(
width: 30,
height: 20,
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.55),
borderRadius: BorderRadius.circular(4),
),
child: const Icon(
Icons.movie_creation_outlined,
color: AppColors.muted,
size: 12,
),
),
),
Positioned(
right: 52,
top: 34,
child: Container(
width: 5,
height: 5,
decoration: BoxDecoration(
color: AppColors.blue.withValues(alpha: 0.55),
shape: BoxShape.circle,
),
),
),
const Positioned(
left: 12,
bottom: 10,
child: Text(
'Ready to publish',
style: TextStyle(
color: AppColors.muted,
fontSize: 10,
fontWeight: FontWeight.w700,
),
),
),
],
),
);
}
}
class _CreatePlaceholderPage extends StatelessWidget {
const _CreatePlaceholderPage({required this.title});
final String title;
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return PlainPageScaffold(
pageKey: const Key('create-placeholder-page'),
backKey: const Key('create-placeholder-back'),
title: title,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(
Icons.construction_rounded,
color: AppColors.blue,
size: 42,
),
const SizedBox(height: 12),
Text(
l10n.comingSoon,
style: const TextStyle(
color: AppColors.onSurface,
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
],
),
),
);
}
}