13 Commits

22 changed files with 384 additions and 551 deletions

View File

@ -1,4 +1,6 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:io' show Platform;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_nav_bar/google_nav_bar.dart';
@ -34,45 +36,30 @@ class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: (BuildContext context, Widget? child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaleFactor: 1.0,
),
child: child!,
);
},
debugShowCheckedModeBanner: false,
title: 'Openlib',
theme: ThemeData(
primaryColor: Colors.white,
colorScheme: ColorScheme.light(
primary: Colors.white,
secondary: '#FB0101'.toColor(),
tertiary: Colors.black,
tertiaryContainer: '#F2F2F2'.toColor(),
),
textTheme: const TextTheme(
displayLarge: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 21,
),
displayMedium: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black,
overflow: TextOverflow.ellipsis,
),
),
fontFamily: GoogleFonts.nunito().fontFamily,
return DynamicColorBuilder(
builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) {
return MaterialApp(
// builder: (BuildContext context, Widget? child) {
// return MediaQuery(
// data: MediaQuery.of(context).copyWith(
// textScaleFactor: 1.0,
// ),
// child: child!,
// );
// },
debugShowCheckedModeBanner: false,
title: 'Openlib',
theme: ThemeData(
useMaterial3: true,
textSelectionTheme: TextSelectionThemeData(
selectionColor: '#FB0101'.toColor(),
selectionHandleColor: '#FB0101'.toColor())),
home: const HomePage(),
);
colorScheme: lightDynamic,
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: darkDynamic,
),
home: const HomePage(),
);
});
}
}
@ -94,67 +81,37 @@ class _HomePageState extends ConsumerState<HomePage> {
Widget build(BuildContext context) {
final selectedIndex = ref.watch(selectedIndexProvider);
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
),
body: _widgetOptions.elementAt(selectedIndex),
bottomNavigationBar: SafeArea(
child: GNav(
rippleColor: Colors.redAccent,
backgroundColor: Colors.black,
haptic: true,
tabBorderRadius: 50,
tabActiveBorder: Border.all(
color: Theme.of(context).colorScheme.secondary,
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarColor: ElevationOverlay.applySurfaceTint(
Theme.of(context).colorScheme.surface,
Theme.of(context).colorScheme.surfaceTint,
3)),
child: Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
appBar: AppBar(
leading:
Icon(Icons.book, color: Theme.of(context).colorScheme.primary),
title: const Text(
"Openlib",
style: TextStyle(fontWeight: FontWeight.w600),
),
tabMargin: const EdgeInsets.fromLTRB(13, 6, 13, 2.5),
curve: Curves.easeInOut, // tab animation curves
duration: const Duration(milliseconds: 150),
gap: 5,
color: const Color.fromARGB(255, 255, 255, 255),
activeColor: const Color.fromARGB(255, 255, 255, 255),
iconSize: 21, // tab button icon size
tabBackgroundColor: Theme.of(context).colorScheme.secondary,
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 6.5),
tabs: const [
GButton(
icon: Icons.trending_up,
text: 'Trending',
iconColor: Colors.white,
textStyle: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.white,
fontSize: 13,
),
),
GButton(
icon: Icons.search,
text: 'Search',
iconColor: Colors.white,
textStyle: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.white,
fontSize: 13,
),
),
GButton(
icon: Icons.collections_bookmark,
text: 'My Library',
iconColor: Colors.white,
textStyle: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.white,
fontSize: 13,
),
),
titleSpacing: 1,
),
body: _widgetOptions.elementAt(selectedIndex),
bottomNavigationBar: NavigationBar(
destinations: const [
NavigationDestination(
icon: Icon(Icons.trending_up), label: "Trending"),
NavigationDestination(icon: Icon(Icons.search), label: "Search"),
NavigationDestination(
icon: Icon(Icons.collections_bookmark), label: "My Library"),
],
selectedIndex: selectedIndex,
onTabChange: (index) async {
onDestinationSelected: (index) async {
ref.read(selectedIndexProvider.notifier).state = index;
},
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
),
),
);

View File

@ -23,18 +23,21 @@ import 'package:openlib/ui/components/file_buttons_widget.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
class BookInfoPage extends ConsumerWidget {
const BookInfoPage({Key? key, required this.url}) : super(key: key);
const BookInfoPage({Key? key, required this.url, required this.title})
: super(key: key);
final String url;
final String title;
@override
Widget build(BuildContext context, WidgetRef ref) {
final bookInfo = ref.watch(bookInfoProvider(url));
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
// backgroundColor: Theme.of(context).colorScheme.primary,
title: Text(title),
titleSpacing: 0,
// titleTextStyle: Theme.of(context).textTheme.displayLarge,
),
body: bookInfo.when(
data: (data) {
@ -95,21 +98,23 @@ class _ActionButtonWidgetState extends ConsumerState<ActionButtonWidget> {
} else {
return Padding(
padding: const EdgeInsets.only(top: 21, bottom: 21),
child: TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary,
textStyle: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w900,
color: Colors.white,
)),
child: ElevatedButton(
// style: ElevatedButton.styleFrom(
// // backgroundColor: Theme.of(context).colorScheme.secondary,
// textStyle: const TextStyle(
// // fontSize: 13,
// fontWeight: FontWeight.w500,
// // color: Colors.white,
// )),
onPressed: () async {
await downloadFileWidget(ref, context, widget.data);
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text('Add To My Library'),
),
child: const Text('Add To My Library',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
// color: Colors.white,
)),
),
);
}
@ -190,111 +195,33 @@ class _ShowDialog extends ConsumerWidget {
Navigator.of(context).pop();
}
return Stack(
alignment: Alignment.center,
children: [
Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
width: double.infinity,
height: 255,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.white,
),
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.all(8),
child: Text(
"Downloading Book",
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 54, 54, 54),
decoration: TextDecoration.none),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: Text(
title,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black54,
decoration: TextDecoration.none),
overflow: TextOverflow.ellipsis,
maxLines: 2,
textAlign: TextAlign.start,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Text(
'$downloadedFileSize/$fileSize',
style: TextStyle(
fontSize: 9,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.secondary,
decoration: TextDecoration.none,
letterSpacing: 1),
overflow: TextOverflow.ellipsis,
maxLines: 1,
textAlign: TextAlign.start,
),
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(50)),
child: LinearProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
backgroundColor: Colors.black26,
value: downloadProgress,
minHeight: 4,
),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
style: TextButton.styleFrom(
backgroundColor:
Theme.of(context).colorScheme.secondary,
textStyle: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.w900,
color: Colors.white,
)),
onPressed: () {
ref.read(cancelCurrentDownload).cancel();
Navigator.of(context).pop();
},
child: const Padding(
padding: EdgeInsets.all(3.0),
child: Text('Cancel'),
),
)
],
),
)
],
),
),
return AlertDialog(
title: const Text("Downloading Book"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(title),
const SizedBox(
height: 20,
),
LinearProgressIndicator(
value: downloadProgress,
),
const SizedBox(
height: 20,
),
Text(
'$downloadedFileSize/$fileSize',
)
],
),
actions: <Widget>[
TextButton(
onPressed: () {
ref.read(cancelCurrentDownload).cancel();
Navigator.pop(context, 'Cancel');
},
child: const Text('Cancel'),
),
],
);

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:openlib/ui/extensions.dart';
import 'package:cached_network_image/cached_network_image.dart';
// TODO: Redesign this widget
class BookInfoCard extends StatelessWidget {
const BookInfoCard(
{Key? key,
@ -22,26 +23,29 @@ class BookInfoCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onClick,
child: Container(
width: double.infinity,
height: 120,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Theme.of(context).colorScheme.tertiaryContainer,
return Card(
shadowColor: Colors.black.withOpacity(0),
margin: const EdgeInsets.only(bottom: 20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
side: BorderSide(
color: Theme.of(context).colorScheme.surfaceVariant,
width: 1,
),
margin: const EdgeInsets.only(bottom: 10),
),
child: InkWell(
onTap: onClick,
borderRadius: BorderRadius.circular(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
CachedNetworkImage(
height: 120,
width: 90,
height: 140,
width: 105,
imageUrl: thumbnail ?? "",
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(5)),
borderRadius: BorderRadius.circular(5),
image: DecorationImage(
image: imageProvider,
fit: BoxFit.fill,
@ -51,7 +55,7 @@ class BookInfoCard extends StatelessWidget {
placeholder: (context, url) => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: "#F8C0C8".toColor(),
color: Theme.of(context).colorScheme.surfaceVariant,
),
height: 120,
width: 90,
@ -60,7 +64,7 @@ class BookInfoCard extends StatelessWidget {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: "#F8C0C8".toColor(),
color: Theme.of(context).colorScheme.surfaceVariant,
),
height: 120,
width: 90,
@ -72,7 +76,7 @@ class BookInfoCard extends StatelessWidget {
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(5),
padding: const EdgeInsets.all(18),
child: SizedBox(
width: double.infinity,
child: Column(
@ -82,29 +86,33 @@ class BookInfoCard extends StatelessWidget {
Text(
title,
style: const TextStyle(
fontSize: 15,
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black,
// color: Colors.black,
),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
Text(
publisher,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: "#4D4D4D".toColor(),
Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Text(
publisher,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
// color: "#4D4D4D".toColor(),
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
Text(
author,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: "#7B7B7B".toColor(),
fontSize: 14,
fontWeight: FontWeight.w500,
// color: "#7B7B7B".toColor(),
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,

View File

@ -12,10 +12,10 @@ class BookInfoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
physics: const BouncingScrollPhysics(),
// physics: const BouncingScrollPhysics(),
scrollDirection: Axis.vertical,
child: Padding(
padding: const EdgeInsets.only(left: 15, right: 15, top: 10),
padding: const EdgeInsets.only(left: 20, right: 20, top: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
@ -26,8 +26,8 @@ class BookInfoWidget extends StatelessWidget {
),
Center(
child: CachedNetworkImage(
height: 230,
width: 170,
height: 240,
width: 180,
imageUrl: data.thumbnail,
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
@ -43,8 +43,8 @@ class BookInfoWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(10),
color: Colors.grey,
),
height: 230,
width: 170,
height: 240,
width: 180,
),
errorWidget: (context, url, error) {
return Container(
@ -63,21 +63,22 @@ class BookInfoWidget extends StatelessWidget {
),
_TopPaddedText(
text: data.title,
fontSize: 19,
fontSize: 22,
topPadding: 15,
color: Colors.black,
fontWeight: FontWeight.w600,
// color: Colors.black,
maxLines: 7,
),
_TopPaddedText(
text: data.publisher ?? "unknown",
fontSize: 15,
fontSize: 17,
topPadding: 7,
color: "#595E60".toColor(),
color: Theme.of(context).colorScheme.onSecondaryContainer,
maxLines: 4,
),
_TopPaddedText(
text: data.author ?? "unknown",
fontSize: 13,
fontSize: 20,
topPadding: 7,
color: "#7F7F7F".toColor(),
maxLines: 3,
@ -91,33 +92,41 @@ class BookInfoWidget extends StatelessWidget {
),
// child slot of page
child,
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Description",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w900,
color: Theme.of(context).colorScheme.tertiary,
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
child: SizedBox(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Description",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
Padding(
padding: const EdgeInsets.only(top: 15, bottom: 10),
child: Text(
data.description ?? "",
style: const TextStyle(
fontSize: 16,
),
),
)
],
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
Padding(
padding: const EdgeInsets.only(top: 7, bottom: 10),
child: Text(
data.description ?? "",
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: "#6B6B6B".toColor(),
letterSpacing: 1.5,
),
),
)
],
),
)
],
),
@ -130,14 +139,16 @@ class _TopPaddedText extends StatelessWidget {
final String text;
final double fontSize;
final double topPadding;
final Color color;
final Color? color;
final int maxLines;
final FontWeight fontWeight;
const _TopPaddedText(
{required this.text,
required this.fontSize,
required this.topPadding,
required this.color,
this.color,
this.fontWeight = FontWeight.w400,
required this.maxLines,
Key? key})
: super(key: key);
@ -150,9 +161,9 @@ class _TopPaddedText extends StatelessWidget {
text,
style: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.w900,
fontWeight: fontWeight,
color: color,
letterSpacing: 0.5,
// letterSpacing: 0.5,
),
overflow: TextOverflow.ellipsis,
maxLines: maxLines,

View File

@ -16,117 +16,28 @@ class ShowDeleteDialog extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Stack(
alignment: Alignment.center,
children: [
Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
width: double.infinity,
height: 219,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.white,
),
padding: const EdgeInsets.fromLTRB(20, 50, 20, 20),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.all(8),
child: Text(
"Delete Book",
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.bold,
color: Color.fromARGB(255, 54, 54, 54),
decoration: TextDecoration.none),
),
),
const Padding(
padding: EdgeInsets.all(8),
child: Text(
"This is permanent and cannot be undone",
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black54,
decoration: TextDecoration.none),
overflow: TextOverflow.ellipsis,
maxLines: 2,
textAlign: TextAlign.start,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
style: ButtonStyle(
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50.0),
side: BorderSide(
width: 3,
color: Theme.of(context)
.colorScheme
.secondary),
),
),
),
onPressed: () {
ref.read(deleteFileFromMyLib(
FileName(md5: id, format: format)));
Navigator.of(context).pop();
// if (false) {
// return
// }
showSnackBar(
context: context,
message: 'Book has been Deleted!');
return AlertDialog(
title: const Text("Delete Book?"),
content: const Text("This is permanent and cannot be undone"),
actions: <Widget>[
TextButton(
onPressed: () {
ref.read(deleteFileFromMyLib(FileName(md5: id, format: format)));
Navigator.of(context).pop();
onDelete();
},
child: const Padding(
padding: EdgeInsets.all(5.0),
child: Text(
'Delete',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
),
const SizedBox(
width: 10,
),
TextButton(
style: TextButton.styleFrom(
backgroundColor:
Theme.of(context).colorScheme.secondary,
textStyle: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.w900,
color: Colors.white,
)),
onPressed: () {
Navigator.of(context).pop();
},
child: const Padding(
padding: EdgeInsets.all(5.0),
child: Text('Cancel'),
),
)
],
),
)
],
),
),
),
showSnackBar(context: context, message: 'Book has been Deleted!');
onDelete();
},
child: const Text('Delete'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
],
);

View File

@ -24,7 +24,7 @@ class FileOpenAndDeleteButtons extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextButton(
FilledButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary,
textStyle: const TextStyle(
@ -60,7 +60,7 @@ class FileOpenAndDeleteButtons extends StatelessWidget {
const SizedBox(
width: 10,
),
TextButton(
OutlinedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
@ -82,14 +82,14 @@ class FileOpenAndDeleteButtons extends StatelessWidget {
);
});
},
child: const Padding(
padding: EdgeInsets.all(5.3),
child: Padding(
padding: const EdgeInsets.all(5.3),
child: Text(
'Delete',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black,
color: Theme.of(context).colorScheme.onSurface,
),
),
),

View File

@ -7,13 +7,13 @@ class TitleText extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 10, bottom: 7),
padding: const EdgeInsets.only(left: 10, right: 10, top: 20, bottom: 10),
child: Text(
text,
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.secondary,
style: const TextStyle(
fontSize: 25,
fontWeight: FontWeight.w500,
// color: Theme.of(context).colorScheme.onInverseSurface,
),
),
);

View File

@ -5,14 +5,14 @@ void showSnackBar({required BuildContext context, required String message}) {
content: Text(
message,
style: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12,
// fontWeight: FontWeight.bold,
// color: Colors.white,
),
textAlign: TextAlign.center,
),
// ignore: use_build_context_synchronously
backgroundColor: Theme.of(context).colorScheme.secondary,
// backgroundColor: Theme.of(context).colorScheme.secondary,
width: 300,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(50))),

View File

@ -24,18 +24,18 @@ class _EpubViewState extends ConsumerState<EpubViewerWidget> {
}, error: (error, stack) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
// backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
// titleTextStyle: Theme.of(context).textTheme.displayLarge,
),
body: Center(child: Text(error.toString())),
);
}, loading: () {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
// backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
// titleTextStyle: Theme.of(context).textTheme.displayLarge,
),
body: Center(
child: SizedBox(
@ -94,9 +94,10 @@ class _EpubViewerState extends ConsumerState<EpubViewer> {
final position = ref.watch(getBookPosition(widget.fileName));
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
// backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
titleSpacing: 0,
// titleTextStyle: Theme.of(context).textTheme.displayLarge,
),
endDrawer: Drawer(
child: EpubViewTableOfContents(controller: _epubReaderController),

View File

@ -7,17 +7,18 @@ import 'package:openlib/ui/components/book_info_widget.dart';
import 'package:openlib/ui/components/file_buttons_widget.dart';
class BookPage extends StatelessWidget {
const BookPage({Key? key, required this.id}) : super(key: key);
const BookPage({Key? key, required this.id, required this.title})
: super(key: key);
final String id;
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
title: Text(title),
titleSpacing: 0,
),
body: Consumer(
builder: (BuildContext context, WidgetRef ref, _) {
@ -42,12 +43,8 @@ class BookPage extends StatelessWidget {
);
} else {
return Center(
child: SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
),
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
));
}
});

View File

@ -38,7 +38,7 @@ class MyLibraryPage extends ConsumerWidget {
onClick: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BookPage(id: i.id);
return BookPage(id: i.id, title: i.title);
}));
}))
.toList()),
@ -81,12 +81,8 @@ class MyLibraryPage extends ConsumerWidget {
},
loading: () {
return Center(
child: SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
),
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
));
},
);

