13 Commits

33 changed files with 489 additions and 1299 deletions

View File

@ -79,8 +79,6 @@ android {
// Signing with the debug keys for now, so `flutter run --release` works.
// replace with "debug" when running on debug version
signingConfig signingConfigs.release
minifyEnabled false
shrinkResources false
}
}
}

View File

@ -1,22 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEOS" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/>
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
</queries>
<application
android:label="Openlib"
android:name="${applicationName}"

View File

@ -1,15 +1 @@
<p>
<i>Openlib</i> is an open source app to download and read books from shadow library (<a href='https://annas-archive.org/' target='_blank' rel='nofollow noopener'>Annas Archive</a>). The App Has Built In Reader to Read Books.
</p>
<p>
As <i>Annas Archive</i> doesn't have an API, the app works by sending requests to <i>Annas Archive</i> and parses the response to objects. The app extracts the mirrors from the responses, downloads the book and stores it in the application's document directory.
</p>
<p>Main Features:</p>
<ul>
<li>Trending Books</li>
<li>Download And Read Books With In-Built Viewer</li>
<li>Supports Epub And Pdf Formats</li>
<li>Open Books With Your Favourite Ebooks Reader</li>
<li>Filter Books</li>
<li>Sort Books</li>
</ul>
<p><i>Openlib</i> is an open source app to download and read books from shadow library (<a href='https://annas-archive.org/' target='_blank' rel='nofollow noopener'>Annas Archive</a>). The App Has Built In Reader to Read Books.</p><p>As <i>Annas Archive</i> doesn't have an API, the app works by sending requests to <i>Annas Archive</i> and parses the response to objects. The app extracts the mirrors from the responses, downloads the book and stores it in the application's document directory.</p><p>Features include a.o.:</p><ul><li>Trending Books</li><li>Download And Read Books With In-Built Viewer</li><li>Supports Epub And Pdf Formats</li><li>Filter Books</li><li>Sort Books</li></ul>

View File

@ -1,24 +1,19 @@
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';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:openlib/ui/themes.dart';
import 'package:openlib/ui/extensions.dart';
import 'package:openlib/ui/trending_page.dart';
import 'package:openlib/ui/search_page.dart';
import 'package:openlib/ui/mylibrary_page.dart';
import 'package:openlib/ui/settings_page.dart';
import 'package:openlib/services/database.dart' show Sqlite, MyLibraryDb;
import 'package:openlib/services/files.dart'
show moveFilesToAndroidInternalStorage;
import 'package:openlib/state/state.dart'
show
selectedIndexProvider,
themeModeProvider,
openPdfWithExternalAppProvider,
openEpubWithExternalAppProvider,
dbProvider;
show selectedIndexProvider, dbProvider;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@ -28,54 +23,43 @@ void main() async {
databaseFactory = databaseFactoryFfi;
}
Database initDb = await Sqlite.initDb();
MyLibraryDb dataBase = MyLibraryDb(dbInstance: initDb);
bool isDarkMode = await dataBase.getPreference('darkMode');
bool openPdfwithExternalapp =
await dataBase.getPreference('openPdfwithExternalApp');
bool openEpubwithExternalapp =
await dataBase.getPreference('openEpubwithExternalApp');
if (Platform.isAndroid) {
await moveFilesToAndroidInternalStorage();
}
Database db = await Sqlite.initDb();
runApp(
ProviderScope(
overrides: [
dbProvider.overrideWithValue(dataBase),
themeModeProvider.overrideWith(
(ref) => isDarkMode ? ThemeMode.dark : ThemeMode.light),
openPdfWithExternalAppProvider
.overrideWith((ref) => openPdfwithExternalapp),
openEpubWithExternalAppProvider
.overrideWith((ref) => openEpubwithExternalapp)
],
overrides: [dbProvider.overrideWithValue(MyLibraryDb(dbInstance: db))],
child: const MyApp(),
),
);
}
class MyApp extends ConsumerWidget {
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget build(BuildContext context) {
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!,
);
},
// builder: (BuildContext context, Widget? child) {
// return MediaQuery(
// data: MediaQuery.of(context).copyWith(
// textScaleFactor: 1.0,
// ),
// child: child!,
// );
// },
debugShowCheckedModeBanner: false,
title: 'Openlib',
theme: lightTheme,
darkTheme: darkTheme,
themeMode: ref.watch(themeModeProvider),
theme: ThemeData(
useMaterial3: true,
colorScheme: lightDynamic,
),
darkTheme: ThemeData(
useMaterial3: true,
colorScheme: darkDynamic,
),
home: const HomePage(),
);
});
}
}
@ -90,85 +74,44 @@ class _HomePageState extends ConsumerState<HomePage> {
static const List<Widget> _widgetOptions = <Widget>[
TrendingPage(),
SearchPage(),
MyLibraryPage(),
SettingsPage()
MyLibraryPage()
];
@override
Widget build(BuildContext context) {
final selectedIndex = ref.watch(selectedIndexProvider);
return Scaffold(
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(
backgroundColor: Theme.of(context).colorScheme.primary,
title: const Text("Openlib"),
titleTextStyle: Theme.of(context).textTheme.displayLarge,
leading:
Icon(Icons.book, color: Theme.of(context).colorScheme.primary),
title: const Text(
"Openlib",
style: TextStyle(fontWeight: FontWeight.w600),
),
titleSpacing: 1,
),
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,
),
tabMargin: const EdgeInsets.fromLTRB(13, 6, 13, 2.5),
curve: Curves.easeIn,
duration: const Duration(milliseconds: 125),
gap: 5,
color: const Color.fromARGB(255, 255, 255, 255),
activeColor: const Color.fromARGB(255, 255, 255, 255),
iconSize: 19, // tab button icon size
tabBackgroundColor: Theme.of(context).colorScheme.secondary,
padding: const EdgeInsets.symmetric(horizontal: 13, vertical: 6.5),
tabs: const [
GButton(
icon: Icons.trending_up,
text: 'Trending',
iconColor: Colors.white,
textStyle: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.white,
fontSize: 11,
),
),
GButton(
icon: Icons.search,
text: 'Search',
iconColor: Colors.white,
textStyle: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.white,
fontSize: 11,
),
),
GButton(
icon: Icons.collections_bookmark,
text: 'My Library',
iconColor: Colors.white,
textStyle: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.white,
fontSize: 11,
),
),
GButton(
icon: Icons.build,
text: 'Settings',
iconColor: Colors.white,
textStyle: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.white,
fontSize: 11,
),
),
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

