elCaribe app - customization and branding

This commit is contained in:
2025-12-12 19:09:42 -04:00
parent 9e5d0d8ebf
commit ba7deac9f3
402 changed files with 31833 additions and 0 deletions

View File

@@ -0,0 +1,407 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:news/ui/styles/colors.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive/hive.dart';
import 'package:location/location.dart' as loc;
import 'package:marqueer/marqueer.dart';
import 'package:news/app/routes.dart';
import 'package:news/cubits/Auth/authCubit.dart';
import 'package:news/cubits/Auth/registerTokenCubit.dart';
import 'package:news/cubits/Bookmark/bookmarkCubit.dart';
import 'package:news/cubits/LikeAndDislikeNews/LikeAndDislikeCubit.dart';
import 'package:news/cubits/appSystemSettingCubit.dart';
import 'package:news/cubits/breakingNewsCubit.dart';
import 'package:news/cubits/featureSectionCubit.dart';
import 'package:news/cubits/generalNewsCubit.dart';
import 'package:news/cubits/getUserDataByIdCubit.dart';
import 'package:news/cubits/appLocalizationCubit.dart';
import 'package:news/cubits/languageJsonCubit.dart';
import 'package:news/cubits/liveStreamCubit.dart';
import 'package:news/cubits/otherPagesCubit.dart';
import 'package:news/cubits/sectionByIdCubit.dart';
import 'package:news/cubits/settingCubit.dart';
import 'package:news/cubits/weatherCubit.dart';
import 'package:news/data/models/NewsModel.dart';
import 'package:news/data/models/authorModel.dart';
import 'package:news/data/repositories/SectionById/sectionByIdRepository.dart';
import 'package:news/data/repositories/Settings/settingsLocalDataRepository.dart';
import 'package:news/ui/screens/HomePage/Widgets/GeneralNewsRandomStyle.dart';
import 'package:news/ui/screens/HomePage/Widgets/LiveWithSearchView.dart';
import 'package:news/ui/screens/HomePage/Widgets/SectionShimmer.dart';
import 'package:news/ui/screens/HomePage/Widgets/WeatherData.dart';
import 'package:news/ui/screens/HomePage/Widgets/SectionStyle1.dart';
import 'package:news/ui/screens/HomePage/Widgets/SectionStyle2.dart';
import 'package:news/ui/screens/HomePage/Widgets/SectionStyle3.dart';
import 'package:news/ui/screens/HomePage/Widgets/SectionStyle4.dart';
import 'package:news/ui/screens/HomePage/Widgets/SectionStyle5.dart';
import 'package:news/ui/screens/HomePage/Widgets/SectionStyle6.dart';
import 'package:news/ui/screens/Profile/Widgets/customAlertDialog.dart';
import 'package:news/ui/widgets/SnackBarWidget.dart';
import 'package:news/ui/widgets/adSpaces.dart';
import 'package:news/ui/widgets/customTextLabel.dart';
import 'package:news/ui/widgets/errorContainerWidget.dart';
import 'package:news/utils/ErrorMessageKeys.dart';
import 'package:news/utils/hiveBoxKeys.dart';
import 'package:news/utils/strings.dart';
import 'package:news/utils/uiUtils.dart';
import 'package:news/data/models/AuthModel.dart';
import 'package:news/data/models/FeatureSectionModel.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
HomeScreenState createState() => HomeScreenState();
}
class HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = GlobalKey<RefreshIndicatorState>();
late final ScrollController featuredSectionsScrollController = ScrollController()..addListener(hasMoreFeaturedSectionsScrollListener);
final loc.Location _location = loc.Location();
bool? _serviceEnabled;
loc.PermissionStatus? _permissionGranted;
double? lat;
double? lon;
bool updateList = false;
Set<String> get locationValue => SettingsLocalDataRepository().getLocationCityValues();
late final appConfig, authConfig;
String languageId = "14"; //set it as default language code
void getSections() {
Future.delayed(Duration.zero, () {
context.read<SectionCubit>().getSection(langId: languageId, latitude: locationValue.first, longitude: locationValue.last);
}).whenComplete(() => getGeneralNews());
}
void getLiveStreamData() {
Future.delayed(Duration.zero, () {
context.read<LiveStreamCubit>().getLiveStream(langId: languageId);
});
}
void getBookmark() {
Future.delayed(Duration.zero, () {
context.read<BookmarkCubit>().getBookmark(langId: languageId);
});
}
void getLikeNews() {
Future.delayed(Duration.zero, () {
context.read<LikeAndDisLikeCubit>().getLike(langId: languageId);
});
}
void getUserData() {
Future.delayed(Duration.zero, () {
context.read<GetUserByIdCubit>().getUserById();
});
}
checkForAppUpdate() {
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (context.read<AppConfigurationCubit>().state is AppConfigurationFetchSuccess) {
if (context.read<AppConfigurationCubit>().isUpdateRequired()) {
openUpdateDialog();
}
}
});
}
openUpdateDialog() {
bool isForceUpdate = (context.read<AppConfigurationCubit>().getForceUpdateMode() != "" && context.read<AppConfigurationCubit>().getForceUpdateMode() == "1") ? true : false;
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return StatefulBuilder(builder: (BuildContext context, StateSetter setStater) {
return PopScope(
canPop: false,
child: CustomAlertDialog(
isForceAppUpdate: (isForceUpdate) ? true : false,
context: context,
yesButtonText: 'yesLbl',
yesButtonTextPostfix: '',
noButtonText: (isForceUpdate) ? 'exitLbl' : 'noLbl',
imageName: '',
titleWidget: CustomTextLabel(
text: (isForceUpdate) ? 'forceUpdateTitleLbl' : 'newVersionAvailableTitleLbl',
textStyle: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w800, color: UiUtils.getColorScheme(context).primaryContainer)),
messageText: context.read<LanguageJsonCubit>().getTranslatedLabels((isForceUpdate) ? 'forceUpdateDescLbl' : 'newVersionAvailableDescLbl'),
onYESButtonPressed: () => UiUtils.gotoStores(context)),
);
});
});
}
showPermissionPopup() async {
loc.LocationData locationData;
_serviceEnabled = await _location.serviceEnabled();
if (!_serviceEnabled!) {
_serviceEnabled = await _location.requestService();
if (!_serviceEnabled!) {
return;
}
}
_permissionGranted = await _location.hasPermission();
if (_permissionGranted == loc.PermissionStatus.denied) {
SettingsLocalDataRepository().setLocationCityKeys(null, null);
_permissionGranted = await _location.requestPermission();
if (_permissionGranted != loc.PermissionStatus.granted) {
return;
}
}
locationData = await _location.getLocation();
setState(() {
lat = locationData.latitude;
lon = locationData.longitude;
});
getLocationPermission();
return (locationData);
}
getLocationPermission() async {
if (appConfig.getLocationWiseNewsMode() == "1") {
SettingsLocalDataRepository().setLocationCityKeys(lat, lon);
//update latitude,longitude - along with token
if (context.read<SettingsCubit>().getSettings().token != '') {
context.read<RegisterTokenCubit>().registerToken(fcmId: context.read<SettingsCubit>().getSettings().token, context: context);
context.read<SettingsCubit>().changeFcmToken(context.read<SettingsCubit>().getSettings().token);
}
} else {
SettingsLocalDataRepository().setLocationCityKeys(null, null);
}
if (appConfig.getWeatherMode() == "1") {
getWeatherData();
}
}
Future<void> getWeatherData() async {
if (lat != null && lon != null) {
context.read<WeatherCubit>().getWeatherDetails(langId: (Hive.box(settingsBoxKey).get(currentLanguageCodeKey)), lat: lat.toString(), lon: lon.toString());
}
}
void getBreakingNews() {
Future.delayed(Duration.zero, () {
context.read<BreakingNewsCubit>().getBreakingNews(langId: languageId);
});
}
void getGeneralNews() {
context.read<GeneralNewsCubit>().getGeneralNews(langId: languageId, latitude: locationValue.first, longitude: locationValue.last);
}
@override
void initState() {
super.initState();
appConfig = context.read<AppConfigurationCubit>();
authConfig = context.read<AuthCubit>();
languageId = context.read<AppLocalizationCubit>().state.id;
getSections();
if (appConfig.getWeatherMode() == "1" || appConfig.getLocationWiseNewsMode() == "1") showPermissionPopup();
if (authConfig.getUserId() != "0") {
getUserData();
}
getLiveStreamData();
if (appConfig.getBreakingNewsMode() == "1") getBreakingNews();
if (appConfig.getMaintenanceMode() == "1") Navigator.of(context).pushReplacementNamed(Routes.maintenance);
}
@override
void dispose() {
featuredSectionsScrollController.dispose();
super.dispose();
}
void hasMoreFeaturedSectionsScrollListener() {
if (featuredSectionsScrollController.position.atEdge) {
if (context.read<SectionCubit>().hasMoreSections()) {
context.read<SectionCubit>().getMoreSections(langId: languageId, latitude: locationValue.first, longitude: locationValue.last);
} else {}
}
}
Widget breakingNewsMarquee() {
return BlocBuilder<BreakingNewsCubit, BreakingNewsState>(builder: ((context, state) {
return (state is BreakingNewsFetchSuccess && state.breakingNews.isNotEmpty)
? Container(
margin: const EdgeInsets.only(top: 10),
color: primaryColor,
height: 32,
child: Marqueer.builder(
pps: 25.0,
restartAfterInteractionDuration: const Duration(seconds: 1),
separatorBuilder: (_, index) =>
Center(child: Text('', style: Theme.of(context).textTheme.titleSmall!.copyWith(color: UiUtils.getColorScheme(context).secondary, fontWeight: FontWeight.normal))),
itemBuilder: (context, index) {
var multiplier = index ~/ state.breakingNews.length;
var i = index;
if (multiplier > 0) {
i = index - (multiplier * state.breakingNews.length);
}
final item = state.breakingNews[i];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: CustomTextLabel(
text: item.title!, textStyle: Theme.of(context).textTheme.titleSmall!.copyWith(color: UiUtils.getColorScheme(context).secondary, fontWeight: FontWeight.normal)));
},
),
)
: const SizedBox.shrink();
}));
}
Widget getSectionList() {
return BlocBuilder<GeneralNewsCubit, GeneralNewsState>(builder: (context, newsState) {
return BlocBuilder<SectionCubit, SectionState>(builder: (context, sectionState) {
if (sectionState is SectionFetchSuccess) {
//if it has only one section and it doesn't have news in it then show No data found message
if (sectionState.section.length == 1) {
if (sectionState.section.first.newsType == "breaking_news") {
if (sectionState.section.first.breakNewsTotal == 0) {
return ErrorContainerWidget(errorMsg: ErrorMessageKeys.noDataMessage, onRetry: _refresh);
}
} else if (sectionState.section.first.newsTotal != null && sectionState.section.first.newsTotal! == 0) {
return ErrorContainerWidget(errorMsg: ErrorMessageKeys.noDataMessage, onRetry: _refresh);
}
}
return ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: ((context, index) {
FeatureSectionModel model = sectionState.section[index];
//check for more featured sections
if (index == sectionState.section.length - 1 && index != 0) {
if (sectionState.hasMore) {
if (sectionState.hasMoreFetchError) {
return const SizedBox.shrink();
} else {
return Center(child: Padding(padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 8.0), child: UiUtils.showCircularProgress(true, Theme.of(context).primaryColor)));
}
}
}
return sectionData(model: model);
}),
itemCount: sectionState.section.length);
}
if (sectionState is SectionFetchFailure) {
if (context.read<GeneralNewsCubit>().state is GeneralNewsFetchSuccess) {
return sectionData(newsModelList: (context.read<GeneralNewsCubit>().state as GeneralNewsFetchSuccess).generalNews);
} else {
return ErrorContainerWidget(
errorMsg: (sectionState.errorMessage.contains(ErrorMessageKeys.noInternet)) ? UiUtils.getTranslatedLabel(context, 'internetmsg') : sectionState.errorMessage, onRetry: _refresh);
}
}
return sectionShimmer(context); //state is SectionFetchInProgress || state is SectionInitial
});
});
}
Widget sectionData({FeatureSectionModel? model, List<NewsModel>? newsModelList}) {
return (model != null)
? Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
if (model.adSpaceDetails != null) AdSpaces(adsModel: model.adSpaceDetails!), //sponsored ads
if (model.styleApp == 'style_1') Style1Section(model: model),
if (model.styleApp == 'style_2') Style2Section(model: model),
if (model.styleApp == 'style_3') Style3Section(model: model),
if (model.styleApp == 'style_4') Style4Section(model: model),
if (model.styleApp == 'style_5') Style5Section(model: model),
if (model.styleApp == 'style_6') BlocProvider(create: (context) => SectionByIdCubit(SectionByIdRepository()), child: Style6Section(model: model))
])
: GeneralNewsRandomStyle(modelList: newsModelList!);
}
//refresh function to refresh page
Future<void> _refresh() async {
getSections();
getLocationPermission();
if (authConfig.getUserId() != "0") {
getUserData();
getBookmark();
getLikeNews();
}
getLiveStreamData();
getPages();
if (appConfig.getBreakingNewsMode() == "1") getBreakingNews();
if (appConfig.getMaintenanceMode() == "1") Navigator.of(context).pushReplacementNamed(Routes.maintenance);
if (appConfig.getWeatherMode() == "1") getWeatherData();
}
getPages() {
Future.delayed(Duration.zero, () {
context.read<OtherPageCubit>().getOtherPage(langId: languageId);
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: () => _refresh(),
child: BlocListener<GetUserByIdCubit, GetUserByIdState>(
bloc: context.read<GetUserByIdCubit>(),
listener: (context, state) {
if (state is GetUserByIdFetchSuccess) {
var data = state.result;
if (data[STATUS] == 0) {
showSnackBar(UiUtils.getTranslatedLabel(context, 'deactiveMsg'), context);
Future.delayed(const Duration(seconds: 2), () {
UiUtils.userLogOut(contxt: context);
});
} else {
authConfig.updateDetails(
authModel: AuthModel(
id: data[ID].toString(),
name: data[NAME],
status: data[STATUS].toString(),
mobile: data[MOBILE],
email: data[EMAIL],
type: data[TYPE],
profile: data[PROFILE],
role: data[ROLE].toString(),
jwtToken: data[TOKEN],
isAuthor: data[IS_AUTHOR],
authorDetails: (data[IS_AUTHOR] == 1 && data[AUTHOR] != null) ? Author.fromJson(data[AUTHOR]) : null));
}
}
},
child: SingleChildScrollView(
controller: featuredSectionsScrollController,
physics: ClampingScrollPhysics(), //To restrict scrolling on Refresh
child: Padding(
padding: const EdgeInsetsDirectional.only(start: 15.0, end: 15.0, bottom: 10.0),
child: Column(
children: [
const LiveWithSearchView(),
BlocBuilder<WeatherCubit, WeatherState>(builder: (context, state) {
if (state is WeatherFetchSuccess) {
return WeatherDataView(weatherData: state.weatherData);
}
return SizedBox.shrink();
}),
breakingNewsMarquee(),
getSectionList()
],
),
),
),
))),
);
}
}