View File

@ -38,9 +38,9 @@ class _PdfViewState extends ConsumerState<PdfView> {
}, loading: () {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
// backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
// titleTextStyle: Theme.of(context).textTheme.displayLarge,
),
body: Center(
child: SizedBox(
@ -111,9 +111,10 @@ class _PdfViewerState extends ConsumerState<PdfViewer> {
final totalPages = ref.watch(totalPdfPage);
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
// backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
titleSpacing: 0,
// titleTextStyle: Theme.of(context).textTheme.displayLarge,
actions: isMobile
? [
IconButton(
@ -186,12 +187,8 @@ class _PdfViewerState extends ConsumerState<PdfViewer> {
},
loading: () {
return Center(
child: SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
),
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
));
},
)

View File

@ -23,22 +23,30 @@ class ResultPage extends ConsumerWidget {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
// backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text(
"Results",
style: TextStyle(fontWeight: FontWeight.w500),
),
titleSpacing: 0,
// titleTextStyle: Theme.of(context).textTheme.displayLarge,
),
body: searchBooks.when(
data: (data) {
if (data.isNotEmpty) {
return Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10),
padding: const EdgeInsets.only(
left: 5,
right: 5,
),
child: CustomScrollView(
slivers: <Widget>[
const SliverToBoxAdapter(
child: TitleText("Results"),
),
// const SliverToBoxAdapter(
// child: TitleText("Results"),
// ),
SliverPadding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10),
padding: const EdgeInsets.only(left: 5, right: 5, top: 15),
sliver: SliverList(
delegate: SliverChildListDelegate(data
.map((i) => BookInfoCard(
@ -50,7 +58,8 @@ class ResultPage extends ConsumerWidget {
onClick: () {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return BookInfoPage(url: i.link);
return BookInfoPage(
url: i.link, title: i.title);
}));
},
))
@ -103,22 +112,14 @@ class ResultPage extends ConsumerWidget {
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.only(left: 5, right: 5, top: 10),
child: TitleText("Results"),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
),
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
))
],
),