@ -135,19 +135,14 @@ class AnnasArchieve {
Future<BookInfoData?> _bookInfoParser(resData, url) async {
var document = parse(resData.toString());
var main = document.querySelector('main[class="main"]');
var ul = main?.querySelectorAll('ul[class="mb-4"]');
var ul = main?.querySelector('ul[class="mb-4"]');
List<String> mirrors = [];
if (ul != null) {
var anchorTags = [];
if (ul.length == 2) {
anchorTags = ul[1].querySelectorAll('a');
} else {
anchorTags = ul[0].querySelectorAll('a');
}
var a = ul.querySelectorAll('a');
for (var element in anchorTags) {
for (var element in a) {
if (element.attributes['href']!.startsWith('https://')) {
if (element.attributes['href'] != null) {
mirrors.add(element.attributes['href']!);

View File

@ -9,12 +9,10 @@ class Sqlite {
Database dbInstance = await openDatabase(
path,
version: 3,
version: 2,
onCreate: (Database db, int version) async {
await db.execute(
'CREATE TABLE mybooks (id TEXT PRIMARY KEY, title TEXT,author TEXT,thumbnail TEXT,link TEXT,publisher TEXT,info TEXT,format TEXT,description TEXT)');
await db.execute(
'CREATE TABLE preferences (name TEXT PRIMARY KEY,value BOOLEAN)');
if (isMobile) {
await db.execute(
'CREATE TABLE bookposition (fileName TEXT PRIMARY KEY,position TEXT)');
@ -23,12 +21,6 @@ class Sqlite {
onUpgrade: (db, oldVersion, newVersion) async {
List<dynamic> isTableExist = await db.query('sqlite_master',
where: 'name = ?', whereArgs: ['bookposition']);
List<dynamic> isPreferenceTableExist = await db.query('sqlite_master',
where: 'name = ?', whereArgs: ['preferences']);
if (isPreferenceTableExist.isEmpty) {
await db.execute(
'CREATE TABLE preferences (name TEXT PRIMARY KEY,value BOOLEAN)');
}
if (isMobile && isTableExist.isEmpty) {
await db.execute(
'CREATE TABLE bookposition (fileName TEXT PRIMARY KEY,position TEXT)');
@ -172,26 +164,4 @@ class MyLibraryDb {
return null;
}
}
Future<void> savePreference(String name, bool value) async {
int boolInt = value ? 1 : 0;
await dbInstance.insert(
'preferences',
{'name': name, 'value': boolInt},
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<bool> getPreference(String name) async {
List<Map<String, dynamic>> data = await dbInstance
.query('preferences', where: 'name = ?', whereArgs: [name]);
List<dynamic> dataList = List.generate(data.length, (i) {
return {'name': data[i]['name'], 'value': data[i]['value']};
});
if (dataList.isNotEmpty) {
return dataList[0]['value'] == 0 ? false : true;
} else {
return false;
}
}
}

View File

@ -1,9 +1,9 @@
import 'package:path_provider/path_provider.dart';
import 'package:dio/dio.dart';
import 'files.dart';
Future<String> _getFilePath(String fileName) async {
final path = await getAppDirectoryPath;
return '$path/$fileName';
final path = await getApplicationDocumentsDirectory();
return '${path.path}/$fileName';
}
List<String> _reorderMirrors(List<String> mirrors) {
@ -14,8 +14,7 @@ List<String> _reorderMirrors(List<String> mirrors) {
if (element.contains('ipfs') == true) {
ipfsMirrors.add(element);
} else {
if (element.startsWith('https://annas-archive.gs') != true &&
element.startsWith('https://1lib.sk') != true) {
if (element.startsWith('https://annas-archive.gs') != true) {
httpsMirrors.add(element);
}
}

View File

@ -4,33 +4,9 @@ import 'package:path_provider/path_provider.dart';
import 'package:openlib/state/state.dart' show dbProvider, myLibraryProvider;
Future<String> get getAppDirectoryPath async {
if (Platform.isAndroid) {
final directory = await getExternalStorageDirectory();
return directory!.path;
} else {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
}
Future<void> moveFilesToAndroidInternalStorage() async {
try {
final directory = await getApplicationDocumentsDirectory();
final directoryExternal = await getExternalStorageDirectory();
List<FileSystemEntity> files = Directory(directory.path).listSync();
for (var element in files) {
if ((element.path.contains('pdf')) || element.path.contains('epub')) {
String fileName = element.path.split('/').last;
File file = File(element.path);
file.copySync('${directoryExternal!.path}/$fileName');
file.deleteSync();
}
}
} catch (e) {
// ignore: avoid_print
print(e);
}
}
Future<bool> isFileExists(String filePath) async {
return await File(filePath).exists();

View File

@ -1,5 +1,4 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/services/database.dart';
import 'package:dio/dio.dart';
@ -32,8 +31,6 @@ Map<String, String> sortValues = {
final selectedIndexProvider = StateProvider<int>((ref) => 0);
final themeModeProvider = StateProvider<ThemeMode>((ref) => ThemeMode.light);
final selectedTypeState = StateProvider<String>((ref) => "All");
final getTypeValue = Provider.autoDispose<String>((ref) {
@ -144,9 +141,6 @@ final getBookPosition =
return await ref.read(dbProvider).getBookState(fileName);
});
final openPdfWithExternalAppProvider = StateProvider<bool>((ref) => false);
final openEpubWithExternalAppProvider = StateProvider<bool>((ref) => false);
final filePathProvider =
FutureProvider.family<String, String>((ref, fileName) async {
String path = await getFilePath(fileName);

View File

@ -1,131 +0,0 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
class AboutPage extends StatelessWidget {
const AboutPage({Key? key}) : super(key: key);
@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,
),
body: const SingleChildScrollView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.vertical,
child: Padding(
padding: EdgeInsets.only(left: 5, right: 5, top: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TitleText("About"),
Padding(
padding:
EdgeInsets.only(left: 7, right: 7, top: 13, bottom: 10),
child: Text(
"An Open source app to download and read books from shadow library (Anna`s Archive)",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
Padding(
padding: EdgeInsets.only(left: 7, right: 7, top: 10),
child: Text(
"Version",
style: TextStyle(fontSize: 19, fontWeight: FontWeight.bold),
),
),
Padding(
padding: EdgeInsets.only(left: 7, right: 7, top: 5),
child: Text(
"1.0.2",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.grey),
),
),
Padding(
padding: EdgeInsets.only(left: 7, right: 7, top: 15),
child: Text(
"Github",
style: TextStyle(fontSize: 19, fontWeight: FontWeight.bold),
),
),
_UrlText(
text: 'Open Github Page',
url: 'https://github.com/dstark5/Openlib',
),
_UrlText(
text: 'Contribute To Openlib',
url:
'https://github.com/dstark5/Openlib/blob/main/CONTRIBUTING.md'),
_UrlText(
text: 'Report An Issue',
url: 'https://github.com/dstark5/Openlib/issues'),
Padding(
padding: EdgeInsets.only(left: 7, right: 7, top: 15),
child: Text(
"Licence",
style: TextStyle(fontSize: 19, fontWeight: FontWeight.bold),
),
),
_UrlText(
text: "GPL v3.0 license",
url: 'https://www.gnu.org/licenses/gpl-3.0.en.html'),
],
),
),
),
);
}
}
class _UrlText extends StatelessWidget {
const _UrlText({Key? key, required this.text, required this.url})
: super(key: key);
final String url;
final String text;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 7, right: 7, top: 5),
child: InkWell(
onTap: () async {
final Uri uri = Uri.parse(url);
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
// ignore: use_build_context_synchronously
showSnackBar(context: context, message: 'Could not launch $uri');
}
},
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
text,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.blueAccent,
),
),
const SizedBox(
width: 2,
),
const Icon(
Icons.launch,
size: 17,
color: Colors.blueAccent,
)
],
),
),
);
}
}

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,117 +195,33 @@ class _ShowDialog extends ConsumerWidget {
Navigator.of(context).pop();
}
return Stack(
alignment: Alignment.center,
return AlertDialog(
title: const Text("Downloading Book"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
width: double.infinity,
height: 255,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Theme.of(context).colorScheme.tertiaryContainer,
Text(title),
const SizedBox(
height: 20,
),
padding: const EdgeInsets.fromLTRB(20, 20, 20, 20),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Text(
"Downloading Book",
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
decoration: TextDecoration.none),
LinearProgressIndicator(
value: downloadProgress,
),
const SizedBox(
height: 20,
),
Padding(
padding: const EdgeInsets.all(8),
child: Text(
title,
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.colorScheme
.tertiary
.withAlpha(170),
decoration: TextDecoration.none),
overflow: TextOverflow.ellipsis,
maxLines: 2,
textAlign: TextAlign.start,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Text(
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: Theme.of(context)
.colorScheme
.tertiary
.withAlpha(50),
value: downloadProgress,
minHeight: 4,
),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
actions: <Widget>[
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();
Navigator.pop(context, 'Cancel');
},
child: const Padding(
padding: EdgeInsets.all(3.0),
child: Text('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(
return Card(
shadowColor: Colors.black.withOpacity(0),
margin: const EdgeInsets.only(bottom: 20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
color: Theme.of(context).colorScheme.tertiaryContainer,
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(
@ -81,31 +85,34 @@ class BookInfoCard extends StatelessWidget {
children: [
Text(
title,
style: TextStyle(
fontSize: 15,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
// color: Colors.black,
),
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
Text(
Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Text(
publisher,
style: TextStyle(
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color:
Theme.of(context).textTheme.headlineMedium?.color,
fontWeight: FontWeight.w500,
// color: "#4D4D4D".toColor(),
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
Text(
author,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: Theme.of(context).textTheme.headlineSmall?.color,
fontSize: 14,
fontWeight: FontWeight.w500,
// color: "#7B7B7B".toColor(),
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:openlib/ui/extensions.dart';
import 'package:cached_network_image/cached_network_image.dart';
class BookInfoWidget extends StatelessWidget {
@ -10,14 +11,11 @@ class BookInfoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
String description = data.description.toString().length < 3
? "No Description available"
: data.description.toString();
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,
@ -28,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(
@ -45,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(
@ -65,66 +63,70 @@ class BookInfoWidget extends StatelessWidget {
),
_TopPaddedText(
text: data.title,
fontSize: 19,
fontSize: 22,
topPadding: 15,
color: Theme.of(context).colorScheme.tertiary,
fontWeight: FontWeight.w600,
// color: Colors.black,
maxLines: 7,
),
_TopPaddedText(
text: data.publisher ?? "unknown",
fontSize: 15,
fontSize: 17,
topPadding: 7,
color: Theme.of(context).textTheme.headlineMedium!.color!,
color: Theme.of(context).colorScheme.onSecondaryContainer,
maxLines: 4,
),
_TopPaddedText(
text: data.author ?? "unknown",
fontSize: 13,
fontSize: 20,
topPadding: 7,
color: Theme.of(context).textTheme.headlineSmall!.color!,
color: "#7F7F7F".toColor(),
maxLines: 3,
),
_TopPaddedText(
text: data.info ?? "",
fontSize: 11,
topPadding: 9,
color: Theme.of(context)
.textTheme
.headlineSmall!
.color!
.withAlpha(155),
color: "#A9A8A2".toColor(),
maxLines: 4,
),
// child slot of page
child,
Column(
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: 16,
fontWeight: FontWeight.w900,
color: Theme.of(context).colorScheme.tertiary,
fontSize: 20,
fontWeight: FontWeight.w500,
color: Theme.of(context).colorScheme.onSurface,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
Padding(
padding: const EdgeInsets.only(top: 7, bottom: 10),
padding: const EdgeInsets.only(top: 15, bottom: 10),
child: Text(
description,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color:
Theme.of(context).colorScheme.tertiary.withAlpha(150),
letterSpacing: 1.5,
data.description ?? "",
style: const TextStyle(
fontSize: 16,
),
),
)
],
),
),
),
)
],
),
@ -137,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);
@ -157,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,120 +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: Theme.of(context).colorScheme.tertiaryContainer,
),
padding: const EdgeInsets.fromLTRB(20, 50, 20, 20),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8),
child: Text(
"Delete Book",
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
decoration: TextDecoration.none),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: Text(
"This is permanent and cannot be undone",
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.colorScheme
.tertiary
.withAlpha(170),
decoration: TextDecoration.none),
overflow: TextOverflow.ellipsis,
maxLines: 2,
textAlign: TextAlign.start,
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// if (false) {
// return
// }
return AlertDialog(
title: const Text("Delete Book?"),
content: const Text("This is permanent and cannot be undone"),
actions: <Widget>[
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)));
ref.read(deleteFileFromMyLib(FileName(md5: id, format: format)));
Navigator.of(context).pop();
showSnackBar(
context: context,
message: 'Book has been Deleted!');
showSnackBar(context: context, message: 'Book has been Deleted!');
onDelete();
},
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Text(
'Delete',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
),
),
const SizedBox(
width: 10,
child: const Text('Delete'),
),
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'),
),
)
],
),
)
],
),
),
),
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
],
);

View File

@ -1,11 +1,10 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/ui/components/delete_dialog_widget.dart';
import 'package:openlib/ui/epub_viewer.dart' show launchEpubViewer;
import 'package:openlib/ui/pdf_viewer.dart' show launchPdfViewer;
import 'package:openlib/ui/epub_viewer.dart';
import 'package:openlib/ui/pdf_viewer.dart';
class FileOpenAndDeleteButtons extends ConsumerWidget {
class FileOpenAndDeleteButtons extends StatelessWidget {
final String id;
final String format;
final Function onDelete;
@ -18,28 +17,39 @@ class FileOpenAndDeleteButtons extends ConsumerWidget {
: super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 21, bottom: 21),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextButton(
FilledButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary,
textStyle: TextStyle(
textStyle: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w900,
color: Theme.of(context).colorScheme.primary,
color: Colors.white,
)),
onPressed: () async {
if (format == 'pdf') {
await launchPdfViewer(
fileName: '$id.$format', context: context, ref: ref);
} else {
await launchEpubViewer(
fileName: '$id.$format', context: context, ref: ref);
onPressed: () => {
if (format == 'pdf')
{
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return PdfView(
fileName: '$id.$format',
);
}))
}
else
{
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return EpubViewerWidget(
fileName: '$id.$format',
);
}))
}
},
child: const Padding(
@ -50,7 +60,7 @@ class FileOpenAndDeleteButtons extends ConsumerWidget {
const SizedBox(
width: 10,
),
TextButton(
OutlinedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
@ -79,7 +89,7 @@ class FileOpenAndDeleteButtons extends ConsumerWidget {
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
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

@ -1,67 +1,10 @@
import 'dart:io';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:epub_view/epub_view.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:vocsy_epub_viewer/epub_viewer.dart';
import 'package:open_file/open_file.dart';
import 'package:openlib/services/files.dart' show getFilePath;
import 'package:openlib/ui/components/snack_bar_widget.dart';
import 'package:openlib/state/state.dart'
show
filePathProvider,
saveEpubState,
dbProvider,
getBookPosition,
openEpubWithExternalAppProvider;
Future<void> launchEpubViewer(
{required String fileName,
required BuildContext context,
required WidgetRef ref}) async {
if (Platform.isAndroid || Platform.isIOS) {
String path = await getFilePath(fileName);
String? epubConfig = await ref.read(dbProvider).getBookState(fileName);
bool openWithExternalApp = ref.watch(openEpubWithExternalAppProvider);
if (openWithExternalApp) {
await OpenFile.open(path);
} else {
try {
VocsyEpub.setConfig(
// ignore: use_build_context_synchronously
themeColor: const Color.fromARGB(255, 210, 15, 1),
identifier: "iosBook",
scrollDirection: EpubScrollDirection.HORIZONTAL,
);
if ((epubConfig?.isNotEmpty ?? true) &&
(epubConfig != null) &&
(!(epubConfig.startsWith('epubcfi')))) {
VocsyEpub.open(path,
lastLocation: EpubLocator.fromJson(json.decode(epubConfig)));
} else {
VocsyEpub.open(path);
}
VocsyEpub.locatorStream.listen((locator) async {
await saveEpubState(fileName, locator, ref);
// convert locator from string to json and save to your database to be retrieved later
});
} catch (e) {
// ignore: use_build_context_synchronously
showSnackBar(context: context, message: 'Unable to open pdf!');
}
}
} else {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
return EpubViewerWidget(
fileName: fileName,
);
}));
}
}
show filePathProvider, saveEpubState, getBookPosition;
class EpubViewerWidget extends ConsumerStatefulWidget {
const EpubViewerWidget({super.key, required this.fileName});
@ -81,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(
@ -151,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,
),
));
}
});

View File

@ -21,7 +21,6 @@ class MyLibraryPage extends ConsumerWidget {
return Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10),
child: CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: <Widget>[
const SliverToBoxAdapter(
child: TitleText("My Library"),
@ -39,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()),
@ -82,12 +81,8 @@ class MyLibraryPage extends ConsumerWidget {
},
loading: () {
return Center(
child: SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(
color: Theme.of(context).colorScheme.secondary,
),
));
},
);

