diff --git a/packages/uni_app/lib/controller/fetchers/book_fetcher.dart b/packages/uni_app/lib/controller/fetchers/book_fetcher.dart index 3c46fa06e..fb0e3b894 100644 --- a/packages/uni_app/lib/controller/fetchers/book_fetcher.dart +++ b/packages/uni_app/lib/controller/fetchers/book_fetcher.dart @@ -1,26 +1,56 @@ +import 'dart:async'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:uni/controller/networking/network_router.dart'; class BookThumbFetcher { - Future fetchBookThumb(String isbn) async { - final url = Uri.https( + Future fetchBookThumb(String isbn) async { + final googleBooksFuture = _fetchFromGoogleBooks(isbn); + final openLibraryFuture = _fetchFromOpenLibrary(isbn); + + final results = await Future.wait([googleBooksFuture, openLibraryFuture]); + + return results.firstWhere((result) => result != null, orElse: () => null); + } + + Future _fetchFromGoogleBooks(String isbn) async { + final googleBooksUrl = Uri.https( 'www.googleapis.com', '/books/v1/volumes', - {'q': '+isbn:$isbn'}, + {'q': 'isbn:$isbn'}, ); final response = - await http.get(Uri.decodeComponent(url.toString()).toUri()); + await http.get(Uri.decodeComponent(googleBooksUrl.toString()).toUri()); + + final numBooks = (json.decode(response.body) + as Map)['totalItems'] as int; + + if (numBooks > 0) { + final bookInformation = ((json.decode(response.body) + as Map)['items'] as List) + .first as Map; + final thumbnailURL = + ((bookInformation['volumeInfo'] as Map)['imageLinks'] + as Map)['thumbnail']; + return thumbnailURL.toString(); + } + + return null; + } + + Future _fetchFromOpenLibrary(String isbn) async { + final url = Uri.https('covers.openlibrary.org', '/b/isbn/$isbn-M.jpg'); - final bookInformation = ((json.decode(response.body) - as Map)['items'] as List) - .first as Map; + final response = await http.get(url); - final thumbnailURL = - ((bookInformation['volumeInfo'] as Map)['imageLinks'] - as Map)['thumbnail']; + if (response.statusCode == 200) { + final contentType = response.headers['content-type']; + if (contentType != null && contentType.startsWith('image/')) { + return url.toString(); + } + } - return thumbnailURL.toString(); + return null; } } diff --git a/packages/uni_app/lib/view/course_unit_info/widgets/course_unit_sheet.dart b/packages/uni_app/lib/view/course_unit_info/widgets/course_unit_sheet.dart index d4df55a78..e41016f32 100644 --- a/packages/uni_app/lib/view/course_unit_info/widgets/course_unit_sheet.dart +++ b/packages/uni_app/lib/view/course_unit_info/widgets/course_unit_sheet.dart @@ -176,46 +176,48 @@ Widget buildExpandedProfessors( } Widget buildBooksRow(BuildContext context, List books) { - return SizedBox( - height: 500, - width: double.infinity, - child: Wrap( - alignment: WrapAlignment.spaceBetween, - children: [ - ...books.asMap().entries.map((book) { - return FutureBuilder( - builder: (context, snapshot) { - return Padding( - padding: const EdgeInsets.only(left: 15, right: 15, top: 10), - child: Column( - children: [ - SizedBox( - width: 135, - height: 140, // adjust this value as needed - child: snapshot.data != null - ? Image(image: NetworkImage(snapshot.data!)) - : const Image( - image: AssetImage( - 'assets/images/book_placeholder.png', - ), + return Wrap( + alignment: WrapAlignment.spaceBetween, + children: books.map((book) { + return Padding( + padding: const EdgeInsets.only(left: 15, right: 15, top: 10), + child: Column( + children: [ + SizedBox( + width: 135, + height: 140, + child: book.isbn.isNotEmpty + ? FutureBuilder( + future: BookThumbFetcher().fetchBookThumb(book.isbn), + builder: (context, snapshot) { + if (snapshot.hasData && snapshot.data != null) { + return Image(image: NetworkImage(snapshot.data!)); + } else { + return const Image( + image: AssetImage( + 'assets/images/book_placeholder.png', ), - ), - SizedBox( - width: 135, - child: Text( - book.value.title, - textAlign: TextAlign.center, + ); + } + }, + ) + : const Image( + image: AssetImage( + 'assets/images/book_placeholder.png', ), ), - ], - ), - ); - }, - future: BookThumbFetcher().fetchBookThumb(book.value.isbn), - ); - }), - ], - ), + ), + SizedBox( + width: 135, + child: Text( + book.title, + textAlign: TextAlign.center, + ), + ), + ], + ), + ); + }).toList(), ); }