View File

@ -39,19 +39,23 @@ class SearchPage extends ConsumerWidget {
padding: const EdgeInsets.only(left: 7, right: 7, top: 10),
child: TextField(
showCursor: true,
cursorColor: Theme.of(context).colorScheme.secondary,
// cursorColor: Theme.of(context).colorScheme.secondary,
decoration: InputDecoration(
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black45, width: 2),
borderRadius: BorderRadius.all(Radius.circular(50)),
label: const Text("Search"),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.outline, width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black54, width: 2),
borderRadius: BorderRadius.all(Radius.circular(50)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.outline, width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
suffixIcon: IconButton(
padding: const EdgeInsets.only(right: 5),
color: Theme.of(context).colorScheme.secondary,
padding: const EdgeInsets.only(right: 10),
// color: Theme.of(context).colorScheme.secondary,
icon: const Icon(
Icons.search,
size: 23,
@ -59,16 +63,16 @@ class SearchPage extends ConsumerWidget {
onPressed: () => onSubmit(context, ref),
),
filled: true,
hintStyle: const TextStyle(
color: Colors.grey, fontWeight: FontWeight.bold),
hintText: "Search",
fillColor: Theme.of(context).colorScheme.primary,
// hintStyle: const TextStyle(
// color: Colors.grey, fontWeight: FontWeight.bold),
hintText: "Search books ,author or ISBN",
// fillColor: Theme.of(context).colorScheme.primary,
),
onSubmitted: (String value) => onSubmit(context, ref),
style: TextStyle(
color: Theme.of(context).colorScheme.tertiary,
fontWeight: FontWeight.bold,
fontSize: 12,
style: const TextStyle(
// color: Theme.of(context).colorScheme.tertiary,
// fontWeight: FontWeight.bold,
fontSize: 14,
),
onChanged: (String value) {
ref.read(searchQueryProvider.notifier).state = value;
@ -83,17 +87,21 @@ class SearchPage extends ConsumerWidget {
decoration: InputDecoration(
labelText: 'Type',
labelStyle: TextStyle(
fontSize: 11,
fontSize: 12,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.secondary,
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black54, width: 2),
borderRadius: BorderRadius.all(Radius.circular(50)),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.outline,
width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black54, width: 2),
borderRadius: BorderRadius.all(Radius.circular(50)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.outline,
width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
),
icon: const Icon(Icons.arrow_drop_down),
@ -105,7 +113,7 @@ class SearchPage extends ConsumerWidget {
value: value,
child: Text(
value,
style: const TextStyle(fontSize: 12),
style: const TextStyle(fontSize: 14),
),
);
}).toList(),
@ -123,17 +131,21 @@ class SearchPage extends ConsumerWidget {
decoration: InputDecoration(
labelText: 'Sort by',
labelStyle: TextStyle(
fontSize: 11,
fontSize: 12,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.secondary,
),
enabledBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black45, width: 2),
borderRadius: BorderRadius.all(Radius.circular(50)),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.outline,
width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
focusedBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black54, width: 2),
borderRadius: BorderRadius.all(Radius.circular(50)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.outline,
width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
),
value: dropdownSortValue,
@ -144,7 +156,7 @@ class SearchPage extends ConsumerWidget {
value: value,
child: Text(
value,
style: const TextStyle(fontSize: 12),
style: const TextStyle(fontSize: 14),
),
);
}).toList(),
@ -153,7 +165,7 @@ class SearchPage extends ConsumerWidget {
},
),
),
)
),
],
),
),