View File

@ -7,31 +7,10 @@ import 'package:openlib/state/state.dart'
pdfCurrentPage,
totalPdfPage,
savePdfState,
openPdfWithExternalAppProvider,
getBookPosition;
import 'package:url_launcher/url_launcher.dart';
import 'package:open_file/open_file.dart';
import 'dart:io' show Platform;
import 'package:openlib/services/files.dart' show getFilePath;
Future<void> launchPdfViewer(
{required String fileName,
required BuildContext context,
required WidgetRef ref}) async {
bool openWithExternalApp = ref.watch(openPdfWithExternalAppProvider);
if (openWithExternalApp) {
String path = await getFilePath(fileName);
await OpenFile.open(path);
} else {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
return PdfView(
fileName: fileName,
);
}));
}
}
class PdfView extends ConsumerStatefulWidget {
const PdfView({super.key, required this.fileName});
@ -59,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(
@ -132,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(
@ -207,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,
),
));
},
)

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,
),
))
],
),

View File

@ -39,21 +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.grey, 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: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.tertiary,
width: 2),
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,
@ -61,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;
@ -85,17 +87,19 @@ 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.grey, 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: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.tertiary,
color: Theme.of(context).colorScheme.outline,
width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
@ -109,8 +113,7 @@ class SearchPage extends ConsumerWidget {
value: value,
child: Text(
value,
style: const TextStyle(
fontSize: 12, fontWeight: FontWeight.bold),
style: const TextStyle(fontSize: 14),
),
);
}).toList(),
@ -128,17 +131,19 @@ 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.grey, 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: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).colorScheme.tertiary,
color: Theme.of(context).colorScheme.outline,
width: 2),
borderRadius: const BorderRadius.all(Radius.circular(50)),
),
@ -151,8 +156,7 @@ class SearchPage extends ConsumerWidget {
value: value,
child: Text(
value,
style: const TextStyle(
fontSize: 12, fontWeight: FontWeight.bold),
style: const TextStyle(fontSize: 14),
),
);
}).toList(),
@ -161,7 +165,7 @@ class SearchPage extends ConsumerWidget {
},
),
),
)
),
],
),
),

