482 lines
23 KiB
Dart
482 lines
23 KiB
Dart
// ignore_for_file: deprecated_member_use
|
|
|
|
import 'package:carousel_slider/carousel_slider.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:flutter_svg/svg.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hoshan/core/gen/assets.gen.dart';
|
|
import 'package:hoshan/core/routes/route_generator.dart';
|
|
import 'package:hoshan/core/services/api/dio_service.dart';
|
|
import 'package:hoshan/data/model/chat_args.dart';
|
|
import 'package:hoshan/data/model/photo_gen_model.dart';
|
|
import 'package:hoshan/ui/screens/main/persons/cubit/persons_cubit.dart';
|
|
import 'package:hoshan/ui/theme/colors.dart';
|
|
import 'package:hoshan/ui/theme/responsive.dart';
|
|
import 'package:hoshan/ui/theme/text.dart';
|
|
import 'package:hoshan/ui/widgets/components/button/loading_button.dart';
|
|
import 'package:hoshan/ui/widgets/components/image/network_image.dart';
|
|
|
|
class PersonsScreen extends StatefulWidget {
|
|
const PersonsScreen({super.key});
|
|
|
|
@override
|
|
State<PersonsScreen> createState() => _PersonsScreenState();
|
|
}
|
|
|
|
class _PersonsScreenState extends State<PersonsScreen> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: BlocBuilder<PersonsCubit, PersonsState>(
|
|
builder: (context, state) {
|
|
if (state is PersonsSuccess) {
|
|
if (state.chars.categories?.isEmpty ?? true) {
|
|
return SizedBox.shrink();
|
|
}
|
|
return SingleChildScrollView(
|
|
physics: const BouncingScrollPhysics(),
|
|
child: Responsive(context).maxWidthInDesktop(
|
|
maxWidth: 1200,
|
|
child: (contxet, mw) => Column(
|
|
children: [
|
|
Responsive(context).isMobile()
|
|
? ListView.builder(
|
|
itemCount: state.chars.categories?.length ?? 0,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
shrinkWrap: true,
|
|
itemBuilder: (context, index) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 32.0),
|
|
child: personsCat(context,
|
|
state.chars.categories![index], mw),
|
|
);
|
|
})
|
|
: GridView.builder(
|
|
itemCount: state.chars.categories?.length ?? 0,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
shrinkWrap: true,
|
|
gridDelegate:
|
|
SliverGridDelegateWithFixedCrossAxisCount(
|
|
crossAxisCount: 2),
|
|
itemBuilder: (context, index) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 32.0),
|
|
child: personsCat(context,
|
|
state.chars.categories![index], mw / 2),
|
|
);
|
|
},
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(16.0),
|
|
child: Row(
|
|
children: [
|
|
Assets.icon.outline.messageQuestion.svg(
|
|
color: Theme.of(context).colorScheme.onSurface),
|
|
const SizedBox(
|
|
width: 8,
|
|
),
|
|
Text.rich(
|
|
TextSpan(
|
|
children: [
|
|
const TextSpan(
|
|
text: 'جای کدوم شخصیت اینجا خالیه؟ '),
|
|
TextSpan(
|
|
text: 'بهمون بگو.',
|
|
recognizer: TapGestureRecognizer()
|
|
..onTap = () {
|
|
// DialogHandler(context: context)
|
|
// .showPersonsAlert();
|
|
context.go(Routes.ticket);
|
|
},
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
color: Theme.of(context)
|
|
.colorScheme
|
|
.primary)),
|
|
],
|
|
),
|
|
style: AppTextStyles.body4.copyWith(
|
|
color: Theme.of(context).colorScheme.onSurface),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
if (state is PersonsFail) {
|
|
return SizedBox.shrink();
|
|
}
|
|
return const Center(
|
|
child: CircularProgressIndicator(),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Column personsCat(BuildContext context, GenModel item, double maxWidth) {
|
|
final PageController pageController = PageController(initialPage: 0);
|
|
final ValueNotifier<int> currentPageNotifier = ValueNotifier<int>(0);
|
|
final ValueNotifier<int> currentSliderNotifier = ValueNotifier<int>(0);
|
|
return Column(
|
|
children: [
|
|
ListTile(
|
|
leading: SvgPicture.network(
|
|
DioService.baseURL + item.icon!,
|
|
color: Theme.of(context).colorScheme.onSurface,
|
|
),
|
|
title: Text(
|
|
item.name ?? '',
|
|
style: AppTextStyles.headline6
|
|
.copyWith(color: Theme.of(context).colorScheme.onSurface),
|
|
maxLines: 1,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
trailing: ValueListenableBuilder<int>(
|
|
valueListenable: currentPageNotifier,
|
|
builder: (context, currentPage, child) {
|
|
return InkWell(
|
|
onTap: () {
|
|
if (currentPage == 0) {
|
|
pageController.animateToPage(1,
|
|
duration: const Duration(milliseconds: 500),
|
|
curve: Curves.easeInOut);
|
|
} else {
|
|
pageController.animateToPage(0,
|
|
duration: const Duration(milliseconds: 500),
|
|
curve: Curves.easeInOut);
|
|
}
|
|
},
|
|
child: Text(
|
|
currentPage != 0 ? 'بازگشت' : 'همه',
|
|
style: AppTextStyles.body5
|
|
.copyWith(color: Theme.of(context).colorScheme.primary),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
const SizedBox(
|
|
height: 8,
|
|
),
|
|
SizedBox(
|
|
width: maxWidth,
|
|
height: maxWidth * 0.8,
|
|
child: PageView(
|
|
controller: pageController,
|
|
onPageChanged: (value) {
|
|
currentPageNotifier.value = value;
|
|
},
|
|
physics:
|
|
const NeverScrollableScrollPhysics(), // Disable swipe, use button
|
|
children: [
|
|
// Second Widget
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Flexible(
|
|
child: CarouselSlider.builder(
|
|
itemCount: item.bots?.length ?? 0,
|
|
itemBuilder: (context, index, realIndex) {
|
|
if (item.bots == null || item.bots!.isEmpty) {
|
|
return SizedBox();
|
|
}
|
|
final bot = item.bots![index];
|
|
return Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: InkWell(
|
|
onTap: () {
|
|
context.go(Routes.chat,
|
|
extra: ChatArgs(bot: bot, isPerson: true));
|
|
},
|
|
child: Stack(
|
|
children: [
|
|
ImageNetwork(
|
|
width: double.infinity,
|
|
height: double.infinity,
|
|
radius: 16,
|
|
url: bot.image ?? ''),
|
|
Positioned.fill(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(16),
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Theme.of(context)
|
|
.colorScheme
|
|
.surface
|
|
.withAlpha(40),
|
|
AppColors.primaryColor[600]
|
|
.withAlpha(180)
|
|
])),
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
Text(
|
|
bot.name ?? '',
|
|
style: AppTextStyles.body6.copyWith(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold),
|
|
),
|
|
Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(
|
|
top: 4.0),
|
|
child: Text(
|
|
bot.cost == 0 ||
|
|
bot.cost == null
|
|
? 'رایگان'
|
|
: bot.cost.toString(),
|
|
style: AppTextStyles.body6
|
|
.copyWith(
|
|
color: Colors.white),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Assets.icon.outline.coin.svg(
|
|
color: Colors.white,
|
|
width: 14,
|
|
height: 14)
|
|
],
|
|
)
|
|
],
|
|
),
|
|
))
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
options: CarouselOptions(
|
|
scrollPhysics: const NeverScrollableScrollPhysics(),
|
|
height: double.infinity,
|
|
autoPlay: true,
|
|
aspectRatio: 1 / 1,
|
|
viewportFraction: 1 / 3,
|
|
autoPlayInterval: const Duration(seconds: 3),
|
|
autoPlayAnimationDuration:
|
|
const Duration(milliseconds: 800),
|
|
scrollDirection: Axis.vertical,
|
|
enableInfiniteScroll: true,
|
|
onPageChanged: (index, reason) {
|
|
currentSliderNotifier.value = index;
|
|
},
|
|
),
|
|
),
|
|
),
|
|
SizedBox(
|
|
width: maxWidth * 0.6,
|
|
child: ValueListenableBuilder(
|
|
valueListenable: currentSliderNotifier,
|
|
builder: (context, index, child) {
|
|
final bot = item.bots![index];
|
|
return AnimatedSwitcher(
|
|
duration: const Duration(milliseconds: 500),
|
|
transitionBuilder:
|
|
(Widget child, Animation<double> animation) {
|
|
return FadeTransition(
|
|
opacity: animation, child: child);
|
|
},
|
|
child: Column(
|
|
key: ValueKey<int>(index),
|
|
children: [
|
|
Expanded(
|
|
child: Stack(
|
|
children: [
|
|
ImageNetwork(
|
|
width: double.infinity,
|
|
height: double.infinity,
|
|
radius: 16,
|
|
url: bot.image ?? ''),
|
|
Positioned.fill(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
borderRadius:
|
|
BorderRadius.circular(16),
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Theme.of(context)
|
|
.colorScheme
|
|
.surface
|
|
.withAlpha(40),
|
|
AppColors.primaryColor[600]
|
|
.withAlpha(180)
|
|
])),
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.end,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment:
|
|
MainAxisAlignment.end,
|
|
children: [
|
|
Padding(
|
|
padding:
|
|
const EdgeInsets.only(
|
|
top: 4.0),
|
|
child: Text(
|
|
bot.cost == 0 ||
|
|
bot.cost == null
|
|
? 'رایگان'
|
|
: bot.cost.toString(),
|
|
style: AppTextStyles.body3
|
|
.copyWith(
|
|
color:
|
|
Colors.white),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Assets.icon.outline.coin.svg(
|
|
color: Colors.white,
|
|
width: 18,
|
|
height: 18)
|
|
],
|
|
)
|
|
],
|
|
),
|
|
))
|
|
],
|
|
)),
|
|
const SizedBox(
|
|
height: 12,
|
|
),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: LoadingButton(
|
|
onPressed: () {
|
|
context.go(Routes.chat,
|
|
extra: ChatArgs(
|
|
bot: bot, isPerson: true));
|
|
},
|
|
width: double.infinity,
|
|
child: Text(
|
|
'گپ با ${bot.name ?? ''}',
|
|
style: AppTextStyles.body4
|
|
.copyWith(color: Colors.white),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
);
|
|
}),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
|
|
SizedBox(
|
|
height: maxWidth,
|
|
child: GridView.builder(
|
|
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
|
childAspectRatio: 1 / 1,
|
|
crossAxisSpacing: 8,
|
|
mainAxisSpacing: 8,
|
|
maxCrossAxisExtent: maxWidth / 2),
|
|
scrollDirection: Axis.horizontal,
|
|
shrinkWrap: true,
|
|
itemCount: item.bots?.length ?? 0,
|
|
physics: const BouncingScrollPhysics(),
|
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
|
itemBuilder: (context, index) {
|
|
final bot = item.bots![index];
|
|
return InkWell(
|
|
onTap: () {
|
|
context.go(Routes.chat,
|
|
extra: ChatArgs(bot: bot, isPerson: true));
|
|
},
|
|
child: Stack(
|
|
children: [
|
|
ImageNetwork(radius: 16, url: bot.image ?? ''),
|
|
Positioned.fill(
|
|
child: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(16),
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [
|
|
Theme.of(context)
|
|
.colorScheme
|
|
.surface
|
|
.withAlpha(40),
|
|
AppColors.primaryColor[600].withAlpha(180)
|
|
])),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
Text(
|
|
bot.name ?? '',
|
|
style: AppTextStyles.body6.copyWith(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold),
|
|
),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 4.0),
|
|
child: Text(
|
|
bot.cost == 0 || bot.cost == null
|
|
? 'رایگان'
|
|
: bot.cost.toString(),
|
|
style: AppTextStyles.body6
|
|
.copyWith(color: Colors.white),
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Assets.icon.outline.coin.svg(
|
|
color: Colors.white,
|
|
width: 14,
|
|
height: 14)
|
|
],
|
|
)
|
|
],
|
|
),
|
|
))
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}
|
|
}
|