首次远程推送

This commit is contained in:
2026-09-27 23:40:22 +08:00
parent 2e0bf3c784
commit 8afa47952a
70 changed files with 8603 additions and 4502 deletions
+65 -101
View File
@@ -1,9 +1,13 @@
import 'package:flutter/material.dart';
import '../../app/app_theme.dart';
import '../../application/focus_seed_controller.dart';
import '../../core/date_keys.dart';
import '../../l10n/l10n.dart';
import '../../widgets/app_bottom_sheet.dart';
import '../../widgets/app_empty_state.dart';
import '../../widgets/dialogs.dart';
import '../../widgets/loading_view.dart';
import '../today/widgets/compact_habit_row.dart';
Future<void> showHabitManagerSheet(
@@ -21,89 +25,63 @@ Future<void> showHabitManagerSheet(
animation: controller,
builder: (context, _) {
final state = controller.state;
if (state == null) {
return const Center(child: CircularProgressIndicator());
}
final l10n = context.l10n;
final visuals = FocusSeedVisuals.of(context);
if (state == null) {
return AppBottomSheetScaffold(
title: l10n.habitsTitle,
subtitle: l10n.habitsSubtitle,
icon: Icons.add_task_rounded,
accent: visuals.habit,
expand: true,
child: const LoadingView(),
);
}
final today = todayKey();
return Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(20, 4, 12, 12),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
l10n.habitsTitle,
style: Theme.of(context).textTheme.titleLarge,
),
Text(
l10n.habitsSubtitle,
style: Theme.of(
context,
).textTheme.bodySmall?.copyWith(
color:
Theme.of(
context,
).colorScheme.onSurfaceVariant,
),
),
],
),
),
IconButton.filledTonal(
tooltip: l10n.addHabit,
onPressed:
return AppBottomSheetScaffold(
title: l10n.habitsTitle,
subtitle: l10n.habitsSubtitle,
icon: Icons.add_task_rounded,
accent: visuals.habit,
expand: true,
trailing: IconButton.filledTonal(
tooltip: l10n.addHabit,
onPressed:
() => showHabitDialog(context, controller.addHabit),
icon: const Icon(Icons.add_rounded),
),
child:
state.habits.isEmpty
? _EmptyHabits(
onAdd:
() =>
showHabitDialog(context, controller.addHabit),
icon: const Icon(Icons.add_rounded),
),
],
),
),
const Divider(),
Expanded(
child:
state.habits.isEmpty
? _EmptyHabits(
onAdd:
)
: ListView.separated(
padding: const EdgeInsets.fromLTRB(0, 2, 0, 24),
itemCount: state.habits.length,
separatorBuilder: (_, _) => const SizedBox(height: 8),
itemBuilder: (context, index) {
final habit = state.habits[index];
return CompactHabitRow(
habit: habit,
dateKey: today,
onToggle: () => controller.toggleHabit(habit),
onEdit:
() => showHabitDialog(
context,
controller.addHabit,
(value) =>
controller.renameHabit(habit, value),
initialValue: habit.title,
),
)
: ListView.separated(
padding: const EdgeInsets.fromLTRB(20, 8, 20, 32),
itemCount: state.habits.length,
separatorBuilder: (_, _) => const Divider(),
itemBuilder: (context, index) {
final habit = state.habits[index];
return CompactHabitRow(
habit: habit,
dateKey: today,
onToggle: () => controller.toggleHabit(habit),
onEdit:
() => showHabitDialog(
context,
(value) => controller.renameHabit(
habit,
value,
),
initialValue: habit.title,
),
onDelete:
() => confirmDeleteHabit(
context,
() => controller.deleteHabit(habit),
),
);
},
),
),
],
onDelete:
() => confirmDeleteHabit(
context,
() => controller.deleteHabit(habit),
),
);
},
),
);
},
),
@@ -118,31 +96,17 @@ class _EmptyHabits extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: const EdgeInsets.all(28),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.eco_outlined,
size: 40,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 12),
Text(
context.l10n.emptyHabitsTitle,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 14),
FilledButton.icon(
onPressed: onAdd,
icon: const Icon(Icons.add_rounded),
label: Text(context.l10n.addHabit),
),
],
),
),
final l10n = context.l10n;
return AppEmptyState(
title: l10n.emptyHabitsTitle,
body: l10n.emptyHabitPrompt,
icon: Icons.add_task_rounded,
actionLabel: l10n.addHabit,
actionIcon: Icons.add_rounded,
onAction: onAdd,
accent: FocusSeedVisuals.of(context).habit,
illustrationHeight: 86,
padding: const EdgeInsets.all(28),
);
}
}