View File

@ -1,155 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
import 'package:openlib/ui/about_page.dart';
import 'package:openlib/state/state.dart'
show
themeModeProvider,
openPdfWithExternalAppProvider,
openEpubWithExternalAppProvider,
dbProvider;
class SettingsPage extends ConsumerWidget {
const SettingsPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
return Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const TitleText("Settings"),
_PaddedContainer(
children: [
Text(
"Dark Mode",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
Switch(
// This bool value toggles the switch.
value: ref.watch(themeModeProvider) == ThemeMode.dark,
activeColor: Colors.red,
onChanged: (bool value) {
ref.read(themeModeProvider.notifier).state =
value == true ? ThemeMode.dark : ThemeMode.light;
ref.read(dbProvider).savePreference('darkMode', value);
},
)
],
),
_PaddedContainer(
children: [
Text(
"Open PDF with External Reader",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
Switch(
// This bool value toggles the switch.
value: ref.watch(openPdfWithExternalAppProvider),
activeColor: Colors.red,
onChanged: (bool value) {
ref.read(openPdfWithExternalAppProvider.notifier).state =
value;
ref
.read(dbProvider)
.savePreference('openPdfwithExternalApp', value);
},
)
],
),
_PaddedContainer(
children: [
Text(
"Open Epub with External Reader",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
Switch(
// This bool value toggles the switch.
value: ref.watch(
openEpubWithExternalAppProvider,
),
activeColor: Colors.red,
onChanged: (bool value) {
ref.read(openEpubWithExternalAppProvider.notifier).state =
value;
ref
.read(dbProvider)
.savePreference('openEpubwithExternalApp', value);
},
)
],
),
_PaddedContainer(
onClick: () {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return const AboutPage();
}));
},
children: [
Text(
"About",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
],
)
],
),
),
);
}
}
class _PaddedContainer extends StatelessWidget {
const _PaddedContainer({Key? key, this.onClick, required this.children})
: super(key: key);
final VoidCallback? onClick;
final List<Widget> children;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10),
child: InkWell(
onTap: onClick,
child: Container(
height: 61,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Theme.of(context).colorScheme.tertiaryContainer,
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: children,
),
),
),
),
);
}
}

