checkpoint: focus seed 1.0.1 localized dev switch

This commit is contained in:
2026-06-11 23:35:49 +08:00
parent c51abdfb73
commit d06dc35ee6
72 changed files with 6155 additions and 1390 deletions
+145
View File
@@ -0,0 +1,145 @@
import 'package:flutter/material.dart';
import '../l10n/l10n.dart';
class FocusSeedHeader extends StatelessWidget {
const FocusSeedHeader({
required this.title,
required this.subtitle,
this.showBrand = true,
this.isSaving = false,
this.trailing,
super.key,
});
final String title;
final String subtitle;
final bool showBrand;
final bool isSaving;
final Widget? trailing;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final l10n = context.l10n;
return Padding(
padding: const EdgeInsets.fromLTRB(20, 14, 20, 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showBrand) ...[
LayoutBuilder(
builder: (context, constraints) {
final textScale =
MediaQuery.textScalerOf(context).scale(14) / 14;
final compact = constraints.maxWidth < 340 || textScale > 1.3;
return Row(
children: [
Container(
width: 34,
height: 34,
decoration: BoxDecoration(
color: theme.colorScheme.primary.withValues(
alpha: 0.12,
),
borderRadius: BorderRadius.circular(10),
),
child: Icon(
Icons.spa_rounded,
color: theme.colorScheme.primary,
size: 21,
),
),
const SizedBox(width: 10),
Expanded(
child: Text(
l10n.brandName,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w700,
),
),
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 180),
child:
isSaving
? _SaveStatus(
key: const ValueKey('saving'),
icon: Icons.sync_rounded,
label: l10n.saving,
compact: compact,
)
: _SaveStatus(
key: const ValueKey('saved'),
icon: Icons.smartphone_outlined,
label: l10n.local,
compact: compact,
),
),
if (trailing != null) ...[
const SizedBox(width: 4),
trailing!,
],
],
);
},
),
const SizedBox(height: 12),
],
Text(
title,
style: theme.textTheme.titleLarge?.copyWith(fontSize: 24),
),
const SizedBox(height: 4),
Text(
subtitle,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
],
),
);
}
}
class _SaveStatus extends StatelessWidget {
const _SaveStatus({
required this.icon,
required this.label,
required this.compact,
super.key,
});
final IconData icon;
final String label;
final bool compact;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Semantics(
label: label,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 5),
decoration: BoxDecoration(
color: theme.colorScheme.surfaceContainerLow,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: theme.colorScheme.outlineVariant),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(icon, size: 15, color: theme.colorScheme.primary),
if (!compact) ...[
const SizedBox(width: 4),
Text(label, style: theme.textTheme.labelSmall),
],
],
),
),
);
}
}