View File

@ -19,7 +19,7 @@ class TrendingPage extends ConsumerWidget {
final trendingBooks = ref.watch(getTrendingBooks);
return trendingBooks.when(data: (data) {
return Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10),
padding: const EdgeInsets.only(left: 5, right: 5, top: 0),
child: CustomScrollView(
slivers: [
const SliverToBoxAdapter(
@ -37,6 +37,7 @@ class TrendingPage extends ConsumerWidget {
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return InkWell(
borderRadius: BorderRadius.circular(10),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
@ -45,72 +46,66 @@ class TrendingPage extends ConsumerWidget {
);
}));
},
child: Container(
width: double.infinity,
height: double.infinity,
color: const Color.fromARGB(255, 255, 255, 255),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CachedNetworkImage(
height: imageHeight,
width: imageWidth,
imageUrl: data[index].thumbnail!,
imageBuilder: (context, imageProvider) =>
Container(
decoration: BoxDecoration(
boxShadow: const [
BoxShadow(
color: Colors.grey,
spreadRadius: 0.1,
blurRadius: 1)
],
borderRadius: const BorderRadius.all(
Radius.circular(5)),
image: DecorationImage(
image: imageProvider,
fit: BoxFit.fill,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CachedNetworkImage(
height: imageHeight,
width: imageWidth,
imageUrl: data[index].thumbnail!,
imageBuilder: (context, imageProvider) =>
Container(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(5)),
image: DecorationImage(
image: imageProvider,
fit: BoxFit.fill,
),
),
placeholder: (context, url) => Container(
),
placeholder: (context, url) => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
// color: "#E3E8E9".toColor(),
color: Theme.of(context)
.colorScheme
.surfaceVariant,
),
height: imageHeight,
width: imageWidth,
),
errorWidget: (context, url, error) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: "#E3E8E9".toColor(),
color: Theme.of(context)
.colorScheme
.surfaceVariant,
),
height: imageHeight,
width: imageWidth,
),
errorWidget: (context, url, error) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.grey,
),
height: imageHeight,
width: imageWidth,
child: const Center(
child: Icon(Icons.image_rounded),
),
);
},
),
Padding(
padding: const EdgeInsets.only(top: 4),
child: SizedBox(
width: imageWidth,
child: Text(
data[index].title!,
style: Theme.of(context)
.textTheme
.displayMedium,
maxLines: 2,
child: const Center(
child: Icon(Icons.image_rounded),
),
);
},
),
Padding(
padding: const EdgeInsets.only(top: 8),
child: SizedBox(
width: imageWidth,
child: Text(
data[index].title!,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400),
maxLines: 2,
),
),
]),
),
),
]),
);
},
childCount: data.length,
@ -130,13 +125,13 @@ class TrendingPage extends ConsumerWidget {
},
);
}, loading: () {
return Center(
return const Center(
child: SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
),
// color: Theme.of(context).colorScheme.secondary,
),
));
});
}

View File

@ -6,9 +6,13 @@
#include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) dynamic_color_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin");
dynamic_color_plugin_register_with_registrar(dynamic_color_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
url_launcher_linux
)

View File

@ -5,11 +5,13 @@
import FlutterMacOS
import Foundation
import dynamic_color
import path_provider_foundation
import sqflite
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))

View File

@ -145,6 +145,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.3.0"
dynamic_color:
dependency: "direct main"
description:
name: dynamic_color
sha256: de4798a7069121aee12d5895315680258415de9b00e717723a1bd73d58f0126d
url: "https://pub.dev"
source: hosted
version: "1.6.6"
epub_view:
dependency: "direct main"
description:

View File

@ -56,6 +56,7 @@ dependencies:
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
dev: ^1.0.0
dynamic_color: ^1.6.6
dev_dependencies:
flutter_test:

View File

@ -6,9 +6,12 @@
#include "generated_plugin_registrant.h"
#include <dynamic_color/dynamic_color_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
DynamicColorPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
dynamic_color
url_launcher_windows
)