View File

@ -1,72 +0,0 @@
import 'package:flutter/material.dart';
import 'package:openlib/ui/extensions.dart';
import 'package:google_fonts/google_fonts.dart';
ThemeData lightTheme = ThemeData(
primaryColor: Colors.white,
colorScheme: ColorScheme.light(
primary: Colors.white,
secondary: '#FB0101'.toColor(),
tertiary: Colors.black,
tertiaryContainer: '#F2F2F2'.toColor(),
),
textTheme: TextTheme(
displayLarge: const TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 21,
),
displayMedium: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black,
overflow: TextOverflow.ellipsis,
),
headlineMedium: TextStyle(
color: "#595E60".toColor(),
),
headlineSmall: TextStyle(
color: "#7F7F7F".toColor(),
)),
fontFamily: GoogleFonts.nunito().fontFamily,
useMaterial3: true,
textSelectionTheme: TextSelectionThemeData(
selectionColor: '#FB0101'.toColor(),
selectionHandleColor: '#FB0101'.toColor(),
),
);
ThemeData darkTheme = ThemeData(
primaryColor: Colors.black,
colorScheme: ColorScheme.dark(
primary: Colors.black,
secondary: '#FB0101'.toColor(),
tertiary: Colors.white,
tertiaryContainer: '#2B2B2B'.toColor(),
),
textTheme: TextTheme(
displayLarge: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 21,
),
displayMedium: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.white,
overflow: TextOverflow.ellipsis,
),
headlineMedium: TextStyle(
color: "#F5F5F5".toColor(),
),
headlineSmall: TextStyle(
color: "#E8E2E2".toColor(),
),
),
fontFamily: GoogleFonts.nunito().fontFamily,
useMaterial3: true,
textSelectionTheme: TextSelectionThemeData(
selectionColor: '#FB0101'.toColor(),
selectionHandleColor: '#FB0101'.toColor(),
),
);

