From cc0851048580da2180bb81334aae04dc0155f825 Mon Sep 17 00:00:00 2001 From: jayesh Date: Thu, 11 Apr 2024 18:53:14 +0530 Subject: [PATCH] faq like dislike, content bytes --- lib/Utils/api_urls.dart | 1 + lib/controller/content_bytes_controller.dart | 165 ++++++ lib/data/network/network_api_services.dart | 5 +- lib/model/FAQModel/faq_model.dart | 59 +- lib/view/MainScreen/HomeScreen.dart | 6 +- lib/view/MainScreen/ShortTrade.dart | 6 +- .../Sidemenu/ContentByte/ContentBytes.dart | 506 +++++++++++------- .../Sidemenu/ContentByte/PlayerWidget.dart | 11 +- lib/view/Sidemenu/FaqScreen.dart | 216 ++++++-- lib/view/onBoarding/splashScreen.dart | 98 ++-- lib/view_model/FaqApi/faq_api.dart | 30 +- pubspec.lock | 40 ++ pubspec.yaml | 2 + 13 files changed, 841 insertions(+), 304 deletions(-) diff --git a/lib/Utils/api_urls.dart b/lib/Utils/api_urls.dart index 102c602..9c14dbe 100644 --- a/lib/Utils/api_urls.dart +++ b/lib/Utils/api_urls.dart @@ -26,6 +26,7 @@ class ApiUrls { //FAQ API static String faqApi = "${base}getFaq"; + static String faqLikeDislikeApi = "${base}userFaqLikeDislike"; //RISK PROFILE API static String getRiskProfileQuestionAnswerApi = "${base}riskProfileQueAns"; diff --git a/lib/controller/content_bytes_controller.dart b/lib/controller/content_bytes_controller.dart index 7fa544c..98e9a80 100644 --- a/lib/controller/content_bytes_controller.dart +++ b/lib/controller/content_bytes_controller.dart @@ -1,11 +1,176 @@ +import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:just_audio/just_audio.dart'; import 'package:traderscircuit/model/ContentBytesModel/content_bytes_categories_model.dart'; import 'package:traderscircuit/model/ContentBytesModel/content_bytes_model.dart'; +import '../view/Sidemenu/ContentByte/ContentBytes.dart'; + class ContentBytesController extends GetxController { ContentBytesCategoriesModel contentBytesCategoriesModel = ContentBytesCategoriesModel(); ContentBytesModel contentBytesModel = ContentBytesModel(); int filterId = 0; RxBool isApiCalling = true.obs; + RxBool isAudioSeekBarVisible = false.obs; + RxInt indexForAudios = 0.obs; + RxBool titlePlaying = false.obs; + RxList? titlePlayingList = [].obs; + + final progressNotifier = ValueNotifier( + ProgressBarState( + current: Duration.zero, + buffered: Duration.zero, + total: Duration.zero, + ), + ); + final buttonNotifier = ValueNotifier(ButtonState.paused); + + late AudioPlayer _audioPlayer; + ContentBytesController() { + init(0); + } + + void init(index) async { + _audioPlayer = AudioPlayer(); + try { + await _audioPlayer.setUrl(contentBytesModel.data!.audio![index].file ?? + 'https://ghantalele.com/uploads/files/data-78/38825/Besharam%20Rang_192(Ghantalele.com).mp3'); + // await _audioPlayer.setAsset(url); + } on PlayerException catch (e) { + print("Error code: ${e.code}"); + // iOS/macOS: maps to NSError.localizedDescription + // Android: maps to ExoPlaybackException.getMessage() + // Web/Linux: a generic message + // Windows: MediaPlayerError.message + print("Error message: ${e.message}"); + } +//Catching errors during playback (e.g. lost network connection) + _audioPlayer.playbackEventStream.listen((event) {}, + onError: (Object e, StackTrace st) { + if (e is PlayerException) { + print('Error code: ${e.code}'); + print('Error message: ${e.message}'); + } else { + print('An error occurred: $e'); + } + }); + + _audioPlayer.playerStateStream.listen((playerState) { + final isPlaying = playerState.playing; + final processingState = playerState.processingState; + if (!isPlaying) { + buttonNotifier.value = ButtonState.paused; + } else if (processingState != ProcessingState.completed) { + buttonNotifier.value = ButtonState.playing; + } else { + _playNextTrack(); + + // _audioPlayer.seek(Duration.zero); + // _audioPlayer.pause(); + } + }); + + _audioPlayer.positionStream.listen((position) { + final oldState = progressNotifier.value; + progressNotifier.value = ProgressBarState( + current: position, + buffered: oldState.buffered, + total: oldState.total, + ); + }); + + _audioPlayer.bufferedPositionStream.listen((bufferedPosition) { + final oldState = progressNotifier.value; + progressNotifier.value = ProgressBarState( + current: oldState.current, + buffered: bufferedPosition, + total: oldState.total, + ); + }); + + _audioPlayer.durationStream.listen((totalDuration) { + final oldState = progressNotifier.value; + progressNotifier.value = ProgressBarState( + current: oldState.current, + buffered: oldState.buffered, + total: totalDuration ?? Duration.zero, + ); + }); + } + + void _playNextTrack() { + // Determine the index of the next track (you need to implement this logic) + int nextIndex = getNextTrackIndex(); + + if (nextIndex != -1) { + // Play the next track + updateTitlePlaying(nextIndex); + if (isPlaying()) { + stop(); + } + init(nextIndex); + play(nextIndex); + } else { + _audioPlayer.seek(Duration.zero); + _audioPlayer.pause(); + } + } + + int getNextTrackIndex() { + if (indexForAudios.value == contentBytesModel.data!.audio!.length - 1) { + return -1; + } else { + return indexForAudios.value + 1; + } + + // You need to implement this logic based on your playlist structure + // For example, if you have a list of tracks, return the index of the next track + // If there is no next track, return -1 + // This logic depends on how you manage your playlist + // Example: return currentTrackIndex + 1; + } + + void play(index) { + _audioPlayer.play(); + isAudioSeekBarVisible.value = false; + isAudioSeekBarVisible.value = true; + indexForAudios.value = index; + } + + void pause() { + _audioPlayer.pause(); + } + + void seek(Duration position) { + _audioPlayer.seek(position); + } + + void stop() { + _audioPlayer.stop(); + } + + bool isPlaying() { + return _audioPlayer.playing; + } + + addTitles() { + titlePlayingList = List.generate( + contentBytesModel.data!.audio!.length, + (index) => false, + ).obs; + } + + void updateTitlePlaying(int index) { + // Check if the index is within valid range + if (index >= 0 && index < titlePlayingList!.length) { + // Set all values to false + titlePlayingList!.assignAll(List.generate( + titlePlayingList!.length, + (index) => false, + )); + // Set the specified index to true + titlePlayingList![index] = true; + } + } } diff --git a/lib/data/network/network_api_services.dart b/lib/data/network/network_api_services.dart index 513c5d0..38ffc6c 100644 --- a/lib/data/network/network_api_services.dart +++ b/lib/data/network/network_api_services.dart @@ -64,7 +64,10 @@ class NetworkApiServices extends BaseApiServices { } @override - Future postApi(data, String url, {bool isAuth = false}) async { + Future postApi( + data, + String url, + ) async { if (kDebugMode) { print("data >>> $data"); print("api url is >>> $url"); diff --git a/lib/model/FAQModel/faq_model.dart b/lib/model/FAQModel/faq_model.dart index 6e7b938..4822d9b 100644 --- a/lib/model/FAQModel/faq_model.dart +++ b/lib/model/FAQModel/faq_model.dart @@ -1,3 +1,5 @@ +import 'package:get/get.dart'; + class FAQModel { String? status; int? statusCode; @@ -97,6 +99,7 @@ class FaqQueAns { String? deletedAt; String? createdAt; String? updatedAt; + List? userLikes; FaqQueAns( {this.id, @@ -108,7 +111,8 @@ class FaqQueAns { this.modifiedBy, this.deletedAt, this.createdAt, - this.updatedAt}); + this.updatedAt, + this.userLikes}); FaqQueAns.fromJson(Map json) { id = json['id']; @@ -121,6 +125,12 @@ class FaqQueAns { deletedAt = json['deleted_at'] ?? ""; createdAt = json['created_at']; updatedAt = json['updated_at']; + if (json['user_likes'] != null) { + userLikes = []; + json['user_likes'].forEach((v) { + userLikes!.add(UserLikes.fromJson(v)); + }); + } } Map toJson() { @@ -133,6 +143,53 @@ class FaqQueAns { data['created_by'] = createdBy; data['modified_by'] = modifiedBy; data['deleted_at'] = deletedAt; + data['created_at'] = createdAt; + data['updated_at'] = updatedAt; + if (userLikes != null) { + data['user_likes'] = userLikes!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class UserLikes { + int? id; + int? userId; + int? faqId; + int? status; //RxInt? status; + String? isActive; + + String? createdAt; + String? updatedAt; + + UserLikes( + {this.id, + this.userId, + this.faqId, + this.status, + this.isActive, + this.createdAt, + this.updatedAt}); + + UserLikes.fromJson(Map json) { + id = json['id']; + userId = json['user_id']; + faqId = json['faq_id']; + status = (json['status']); // RxInt(json['status']); + isActive = json['is_active']; + + createdAt = json['created_at']; + updatedAt = json['updated_at']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['user_id'] = userId; + data['faq_id'] = faqId; + data['status'] = status; + data['is_active'] = isActive; + data['created_at'] = createdAt; data['updated_at'] = updatedAt; return data; diff --git a/lib/view/MainScreen/HomeScreen.dart b/lib/view/MainScreen/HomeScreen.dart index e63c15c..aa3effe 100644 --- a/lib/view/MainScreen/HomeScreen.dart +++ b/lib/view/MainScreen/HomeScreen.dart @@ -244,9 +244,9 @@ Widget ActiveCallsTab() { children: [ InkWell( onTap: () { - Get.to( - () => PlayerWidget(), - ); + Get.to(() => PlayerWidget(), arguments: { + "video_url": "", + }); }, child: Container( height: 200.h, diff --git a/lib/view/MainScreen/ShortTrade.dart b/lib/view/MainScreen/ShortTrade.dart index f5c93c4..d9adedd 100644 --- a/lib/view/MainScreen/ShortTrade.dart +++ b/lib/view/MainScreen/ShortTrade.dart @@ -194,9 +194,9 @@ class _ShortTradeState extends State { children: [ InkWell( onTap: () { - Get.to( - () => PlayerWidget(), - ); + Get.to(() => PlayerWidget(), arguments: { + "video_url": "", + }); }, child: Container( height: 200.h, diff --git a/lib/view/Sidemenu/ContentByte/ContentBytes.dart b/lib/view/Sidemenu/ContentByte/ContentBytes.dart index 32bcf70..2b7d9a5 100644 --- a/lib/view/Sidemenu/ContentByte/ContentBytes.dart +++ b/lib/view/Sidemenu/ContentByte/ContentBytes.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -19,6 +20,19 @@ import 'package:traderscircuit/view/Sidemenu/ContentByte/Reels.dart'; import 'package:traderscircuit/view/onBoarding/splashScreen1.dart'; import 'package:traderscircuit/view_model/ContentBytesApi/content_bytes_api.dart'; +class ProgressBarState { + ProgressBarState({ + required this.current, + required this.buffered, + required this.total, + }); + final Duration current; + final Duration buffered; + final Duration total; +} + +enum ButtonState { paused, playing } + class ContentBytes extends StatefulWidget { const ContentBytes({super.key}); @@ -37,27 +51,12 @@ class _ContentBytesState extends State { "assets/images/png/sidemenu/reels4.png", ]; - List audionewimage = [ - "assets/images/png/sidemenu/audionew1.png", - "assets/images/png/sidemenu/audionew2.png", - "assets/images/png/sidemenu/audionew1.png", - ]; - List mostread = [ "assets/images/png/sidemenu/Read1.png", "assets/images/png/sidemenu/Read2.png", "assets/images/png/sidemenu/Read1.png", ]; - List audio = [ - "assets/images/png/sidemenu/audio1.png", - "assets/images/png/sidemenu/audio2.png", - "assets/images/png/sidemenu/audio3.png", - "assets/images/png/sidemenu/audio4.png", - "assets/images/png/sidemenu/audio1.png", - "assets/images/png/sidemenu/audio2.png", - ]; - List audioname = [ "Week of 21st March 2024", "Week of 21st March 2024", @@ -93,6 +92,122 @@ class _ContentBytesState extends State { Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey1, + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + floatingActionButton: Obx(() => contentBytesController + .isAudioSeekBarVisible.value + ? Container( + width: Get.size.width, + height: 100, + decoration: const BoxDecoration( + color: Colors.red, + ), + child: Row( + children: [ + Expanded( + flex: 1, + child: Align( + child: ClipRRect( + borderRadius: BorderRadius.circular(100), + child: Image.network( + contentBytesController + .contentBytesModel + .data! + .audio![ + contentBytesController.indexForAudios.value] + .image!, + width: 57, + height: 57, + fit: BoxFit.cover, + ), + ), + ), + ), + Expanded( + flex: 3, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + contentBytesController + .contentBytesModel + .data! + .audio![ + contentBytesController.indexForAudios.value] + .title!, + style: const TextStyle( + fontSize: 14, + color: Colors.black, + fontFamily: 'SFPRO', + fontWeight: FontWeight.w600, + height: 1.5, + ), + ), + // SizedBox(height: 5), + Text( + contentBytesController + .contentBytesModel + .data! + .audio![ + contentBytesController.indexForAudios.value] + .description!, + style: const TextStyle( + fontSize: 14, + color: Colors.black, + fontFamily: 'SFPRO', + fontWeight: FontWeight.w600, + height: 1.5, + ), + ), + ValueListenableBuilder( + valueListenable: + contentBytesController.progressNotifier, + builder: (context, value, _) { + return ProgressBar( + progress: value.current, + buffered: value.buffered, + total: value.total, + onSeek: contentBytesController.seek, + barHeight: 4, + thumbRadius: 6, + thumbGlowRadius: 15, + thumbColor: Colors.black, + baseBarColor: Colors.black.withOpacity(0.3), + progressBarColor: Colors.black, + bufferedBarColor: Colors.black.withOpacity(0.3), + ); + }, + ), + ], + ), + ), + Expanded( + flex: 1, + child: ValueListenableBuilder( + valueListenable: contentBytesController.buttonNotifier, + builder: (context, value, _) { + switch (value) { + case ButtonState.paused: + return IconButton( + icon: const Icon(Icons.play_arrow_rounded), + iconSize: 50.0, + onPressed: () => contentBytesController.play( + contentBytesController.indexForAudios.value), + ); + case ButtonState.playing: + return IconButton( + icon: const Icon(Icons.pause), + iconSize: 50.0, + onPressed: contentBytesController.pause, + ); + } + }, + ), + ), + ], + ), + ) + : Container()), backgroundColor: Colors.black, extendBody: true, appBar: const CommonAppbar(titleTxt: "Content Bytes"), @@ -124,11 +239,7 @@ class _ContentBytesState extends State { child: TabBarView( children: [ Videos(images: reels), - Audios( - audio: audio, - audioname: audioname, - audionewimage: audionewimage, - audionamenewrelease: audionamenewrelease), + Audios(), Reads(mostread: mostread), ], ), @@ -162,27 +273,27 @@ class Reads extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - const SizedBox( - width: 300, - child: CustomTextFormField( - leadingIcon: Icon(Icons.search), - ), - ), - SizedBox( - width: 15.w, - ), - Image.asset( - "assets/images/png/filter.png", - height: 30.h, - width: 30.w, - ), - ], - ), - SizedBox( - height: 10.h, - ), + // Row( + // children: [ + // const SizedBox( + // width: 300, + // child: CustomTextFormField( + // leadingIcon: Icon(Icons.search), + // ), + // ), + // SizedBox( + // width: 15.w, + // ), + // Image.asset( + // "assets/images/png/filter.png", + // height: 30.h, + // width: 30.w, + // ), + // ], + // ), + // SizedBox( + // height: 10.h, + // ), text22W600('Harnessing the Power of Ebooks"'), sizedBoxHeight(20.h), commonGlassContainer( @@ -391,19 +502,18 @@ class Reads extends StatelessWidget { } } -class Audios extends StatelessWidget { +class Audios extends StatefulWidget { const Audios({ super.key, - required this.audio, - required this.audioname, - required this.audionewimage, - required this.audionamenewrelease, }); - final List audio; - final List audioname; - final List audionewimage; - final List audionamenewrelease; + @override + State createState() => _AudiosState(); +} + +class _AudiosState extends State { + ContentBytesController contentBytesController = + Get.put(ContentBytesController()); @override Widget build(BuildContext context) { @@ -411,89 +521,90 @@ class Audios extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - const SizedBox( - width: 300, - child: CustomTextFormField( - leadingIcon: Icon(Icons.search), - ), - ), - SizedBox( - width: 15.w, - ), - Image.asset( - "assets/images/png/filter.png", - height: 30.h, - width: 30.w, - ), - ], - ), - SizedBox( - height: 10.h, - ), + // Row( + // children: [ + // const SizedBox( + // width: 300, + // child: CustomTextFormField( + // leadingIcon: Icon(Icons.search), + // ), + // ), + // SizedBox( + // width: 15.w, + // ), + // Image.asset( + // "assets/images/png/filter.png", + // height: 30.h, + // width: 30.w, + // ), + // ], + // ), + // SizedBox( + // height: 10.h, + // ), text22W600('Content Bytes'), sizedBoxHeight(8.w), - text16W400_DADADA('The Beauty and Power of Video'), + text16W400_DADADA('The Beauty and Power of Audios'), sizedBoxHeight(20.h), - Container( - height: 550, - child: GridView.builder( - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - mainAxisExtent: 172, - crossAxisCount: 2, // number of items in each row - mainAxisSpacing: 8.0, // spacing between rows - crossAxisSpacing: 8.0, // spacing between columns - ), + GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + mainAxisExtent: 172, + crossAxisCount: 2, // number of items in each row + mainAxisSpacing: 8.0, // spacing between rows + crossAxisSpacing: 8.0, // spacing between columns + ), - itemCount: 6, // total number of items - itemBuilder: (context, index) { - return Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.white.withOpacity(0.1), - const Color(0xFFFFFFFF).withOpacity(0.05), - ], - stops: [ - 0.1, - 1, - ], - ), - borderRadius: BorderRadius.circular(8), - ), - child: Stack( - children: [ - Image.asset( - audio[index], - ), - Positioned( - bottom: 5, - left: 5, - child: Row( - children: [ - CircleAvatar( - radius: 18.sp, - child: const Icon(Icons.headphones), - ), - SizedBox( - width: 5.w, - ), - SizedBox( - width: 125.w, - child: text14W500(audioname[index]), - ), - ], - ), - ), + itemCount: contentBytesController + .contentBytesModel.data!.audio!.length, // total number of items + itemBuilder: (context, index) { + return Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Colors.white.withOpacity(0.1), + const Color(0xFFFFFFFF).withOpacity(0.05), + ], + stops: [ + 0.1, + 1, ], ), - ); - }, - ), + borderRadius: BorderRadius.circular(8), + ), + child: Stack( + children: [ + Image.network( + contentBytesController + .contentBytesModel.data!.audio![index].image!, + ), + Positioned( + bottom: 5, + left: 5, + child: Row( + children: [ + CircleAvatar( + radius: 18.sp, + child: const Icon(Icons.headphones), + ), + SizedBox( + width: 5.w, + ), + SizedBox( + width: 125.w, + child: text14W500(contentBytesController + .contentBytesModel.data!.audio![index].title!), + ), + ], + ), + ), + ], + ), + ); + }, ), SizedBox( height: 20.h, @@ -511,7 +622,8 @@ class Audios extends StatelessWidget { ); }, scrollDirection: Axis.horizontal, - itemCount: 3, + itemCount: + contentBytesController.contentBytesModel.data!.audio!.length, itemBuilder: (context, index) { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -536,7 +648,10 @@ class Audios extends StatelessWidget { ), child: Stack( children: [ - Image.asset(audionewimage[index]), + Image.network( + contentBytesController + .contentBytesModel.data!.audio![index].image!, + ), const Positioned( right: 5, top: 5, @@ -559,7 +674,10 @@ class Audios extends StatelessWidget { children: [ SizedBox( width: 148.w, - child: text14W500Overflow(audionamenewrelease[index]), + child: text14W500Overflow( + contentBytesController + .contentBytesModel.data!.audio![index].title!, + ), ), ], ) @@ -695,7 +813,7 @@ class _VideosState extends State { Widget videoCard(Video video) { return InkWell( onTap: () { - Get.to(() => PlayerWidget(), arguments: { + Get.to(() => const PlayerWidget(), arguments: { "video_url": video.file, }); }, @@ -756,23 +874,23 @@ class _VideosState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - children: [ - const SizedBox( - width: 295, - child: CustomTextFormField( - leadingIcon: Icon(Icons.search), - ), - ), - SizedBox( - width: 15.w, - ), - filter(), - ], - ), - SizedBox( - height: 10.h, - ), + // Row( + // children: [ + // const SizedBox( + // width: 295, + // child: CustomTextFormField( + // leadingIcon: Icon(Icons.search), + // ), + // ), + // SizedBox( + // width: 15.w, + // ), + // filter(), + // ], + // ), + // SizedBox( + // height: 10.h, + // ), text22W600('Content Bytes'), sizedBoxHeight(8.w), text16W400_DADADA('The Beauty and Power of Video'), @@ -808,64 +926,66 @@ class _VideosState extends State { : videoCard(contentBytesController .contentBytesModel.data!.video![1]), sizedBoxHeight(15.h), - text22W600("Reels"), - sizedBoxHeight(25.h), - Container( - height: 500, - child: GridView.builder( - physics: const NeverScrollableScrollPhysics(), - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - mainAxisExtent: 215, - crossAxisCount: 2, // number of items in each row - mainAxisSpacing: 8.0, // spacing between rows - crossAxisSpacing: 8.0, // spacing between columns - ), + // text22W600("Reels"), + // sizedBoxHeight(25.h), + // Container( + // height: 500, + // child: GridView.builder( + // physics: const NeverScrollableScrollPhysics(), + // gridDelegate: + // const SliverGridDelegateWithFixedCrossAxisCount( + // mainAxisExtent: 215, + // crossAxisCount: 2, // number of items in each row + // mainAxisSpacing: 8.0, // spacing between rows + // crossAxisSpacing: 8.0, // spacing between columns + // ), + + // itemCount: 4, // total number of items + // itemBuilder: (context, index) { + // return InkWell( + // onTap: () { + // Get.to( + // () => const Reels(), + // ); + // }, + // child: Container( + // decoration: BoxDecoration( + // gradient: LinearGradient( + // begin: Alignment.topLeft, + // end: Alignment.bottomRight, + // colors: [ + // Colors.white.withOpacity(0.1), + // const Color(0xFFFFFFFF).withOpacity(0.05), + // ], + // stops: [ + // 0.1, + // 1, + // ], + // ), + // borderRadius: BorderRadius.circular(8), + // ), + // child: Image.asset(widget.images[index]), + // ), + // ); + // }, + // ), + // ), - itemCount: 4, // total number of items - itemBuilder: (context, index) { - return InkWell( - onTap: () { - Get.to( - () => const Reels(), - ); - }, - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Colors.white.withOpacity(0.1), - const Color(0xFFFFFFFF).withOpacity(0.05), - ], - stops: [ - 0.1, - 1, - ], - ), - borderRadius: BorderRadius.circular(8), - ), - child: Image.asset(widget.images[index]), - ), - ); - }, - ), - ), // sizedBoxHeight(10.h), + contentBytesController .contentBytesModel.data!.video!.length < 3 ? const SizedBox() : ListView.builder( - physics: NeverScrollableScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), itemCount: contentBytesController .contentBytesModel.data!.video!.length - 2, shrinkWrap: true, itemBuilder: (ctx, index) { return Container( - margin: EdgeInsets.only( + margin: const EdgeInsets.only( bottom: 20, ), child: videoCard(contentBytesController diff --git a/lib/view/Sidemenu/ContentByte/PlayerWidget.dart b/lib/view/Sidemenu/ContentByte/PlayerWidget.dart index 6ff9eda..0d4bb05 100644 --- a/lib/view/Sidemenu/ContentByte/PlayerWidget.dart +++ b/lib/view/Sidemenu/ContentByte/PlayerWidget.dart @@ -13,7 +13,9 @@ class PlayerWidget extends StatefulWidget { class _PlayerWidgetState extends State { late VideoPlayerController videoPlayerController; late ChewieController chewieController; - var videoUrl = Get.arguments["video_url"]; + var videoUrl = Get.arguments["video_url"] == "" + ? "https://player.vimeo.com/progressive_redirect/playback/930595309/rendition/360p/file.mp4?loc=external&signature=55ffa7ff72b807e1b3830cd6d308b092d4b1f82baadf6c20e7c235cd9a33bcdf" + : Get.arguments["video_url"]; @override void initState() { _initializePlayer(); @@ -41,6 +43,13 @@ class _PlayerWidgetState extends State { looping: false); } + @override + void dispose() { + videoPlayerController.dispose(); + chewieController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return videoPlayerController != null && diff --git a/lib/view/Sidemenu/FaqScreen.dart b/lib/view/Sidemenu/FaqScreen.dart index 0532b1c..8782327 100644 --- a/lib/view/Sidemenu/FaqScreen.dart +++ b/lib/view/Sidemenu/FaqScreen.dart @@ -1,7 +1,10 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:traderscircuit/Utils/Common/CommonAppBar.dart'; import 'package:traderscircuit/Utils/Common/CustomTextFormField.dart'; import 'package:traderscircuit/Utils/Common/comonGlassmorphicContainer.dart'; @@ -11,6 +14,8 @@ import 'package:traderscircuit/model/FAQModel/faq_model.dart'; import 'package:traderscircuit/view/onBoarding/splashScreen1.dart'; import 'package:traderscircuit/view_model/FaqApi/faq_api.dart'; +Rx faqModel = FAQModel().obs; + class FaqScreen extends StatefulWidget { const FaqScreen({super.key}); @@ -22,23 +27,29 @@ class _FaqScreenState extends State { List categoryList = []; RxBool isLoading = true.obs; - FAQModel faqModel = FAQModel(); @override void initState() { + getData(); FAQApi().getFAQData().then((value) { - faqModel = FAQModel.fromJson(value.data); - for (var a in faqModel.data!) { + faqModel.value = FAQModel.fromJson(value.data); + for (var a in faqModel.value.data!) { categoryList.add(a.categoryName!); } isExpandedList = RxList.generate( - faqModel.data![selectedIndex.value].faqQueAns!.length, + faqModel.value.data![selectedIndex.value].faqQueAns!.length, (index) => index == 0); isLoading.value = false; }); super.initState(); } + String? token; + getData() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + token = prefs.getString('accessToken'); + } + final selectedIndex = 0.obs; late RxList isExpandedList; @@ -95,6 +106,7 @@ class _FaqScreenState extends State { selectedIndex.value = index; isExpandedList = RxList.generate( faqModel + .value .data![selectedIndex.value] .faqQueAns! .length, @@ -114,16 +126,33 @@ class _FaqScreenState extends State { Obx(() { return Column( children: List.generate( - faqModel.data![selectedIndex.value] - .faqQueAns!.length, (index) { + faqModel + .value + .data![selectedIndex.value] + .faqQueAns! + .length, (index) { return customExpandableItem( + index: index, + selectedIndex: selectedIndex.value, + faqModel1: faqModel.value, isExpanded: isExpandedList[index], - title: faqModel.data![selectedIndex.value] - .faqQueAns![index].faqQuestion!, - content: faqModel.data![selectedIndex.value] - .faqQueAns![index].faqAnswer!, + title: faqModel + .value + .data![selectedIndex.value] + .faqQueAns![index] + .faqQuestion!, + content: faqModel + .value + .data![selectedIndex.value] + .faqQueAns![index] + .faqAnswer!, toggleExpansion: () => toggleExpansion(index), + faqId: faqModel + .value + .data![selectedIndex.value] + .faqQueAns![index] + .id!, ); })); }), @@ -144,13 +173,21 @@ class _FaqScreenState extends State { borderRadius: BorderRadius.circular(5), color: const Color(0XFF3F0502), border: Border.all(color: const Color(0xFF9A0000), width: 1)), - child: Center(child: text16W500(text)), + child: Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: FittedBox(child: text16W500(text)), + )), ) : commonGlassContainer( width: 136.w, height: 38.h, borderradius: 5, - customWidget: Center(child: text16W400(text)), + customWidget: Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 9), + child: FittedBox(child: text16W400(text)), + )), ); }); } @@ -171,6 +208,10 @@ class _FaqScreenState extends State { required String title, required String content, required VoidCallback toggleExpansion, + required int faqId, + required FAQModel faqModel1, + required int selectedIndex, + required int index, }) { return Column( mainAxisAlignment: MainAxisAlignment.center, @@ -230,58 +271,123 @@ class _FaqScreenState extends State { child: Text( content, style: TextStyle( - - color: Color(0xFFFFFFFF), + color: const Color(0xFFFFFFFF), fontFamily: 'hiragino', - - fontSize: 14.sp, fontWeight: FontWeight.w400, ), ), ), ), - sizedBoxHeight(12.h), - commonGlassContainer( - width: double.infinity, - height: 65.h, - borderradius: 8, - customWidget: Padding( - padding: EdgeInsets.only(right: 8.w, left: 13.w), - child: Center( - child: Row(children: [ - Text( - 'Was this answer helpful?', - style: TextStyle( - fontFamily: 'hiragino', - fontSize: 16.sp, - fontWeight: FontWeight.w500, - color: Colors.white, - ), - ), - const Spacer(), - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - text16W500('Yes'), - sizedBoxWidth(2.w), - SvgPicture.asset( - 'assets/images/svg/thumbs-up.svg'), - sizedBoxWidth(8.w), - text16W500('No'), - sizedBoxWidth(2.w), - Column( - mainAxisAlignment: MainAxisAlignment.center, + token == null || token!.isEmpty + ? const SizedBox() + : sizedBoxHeight(12.h), + token == null || token!.isEmpty + ? const SizedBox() + : commonGlassContainer( + width: double.infinity, + height: 65.h, + borderradius: 8, + customWidget: Padding( + padding: EdgeInsets.only(right: 8.w, left: 13.w), + child: Center( + child: Row(children: [ + Text( + 'Was this answer helpful?', + style: TextStyle( + fontFamily: 'hiragino', + fontSize: 16.sp, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + const Spacer(), + Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - sizedBoxHeight(5.h), - SvgPicture.asset( - 'assets/images/svg/thumbs-down.svg'), + InkWell( + onTap: () { + FAQApi() + .updaeFAQLikeDisklikeData(faqId, 1) + .then((value) { + FAQApi().getFAQData().then((value) { + faqModel.value = + FAQModel.fromJson(value.data); + + setState(() {}); + }); + }); + }, + child: Row( + children: [ + text16W500('Yes'), + sizedBoxWidth(2.w), + (faqModel + .value + .data![selectedIndex] + .faqQueAns![index] + .userLikes! + .isNotEmpty && + faqModel + .value + .data![selectedIndex] + .faqQueAns![index] + .userLikes![0] + .status! == + 1) + ? Icon(Icons.check) + : SvgPicture.asset( + 'assets/images/svg/thumbs-up.svg'), + ], + ), + ), + sizedBoxWidth(8.w), + InkWell( + onTap: () { + FAQApi() + .updaeFAQLikeDisklikeData(faqId, 0) + .then((value) { + FAQApi().getFAQData().then((value) { + faqModel.value = + FAQModel.fromJson(value.data); + }); + }); + }, + child: Row( + children: [ + text16W500('No'), + sizedBoxWidth(2.w), + Column( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + sizedBoxHeight(5.h), + (faqModel + .value + .data![selectedIndex] + .faqQueAns![index] + .userLikes! + .isNotEmpty && + faqModel + .value + .data![ + selectedIndex] + .faqQueAns![index] + .userLikes![0] + .status! == + 0) + ? Icon(Icons.cancel) + : SvgPicture.asset( + 'assets/images/svg/thumbs-down.svg'), + ], + ) + ], + ), + ) ], - ) - ], - ) - ]), - ))) + ), + ]), + ))) ], ), ), diff --git a/lib/view/onBoarding/splashScreen.dart b/lib/view/onBoarding/splashScreen.dart index a5ffe5f..049f6ca 100644 --- a/lib/view/onBoarding/splashScreen.dart +++ b/lib/view/onBoarding/splashScreen.dart @@ -9,6 +9,8 @@ import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:traderscircuit/resources/routes/route_name.dart'; +import '../../Utils/Common/noInternet.dart'; + class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @@ -44,52 +46,55 @@ class _SplashScreenState extends State void initState() { super.initState(); checkInternet(); - log(_connectionStatus.toString()); - Future.delayed(Duration(seconds: 2), () async { - Get.toNamed(RouteName.sliderscreen1); - // if (_connectionStatus == ConnectivityResult.none) { - // var result = await Get.to(NoInternet()); - // if (result != null && result) { - // Timer(const Duration(seconds: 1), () async { - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // token = prefs.getString('token'); - // myusername = prefs.getString('name'); - // phonenumber = prefs.getString('contact_number'); - // OnBoard = prefs.getBool('OnBoard') ?? false; - // if (OnBoard == false) { - // Get.toNamed(RouteName.sliderscreen1); - // } else { - // if (token == null || token!.isEmpty) { - // Get.offAndToNamed(RouteName.loginScreen); - // } else { - // GetProfile().GetProfileAPI().then((value) { - // Get.toNamed(RouteName.mainScreen, arguments: 0); - // }); - // } - // } - // }); - // } - // } else { - // Timer(const Duration(seconds: 2), () async { - // SharedPreferences prefs = await SharedPreferences.getInstance(); - // token = prefs.getString('token'); - // myusername = prefs.getString('name'); - // phonenumber = prefs.getString('contact_number'); - // OnBoard = prefs.getBool('OnBoard') ?? false; - // if (OnBoard == false) { - // Get.toNamed(RouteName.sliderscreen1); - // } else { - // if (token == null || token!.isEmpty) { - // Get.offAndToNamed(RouteName.loginScreen); - // } else { - // GetProfile().GetProfileAPI().then((value) { - // Get.toNamed(RouteName.mainScreen, arguments: 0); - // }); - // } - // } - // }); - // } + Future.delayed(Duration(seconds: 2), () async { + if (_connectionStatus == ConnectivityResult.none) { + var result = await Get.to(NoInternet()); + if (result != null && result) { + Timer(const Duration(seconds: 1), () async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + var token = prefs.getString('accessToken'); + // myusername = prefs.getString('name'); + // phonenumber = prefs.getString('contact_number'); + // OnBoard = prefs.getBool('OnBoard') ?? false; + // if (OnBoard == false) { + // Get.toNamed(RouteName.sliderscreen1); + // } + // else { + if (token == null || token!.isEmpty) { + Get.offAndToNamed(RouteName.loginscreen); + } else { + // GetProfile().GetProfileAPI().then((value) { + // Get.toNamed(RouteName.mainScreen, arguments: 0); + // }); + Get.toNamed(RouteName.mainscreen); + } + // } + }); + } + } else { + Timer(const Duration(seconds: 2), () async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + + var token = prefs.getString('accessToken'); + // myusername = prefs.getString('name'); + // phonenumber = prefs.getString('contact_number'); + // OnBoard = prefs.getBool('OnBoard') ?? false; + // if (OnBoard == false) { + // Get.toNamed(RouteName.sliderscreen1); + // } + // else { + if (token == null || token!.isEmpty) { + Get.offAndToNamed(RouteName.loginscreen); + } else { + // GetProfile().GetProfileAPI().then((value) { + // Get.toNamed(RouteName.mainScreen, arguments: 0); + // }); + Get.toNamed(RouteName.mainscreen); + } + // } + }); + } }); // for scaleTansition _scaleController = AnimationController( @@ -131,7 +136,8 @@ class _SplashScreenState extends State scale: _scaleAnimation, child: Text( "Traders Circuit", - style: TextStyle(fontFamily: 'hiragino', + style: TextStyle( + fontFamily: 'hiragino', fontSize: 50, fontWeight: FontWeight.w600, color: Colors.white), diff --git a/lib/view_model/FaqApi/faq_api.dart b/lib/view_model/FaqApi/faq_api.dart index 4fc4a4e..9a8ab86 100644 --- a/lib/view_model/FaqApi/faq_api.dart +++ b/lib/view_model/FaqApi/faq_api.dart @@ -3,10 +3,15 @@ import 'dart:developer'; import '../../Utils/api_urls.dart'; import '../../Utils/base_manager.dart'; import '../../data/network/network_api_services.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class FAQApi { Future> getFAQData() async { - final response = await NetworkApiServices().getApi( + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('accessToken'); + + final response = await NetworkApiServices().postApi( + token == null || token.isEmpty ? {} : {"token": token}, ApiUrls.faqApi, ); log(response.data.toString()); @@ -22,4 +27,27 @@ class FAQApi { } return response; } + + Future> updaeFAQLikeDisklikeData( + int faqId, int status) async { + final response = await NetworkApiServices().postApi( + { + "faq_id": faqId, + "status": status, + }, + ApiUrls.faqLikeDislikeApi, + ); + log(response.data.toString()); + if (response.status == ResponseStatus.SUCCESS) { + Map responseData = + Map.from(response.data); + if (responseData['status'] == "success") { + return response; + } else { + return ResponseData( + responseData['message'], ResponseStatus.FAILED); + } + } + return response; + } } diff --git a/pubspec.lock b/pubspec.lock index 389bb18..e2df44c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -33,6 +33,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + audio_session: + dependency: transitive + description: + name: audio_session + sha256: a49af9981eec5d7cd73b37bacb6ee73f8143a6a9f9bd5b6021e6c346b9b6cf4e + url: "https://pub.dev" + source: hosted + version: "0.1.19" + audio_video_progress_bar: + dependency: "direct main" + description: + name: audio_video_progress_bar + sha256: ccc7d7b83d2a16c52d4a7fb332faabd1baa053fb0e4c16815aefd3945ab33b81 + url: "https://pub.dev" + source: hosted + version: "2.0.2" boolean_selector: dependency: transitive description: @@ -520,6 +536,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + just_audio: + dependency: "direct main" + description: + name: just_audio + sha256: b7cb6bbf3750caa924d03f432ba401ec300fd90936b3f73a9b33d58b1e96286b + url: "https://pub.dev" + source: hosted + version: "0.9.37" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: c3dee0014248c97c91fe6299edb73dc4d6c6930a2f4f713579cd692d9e47f4a1 + url: "https://pub.dev" + source: hosted + version: "4.2.2" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "134356b0fe3d898293102b33b5fd618831ffdc72bb7a1b726140abdf22772b70" + url: "https://pub.dev" + source: hosted + version: "0.4.9" lints: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1f9325b..247e3fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,6 +41,8 @@ dependencies: expansion_tile_group: ^1.2.4 scgateway_flutter_plugin: ^2.3.1 async: ^2.4.1 + just_audio: ^0.9.37 + audio_video_progress_bar: ^2.0.2 dev_dependencies: flutter_test: