30 Commits

Author SHA1 Message Date
a7ca206b10 Fixed Stuck on Solve Captcha Screen 2024-09-28 13:10:48 +05:30
6be9927b26 Updated build number in pubspec.yaml 2024-09-10 18:49:23 +05:30
ea86d76015 removed unused imports 2024-08-31 16:00:48 +05:30
f396f92463 Fixed "no mirror found" and "always redirected to captcha" issues 2024-08-31 14:17:50 +05:30
70e96b12e1 Merge pull request #100 from clovis-dugue/develop
Multiple features and updates
2024-08-27 12:49:40 +05:30
9a91cffb31 chore: update Podfile.lock 2024-08-26 19:32:44 +02:00
669e5f7a66 feat: move files when changing book directory in settings 2024-08-26 19:32:29 +02:00
6e1f75b11a Merge pull request #96 from clovis-dugue/fix/no-mirrors
fix: no mirrors found after anna's archive ui update
2024-08-24 11:11:29 +05:30
7f36ca98b7 feat: add a setting for the destination folder of downloaded books 2024-08-24 00:23:12 +02:00
1025552f2f chore: format README.md 2024-08-23 23:35:35 +02:00
11a7dca93c chore: organize imports 2024-08-23 23:35:09 +02:00
ccd60ac357 fix: macos internet permission 2024-08-23 20:09:55 +02:00
d0c8128631 fix: no mirrors found after anna's archive ui update 2024-08-22 22:26:55 +02:00
e1a42df7e7 chore: update macos build 2024-08-22 18:58:07 +02:00
50f907eff7 chore: update ios build 2024-08-22 18:57:56 +02:00
c0c0de58a5 fix: update dependencies to be compatible with the latest flutter version 2024-08-22 18:55:47 +02:00
f0940e2947 chore: remove in-app reader 2024-08-22 18:47:40 +02:00
62ff665b87 fix: no mirrors found after anna's archive ui update 2024-08-22 18:46:00 +02:00
67d894855a Update README.md 2024-03-31 22:16:19 +05:30
a3ca57772d Update README.md 2024-03-31 21:55:44 +05:30
d9b19a6ec3 Merge pull request #71 from inson1/patch-3
Update badges in Readme
2024-03-10 18:54:24 +05:30
e013713516 Update badges in Readme 2024-02-26 16:17:25 +01:00
d655a4bd32 fixed mirror not found error 2024-02-25 18:32:34 +05:30
9b696c7e9d updated about page 2024-02-15 22:53:41 +05:30
cbbe049ef8 reverted back to old version as the issue still exist 2024-02-15 22:52:33 +05:30
cddaeb553a updated version number 2024-02-15 22:31:16 +05:30
ced66d0d1c Merge branch 'main' of https://github.com/dstark5/Openlib 2024-02-15 22:26:27 +05:30
17dcbb05b3 Fixed no mirror and download failed error 2024-02-15 22:25:27 +05:30
27e43a358c Merge pull request #64 from inson1/patch-2
Fix dot in README.md
2024-02-07 15:06:02 +05:30
1715b73494 Fix dot in README.md 2024-02-06 10:37:42 +01:00
49 changed files with 1286 additions and 600 deletions

View File