View File

@ -19,9 +19,8 @@ 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(
physics: const BouncingScrollPhysics(),
slivers: [
const SliverToBoxAdapter(
child: TitleText("Trending"),
@ -38,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) {
@ -46,9 +46,6 @@ class TrendingPage extends ConsumerWidget {
);
}));
},
child: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
@ -60,12 +57,6 @@ class TrendingPage extends ConsumerWidget {
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(
@ -77,7 +68,10 @@ class TrendingPage extends ConsumerWidget {
placeholder: (context, url) => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: "#E3E8E9".toColor(),
// color: "#E3E8E9".toColor(),
color: Theme.of(context)
.colorScheme
.surfaceVariant,
),
height: imageHeight,
width: imageWidth,
@ -86,7 +80,9 @@ class TrendingPage extends ConsumerWidget {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.grey,
color: Theme.of(context)
.colorScheme
.surfaceVariant,
),
height: imageHeight,
width: imageWidth,
@ -97,20 +93,19 @@ class TrendingPage extends ConsumerWidget {
},
),
Padding(
padding: const EdgeInsets.only(top: 4),
padding: const EdgeInsets.only(top: 8),
child: SizedBox(
width: imageWidth,
child: Text(
data[index].title!,
style: Theme.of(context)
.textTheme
.displayMedium,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w400),
maxLines: 2,
),
),
),
]),
),
);
},
childCount: data.length,
@ -130,12 +125,12 @@ 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

