Major UI/UX and architecture improvements
- Implemented new navigation system with NavigationProvider and route management - Added adaptive theme system with ThemeProvider for better theme handling - Introduced glassmorphism design elements (app bars, scaffolds, cards) - Added advanced animations (spring animations, page transitions, staggered lists) - Implemented performance optimizations (memory manager, lazy loading) - Refactored Analysis screen into modular components - Added floating navigation bar with haptic feedback - Improved subscription cards with swipe actions - Enhanced skeleton loading with better animations - Added cached network image support - Improved overall app architecture and code organization 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
154
lib/widgets/home_content.dart
Normal file
154
lib/widgets/home_content.dart
Normal file
@@ -0,0 +1,154 @@
|
||||
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 '../widgets/glassmorphic_app_bar.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
import '../routes/app_routes.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,
|
||||
);
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await provider.refreshSubscriptions();
|
||||
},
|
||||
color: const Color(0xFF3B82F6),
|
||||
child: CustomScrollView(
|
||||
controller: scrollController,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
slivers: [
|
||||
const GlassmorphicSliverAppBar(
|
||||
title: '홈',
|
||||
pinned: true,
|
||||
expandedHeight: kToolbarHeight,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: NativeAdWidget(key: const 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(
|
||||
'나의 구독 서비스',
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
),
|
||||
SlideTransition(
|
||||
position: Tween<Offset>(
|
||||
begin: const Offset(0.2, 0),
|
||||
end: Offset.zero,
|
||||
).animate(CurvedAnimation(
|
||||
parent: slideController, curve: Curves.easeOutCubic)),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'${provider.subscriptions.length}개',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColors.primaryColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Icon(
|
||||
Icons.arrow_forward_ios,
|
||||
size: 14,
|
||||
color: AppColors.primaryColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
SubscriptionListWidget(
|
||||
categorizedSubscriptions: categorizedSubscriptions,
|
||||
fadeController: fadeController,
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: 100 + MediaQuery.of(context).padding.bottom,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user