Files
submanager/lib/widgets/home_content.dart
2025-12-07 21:14:54 +09:00

226 lines
7.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../l10n/app_localizations.dart';
import '../providers/category_provider.dart';
import '../providers/payment_card_provider.dart';
import '../providers/subscription_provider.dart';
import '../utils/subscription_grouping_helper.dart';
import '../widgets/empty_state_widget.dart';
import '../widgets/main_summary_card.dart';
import '../theme/ui_constants.dart';
import '../widgets/subscription_list_widget.dart';
class HomeContent extends StatefulWidget {
final AnimationController fadeController;
final AnimationController rotateController;
final AnimationController slideController;
final AnimationController pulseController;
final AnimationController waveController;
final ScrollController scrollController;
final VoidCallback onAddPressed;
const HomeContent({
super.key,
required this.fadeController,
required this.rotateController,
required this.slideController,
required this.pulseController,
required this.waveController,
required this.scrollController,
required this.onAddPressed,
});
@override
State<HomeContent> createState() => _HomeContentState();
}
class _HomeContentState extends State<HomeContent> {
static const _groupingPrefKey = 'home_grouping_mode';
SubscriptionGroupingMode _groupingMode = SubscriptionGroupingMode.category;
@override
void initState() {
super.initState();
_loadGroupingPreference();
}
Future<void> _loadGroupingPreference() async {
final prefs = await SharedPreferences.getInstance();
final stored = prefs.getString(_groupingPrefKey);
if (stored == 'paymentCard') {
setState(() {
_groupingMode = SubscriptionGroupingMode.paymentCard;
});
}
}
Future<void> _saveGroupingPreference(SubscriptionGroupingMode mode) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(
_groupingPrefKey,
mode == SubscriptionGroupingMode.paymentCard
? 'paymentCard'
: 'category');
}
void _updateGroupingMode(SubscriptionGroupingMode mode) {
if (_groupingMode == mode) return;
setState(() {
_groupingMode = mode;
});
_saveGroupingPreference(mode);
}
@override
Widget build(BuildContext context) {
final subscriptionProvider = context.watch<SubscriptionProvider>();
final categoryProvider = context.watch<CategoryProvider>();
final paymentCardProvider = context.watch<PaymentCardProvider>();
if (subscriptionProvider.isLoading) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.primary,
),
),
);
}
if (subscriptionProvider.subscriptions.isEmpty) {
return EmptyStateWidget(
fadeController: widget.fadeController,
rotateController: widget.rotateController,
slideController: widget.slideController,
onAddPressed: widget.onAddPressed,
);
}
final groupedSubscriptions = SubscriptionGroupingHelper.buildGroups(
context: context,
subscriptions: subscriptionProvider.subscriptions,
mode: _groupingMode,
categoryProvider: categoryProvider,
paymentCardProvider: paymentCardProvider,
);
return RefreshIndicator(
onRefresh: () async {
await subscriptionProvider.refreshSubscriptions();
},
color: Theme.of(context).colorScheme.primary,
child: CustomScrollView(
controller: widget.scrollController,
physics: const BouncingScrollPhysics(),
slivers: [
const SliverToBoxAdapter(
child: SizedBox(height: UIConstants.pageTopPadding),
),
SliverToBoxAdapter(
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0.2),
end: Offset.zero,
).animate(CurvedAnimation(
parent: widget.slideController, curve: Curves.easeOutCubic)),
child: MainScreenSummaryCard(
provider: subscriptionProvider,
fadeController: widget.fadeController,
pulseController: widget.pulseController,
waveController: widget.waveController,
slideController: widget.slideController,
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 24, 20, 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SlideTransition(
position: Tween<Offset>(
begin: const Offset(-0.2, 0),
end: Offset.zero,
).animate(CurvedAnimation(
parent: widget.slideController,
curve: Curves.easeOutCubic)),
child: Text(
AppLocalizations.of(context).mySubscriptions,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Theme.of(context).colorScheme.onSurface,
),
),
),
SlideTransition(
position: Tween<Offset>(
begin: const Offset(0.2, 0),
end: Offset.zero,
).animate(CurvedAnimation(
parent: widget.slideController,
curve: Curves.easeOutCubic)),
child: Row(
children: [
Text(
AppLocalizations.of(context).subscriptionCount(
subscriptionProvider.subscriptions.length),
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(width: 4),
Icon(
Icons.arrow_forward_ios,
size: 14,
color: Theme.of(context).colorScheme.primary,
),
],
),
),
],
),
),
),
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
child: Wrap(
spacing: 8,
children: [
ChoiceChip(
label: Text(AppLocalizations.of(context).category),
selected:
_groupingMode == SubscriptionGroupingMode.category,
onSelected: (_) =>
_updateGroupingMode(SubscriptionGroupingMode.category),
),
ChoiceChip(
label: Text(AppLocalizations.of(context).paymentCard),
selected:
_groupingMode == SubscriptionGroupingMode.paymentCard,
onSelected: (_) => _updateGroupingMode(
SubscriptionGroupingMode.paymentCard),
),
],
),
),
),
SubscriptionListWidget(
groups: groupedSubscriptions,
fadeController: widget.fadeController,
),
SliverToBoxAdapter(
child: SizedBox(
height: 120 + MediaQuery.of(context).padding.bottom,
),
),
],
),
);
}
}