@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: archive
sha256: "49b1fad315e57ab0bbc15bcbb874e83116a1d78f77ebd500a4af6c9407d6b28e"
sha256: "0c8368c9b3f0abbc193b9d6133649a614204b528982bebc7026372d61677ce3a"
url: "https://pub.dev"
source: hosted
version: "3.3.8"
version: "3.3.7"
args:
dependency: transitive
description:
@ -93,10 +93,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
url: "https://pub.dev"
source: hosted
version: "1.17.2"
version: "1.17.1"
convert:
dependency: transitive
description:
@ -125,10 +125,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
url: "https://pub.dev"
source: hosted
version: "1.0.6"
version: "1.0.5"
dev:
dependency: "direct main"
description:
@ -141,10 +141,18 @@ packages:
dependency: "direct main"
description:
name: dio
sha256: ce75a1b40947fea0a0e16ce73337122a86762e38b982e1ccb909daa3b9bc4197
sha256: "3866d67f93523161b643187af65f5ac08bc991a5bcdaf41a2d587fe4ccb49993"
url: "https://pub.dev"
source: hosted
version: "5.3.2"
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:
@ -181,10 +189,10 @@ packages:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
url: "https://pub.dev"
source: hosted
version: "2.1.0"
version: "2.0.2"
file:
dependency: transitive
description:
@ -234,10 +242,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
url: "https://pub.dev"
source: hosted
version: "2.0.3"
version: "2.0.2"
flutter_pdfview:
dependency: "direct main"
description:
@ -250,10 +258,10 @@ packages:
dependency: "direct main"
description:
name: flutter_riverpod
sha256: b04d4e9435a563673746ccb328d22018c6c9496bb547e11dd56c1b0cc9829fe5
sha256: b83ac5827baadefd331ea1d85110f34645827ea234ccabf53a655f41901a9bf4
url: "https://pub.dev"
source: hosted
version: "2.3.10"
version: "2.3.6"
flutter_svg:
dependency: "direct main"
description:
@ -364,18 +372,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
url: "https://pub.dev"
source: hosted
version: "0.12.16"
version: "0.12.15"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
url: "https://pub.dev"
source: hosted
version: "0.5.0"
version: "0.2.0"
meta:
dependency: transitive
description:
@ -392,14 +400,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.2"
open_file:
dependency: "direct main"
description:
name: open_file
sha256: a5a32d44acb7c899987d0999e1e3cbb0a0f1adebbf41ac813ec6d2d8faa0af20
url: "https://pub.dev"
source: hosted
version: "3.3.2"
path:
dependency: transitive
description:
@ -420,90 +420,50 @@ packages:
dependency: "direct main"
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.0.15"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1"
sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
version: "2.0.27"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
sha256: "916731ccbdce44d545414dd9961f26ba5fbaa74bcbb55237d8e65a623a8c7297"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
version: "2.2.4"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57
url: "https://pub.dev"
source: hosted
version: "2.2.1"
version: "2.1.11"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.0.6"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: "63e5216aae014a72fe9579ccd027323395ce7a98271d9defa9d57320d001af81"
url: "https://pub.dev"
source: hosted
version: "10.4.3"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: d74e77a5ecd38649905db0a7d05ef16bed42ff263b9efb73ed794317c5764ec3
url: "https://pub.dev"
source: hosted
version: "10.3.4"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
url: "https://pub.dev"
source: hosted
version: "9.1.4"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "7c6b1500385dd1d2ca61bb89e2488ca178e274a69144d26bbd65e33eae7c02a9"
url: "https://pub.dev"
source: hosted
version: "3.11.3"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
url: "https://pub.dev"
source: hosted
version: "0.1.3"
version: "2.1.7"
petitparser:
dependency: transitive
description:
@ -516,18 +476,18 @@ packages:
dependency: transitive
description:
name: platform
sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
version: "3.1.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
url: "https://pub.dev"
source: hosted
version: "2.1.6"
version: "2.1.4"
pointycastle:
dependency: transitive
description:
@ -548,10 +508,10 @@ packages:
dependency: transitive
description:
name: riverpod
sha256: "6c0a2c30c04206ac05494bcccd8148b76866e1a9248a5a8c84ca7b16fbcb3f6a"
sha256: "80e48bebc83010d5e67a11c9514af6b44bbac1ec77b4333c8ea65dbc79e2d8ef"
url: "https://pub.dev"
source: hosted
version: "2.3.10"
version: "2.3.6"
rxdart:
dependency: transitive
description:
@ -577,18 +537,10 @@ packages:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
url: "https://pub.dev"
source: hosted
version: "1.10.0"
sprintf:
dependency: transitive
description:
name: sprintf
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
version: "1.9.1"
sqflite:
dependency: "direct main"
description:
@ -633,10 +585,10 @@ packages:
dependency: transitive
description:
name: state_notifier
sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
version: "0.7.2+1"
stream_channel:
dependency: transitive
description:
@ -673,10 +625,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
url: "https://pub.dev"
source: hosted
version: "0.6.0"
version: "0.5.1"
typed_data:
dependency: transitive
description:
@ -697,74 +649,74 @@ packages:
dependency: "direct main"
description:
name: url_launcher
sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27"
sha256: "781bd58a1eb16069412365c98597726cd8810ae27435f04b3b4d3a470bacd61e"
url: "https://pub.dev"
source: hosted
version: "6.1.14"
version: "6.1.12"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330
sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025"
url: "https://pub.dev"
source: hosted
version: "6.1.0"
version: "6.0.38"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f"
sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
url: "https://pub.dev"
source: hosted
version: "6.1.5"
version: "6.1.4"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e
sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
version: "3.0.5"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88
sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1"
url: "https://pub.dev"
source: hosted
version: "3.0.7"
version: "3.0.6"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618"
sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea
url: "https://pub.dev"
source: hosted
version: "2.1.5"
version: "2.1.3"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
sha256: "2942294a500b4fa0b918685aff406773ba0a4cd34b7f42198742a94083020ce5"
sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4
url: "https://pub.dev"
source: hosted
version: "2.0.20"
version: "2.0.18"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069"
sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422"
url: "https://pub.dev"
source: hosted
version: "3.0.8"
version: "3.0.7"
uuid:
dependency: transitive
description:
name: uuid
sha256: e03928880bdbcbf496fb415573f5ab7b1ea99b9b04f669c01104d085893c3134
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
version: "3.0.7"
vector_graphics:
dependency: transitive
description:
@ -797,38 +749,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vocsy_epub_viewer:
dependency: "direct main"
description:
name: vocsy_epub_viewer
sha256: "30aab4a5be22e8c98f22fed3345f6989caaca861178c38cab2a8b8cd66ad53de"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
win32:
dependency: transitive
description:
name: win32
sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa"
sha256: dfdf0136e0aa7a1b474ea133e67cb0154a0acd2599c4f3ada3b49d38d38793ee
url: "https://pub.dev"
source: hosted
version: "5.0.7"
version: "5.0.5"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff
url: "https://pub.dev"
source: hosted
version: "1.0.3"
version: "1.0.1"
xml:
dependency: transitive
description:
@ -846,5 +782,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.1.0 <4.0.0"
flutter: ">=3.13.0"
dart: ">=3.0.5 <4.0.0"
flutter: ">=3.10.0"

View File

@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.2+1
version: 1.0.0+1
environment:
sdk: '>=3.0.5 <4.0.0'
@ -36,7 +36,6 @@ dependencies:
epub_view: ^3.2.0
flutter_pdfview: ^1.2.7
vocsy_epub_viewer: ^2.0.0
# syncfusion_flutter_pdfviewer: ^22.2.5
# pdfx: ^2.4.0
@ -45,8 +44,6 @@ dependencies:
sqflite: ^2.3.0
path_provider: ^2.0.15
permission_handler: ^10.4.3
open_file: ^3.3.2
flutter_svg: ^2.0.7
google_fonts: ^5.1.0
@ -59,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,12 +6,12 @@
#include "generated_plugin_registrant.h"
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <dynamic_color/dynamic_color_plugin_c_api.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
DynamicColorPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}

View File

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