BlocConsumer<SearchBloc, SearchState>(
listener: (context, state) {
if (state is SearchFailure) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(state.errorMessage),
backgroundColor: Colors.red.shade300,
behavior: SnackBarBehavior.floating,
),
);
} else if (state is SearchSuccess) {
setState(() => isLoadingMore = false);
}
},
builder: (context, state) {
if (state is SearchLoading && !isLoadingMore) {
return const Center(
child: CircularProgressIndicator(color: AppColors.primaryColor),
);
} else if (state is SearchSuccess) {
return ListView.builder(
controller: _scrollController,
padding: const EdgeInsets.all(8),
itemCount: state.audiobooks.length + 1,
itemBuilder: (context, index) {
if (index == state.audiobooks.length) {
return isLoadingMore
? const Padding(
padding: EdgeInsets.all(16),
child: Center(
child: CircularProgressIndicator(
color: AppColors.primaryColor,
),
),
)
: const SizedBox();
}
final audiobook = state.audiobooks[index];
return Card(
elevation: 2,
margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: ListTile(
contentPadding: const EdgeInsets.all(8),
leading: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: LowAndHighImage(
lowQImage: audiobook.lowQCoverImage,
highQImage: audiobook.lowQCoverImage,
width: 60,
height: 60,
),
),
title: Text(
audiobook.title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(
audiobook.author ?? 'Unknown Author',
style: TextStyle(color: Colors.grey.shade600),
),
onTap: () {
context.push('/audiobook-details', extra: {
'audiobook': audiobook,
'isDownload': false,
'isYoutube': false,
'isLocal': false,
});
},
),
);
},
);
}
return const SizedBox();
},
)