Files
submanager/lib/widgets/home_content.dart
JiWoong Sul 0f0b02bf08 feat: 다국어 지원 및 다중 통화 환율 변환 기능 확대
- ExchangeRateService에 JPY, CNY 환율 지원 추가
- 구독 서비스별 다국어 표시 이름 지원
- 분석 화면 차트 및 UI/UX 개선
- 설정 화면 전면 리팩토링
- SMS 스캔 기능 사용성 개선
- 전체 앱 다국어 번역 확대

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-16 17:34:32 +09:00

156 lines
5.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/subscription_provider.dart';
import '../providers/category_provider.dart';
import '../utils/subscription_category_helper.dart';
import '../widgets/native_ad_widget.dart';
import '../widgets/main_summary_card.dart';
import '../widgets/subscription_list_widget.dart';
import '../widgets/empty_state_widget.dart';
import '../theme/app_colors.dart';
import '../l10n/app_localizations.dart';
class HomeContent extends StatelessWidget {
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
Widget build(BuildContext context) {
final provider = context.watch<SubscriptionProvider>();
if (provider.isLoading) {
return const Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFF3B82F6)),
),
);
}
if (provider.subscriptions.isEmpty) {
return EmptyStateWidget(
fadeController: fadeController,
rotateController: rotateController,
slideController: slideController,
onAddPressed: onAddPressed,
);
}
// 카테고리별 구독 구분
final categoryProvider = Provider.of<CategoryProvider>(context, listen: false);
final categorizedSubscriptions = SubscriptionCategoryHelper.categorizeSubscriptions(
provider.subscriptions,
categoryProvider,
context,
);
return RefreshIndicator(
onRefresh: () async {
await provider.refreshSubscriptions();
},
color: const Color(0xFF3B82F6),
child: CustomScrollView(
controller: scrollController,
physics: const BouncingScrollPhysics(),
slivers: [
SliverToBoxAdapter(
child: SizedBox(
height: kToolbarHeight + MediaQuery.of(context).padding.top,
),
),
const SliverToBoxAdapter(
child: NativeAdWidget(key: ValueKey('home_ad')),
),
SliverToBoxAdapter(
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0.2),
end: Offset.zero,
).animate(CurvedAnimation(
parent: slideController, curve: Curves.easeOutCubic)),
child: MainScreenSummaryCard(
provider: provider,
fadeController: fadeController,
pulseController: pulseController,
waveController: waveController,
slideController: 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: slideController, curve: Curves.easeOutCubic)),
child: Text(
AppLocalizations.of(context).mySubscriptions,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: AppColors.darkNavy,
),
),
),
SlideTransition(
position: Tween<Offset>(
begin: const Offset(0.2, 0),
end: Offset.zero,
).animate(CurvedAnimation(
parent: slideController, curve: Curves.easeOutCubic)),
child: Row(
children: [
Text(
AppLocalizations.of(context).subscriptionCount(provider.subscriptions.length),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.primaryColor,
),
),
const SizedBox(width: 4),
const Icon(
Icons.arrow_forward_ios,
size: 14,
color: AppColors.primaryColor,
),
],
),
),
],
),
),
),
SubscriptionListWidget(
categorizedSubscriptions: categorizedSubscriptions,
fadeController: fadeController,
),
SliverToBoxAdapter(
child: SizedBox(
height: 120 + MediaQuery.of(context).padding.bottom,
),
),
],
),
);
}
}