@ -4,30 +4,31 @@
# Openlib
#### An Open source app to download and read books from shadow library ([Annas Archive](https://annas-archive.org/)).
An Open source app to download and read books from shadow library ([Annas Archive](https://annas-archive.org/))
[![made-with-flutter](https://img.shields.io/badge/Made%20with-Flutter-4361ee.svg?style=for-the-badge)](https://flutter.dev/)
[![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-e63946.svg?style=for-the-badge)](https://opensource.org/licenses/)
[![made-with-flutter](https://img.shields.io/badge/Made%20with-Flutter-4361ee.svg?style=for-the-badge)](https://flutter.dev/)
[![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-e63946.svg?style=for-the-badge)](https://opensource.org/licenses/)
[![Latest release](https://img.shields.io/github/release/dstark5/Openlib.svg?style=for-the-badge)](https://github.com/dstark5/Openlib/releases)
[<img src="github_releases.png"
[<img src="github_releases.png"
alt="Get it on GitHub"
height="60">](https://github.com/dstark5/Openlib/releases) [<img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png"
alt="Get it on IzzyDroid"
height="60">](https://github.com/dstark5/Openlib/releases)
[<img src="https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png"
alt="Get it on IzzyOnDroid"
height="60">](https://android.izzysoft.de/repo/apk/com.app.openlib)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="60">](https://f-droid.org/en/packages/com.app.openlib/)
[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="60">](https://f-droid.org/en/packages/com.app.openlib/)
</div>
## Note
## Note 📝
**WARNING:** This App Is In Beta Stage, So You May Encounter Bugs. If You Do, Open An Issue In Github Repository.
#### Publishing Openlib, Or Any Fork Of It In The Google Play Store Violates Their Terms And Conditions.
**Publishing Openlib, Or Any Fork Of It In The Google Play Store Violates Their Terms And Conditions**
## Screenshots
## Screenshots 🖼️
[<img src="screenshots/Screenshot_1.png" width=160>](screenshots/Screenshot_1.png)
[<img src="screenshots/Screenshot_2.png" width=160>](screenshots/Screenshot_2.png)
@ -38,13 +39,13 @@
[<img src="screenshots/Screenshot_7.png" width=160>](screenshots/Screenshot_7.png)
[<img src="screenshots/Screenshot_8.png" width=160>](screenshots/Screenshot_8.png)
## Description
## Description 📖
##### Openlib Is An Open Source App To Download And Read Books From Shadow Library ([Annas Archive](https://annas-archive.org/)). The App Has Built In Reader to Read Books.
Openlib Is An Open Source App To Download And Read Books From Shadow Library ([Annas Archive](https://annas-archive.org/)). The App Has Built In Reader to Read Books
##### As [Annas Archive](https://annas-archive.org/) Doesn't Have An API. The App Works By Sending Request To Annas Archive And Parses The Response To objects. The App Extracts The Mirrors From Response And Downloads The Book.
As [Annas Archive](https://annas-archive.org/) Doesn't Have An API. The App Works By Sending Request To Annas Archive And Parses The Response To objects. The App Extracts The Mirrors From Response And Downloads The Book
## Features
## Features
- Trending Books
- Download And Read Books With In-Built Viewer
@ -53,12 +54,12 @@
- Filter Books
- Sort Books
## Roadmap
## Roadmap 🎯
- Adding More Book Format supports (cbz,cbr,azw3,etc...)
- Adding Support For Background Downloads
- Adding Support For Multiple Downloads
- Move existing books when changing the storage path
## Building from Source
@ -66,45 +67,55 @@
- Git Clone The Repo
```
git clone https://github.com/dstark5/Openlib.git
```
```sh
git clone https://github.com/dstark5/Openlib.git
```
- Run the app with Android Studio or VS Code. Or the command line:
```
flutter pub get
flutter run
```
```sh
flutter pub get
flutter run
```
- To Build App Run:
```
flutter build
```
```sh
flutter build
```
- The Build Will Be In './build/app/outputs/flutter-apk/app-release.apk'
## Contribution
### Android
Make sure that `android/local.properties` has `flutter.minSdkVersion=21` or above
## Contributor required 🚧
We are actively seeking contributors. Whether you're a seasoned developer or just starting out, we welcome your contributions to help make this project even better!
## Contribution 💝
Whether you have ideas, design changes or even major code changes, help is always welcome. The app gets better and better with each contribution, no matter how big or small!
If you'd like to get involved See [CONTRIBUTING.md](./CONTRIBUTING.md) for the guidelines.
## Issues
## Issues 🚩
Please report bugs via the [issue tracker](https://github.com/dstark5/Openlib/issues).
## Donate
## Donate 🎁
If you like Openlib, you're welcome to send a donation.
#### [Donate To Annas Archive](https://annas-archive.org/donate?tier=1).
[Donate To Annas Archive.](https://annas-archive.org/donate?tier=1)
## License
## License 📜
[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](https://www.gnu.org/licenses/gpl-3.0.en.html)
Openlib is a free software licensed under GPL v3.0 It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. [GNU General Public License](https://www.gnu.org/licenses/gpl.html) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
## Disclaimer
## Disclaimer ⚠️
Openlib does not own or have any affiliation with the books available through the app. All books are the property of their respective owners and are protected by copyright law. Openlib is not responsible for any infringement of copyright or other intellectual property rights that may result from the use of the books available through the app. By using the app, you agree to use the books only for personal, non-commercial purposes and in compliance with all applicable laws and regulations.

View File

@ -25,7 +25,8 @@
android:name="${applicationName}"
android:requestLegacyExternalStorage="true"
android:networkSecurityConfig="@xml/network_security_config"
android:icon="@mipmap/launcher_icon">
android:icon="@mipmap/launcher_icon"
android:enableOnBackInvokedCallback="true">
<activity
android:name=".MainActivity"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

44
ios/Podfile Normal file
View File

@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

View File

@ -1,16 +1,23 @@
// Dart imports:
import 'dart:io' show Platform;
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_nav_bar/google_nav_bar.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
// Project imports:
import 'package:openlib/services/database.dart' show MyLibraryDb;
import 'package:openlib/ui/mylibrary_page.dart';
import 'package:openlib/ui/search_page.dart';
import 'package:openlib/ui/settings_page.dart';
import 'package:openlib/ui/themes.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'
@ -20,8 +27,7 @@ import 'package:openlib/state/state.dart'
openPdfWithExternalAppProvider,
openEpubWithExternalAppProvider,
userAgentProvider,
cookieProvider,
dbProvider;
cookieProvider;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@ -31,13 +37,22 @@ 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');
MyLibraryDb dataBase = MyLibraryDb.instance;
bool isDarkMode =
await dataBase.getPreference('darkMode') == 0 ? false : true;
bool openPdfwithExternalapp = await dataBase
.getPreference('openPdfwithExternalApp')
.catchError((e) => print(e)) ==
0
? false
: true;
bool openEpubwithExternalapp = await dataBase
.getPreference('openEpubwithExternalApp')
.catchError((e) => print(e)) ==
0
? false
: true;
String browserUserAgent = await dataBase.getBrowserOptions('userAgent');
String browserCookie = await dataBase.getBrowserOptions('cookie');
@ -53,7 +68,6 @@ void main() async {
runApp(
ProviderScope(
overrides: [
dbProvider.overrideWithValue(dataBase),
themeModeProvider.overrideWith(
(ref) => isDarkMode ? ThemeMode.dark : ThemeMode.light),
openPdfWithExternalAppProvider

View File

@ -1,6 +1,8 @@
import 'package:dio/dio.dart';
import 'dart:convert';
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:dio/dio.dart';
import 'package:html/parser.dart' show parse;
class BookData {
@ -23,7 +25,7 @@ class BookData {
}
class BookInfoData extends BookData {
final List<String>? mirrors;
String? mirror;
final String? description;
final String? format;
@ -35,13 +37,13 @@ class BookInfoData extends BookData {
required super.info,
required super.link,
required super.md5,
required this.mirrors,
required this.format,
required this.mirror,
required this.description});
}
class AnnasArchieve {
String baseUrl = "https://annas-archive.org";
static const String baseUrl = "https://annas-archive.org";
final Dio dio = Dio();
@ -126,67 +128,82 @@ class AnnasArchieve {
}
}
Future<String?> _getMirrorLink(
String url, String userAgent, String cookie) async {
try {
final response = await dio.get(url,
options: Options(extra: {
'withCredentials': true
}, headers: {
"Host": "annas-archive.org",
"Origin": "https://annas-archive.org",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "secure",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-site",
"Cookie": cookie,
"User-Agent": userAgent
}));
// Future<String?> _getMirrorLink(
// String url, String userAgent, String cookie) async {
// try {
// final response = await dio.get(url,
// options: Options(extra: {
// 'withCredentials': true
// }, headers: {
// "Host": "annas-archive.org",
// "Origin": baseUrl,
// "Upgrade-Insecure-Requests": "1",
// "Sec-Fetch-Dest": "secure",
// "Sec-Fetch-Mode": "navigate",
// "Sec-Fetch-Site": "same-site",
// "Cookie": cookie,
// "User-Agent": userAgent
// }));
var document = parse(response.data.toString());
// var document = parse(response.data.toString());
var pTag = document.querySelectorAll('p[class="mb-4"]');
String? link = pTag[1].querySelector('a')?.attributes['href'];
return link;
} catch (e) {
// print('${url} ${e}');
if (e.toString().contains("403")) {
throw jsonEncode({"code": "403", "url": url});
}
return null;
}
}
// var pTag = document.querySelectorAll('p[class="mb-4"]');
// String? link = pTag[1].querySelector('a')?.attributes['href'];
// return link;
// } catch (e) {
// // print('${url} ${e}');
// if (e.toString().contains("403")) {
// throw jsonEncode({"code": "403", "url": url});
// }
// return null;
// }
// }
Future<BookInfoData?> _bookInfoParser(resData, url, userAgent, cookie) async {
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?.querySelectorAll('ul[class="list-inside mb-4 ml-1"]');
List<String> mirrors = [];
// List<String> mirrors = [];
// if (ul != null) {
// var anchorTags = [];
// for (var e in ul) {
// anchorTags.insertAll(0, e.querySelectorAll('a'));
// }
// for (var element in anchorTags) {
// if (element.attributes['href'] != null &&
// element.attributes['href']!.startsWith('/slow_download') &&
// element.attributes['href']!.endsWith('/2')) {
// String? url =
// await _getMirrorLink('$baseUrl${element.attributes['href']!}');
// if (url != null && url.isNotEmpty) {
// mirrors.add(url);
// }
// } else if (element.attributes['href']!.startsWith('https://')) {
// if (element.attributes['href'] != null &&
// element.attributes['href'].contains('ipfs') == true) {
// mirrors.add(element.attributes['href']!);
// }
// }
// }
// }
String? mirror;
var anchorTags = [];
if (ul != null) {
var anchorTags = [];
if (ul.length == 2) {
anchorTags = ul[1].querySelectorAll('a');
} else {
anchorTags = ul[0].querySelectorAll('a');
for (var e in ul) {
anchorTags.insertAll(0, e.querySelectorAll('a'));
}
}
for (var element in anchorTags) {
if (element.attributes['href']!.startsWith('https://')) {
if (element.attributes['href'] != null &&
element.attributes['href'].startsWith('https://1lib.sk') !=
true) {
mirrors.add(element.attributes['href']!);
}
} else if (element.attributes['href'] != null &&
element.attributes['href']!.startsWith('/slow_download')) {
String? url = await _getMirrorLink(
'$baseUrl${element.attributes['href']!}', userAgent, cookie);
if (url != null && url.isNotEmpty) {
mirrors.add(url);
}
}
for (var element in anchorTags) {
if (element.attributes['href'] != null &&
element.attributes['href']!.startsWith('/slow_download') &&
element.attributes['href']!.endsWith('/2')) {
mirror = '$baseUrl${element.attributes['href']}';
}
}
@ -202,9 +219,9 @@ class AnnasArchieve {
'info':
main?.querySelector('div[class="text-sm text-gray-500"]')?.text ?? '',
'description': main
?.querySelector(
'div[class="mt-4 line-clamp-[5] js-md5-top-box-description"]')
?.text ??
?.querySelector('div[class="mb-1"]')
?.text
.replaceFirst("description", '') ??
" "
};
@ -229,7 +246,7 @@ class AnnasArchieve {
link: data['link'],
md5: getMd5(data['link'].toString()),
format: getFormat(data['info']),
mirrors: mirrors,
mirror: mirror,
description: data['description'],
);
} else {
@ -279,15 +296,11 @@ class AnnasArchieve {
}
}
Future<BookInfoData> bookInfo(
{required String url,
required String userAgent,
required String cookie}) async {
Future<BookInfoData> bookInfo({required String url}) async {
try {
final response =
await dio.get(url, options: Options(headers: defaultDioHeaders));
BookInfoData? data =
await _bookInfoParser(response.data, url, userAgent, cookie);
BookInfoData? data = await _bookInfoParser(response.data, url);
if (data != null) {
return data;
} else {

View File

@ -1,51 +1,11 @@
// Dart imports:
import 'dart:io';
// Package imports:
import 'package:sqflite/sqflite.dart';
class Sqlite {
static Future<Database> initDb() async {
var databasesPath = await getDatabasesPath();
String path = '$databasesPath/mylibrary.db';
bool isMobile = Platform.isAndroid || Platform.isIOS;
Database dbInstance = await openDatabase(
path,
version: 5,
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)');
await db.execute(
'CREATE TABLE browserOptions (name TEXT PRIMARY KEY,value TEXT)');
}
},
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']);
List<dynamic> isbrowserOptionsExist = await db.query('sqlite_master',
where: 'name = ?', whereArgs: ['browserOptions']);
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)');
}
if (isMobile && isbrowserOptionsExist.isEmpty) {
await db.execute(
'CREATE TABLE browserOptions (name TEXT PRIMARY KEY,value TEXT)');
}
},
);
return dbInstance;
}
}
// Project imports:
import 'package:openlib/services/files.dart';
class MyBook {
final String id;
@ -90,12 +50,79 @@ class MyBook {
}
class MyLibraryDb {
Database dbInstance;
static final MyLibraryDb instance = MyLibraryDb._internal();
static Database? _database;
MyLibraryDb._internal();
Future<Database> get database async {
if (_database != null) {
return _database!;
}
_database = await _initDatabase();
return _database!;
}
Future<Database> _initDatabase() async {
final databasePath = await getDatabasesPath();
final path = '$databasePath/mylibrary.db';
final bool isMobile = Platform.isAndroid || Platform.isIOS;
return await openDatabase(
path,
version: 5,
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 TEXT)');
if (isMobile || true) {
// TODO: Breaks getBrowserOptions() on Mac
await db.execute(
'CREATE TABLE bookposition (fileName TEXT PRIMARY KEY,position TEXT)');
await db.execute(
'CREATE TABLE browserOptions (name TEXT PRIMARY KEY,value TEXT)');
}
},
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']);
List<dynamic> isbrowserOptionsExist = await db.query('sqlite_master',
where: 'name = ?', whereArgs: ['browserOptions']);
if (isPreferenceTableExist.isEmpty) {
await db.execute(
'CREATE TABLE preferences (name TEXT PRIMARY KEY,value TEXT)');
}
if (isMobile && isTableExist.isEmpty) {
await db.execute(
'CREATE TABLE bookposition (fileName TEXT PRIMARY KEY,position TEXT)');
}
if (isMobile && isbrowserOptionsExist.isEmpty) {
await db.execute(
'CREATE TABLE browserOptions (name TEXT PRIMARY KEY,value TEXT)');
}
},
onOpen: (db) async {
final bookStorageDefaultDirectory =
await getBookStorageDefaultDirectory;
await db.execute(
"INSERT OR IGNORE INTO preferences (name, value) VALUES ('darkMode', 0)");
await db.execute(
"INSERT OR IGNORE INTO preferences (name, value) VALUES ('openPdfwithExternalApp', 0)");
await db.execute(
"INSERT OR IGNORE INTO preferences (name, value) VALUES ('openEpubwithExternalApp', 0)");
await db.execute(
"INSERT OR IGNORE INTO preferences (name, value) VALUES ('bookStorageDirectory', '$bookStorageDefaultDirectory')");
},
);
}
// Database dbInstance;
String tableName = 'mybooks';
MyLibraryDb({required this.dbInstance});
Future<void> insert(MyBook book) async {
final dbInstance = await instance.database;
await dbInstance.insert(
tableName,
book.toMap(),
@ -104,6 +131,7 @@ class MyLibraryDb {
}
Future<void> delete(String id) async {
final dbInstance = await instance.database;
await dbInstance.delete(
tableName,
where: 'id = ?',
@ -112,6 +140,7 @@ class MyLibraryDb {
}
Future<MyBook?> getId(String id) async {
final dbInstance = await instance.database;
List<Map<String, dynamic>> data =
await dbInstance.query(tableName, where: 'id = ?', whereArgs: [id]);
List<MyBook> book = listMapToMyBook(data);
@ -122,6 +151,7 @@ class MyLibraryDb {
}
Future<bool> checkIdExists(String id) async {
final dbInstance = await instance.database;
List<Map<String, dynamic>> data =
await dbInstance.query(tableName, where: 'id = ?', whereArgs: [id]);
List<MyBook> book = listMapToMyBook(data);
@ -132,6 +162,7 @@ class MyLibraryDb {
}
Future<List<MyBook>> getAll() async {
final dbInstance = await instance.database;
final List<Map<String, dynamic>> maps = await dbInstance.query(tableName);
return listMapToMyBook(maps);
}
@ -153,6 +184,7 @@ class MyLibraryDb {
}
Future<void> saveBookState(String fileName, String position) async {
final dbInstance = await instance.database;
await dbInstance.insert(
'bookposition',
{'fileName': fileName, 'position': position},
@ -161,6 +193,7 @@ class MyLibraryDb {
}
Future<void> deleteBookState(String fileName) async {
final dbInstance = await instance.database;
await dbInstance.delete(
'bookposition',
where: 'fileName = ?',
@ -169,6 +202,7 @@ class MyLibraryDb {
}
Future<String?> getBookState(String fileName) async {
final dbInstance = await instance.database;
List<Map<String, dynamic>> data = await dbInstance
.query('bookposition', where: 'fileName = ?', whereArgs: [fileName]);
List<dynamic> dataList = List.generate(data.length, (i) {
@ -181,29 +215,45 @@ class MyLibraryDb {
}
}
Future<void> savePreference(String name, bool value) async {
int boolInt = value ? 1 : 0;
Future<void> savePreference(String name, dynamic value) async {
switch (value.runtimeType) {
case bool:
value = value ? 1 : 0;
break;
case int || String:
break;
default:
throw 'Invalid type';
}
Database dbInstance = await instance.database;
await dbInstance.insert(
'preferences',
{'name': name, 'value': boolInt},
{'name': name, 'value': value},
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<bool> getPreference(String name) async {
Future<dynamic> getPreference(String name) async {
Database dbInstance = await instance.database;
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;
// Convert to int if possible
int? preference = int.tryParse(dataList[0]['value']);
if (preference != null) {
return preference;
}
// Return string value if not int
return dataList[0]['value'];
}
throw "Preference $name not found";
}
Future<void> setBrowserOptions(String name, String value) async {
final dbInstance = await instance.database;
await dbInstance.insert(
'browserOptions',
{'name': name, 'value': value},
@ -212,6 +262,7 @@ class MyLibraryDb {
}
Future<String> getBrowserOptions(String name) async {
final dbInstance = await instance.database;
List<Map<String, dynamic>> data = await dbInstance
.query('browserOptions', where: 'name = ?', whereArgs: [name]);
List<dynamic> dataList = List.generate(data.length, (i) {

View File

@ -1,11 +1,19 @@
// Dart imports:
import 'dart:io';
// Package imports:
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'files.dart';
// Project imports:
import 'package:openlib/services/database.dart' show MyLibraryDb;
MyLibraryDb dataBase = MyLibraryDb.instance;
Future<String> _getFilePath(String fileName) async {
final path = await getAppDirectoryPath;
return '$path/$fileName';
String bookStorageDirectory =
await dataBase.getPreference('bookStorageDirectory');
return '$bookStorageDirectory/$fileName';
}
List<String> _reorderMirrors(List<String> mirrors) {
@ -108,8 +116,9 @@ Future<void> downloadFile(
Future<bool> verifyFileCheckSum(
{required String md5Hash, required String format}) async {
try {
final path = await getAppDirectoryPath;
final filePath = '$path/$md5Hash.$format';
final bookStorageDirectory =
await dataBase.getPreference('bookStorageDirectory');
final filePath = '$bookStorageDirectory/$md5Hash.$format';
final file = File(filePath);
final stream = file.openRead();
final hash = await md5.bind(stream).first;

View File

@ -1,9 +1,17 @@
// Dart imports:
import 'dart:io';
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:path_provider/path_provider.dart';
import 'package:openlib/state/state.dart' show dbProvider, myLibraryProvider;
Future<String> get getAppDirectoryPath async {
// Project imports:
import 'package:openlib/services/database.dart';
import 'package:openlib/state/state.dart' show myLibraryProvider;
MyLibraryDb dataBase = MyLibraryDb.instance;
Future<String> get getBookStorageDefaultDirectory async {
if (Platform.isAndroid) {
final directory = await getExternalStorageDirectory();
return directory!.path;
@ -32,6 +40,23 @@ Future<void> moveFilesToAndroidInternalStorage() async {
}
}
Future<void> moveFolderContents(
String source_path, String destination_path) async {
final source = Directory(source_path);
source.listSync(recursive: false).forEach((var entity) {
if (entity is Directory) {
var newDirectory =
Directory('${destination_path}/${entity.path.split('/').last}');
newDirectory.createSync();
moveFolderContents(entity.path, newDirectory.path);
entity.deleteSync();
} else if (entity is File) {
entity.copySync('${destination_path}/${entity.path.split('/').last}');
entity.deleteSync();
}
});
}
Future<bool> isFileExists(String filePath) async {
return await File(filePath).exists();
}
@ -43,8 +68,9 @@ Future<void> deleteFile(String filePath) async {
}
Future<String> getFilePath(String fileName) async {
String appDirPath = await getAppDirectoryPath;
String filePath = '$appDirPath/$fileName';
final bookStorageDirectory =
await dataBase.getPreference('bookStorageDirectory');
String filePath = '$bookStorageDirectory/$fileName';
bool isExists = await isFileExists(filePath);
if (isExists == true) {
return filePath;
@ -56,10 +82,11 @@ Future<void> deleteFileWithDbData(
FutureProviderRef ref, String md5, String format) async {
try {
String fileName = '$md5.$format';
String appDirPath = await getAppDirectoryPath;
await deleteFile('$appDirPath/$fileName');
await ref.read(dbProvider).delete(md5);
await ref.read(dbProvider).deleteBookState(fileName);
final bookStorageDirectory =
await dataBase.getPreference('bookStorageDirectory');
await deleteFile('$bookStorageDirectory/$fileName');
await dataBase.delete(md5);
await dataBase.deleteBookState(fileName);
// ignore: unused_result
ref.refresh(myLibraryProvider);
} catch (e) {

View File

@ -1,3 +1,4 @@
// Package imports:
import 'package:dio/dio.dart';
import 'package:html/parser.dart' show parse;

View File

@ -1,12 +1,20 @@
// Dart imports:
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';
import 'package:openlib/services/open_library.dart';
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// Project imports:
import 'package:openlib/services/annas_archieve.dart';
import 'package:openlib/services/database.dart';
import 'package:openlib/services/files.dart';
import 'package:openlib/services/open_library.dart';
MyLibraryDb dataBase = MyLibraryDb.instance;
//Provider for dropdownbutton in search page
@ -97,14 +105,13 @@ final searchProvider = FutureProvider.family
final cookieProvider = StateProvider<String>((ref) => "");
final userAgentProvider = StateProvider<String>((ref) => "");
final webViewLoadingState = StateProvider.autoDispose<bool>((ref) => true);
//Provider for Book Info
final bookInfoProvider =
FutureProvider.family<BookInfoData, String>((ref, url) async {
AnnasArchieve annasArchieve = AnnasArchieve();
BookInfoData data = await annasArchieve.bookInfo(
url: url,
userAgent: ref.read(userAgentProvider),
cookie: ref.read(cookieProvider));
BookInfoData data = await annasArchieve.bookInfo(url: url);
return data;
});
@ -145,15 +152,13 @@ final downloadState =
final checkSumState = StateProvider.autoDispose<CheckSumProcessState>(
(ref) => CheckSumProcessState.waiting);
final dbProvider = Provider<MyLibraryDb>((ref) => throw UnimplementedError());
final myLibraryProvider = FutureProvider((ref) async {
return await ref.read(dbProvider).getAll();
return dataBase.getAll();
});
final checkIdExists =
FutureProvider.family.autoDispose<bool, String>((ref, id) async {
return await ref.read(dbProvider).checkIdExists(id);
return await dataBase.checkIdExists(id);
});
class FileName {
@ -173,18 +178,18 @@ final totalPdfPage = StateProvider.autoDispose<int>((ref) => 0);
Future<void> savePdfState(String fileName, WidgetRef ref) async {
String position = ref.watch(pdfCurrentPage).toString();
await ref.watch(dbProvider).saveBookState(fileName, position);
await dataBase.saveBookState(fileName, position);
}
Future<void> saveEpubState(
String fileName, String? position, WidgetRef ref) async {
String pos = position ?? '';
await ref.watch(dbProvider).saveBookState(fileName, pos);
await dataBase.saveBookState(fileName, pos);
}
final getBookPosition =
FutureProvider.family.autoDispose<String?, String>((ref, fileName) async {
return await ref.read(dbProvider).getBookState(fileName);
return await dataBase.getBookState(fileName);
});
final openPdfWithExternalAppProvider = StateProvider<bool>((ref) => false);

View File

@ -1,8 +1,12 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:url_launcher/url_launcher.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
// Project imports:
import 'package:openlib/ui/components/page_title_widget.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
class AboutPage extends StatelessWidget {
const AboutPage({super.key});
@ -43,7 +47,7 @@ class AboutPage extends StatelessWidget {
Padding(
padding: EdgeInsets.only(left: 7, right: 7, top: 5),
child: Text(
"1.0.5",
"1.0.8",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,

View File

@ -1,13 +1,25 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:dio/dio.dart' show CancelToken;
// Dart imports:
// import 'dart:convert';
import 'package:openlib/services/database.dart';
import 'package:openlib/ui/components/error_widget.dart';
import 'package:openlib/services/download_file.dart';
// Flutter imports:
import 'package:flutter/material.dart';
// import 'package:flutter/scheduler.dart';
// Package imports:
import 'package:dio/dio.dart' show CancelToken;
import 'package:flutter_riverpod/flutter_riverpod.dart';
// import 'package:flutter_svg/svg.dart';
// Project imports:
import 'package:openlib/services/annas_archieve.dart' show BookInfoData;
import 'package:openlib/services/database.dart';
import 'package:openlib/services/download_file.dart';
import 'package:openlib/ui/components/book_info_widget.dart';
import 'package:openlib/ui/components/error_widget.dart';
import 'package:openlib/ui/components/file_buttons_widget.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
import 'package:openlib/ui/webview_page.dart';
import 'package:openlib/state/state.dart'
show
bookInfoProvider,
@ -22,16 +34,9 @@ import 'package:openlib/state/state.dart'
CheckSumProcessState,
downloadState,
checkSumState,
dbProvider,
checkIdExists,
myLibraryProvider;
import 'package:openlib/ui/components/book_info_widget.dart';
import 'package:openlib/ui/components/file_buttons_widget.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
import 'package:flutter_svg/svg.dart';
import 'package:openlib/ui/webview_page.dart';
class BookInfoPage extends ConsumerWidget {
const BookInfoPage({super.key, required this.url});
@ -53,91 +58,91 @@ class BookInfoPage extends ConsumerWidget {
data: data, child: ActionButtonWidget(data: data));
},
error: (err, _) {
if (err.toString().contains("403")) {
var errJson = jsonDecode(err.toString());
// if (err.toString().contains("403")) {
// var errJson = jsonDecode(err.toString());
if (SchedulerBinding.instance.schedulerPhase ==
SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback((_) {
Future.delayed(
const Duration(seconds: 3),
() => Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) {
return Webview(url: errJson["url"]);
})));
});
}
// if (SchedulerBinding.instance.schedulerPhase ==
// SchedulerPhase.persistentCallbacks) {
// SchedulerBinding.instance.addPostFrameCallback((_) {
// Future.delayed(
// const Duration(seconds: 3),
// () => Navigator.pushReplacement(context,
// MaterialPageRoute(builder: (BuildContext context) {
// return Webview(url: errJson["url"]);
// })));
// });
// }
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(
width: 210,
child: SvgPicture.asset(
'assets/captcha.svg',
width: 210,
),
),
const SizedBox(
height: 30,
),
Text(
"Captcha required",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Theme.of(context).textTheme.headlineMedium?.color,
overflow: TextOverflow.ellipsis,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"you will be redirected to solve captcha",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Theme.of(context).textTheme.headlineSmall?.color,
overflow: TextOverflow.ellipsis,
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(30, 15, 30, 10),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: const Color.fromARGB(255, 255, 186, 186),
borderRadius: BorderRadius.circular(5)),
child: const Padding(
padding: EdgeInsets.all(10.0),
child: Text(
"If you have solved the captcha then you will be automatically redirected to the results page . In case you seeing this page even after completing try using a VPN .",
textAlign: TextAlign.start,
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
),
)
],
);
} else {
return CustomErrorWidget(
error: err,
stackTrace: _,
onRefresh: () {
// ignore: unused_result
ref.refresh(bookInfoProvider(url));
},
);
}
// return Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.stretch,
// children: [
// SizedBox(
// width: 210,
// child: SvgPicture.asset(
// 'assets/captcha.svg',
// width: 210,
// ),
// ),
// const SizedBox(
// height: 30,
// ),
// Text(
// "Captcha required",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 18,
// fontWeight: FontWeight.bold,
// color: Theme.of(context).textTheme.headlineMedium?.color,
// overflow: TextOverflow.ellipsis,
// ),
// ),
// Padding(
// padding: const EdgeInsets.all(8.0),
// child: Text(
// "you will be redirected to solve captcha",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 13,
// fontWeight: FontWeight.bold,
// color: Theme.of(context).textTheme.headlineSmall?.color,
// overflow: TextOverflow.ellipsis,
// ),
// ),
// ),
// Padding(
// padding: const EdgeInsets.fromLTRB(30, 15, 30, 10),
// child: Container(
// width: double.infinity,
// decoration: BoxDecoration(
// color: const Color.fromARGB(255, 255, 186, 186),
// borderRadius: BorderRadius.circular(5)),
// child: const Padding(
// padding: EdgeInsets.all(10.0),
// child: Text(
// "If you have solved the captcha then you will be automatically redirected to the results page . In case you seeing this page even after completing try using a VPN .",
// textAlign: TextAlign.start,
// style: TextStyle(
// fontSize: 13,
// fontWeight: FontWeight.bold,
// color: Colors.black,
// ),
// ),
// ),
// ),
// )
// ],
// );
// } else {
return CustomErrorWidget(
error: err,
stackTrace: _,
onRefresh: () {
// ignore: unused_result
ref.refresh(bookInfoProvider(url));
},
);
// }
},
loading: () {
return Center(
@ -193,7 +198,17 @@ class _ActionButtonWidgetState extends ConsumerState<ActionButtonWidget> {
color: Colors.white,
)),
onPressed: () async {
await downloadFileWidget(ref, context, widget.data);
final result = await Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return Webview(url: widget.data.mirror ?? '');
}));
if (result != null) {
// ignore: use_build_context_synchronously
widget.data.mirror = result;
// ignore: use_build_context_synchronously
await downloadFileWidget(ref, context, widget.data);
}
},
child: const Padding(
padding: EdgeInsets.all(8.0),
@ -217,7 +232,7 @@ class _ActionButtonWidgetState extends ConsumerState<ActionButtonWidget> {
}
Future<void> downloadFileWidget(
WidgetRef ref, BuildContext context, dynamic data) async {
WidgetRef ref, BuildContext context, BookInfoData data) async {
showDialog(
context: context,
barrierDismissible: false,
@ -225,8 +240,10 @@ Future<void> downloadFileWidget(
return _ShowDialog(title: data.title);
});
List<String> mirrors = [data.mirror!];
print(mirrors);
downloadFile(
mirrors: data.mirrors!,
mirrors: mirrors,
md5: data.md5,
format: data.format!,
onStart: () {
@ -240,7 +257,9 @@ Future<void> downloadFileWidget(
ref.read(downloadProgressProvider.notifier).state = rcv / total;
if (rcv / total == 1.0) {
await ref.read(dbProvider).insert(MyBook(
MyLibraryDb dataBase = MyLibraryDb.instance;
await dataBase.insert(MyBook(
id: data.md5,
title: data.title,
author: data.author,
@ -256,7 +275,7 @@ Future<void> downloadFileWidget(
try {
final checkSum = await verifyFileCheckSum(
md5Hash: data.md5, format: data.format);
md5Hash: data.md5, format: data.format!);
if (checkSum == true) {
ref.read(checkSumState.notifier).state =
CheckSumProcessState.success;

View File

@ -1,7 +1,12 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:openlib/ui/extensions.dart';
// Package imports:
import 'package:cached_network_image/cached_network_image.dart';
// Project imports:
import 'package:openlib/ui/extensions.dart';
String? getFileType(String? info) {
if (info != null && info.isNotEmpty) {
info = info.toLowerCase();

View File

@ -1,4 +1,7 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:cached_network_image/cached_network_image.dart';
class BookInfoWidget extends StatelessWidget {

View File

@ -1,7 +1,12 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
// Project imports:
import 'package:openlib/state/state.dart' show FileName, deleteFileFromMyLib;
import 'package:openlib/ui/components/snack_bar_widget.dart';
class ShowDeleteDialog extends ConsumerWidget {
final String id;

View File

@ -1,7 +1,12 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:openlib/ui/extensions.dart';
// Package imports:
import 'package:flutter_svg/svg.dart';
// Project imports:
import 'package:openlib/ui/extensions.dart';
// ignore: must_be_immutable
class CustomErrorWidget extends StatelessWidget {
final Object error;

View File

@ -1,10 +1,14 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:open_file/open_file.dart';
// Project imports:
import 'package:openlib/services/files.dart' show getFilePath;
import 'package:openlib/ui/components/snack_bar_widget.dart';
import 'package:openlib/ui/components/delete_dialog_widget.dart';
import 'package:openlib/ui/components/snack_bar_widget.dart';
import 'package:openlib/ui/epub_viewer.dart' show launchEpubViewer;
import 'package:openlib/ui/pdf_viewer.dart' show launchPdfViewer;
@ -98,11 +102,11 @@ Future<void> openCbrAndCbz(
{required String fileName, required BuildContext context}) async {
try {
String path = await getFilePath(fileName);
await OpenFile.open(path);
await OpenFile.open(path, linuxByProcess: true);
} catch (e) {
// ignore: avoid_print
// print(e);
// ignore: use_build_context_synchronously
showSnackBar(context: context, message: 'Unable to open pdf!');
showSnackBar(context: context, message: 'Unable to open file!');
}
}

View File

@ -1,3 +1,4 @@
// Flutter imports:
import 'package:flutter/material.dart';
class TitleText extends StatelessWidget {

View File

@ -1,3 +1,4 @@
// Flutter imports:
import 'package:flutter/material.dart';
void showSnackBar({required BuildContext context, required String message}) {

View File

@ -1,18 +1,21 @@
// Dart imports:
import 'dart:io';
import 'dart:convert';
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
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';
// Project imports:
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;
@ -22,33 +25,19 @@ Future<void> launchEpubViewer(
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);
await OpenFile.open(path, linuxByProcess: true);
} 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
});
// ignore: use_build_context_synchronously
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return EpubViewerWidget(
fileName: fileName,
);
}));
} catch (e) {
// ignore: use_build_context_synchronously
showSnackBar(context: context, message: 'Unable to open pdf!');

View File

@ -1,3 +1,4 @@
// Flutter imports:
import 'package:flutter/material.dart';
extension ColorExtension on String {

View File

@ -1,8 +1,11 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/services/database.dart';
import 'package:openlib/state/state.dart' show dbProvider;
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
// Project imports:
import 'package:openlib/services/database.dart';
import 'package:openlib/ui/components/book_info_widget.dart';
import 'package:openlib/ui/components/file_buttons_widget.dart';
@ -21,7 +24,9 @@ class BookPage extends StatelessWidget {
),
body: Consumer(
builder: (BuildContext context, WidgetRef ref, _) {
final bookInfo = ref.read(dbProvider).getId(id);
MyLibraryDb dataBase = MyLibraryDb.instance;
final bookInfo = dataBase.getId(id);
return FutureBuilder(
future: bookInfo,

View File

@ -1,13 +1,17 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/ui/extensions.dart';
import 'package:openlib/ui/mybook_page.dart';
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
// Project imports:
import 'package:openlib/state/state.dart' show myLibraryProvider;
import 'package:openlib/ui/components/book_card_widget.dart';
import 'package:openlib/ui/components/error_widget.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
import 'package:openlib/ui/components/book_card_widget.dart';
import 'package:openlib/state/state.dart' show myLibraryProvider;
import 'package:openlib/ui/extensions.dart';
import 'package:openlib/ui/mybook_page.dart';
class MyLibraryPage extends ConsumerWidget {
const MyLibraryPage({super.key});

View File

@ -1,6 +1,18 @@
// Dart imports:
import 'dart:io' show Platform;
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:open_file/open_file.dart';
import 'package:url_launcher/url_launcher.dart';
// Project imports:
import 'package:openlib/services/files.dart' show getFilePath;
import 'package:openlib/state/state.dart'
show
filePathProvider,
@ -9,11 +21,6 @@ import 'package:openlib/state/state.dart'
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,
@ -22,7 +29,7 @@ Future<void> launchPdfViewer(
bool openWithExternalApp = ref.watch(openPdfWithExternalAppProvider);
if (openWithExternalApp) {
String path = await getFilePath(fileName);
await OpenFile.open(path);
await OpenFile.open(path, linuxByProcess: true);
} else {
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
return PdfView(

View File

@ -1,13 +1,17 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:openlib/ui/extensions.dart';
// Project imports:
import 'package:openlib/state/state.dart' show searchProvider;
import 'package:openlib/ui/book_info_page.dart';
import 'package:openlib/ui/components/book_card_widget.dart';
import 'package:openlib/ui/components/error_widget.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
import 'package:openlib/ui/components/book_card_widget.dart';
import 'package:openlib/state/state.dart' show searchProvider;
import 'package:openlib/ui/extensions.dart';
class ResultPage extends ConsumerWidget {
const ResultPage({super.key, required this.searchQuery});

View File

@ -1,7 +1,14 @@
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/ui/results_page.dart';
// Project imports:
import 'package:openlib/ui/components/page_title_widget.dart';
import 'package:openlib/ui/results_page.dart';
import 'components/snack_bar_widget.dart';
import 'package:openlib/state/state.dart'
show
searchQueryProvider,
@ -12,7 +19,6 @@ import 'package:openlib/state/state.dart'
fileType,
sortValues,
enableFiltersState;
import 'components/snack_bar_widget.dart';
class SearchPage extends ConsumerWidget {
const SearchPage({super.key});

View File

@ -1,22 +1,62 @@
// Dart imports:
import 'dart:io';
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
// Package imports:
import 'package:device_info_plus/device_info_plus.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:openlib/services/files.dart';
import 'package:permission_handler/permission_handler.dart';
// Project imports:
import 'package:openlib/services/database.dart';
import 'package:openlib/ui/about_page.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
import 'package:openlib/state/state.dart'
show
themeModeProvider,
openPdfWithExternalAppProvider,
openEpubWithExternalAppProvider,
dbProvider;
openEpubWithExternalAppProvider;
Future<void> requestStoragePermission() async {
bool permissionGranted = false;
// Check whether the device is running Android 11 or higher
DeviceInfoPlugin plugin = DeviceInfoPlugin();
AndroidDeviceInfo android = await plugin.androidInfo;
// Android < 11
if (android.version.sdkInt < 33) {
if (await Permission.storage.request().isGranted) {
permissionGranted = true;
} else if (await Permission.storage.request().isPermanentlyDenied) {
await openAppSettings();
}
}
// Android > 11
else {
if (await Permission.manageExternalStorage.request().isGranted) {
permissionGranted = true;
} else if (await Permission.manageExternalStorage
.request()
.isPermanentlyDenied) {
await openAppSettings();
} else if (await Permission.manageExternalStorage.request().isDenied) {
permissionGranted = false;
}
}
print("Storage permission status: $permissionGranted");
}
class SettingsPage extends ConsumerWidget {
const SettingsPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
MyLibraryDb dataBase = MyLibraryDb.instance;
return Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 10),
child: SingleChildScrollView(
@ -43,8 +83,7 @@ class SettingsPage extends ConsumerWidget {
onChanged: (bool value) {
ref.read(themeModeProvider.notifier).state =
value == true ? ThemeMode.dark : ThemeMode.light;
ref.read(dbProvider).savePreference('darkMode', value);
dataBase.savePreference('darkMode', value);
if (Platform.isAndroid) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor:
@ -71,9 +110,7 @@ class SettingsPage extends ConsumerWidget {
onChanged: (bool value) {
ref.read(openPdfWithExternalAppProvider.notifier).state =
value;
ref
.read(dbProvider)
.savePreference('openPdfwithExternalApp', value);
dataBase.savePreference('openPdfwithExternalApp', value);
},
)
],
@ -97,13 +134,37 @@ class SettingsPage extends ConsumerWidget {
onChanged: (bool value) {
ref.read(openEpubWithExternalAppProvider.notifier).state =
value;
ref
.read(dbProvider)
.savePreference('openEpubwithExternalApp', value);
dataBase.savePreference('openEpubwithExternalApp', value);
},
)
],
),
_PaddedContainer(
onClick: () async {
final currentDirectory =
await dataBase.getPreference('bookStorageDirectory');
String? pickedDirectory =
await FilePicker.platform.getDirectoryPath();
if (pickedDirectory == null) {
return;
}
await requestStoragePermission();
// Attempt moving existing books to the new directory
moveFolderContents(currentDirectory, pickedDirectory);
dataBase.savePreference(
'bookStorageDirectory', pickedDirectory);
},
children: [
Text(
"Change storage path",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.tertiary,
),
),
Icon(Icons.folder),
]),
_PaddedContainer(
onClick: () {
Navigator.push(context,

View File

@ -1,7 +1,12 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:openlib/ui/extensions.dart';
// Package imports:
import 'package:google_fonts/google_fonts.dart';
// Project imports:
import 'package:openlib/ui/extensions.dart';
ThemeData lightTheme = ThemeData(
primaryColor: Colors.white,
colorScheme: ColorScheme.light(

View File

@ -1,11 +1,16 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'extensions.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
// Package imports:
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// Project imports:
import 'package:openlib/ui/components/error_widget.dart';
import 'package:openlib/ui/components/page_title_widget.dart';
import 'package:openlib/ui/results_page.dart';
import 'extensions.dart';
import 'package:openlib/state/state.dart'
show getTrendingBooks, enableFiltersState;

View File

@ -1,11 +1,9 @@
// Flutter imports:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_cookie_manager/webview_cookie_manager.dart'
as cookiejar;
import 'package:openlib/state/state.dart'
show cookieProvider, userAgentProvider, dbProvider, bookInfoProvider;
// Package imports:
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class Webview extends ConsumerStatefulWidget {
const Webview({super.key, required this.url});
@ -16,9 +14,22 @@ class Webview extends ConsumerStatefulWidget {
}
class _WebviewState extends ConsumerState<Webview> {
WebViewController controller = WebViewController();
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
final urlController = TextEditingController();
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
final cookieManager = cookiejar.WebviewCookieManager();
@override
Widget build(BuildContext context) {
return Scaffold(
@ -27,47 +38,42 @@ class _WebviewState extends ConsumerState<Webview> {
title: const Text("Solve Captcha"),
),
body: SafeArea(
child: WebViewWidget(
controller: controller
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..loadRequest(Uri.parse(widget.url))
..getUserAgent().then((value) {
ref.read(userAgentProvider.notifier).state = value!;
ref.read(dbProvider).setBrowserOptions('userAgent', value);
})
..setNavigationDelegate(NavigationDelegate(
onPageStarted: (url) async {
var urlStatusCode = await controller.runJavaScriptReturningResult(
"var xhr = new XMLHttpRequest();xhr.open('GET', window.location.href, false);xhr.send(null);xhr.status;");
child: Column(
children: <Widget>[
Expanded(
child: Stack(
children: [
InAppWebView(
key: webViewKey,
initialUrlRequest: URLRequest(url: WebUri(widget.url)),
onWebViewCreated: (controller) {
webViewController = controller;
},
onLoadStart: (controller, url) {},
onLoadStop: (controller, url) async {
String query =
"""var paragraphTag=document.querySelector('p[class="mb-4 text-xl font-bold"]');var anchorTagHref=paragraphTag.querySelector('a').href;var url=()=>{return anchorTagHref};url();""";
String? mirrorLink = await webViewController
?.evaluateJavascript(source: query);
// final ipfsUrl = widget.url
// .replaceAll("slow_download", "ipfs_downloads")
// .replaceAll("/0/2", "");
if (urlStatusCode.toString().contains('200')) {
final cookies = await cookieManager
.getCookies("https://annas-archive.org");
List<String> cookie = [];
for (var element in cookies) {
if (element.name == 'cf_clearance' ||
element.name == 'cf_chl_2') {
cookie.add(element.toString().split(';')[0]);
}
}
String cfClearance = cookie.join('; ');
ref.read(cookieProvider.notifier).state = cfClearance;
await ref
.read(dbProvider)
.setBrowserOptions('cookie', cfClearance);
ref.invalidate(bookInfoProvider);
// ignore: use_build_context_synchronously
Navigator.pop(context);
}
},
)),
// await webViewController?.loadUrl(
// urlRequest: URLRequest(
// url: WebUri('https://example.com/new-page')));
if (mirrorLink != null) {
Future.delayed(const Duration(milliseconds: 70), () {
// ignore: use_build_context_synchronously
Navigator.pop(context, mirrorLink);
});
}
},
),
],
),
),
],
),
),
);

View File

@ -6,9 +6,13 @@
#include "generated_plugin_registrant.h"
#include <open_file_linux/open_file_linux_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) open_file_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "OpenFileLinuxPlugin");
open_file_linux_plugin_register_with_registrar(open_file_linux_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
open_file_linux
url_launcher_linux
)

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "ephemeral/Flutter-Generated.xcconfig"

View File

@ -5,11 +5,17 @@
import FlutterMacOS
import Foundation
import device_info_plus
import flutter_inappwebview_macos
import open_file_mac
import path_provider_foundation
import sqflite
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))

43
macos/Podfile Normal file
View File

@ -0,0 +1,43 @@
platform :osx, '10.14'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_macos_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_macos_build_settings(target)
end
end

49
macos/Podfile.lock Normal file
View File

@ -0,0 +1,49 @@
PODS:
- device_info_plus (0.0.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite (0.0.3):
- Flutter
- FlutterMacOS
- url_launcher_macos (0.0.1):
- FlutterMacOS
- webview_flutter_wkwebview (0.0.1):
- Flutter
- FlutterMacOS
DEPENDENCIES:
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- sqflite (from `Flutter/ephemeral/.symlinks/plugins/sqflite/darwin`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- webview_flutter_wkwebview (from `Flutter/ephemeral/.symlinks/plugins/webview_flutter_wkwebview/darwin`)
EXTERNAL SOURCES:
device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
FlutterMacOS:
:path: Flutter/ephemeral
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
sqflite:
:path: Flutter/ephemeral/.symlinks/plugins/sqflite/darwin
url_launcher_macos:
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
webview_flutter_wkwebview:
:path: Flutter/ephemeral/.symlinks/plugins/webview_flutter_wkwebview/darwin
SPEC CHECKSUMS:
device_info_plus: ce1b7762849d3ec103d0e0517299f2db7ad60720
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
url_launcher_macos: 5f437abeda8c85500ceb03f5c1938a8c5a705399
webview_flutter_wkwebview: 0982481e3d9c78fd5c6f62a002fcd24fc791f1e4
PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
COCOAPODS: 1.15.2

View File

@ -27,6 +27,8 @@
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
94DC8CF5FF5142DBE4D793D5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F4FBA8BD682AFDC387908E5 /* Pods_Runner.framework */; };
C7F7B62346249DBF21B09589 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 597839FED6E06332F68C6ADA /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -60,11 +62,15 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
026D244AA1C7FAEB6738F1E2 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
0C77C89AD60C9098EEDED45D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
0F4FBA8BD682AFDC387908E5 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1A522043CF646715895EA782 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* libgen.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "libgen.app"; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* libgen.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = libgen.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@ -76,8 +82,12 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
4CC42A086113EDD186C59134 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
597839FED6E06332F68C6ADA /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
B3FD517C4809A4AF4328C1B7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
BE75E83973607FF4034DF300 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -85,6 +95,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C7F7B62346249DBF21B09589 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -92,6 +103,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
94DC8CF5FF5142DBE4D793D5 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -125,6 +137,7 @@
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
F9274C19F91F0638504DB3B3 /* Pods */,
);
sourceTree = "<group>";
};
@ -175,10 +188,26 @@
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
0F4FBA8BD682AFDC387908E5 /* Pods_Runner.framework */,
597839FED6E06332F68C6ADA /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
F9274C19F91F0638504DB3B3 /* Pods */ = {
isa = PBXGroup;
children = (
B3FD517C4809A4AF4328C1B7 /* Pods-Runner.debug.xcconfig */,
1A522043CF646715895EA782 /* Pods-Runner.release.xcconfig */,
0C77C89AD60C9098EEDED45D /* Pods-Runner.profile.xcconfig */,
026D244AA1C7FAEB6738F1E2 /* Pods-RunnerTests.debug.xcconfig */,
BE75E83973607FF4034DF300 /* Pods-RunnerTests.release.xcconfig */,
4CC42A086113EDD186C59134 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -186,6 +215,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
EAFD152091A84CC666BC9C95 /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
@ -204,11 +234,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
B03B73F3042AD92BAE2F1724 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
A920CB9F33F83AF0095EB7FC /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -227,7 +259,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
@ -328,6 +360,67 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
A920CB9F33F83AF0095EB7FC /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
B03B73F3042AD92BAE2F1724 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
EAFD152091A84CC666BC9C95 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -379,6 +472,7 @@
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 026D244AA1C7FAEB6738F1E2 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@ -393,6 +487,7 @@
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BE75E83973607FF4034DF300 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@ -407,6 +502,7 @@
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 4CC42A086113EDD186C59134 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@ -4,4 +4,7 @@
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,7 +1,7 @@
import Cocoa
import FlutterMacOS
@NSApplicationMain
@main
class AppDelegate: FlutterAppDelegate {
override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true

View File

@ -8,5 +8,7 @@
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View File

@ -4,5 +4,7 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View File

@ -5,18 +5,18 @@ packages:
dependency: transitive
description:
name: archive
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d"
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.dev"
source: hosted
version: "3.4.10"
version: "3.6.1"
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
version: "2.5.0"
async:
dependency: transitive
description:
@ -97,22 +97,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
convert:
cross_file:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
name: cross_file
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
version: "0.3.4+2"
crypto:
dependency: "direct main"
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27
url: "https://pub.dev"
source: hosted
version: "3.0.3"
version: "3.0.5"
csslib:
dependency: transitive
description:
@ -125,10 +125,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
url: "https://pub.dev"
source: hosted
version: "1.0.6"
version: "1.0.8"
dev:
dependency: "direct main"
description:
@ -137,14 +137,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
device_info_plus:
dependency: "direct main"
description:
name: device_info_plus
sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074
url: "https://pub.dev"
source: hosted
version: "10.1.2"
device_info_plus_platform_interface:
dependency: transitive
description:
name: device_info_plus_platform_interface
sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba"
url: "https://pub.dev"
source: hosted
version: "7.0.1"
dio:
dependency: "direct main"
description:
name: dio
sha256: "797e1e341c3dd2f69f2dad42564a6feff3bfb87187d05abb93b9609e6f1645c3"
sha256: "0dfb6b6a1979dac1c1245e17cef824d7b452ea29bd33d3467269f9bef3715fb0"
url: "https://pub.dev"
source: hosted
version: "5.4.0"
version: "5.6.0"
dio_web_adapter:
dependency: transitive
description:
name: dio_web_adapter
sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
epub_view:
dependency: "direct main"
description:
@ -181,10 +205,10 @@ packages:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
version: "2.1.3"
file:
dependency: transitive
description:
@ -193,6 +217,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.0"
file_picker:
dependency: "direct main"
description:
name: file_picker
sha256: "167bb619cdddaa10ef2907609feb8a79c16dfa479d3afaf960f8e223f754bf12"
url: "https://pub.dev"
source: hosted
version: "8.1.2"
fixnum:
dependency: transitive
description:
@ -210,10 +242,10 @@ packages:
dependency: transitive
description:
name: flutter_cache_manager
sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
url: "https://pub.dev"
source: hosted
version: "3.3.1"
version: "3.4.1"
flutter_html:
dependency: transitive
description:
@ -222,6 +254,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0-beta.2"
flutter_inappwebview:
dependency: "direct main"
description:
name: flutter_inappwebview
sha256: "3e9a443a18ecef966fb930c3a76ca5ab6a7aafc0c7b5e14a4a850cf107b09959"
url: "https://pub.dev"
source: hosted
version: "6.0.0"
flutter_inappwebview_android:
dependency: transitive
description:
name: flutter_inappwebview_android
sha256: d247f6ed417f1f8c364612fa05a2ecba7f775c8d0c044c1d3b9ee33a6515c421
url: "https://pub.dev"
source: hosted
version: "1.0.13"
flutter_inappwebview_internal_annotations:
dependency: transitive
description:
name: flutter_inappwebview_internal_annotations
sha256: "5f80fd30e208ddded7dbbcd0d569e7995f9f63d45ea3f548d8dd4c0b473fb4c8"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
flutter_inappwebview_ios:
dependency: transitive
description:
name: flutter_inappwebview_ios
sha256: f363577208b97b10b319cd0c428555cd8493e88b468019a8c5635a0e4312bd0f
url: "https://pub.dev"
source: hosted
version: "1.0.13"
flutter_inappwebview_macos:
dependency: transitive
description:
name: flutter_inappwebview_macos
sha256: b55b9e506c549ce88e26580351d2c71d54f4825901666bd6cfa4be9415bb2636
url: "https://pub.dev"
source: hosted
version: "1.0.11"
flutter_inappwebview_platform_interface:
dependency: transitive
description:
name: flutter_inappwebview_platform_interface
sha256: "545fd4c25a07d2775f7d5af05a979b2cac4fbf79393b0a7f5d33ba39ba4f6187"
url: "https://pub.dev"
source: hosted
version: "1.0.10"
flutter_inappwebview_web:
dependency: transitive
description:
name: flutter_inappwebview_web
sha256: d8c680abfb6fec71609a700199635d38a744df0febd5544c5a020bd73de8ee07
url: "https://pub.dev"
source: hosted
version: "1.0.8"
flutter_launcher_icons:
dependency: "direct dev"
description:
@ -234,10 +322,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
flutter_pdfview:
dependency: "direct main"
description:
@ -246,22 +334,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.2"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda"
url: "https://pub.dev"
source: hosted
version: "2.0.22"
flutter_riverpod:
dependency: "direct main"
description:
name: flutter_riverpod
sha256: "4bce556b7ecbfea26109638d5237684538d4abc509d253e6c5c4c5733b360098"
sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d"
url: "https://pub.dev"
source: hosted
version: "2.4.10"
version: "2.5.1"
flutter_svg:
dependency: "direct main"
description:
name: flutter_svg
sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c
sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2"
url: "https://pub.dev"
source: hosted
version: "2.0.9"
version: "2.0.10+1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -284,10 +380,10 @@ packages:
dependency: "direct main"
description:
name: google_fonts
sha256: f0b8d115a13ecf827013ec9fc883390ccc0e87a96ed5347a3114cac177ef18e8
sha256: b1ac0fe2832c9cc95e5e88b57d627c5e68c223b9657f4b96e1487aa9098c7b82
url: "https://pub.dev"
source: hosted
version: "6.1.0"
version: "6.2.1"
google_nav_bar:
dependency: "direct main"
description:
@ -308,10 +404,10 @@ packages:
dependency: transitive
description:
name: http
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010
url: "https://pub.dev"
source: hosted
version: "1.2.0"
version: "1.2.2"
http_parser:
dependency: transitive
description:
@ -328,6 +424,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.0"
import_sorter:
dependency: "direct dev"
description:
name: import_sorter
sha256: eb15738ccead84e62c31e0208ea4e3104415efcd4972b86906ca64a1187d0836
url: "https://pub.dev"
source: hosted
version: "4.6.0"
js:
dependency: transitive
description:
@ -340,10 +444,34 @@ packages:
dependency: transitive
description:
name: json_annotation
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.dev"
source: hosted
version: "4.8.1"
version: "4.9.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
url: "https://pub.dev"
source: hosted
version: "10.0.5"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
url: "https://pub.dev"
source: hosted
version: "3.0.5"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
@ -364,50 +492,106 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.dev"
source: hosted
version: "0.12.16"
version: "0.12.16+1"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev"
source: hosted
version: "0.5.0"
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.dev"
source: hosted
version: "1.10.0"
version: "1.15.0"
octo_image:
dependency: transitive
description:
name: octo_image
sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d"
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
version: "2.1.0"
open_file:
dependency: "direct main"
description:
name: open_file
sha256: a5a32d44acb7c899987d0999e1e3cbb0a0f1adebbf41ac813ec6d2d8faa0af20
sha256: de371f549b1320a48980952473fae1903d4927975506534c8ea4643642eb5f98
url: "https://pub.dev"
source: hosted
version: "3.3.2"
version: "3.5.3"
open_file_android:
dependency: transitive
description:
name: open_file_android
sha256: b5e1a2e9c5ea8e256b015403e94299039627c7205c2a5e6bb426c33235b6ca9a
url: "https://pub.dev"
source: hosted
version: "1.0.2"
open_file_ios:
dependency: transitive
description:
name: open_file_ios
sha256: "8d9c03495cf14ca70bdbf191894b822ba3b2629cc0046ee311cbbe504db66c44"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
open_file_linux:
dependency: transitive
description:
name: open_file_linux
sha256: cd2088722048b9c40f8615c6d83005fe0726e0e447e9cdfb40c2b65477291f7d
url: "https://pub.dev"
source: hosted
version: "0.0.4"
open_file_mac:
dependency: transitive
description:
name: open_file_mac
sha256: "9d809f528cccc6dc9390caf50893eae9a6944e0f3b8a2558c7ad19e91c9244a1"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
open_file_platform_interface:
dependency: transitive
description:
name: open_file_platform_interface
sha256: "14c50efb1a9667cb96e4fa68d601e6ad348fe337b02789834029b37ae3631498"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
open_file_web:
dependency: transitive
description:
name: open_file_web
sha256: ba35c6f38c21c2bb4268a80927bb828353dda0edfce92e274e0b9639e4f31360
url: "https://pub.dev"
source: hosted
version: "0.0.2"
open_file_windows:
dependency: transitive
description:
name: open_file_windows
sha256: "2f4318d2d3958ec8d63b6dd4430c15b1fcb2fe7a2113e83c734584501a5c6d81"
url: "https://pub.dev"
source: hosted
version: "0.0.2"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
version: "1.9.0"
path_parsing:
dependency: transitive
description:
@ -420,26 +604,26 @@ packages:
dependency: "direct main"
description:
name: path_provider
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378
url: "https://pub.dev"
source: hosted
version: "2.1.2"
version: "2.1.4"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7"
url: "https://pub.dev"
source: hosted
version: "2.2.2"
version: "2.2.10"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
url: "https://pub.dev"
source: hosted
version: "2.3.2"
version: "2.4.0"
path_provider_linux:
dependency: transitive
description:
@ -460,50 +644,50 @@ packages:
dependency: transitive
description:
name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.dev"
source: hosted
version: "2.2.1"
version: "2.3.0"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: "45ff3fbcb99040fde55c528d5e3e6ca29171298a85436274d49c6201002087d6"
sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
url: "https://pub.dev"
source: hosted
version: "11.2.0"
version: "11.3.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "758284a0976772f9c744d6384fc5dc4834aa61e3f7aa40492927f244767374eb"
sha256: "76e4ab092c1b240d31177bb64d2b0bea43f43d0e23541ec866151b9f7b2490fa"
url: "https://pub.dev"
source: hosted
version: "12.0.3"
version: "12.0.12"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: c6bf440f80acd2a873d3d91a699e4cc770f86e7e6b576dda98759e8b92b39830
sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0
url: "https://pub.dev"
source: hosted
version: "9.3.0"
version: "9.4.5"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
sha256: af26edbbb1f2674af65a8f4b56e1a6f526156bc273d0e65dd8075fab51c78851
url: "https://pub.dev"
source: hosted
version: "0.1.1"
version: "0.1.3+2"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: "5c43148f2bfb6d14c5a8162c0a712afe891f2d847f35fcff29c406b37da43c3c"
sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea
url: "https://pub.dev"
source: hosted
version: "4.1.0"
version: "4.2.2"
permission_handler_windows:
dependency: transitive
description:
@ -524,10 +708,10 @@ packages:
dependency: transitive
description:
name: platform
sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
url: "https://pub.dev"
source: hosted
version: "3.1.4"
version: "3.1.5"
plugin_platform_interface:
dependency: transitive
description:
@ -536,38 +720,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.8"
pointycastle:
dependency: transitive
description:
name: pointycastle
sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29"
url: "https://pub.dev"
source: hosted
version: "3.7.4"
quiver:
dependency: transitive
description:
name: quiver
sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47
sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2
url: "https://pub.dev"
source: hosted
version: "3.2.1"
version: "3.2.2"
riverpod:
dependency: transitive
description:
name: riverpod
sha256: "548e2192eb7aeb826eb89387f814edb76594f3363e2c0bb99dd733d795ba3589"
sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d
url: "https://pub.dev"
source: hosted
version: "2.5.0"
version: "2.5.1"
rxdart:
dependency: transitive
description:
name: rxdart
sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962"
url: "https://pub.dev"
source: hosted
version: "0.27.7"
version: "0.28.0"
scrollable_positioned_list:
dependency: transitive
description:
@ -601,34 +777,34 @@ packages:
dependency: "direct main"
description:
name: sqflite
sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6
sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d
url: "https://pub.dev"
source: hosted
version: "2.3.2"
version: "2.3.3+1"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5"
sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e"
url: "https://pub.dev"
source: hosted
version: "2.5.3"
version: "2.5.4+2"
sqflite_common_ffi:
dependency: "direct main"
description:
name: sqflite_common_ffi
sha256: "754927d82de369a6b9e760fb60640aa81da650f35ffd468d5a992814d6022908"
sha256: "4d6137c29e930d6e4a8ff373989dd9de7bac12e3bc87bce950f6e844e8ad3bb5"
url: "https://pub.dev"
source: hosted
version: "2.3.2+1"
version: "2.3.3"
sqlite3:
dependency: transitive
description:
name: sqlite3
sha256: c4a4c5a4b2a32e2d0f6837b33d7c91a67903891a5b7dbe706cf4b1f6b0c798c5
sha256: "45f168ae2213201b54e09429ed0c593dc2c88c924a1488d6f9c523a255d567cb"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
version: "2.4.6"
stack_trace:
dependency: transitive
description:
@ -665,10 +841,10 @@ packages:
dependency: transitive
description:
name: synchronized
sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255
url: "https://pub.dev"
source: hosted
version: "3.1.0+1"
version: "3.2.0"
term_glyph:
dependency: transitive
description:
@ -681,10 +857,18 @@ packages:
dependency: transitive
description:
name: test_api
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
url: "https://pub.dev"
source: hosted
version: "0.6.1"
version: "0.7.2"
tint:
dependency: transitive
description:
name: tint
sha256: "9652d9a589f4536d5e392cf790263d120474f15da3cf1bee7f1fdb31b4de5f46"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
typed_data:
dependency: transitive
description:
@ -705,98 +889,98 @@ packages:
dependency: "direct main"
description:
name: url_launcher
sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c
sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
url: "https://pub.dev"
source: hosted
version: "6.2.4"
version: "6.3.0"
url_launcher_android:
dependency: transitive
description:
name: url_launcher_android
sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f"
sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab
url: "https://pub.dev"
source: hosted
version: "6.2.2"
version: "6.3.10"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03"
sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e
url: "https://pub.dev"
source: hosted
version: "6.2.4"
version: "6.3.1"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811
sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af
url: "https://pub.dev"
source: hosted
version: "3.1.1"
version: "3.2.0"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234
sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
version: "3.2.0"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
version: "2.3.2"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
url: "https://pub.dev"
source: hosted
version: "2.2.3"
version: "2.3.3"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7
sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
version: "3.1.2"
uuid:
dependency: transitive
description:
name: uuid
sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8
sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77
url: "https://pub.dev"
source: hosted
version: "4.3.3"
version: "4.5.0"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
sha256: "18f6690295af52d081f6808f2f7c69f0eed6d7e23a71539d75f4aeb8f0062172"
sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3"
url: "https://pub.dev"
source: hosted
version: "1.1.9+2"
version: "1.1.11+1"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: "531d20465c10dfac7f5cd90b60bbe4dd9921f1ec4ca54c83ebb176dbacb7bb2d"
sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da
url: "https://pub.dev"
source: hosted
version: "1.1.9+2"
version: "1.1.11+1"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "03012b0a33775c5530576b70240308080e1d5050f0faf000118c20e6463bc0ad"
sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81"
url: "https://pub.dev"
source: hosted
version: "1.1.9+2"
version: "1.1.11+1"
vector_math:
dependency: transitive
description:
@ -805,70 +989,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
vocsy_epub_viewer:
dependency: "direct main"
vm_service:
dependency: transitive
description:
name: vocsy_epub_viewer
sha256: "30aab4a5be22e8c98f22fed3345f6989caaca861178c38cab2a8b8cd66ad53de"
name: vm_service
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
version: "14.2.5"
web:
dependency: transitive
description:
name: web
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
url: "https://pub.dev"
source: hosted
version: "0.3.0"
webview_cookie_manager:
dependency: "direct main"
description:
name: webview_cookie_manager
sha256: "425a9feac5cd2cb62a71da3dda5ac2eaf9ece5481ee8d79f3868dc5ba8223ad3"
url: "https://pub.dev"
source: hosted
version: "2.0.6"
webview_flutter:
dependency: "direct main"
description:
name: webview_flutter
sha256: d81b68e88cc353e546afb93fb38958e3717282c5ac6e5d3be4a4aef9fc3c1413
url: "https://pub.dev"
source: hosted
version: "4.5.0"
webview_flutter_android:
dependency: transitive
description:
name: webview_flutter_android
sha256: "4ea3c4e1b8ed590162b15b8a61b41b1ef3ff179a314627c16ce40c086d94b8af"
url: "https://pub.dev"
source: hosted
version: "3.14.0"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
url: "https://pub.dev"
source: hosted
version: "2.10.0"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: b99ca8d8bae9c6b43d568218691aa537fb0aeae1d7d34eadf112a6aa36d26506
url: "https://pub.dev"
source: hosted
version: "3.11.0"
version: "1.0.0"
win32:
dependency: transitive
description:
name: win32
sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a"
url: "https://pub.dev"
source: hosted
version: "5.2.0"
version: "5.5.4"
win32_registry:
dependency: transitive
description:
name: win32_registry
sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6"
url: "https://pub.dev"
source: hosted
version: "1.1.4"
xdg_directories:
dependency: transitive
description:
@ -894,5 +1046,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.2.3 <4.0.0"
flutter: ">=3.16.6"
dart: ">=3.5.0 <4.0.0"
flutter: ">=3.24.0"

View File

@ -1,8 +1,8 @@
name: openlib
description: An Open source app to download and read books from shadow library (Anna`s Archive)
description: An Open source app to download and read books from shadow library (Anna`s Archive)
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
publish_to: "none" # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
@ -16,10 +16,10 @@ 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.5+8
version: 1.0.8+11
environment:
sdk: '>=3.0.5 <4.0.0'
sdk: ">=3.3.0 <4.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
@ -35,7 +35,6 @@ dependencies:
google_nav_bar: ^5.0.6
flutter_pdfview: ^1.2.7
vocsy_epub_viewer: ^2.0.0
epub_view: ^3.2.0
# syncfusion_flutter_pdfviewer: ^22.2.5
# pdfx: ^2.4.0
@ -47,8 +46,6 @@ dependencies:
path_provider: ^2.0.15
permission_handler: ^11.2.0
open_file: ^3.3.2
webview_flutter: ^4.4.1
webview_cookie_manager: ^2.0.6
flutter_svg: ^2.0.7
google_fonts: ^6.1.0
@ -62,8 +59,12 @@ dependencies:
cupertino_icons: ^1.0.2
dev: ^1.0.0
crypto: ^3.0.3
file_picker: ^8.1.2
device_info_plus: ^10.1.2
flutter_inappwebview: ^6.0.0
dev_dependencies:
import_sorter: ^4.6.0
flutter_test:
sdk: flutter
@ -75,7 +76,6 @@ dev_dependencies:
# rules and activating additional ones.
flutter_lints: ^3.0.1
flutter_icons:
android: "launcher_icon"
ios: true
@ -86,7 +86,6 @@ flutter_icons:
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
@ -124,4 +123,4 @@ flutter:
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
# see https://flutter.dev/custom-fonts/#from-packages

View File

@ -5,9 +5,13 @@
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
// Flutter imports:
import 'package:flutter/material.dart';
// Package imports:
import 'package:flutter_test/flutter_test.dart';
// Project imports:
import 'package:openlib/main.dart';
void main() {

View File

@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake)
# https://github.com/flutter/flutter/issues/57146.
set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
# Set fallback configurations for older versions of the flutter tool.
if (NOT DEFINED FLUTTER_TARGET_PLATFORM)
set(FLUTTER_TARGET_PLATFORM "windows-x64")
endif()
# === Flutter Library ===
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
@ -92,7 +97,7 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
windows-x64 $<CONFIG>
${FLUTTER_TARGET_PLATFORM} $<CONFIG>
VERBATIM
)
add_custom_target(flutter_assemble DEPENDS