162 lines
6.1 KiB
Dart
162 lines
6.1 KiB
Dart
import 'package:carousel_slider/carousel_slider.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hoshan/core/routes/route_generator.dart';
|
|
import 'package:hoshan/data/model/banner_model.dart';
|
|
import 'package:hoshan/data/model/chat_args.dart';
|
|
import 'package:hoshan/ui/screens/main/home_page.dart';
|
|
import 'package:hoshan/ui/theme/colors.dart';
|
|
import 'package:hoshan/ui/theme/responsive.dart';
|
|
import 'package:hoshan/ui/widgets/components/image/network_image.dart';
|
|
import 'package:hoshan/ui/widgets/components/slider/custom_carousel_controller.dart';
|
|
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
|
|
import 'package:string_validator/string_validator.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
class CarousleSliderBanners extends StatefulWidget {
|
|
final List<Banners> banners;
|
|
final bool autoPlay;
|
|
final bool enableInfiniteScroll;
|
|
final Function(Banners banner)? onClick;
|
|
const CarousleSliderBanners(
|
|
{super.key,
|
|
required this.banners,
|
|
this.autoPlay = true,
|
|
this.enableInfiniteScroll = true,
|
|
this.onClick});
|
|
|
|
@override
|
|
State<CarousleSliderBanners> createState() => _CarousleSliderBannersState();
|
|
}
|
|
|
|
class _CarousleSliderBannersState extends State<CarousleSliderBanners> {
|
|
final CustomCarouselController _buttonCarouselController =
|
|
CustomCarouselController();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final isWeb =
|
|
Responsive(context).isDesktop(); // Check if the platform is web
|
|
final isTab =
|
|
Responsive(context).isTablet(); // Check if the platform is tablet
|
|
final CarouselOptions carouselOptions = CarouselOptions(
|
|
viewportFraction: isWeb
|
|
? 0.25 // Show 4 banners per slide on web
|
|
: isTab
|
|
? 0.33 // Show 3 banners per slide on tablets
|
|
: 1, // Default to 1 banner per slide
|
|
initialPage: 0,
|
|
disableCenter: false,
|
|
enableInfiniteScroll: widget.enableInfiniteScroll,
|
|
reverse: false,
|
|
autoPlay: widget.autoPlay,
|
|
autoPlayCurve: Curves.fastOutSlowIn,
|
|
enlargeCenterPage: true,
|
|
enlargeFactor: 0,
|
|
onPageChanged: (index, _) {},
|
|
scrollDirection: Axis.horizontal,
|
|
aspectRatio: 16 / 9,
|
|
height: isWeb
|
|
? MediaQuery.sizeOf(context).height * 0.2
|
|
: isTab
|
|
? MediaQuery.sizeOf(context).height * 0.25
|
|
: null, // Adjust height for web and tablets
|
|
);
|
|
return Column(
|
|
children: [
|
|
CarouselSlider.builder(
|
|
carouselController: _buttonCarouselController,
|
|
itemCount: widget.banners.length,
|
|
itemBuilder: (context, index, realIndex) {
|
|
final banner = widget.banners[index];
|
|
return GestureDetector(
|
|
onTap: () async {
|
|
if (banner.bot != null) {
|
|
if (banner.bot?.tool ?? false) {
|
|
context.go(Routes.assistant, extra: banner.bot!.id);
|
|
} else {
|
|
context.go(Routes.chat,
|
|
extra: ChatArgs(bot: banner.bot!));
|
|
}
|
|
} else if (banner.link != null) {
|
|
if (banner.link!.isURL()) {
|
|
await launchUrl(Uri.parse(banner.link!),
|
|
mode: LaunchMode.externalApplication)
|
|
.onError(
|
|
(error, stackTrace) {
|
|
if (kDebugMode) {
|
|
print('error open Link is: $error');
|
|
}
|
|
return false;
|
|
},
|
|
);
|
|
} else {
|
|
try {
|
|
if (banner.link!.contains('navigate')) {
|
|
int? index;
|
|
if (banner.link!.contains('home')) {
|
|
index = 0;
|
|
} else if (banner.link!.contains('assisstant')) {
|
|
index = 1;
|
|
} else if (banner.link!.contains('media')) {
|
|
index = 2;
|
|
} else if (banner.link!.contains('characters')) {
|
|
index = 3;
|
|
} else if (banner.link!.contains('setting')) {
|
|
index = 4;
|
|
}
|
|
|
|
screenIndex.value = index!;
|
|
} else {
|
|
context.go(banner.link!);
|
|
}
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print('Error is: $e');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
widget.onClick?.call(banner);
|
|
},
|
|
child: sliderView(banner));
|
|
},
|
|
options: carouselOptions),
|
|
if (widget.banners.length > 1) sliderIndicator(),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget sliderView(Banners banner) {
|
|
return Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: ImageNetwork(
|
|
width: double.infinity,
|
|
url: banner.image ?? '',
|
|
fit: BoxFit.contain,
|
|
radius: 16,
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget sliderIndicator() {
|
|
return FutureBuilder(
|
|
future: _buttonCarouselController.onReady,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.done) {
|
|
_buttonCarouselController.state!.pageController!.addListener(() {});
|
|
return SmoothPageIndicator(
|
|
controller: _buttonCarouselController.state!.pageController!,
|
|
count: widget.banners.length,
|
|
effect: ScrollingDotsEffect(
|
|
dotWidth: 8,
|
|
dotHeight: 8,
|
|
activeDotColor: AppColors.secondryColor.defaultShade,
|
|
dotColor: AppColors.secondryColor[100]));
|
|
}
|
|
return const SizedBox();
|
|
});
|
|
}
|
|
}
|