didvan-app/lib/views/profile/direct_list/direct_list.dart

267 lines
9.4 KiB
Dart

// ignore_for_file: deprecated_member_use
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/views/profile/direct_list/direct_list_state.dart';
import 'package:didvan/views/profile/direct_list/widgets/direct_item.dart';
import 'package:didvan/views/widgets/didvan/divider.dart';
import 'package:didvan/views/widgets/didvan/scaffold.dart';
import 'package:didvan/views/widgets/shimmer_placeholder.dart';
import 'package:didvan/views/widgets/state_handlers/empty_state.dart';
import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:provider/provider.dart';
class DirectList extends StatefulWidget {
const DirectList({Key? key}) : super(key: key);
@override
State<DirectList> createState() => _DirectListState();
}
class _DirectListState extends State<DirectList>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
bool _hasAnimated = false;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1200),
);
Future.delayed(Duration.zero, () {
context.read<DirectListState>().getDirectsList();
});
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _startAnimationIfNeeded(DirectListState state) {
if (!_hasAnimated && state.appState == AppState.idle) {
_hasAnimated = true;
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
_animationController.forward();
}
});
}
}
Widget _buildAnimatedSection({required Widget child, required int index}) {
final double start = (index * 0.15).clamp(0.0, 1.0);
final double end = (start + 0.4).clamp(0.0, 1.0);
final animation = CurvedAnimation(
parent: _animationController,
curve: Interval(start, end, curve: Curves.easeOutQuint),
);
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0.1),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
@override
Widget build(BuildContext context) {
return Consumer<DirectListState>(
builder: (context, state, child) {
_startAnimationIfNeeded(state);
return DidvanScaffold(
padding: const EdgeInsets.symmetric(vertical: 16),
appBarData: null,
showSliversFirst: true,
slivers: [
SliverAppBar(
pinned: true,
backgroundColor: Theme.of(context).colorScheme.surface,
automaticallyImplyLeading: false,
leadingWidth: 200,
leading: Padding(
padding: const EdgeInsetsDirectional.only(start: 0.0),
child: SvgPicture.asset(
Assets.horizontalLogoWithText,
fit: BoxFit.contain,
height: 80,
),
),
actions: [
IconButton(
onPressed: () {
Navigator.of(context).pushNamed(Routes.bookmarks);
},
icon: SvgPicture.asset(
'lib/assets/icons/hugeicons_telescope-01.svg',
color: DesignConfig.isDark
? Theme.of(context).colorScheme.caption
: null,
)),
IconButton(
onPressed: () => Navigator.of(context).pop(),
icon: SvgPicture.asset(
'lib/assets/icons/arrow-left.svg',
color: Theme.of(context).colorScheme.caption,
)),
const SizedBox(width: 8),
],
),
SliverToBoxAdapter(
child: _buildAnimatedSection(
index: 0,
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
TextButton.icon(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
const Color.fromARGB(255, 0, 126, 167),
),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
onPressed: () {
Navigator.of(context).pushNamed(
Routes.direct,
arguments: {'type': 'پشتیبانی اپلیکیشن'},
).then((value) {
if (mounted) {
context
.read<DirectListState>()
.getDirectsList();
}
});
},
icon: SvgPicture.asset(
'lib/assets/icons/add.svg',
height: 20,
color: Theme.of(context).colorScheme.surface,
),
label: Text(
'تیکت جدید',
style: TextStyle(
color: Theme.of(context).colorScheme.surface,
fontWeight: FontWeight.bold,
),
),
),
// if (state.unreadCount > 0)
// Padding(
// padding: const EdgeInsetsDirectional.only(start: 8),
// child: DidvanBadge(
// text: state.unreadCount.toString(),
// ),
// ),
],
),
],
),
),
),
),
SliverStateHandler<DirectListState>(
onRetry: state.getDirectsList,
itemPadding: const EdgeInsets.symmetric(horizontal: 16),
state: state,
placeholder: const _ChatRoomPlaceholder(),
builder: (context, state, index) => _buildAnimatedSection(
index: index + 1,
child: ChatRoomItem(
chatRoom: state.chatRooms[index],
onBackButtonPressed: () {
state.chatRooms.clear();
state.getDirectsList();
},
),
),
childCount: state.chatRooms.length,
enableEmptyState: state.chatRooms.isEmpty,
paddingEmptyState: 0,
emptyState: const EmptyState(
asset: 'lib/assets/images/empty_states/Empty_List.png',
height: 500,
title: 'لیست خالی است',
titleColor: Color.fromARGB(255, 0, 126, 167),
subtitle:
'در حال حاضر آیتمی در این بخش ثبت نشده است. هر زمان مورد جدیدی اضافه شود، در اینجا نمایش داده می‌شود.',
),
),
],
);
},
);
}
}
class _ChatRoomPlaceholder extends StatelessWidget {
const _ChatRoomPlaceholder({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ShimmerPlaceholder(
height: 24,
width: 24,
),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ShimmerPlaceholder(
height: 24,
width: 100,
),
SizedBox(height: 12),
ShimmerPlaceholder(
height: 16,
width: 300,
),
SizedBox(height: 12),
ShimmerPlaceholder(
height: 12,
width: 80,
),
],
),
),
],
),
DidvanDivider(),
],
);
}
}