mirror of
https://github.com/dstark5/Openlib.git
synced 2025-08-06 15:18:54 +08:00
Fixed "no mirror found" and "always redirected to captcha" issues
This commit is contained in:
@ -25,7 +25,8 @@
|
|||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:networkSecurityConfig="@xml/network_security_config"
|
android:networkSecurityConfig="@xml/network_security_config"
|
||||||
android:icon="@mipmap/launcher_icon">
|
android:icon="@mipmap/launcher_icon"
|
||||||
|
android:enableOnBackInvokedCallback="true">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
@ -25,6 +25,7 @@ import 'package:openlib/state/state.dart'
|
|||||||
selectedIndexProvider,
|
selectedIndexProvider,
|
||||||
themeModeProvider,
|
themeModeProvider,
|
||||||
openPdfWithExternalAppProvider,
|
openPdfWithExternalAppProvider,
|
||||||
|
openEpubWithExternalAppProvider,
|
||||||
userAgentProvider,
|
userAgentProvider,
|
||||||
cookieProvider;
|
cookieProvider;
|
||||||
|
|
||||||
@ -46,6 +47,13 @@ void main() async {
|
|||||||
? false
|
? false
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
|
bool openEpubwithExternalapp = await dataBase
|
||||||
|
.getPreference('openEpubwithExternalApp')
|
||||||
|
.catchError((e) => print(e)) ==
|
||||||
|
0
|
||||||
|
? false
|
||||||
|
: true;
|
||||||
|
|
||||||
String browserUserAgent = await dataBase.getBrowserOptions('userAgent');
|
String browserUserAgent = await dataBase.getBrowserOptions('userAgent');
|
||||||
String browserCookie = await dataBase.getBrowserOptions('cookie');
|
String browserCookie = await dataBase.getBrowserOptions('cookie');
|
||||||
|
|
||||||
@ -64,6 +72,8 @@ void main() async {
|
|||||||
(ref) => isDarkMode ? ThemeMode.dark : ThemeMode.light),
|
(ref) => isDarkMode ? ThemeMode.dark : ThemeMode.light),
|
||||||
openPdfWithExternalAppProvider
|
openPdfWithExternalAppProvider
|
||||||
.overrideWith((ref) => openPdfwithExternalapp),
|
.overrideWith((ref) => openPdfwithExternalapp),
|
||||||
|
openEpubWithExternalAppProvider
|
||||||
|
.overrideWith((ref) => openEpubwithExternalapp),
|
||||||
userAgentProvider.overrideWith((ref) => browserUserAgent),
|
userAgentProvider.overrideWith((ref) => browserUserAgent),
|
||||||
cookieProvider.overrideWith((ref) => browserCookie),
|
cookieProvider.overrideWith((ref) => browserCookie),
|
||||||
],
|
],
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Dart imports:
|
// Dart imports:
|
||||||
import 'dart:convert';
|
// import 'dart:convert';
|
||||||
|
|
||||||
// Flutter imports:
|
// Flutter imports:
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -28,7 +28,7 @@ class BookData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BookInfoData extends BookData {
|
class BookInfoData extends BookData {
|
||||||
final List<String>? mirrors;
|
String? mirror;
|
||||||
final String? description;
|
final String? description;
|
||||||
final String? format;
|
final String? format;
|
||||||
|
|
||||||
@ -40,13 +40,13 @@ class BookInfoData extends BookData {
|
|||||||
required super.info,
|
required super.info,
|
||||||
required super.link,
|
required super.link,
|
||||||
required super.md5,
|
required super.md5,
|
||||||
required this.mirrors,
|
|
||||||
required this.format,
|
required this.format,
|
||||||
|
required this.mirror,
|
||||||
required this.description});
|
required this.description});
|
||||||
}
|
}
|
||||||
|
|
||||||
class AnnasArchieve {
|
class AnnasArchieve {
|
||||||
String baseUrl = "https://annas-archive.org";
|
static const String baseUrl = "https://annas-archive.org";
|
||||||
|
|
||||||
final Dio dio = Dio();
|
final Dio dio = Dio();
|
||||||
|
|
||||||
@ -131,65 +131,82 @@ class AnnasArchieve {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> _getMirrorLink(
|
// Future<String?> _getMirrorLink(
|
||||||
String url, String userAgent, String cookie) async {
|
// String url, String userAgent, String cookie) async {
|
||||||
try {
|
// try {
|
||||||
final response = await dio.get(url,
|
// final response = await dio.get(url,
|
||||||
options: Options(extra: {
|
// options: Options(extra: {
|
||||||
'withCredentials': true
|
// 'withCredentials': true
|
||||||
}, headers: {
|
// }, headers: {
|
||||||
"Host": "annas-archive.org",
|
// "Host": "annas-archive.org",
|
||||||
"Origin": "https://annas-archive.org",
|
// "Origin": baseUrl,
|
||||||
"Upgrade-Insecure-Requests": "1",
|
// "Upgrade-Insecure-Requests": "1",
|
||||||
"Sec-Fetch-Dest": "secure",
|
// "Sec-Fetch-Dest": "secure",
|
||||||
"Sec-Fetch-Mode": "navigate",
|
// "Sec-Fetch-Mode": "navigate",
|
||||||
"Sec-Fetch-Site": "same-site",
|
// "Sec-Fetch-Site": "same-site",
|
||||||
"Cookie": cookie,
|
// "Cookie": cookie,
|
||||||
"User-Agent": userAgent
|
// "User-Agent": userAgent
|
||||||
}));
|
// }));
|
||||||
|
|
||||||
var document = parse(response.data.toString());
|
// var document = parse(response.data.toString());
|
||||||
|
|
||||||
var pTag = document.querySelectorAll('p[class="mb-4"]');
|
// var pTag = document.querySelectorAll('p[class="mb-4"]');
|
||||||
String? link = pTag[1].querySelector('a')?.attributes['href'];
|
// String? link = pTag[1].querySelector('a')?.attributes['href'];
|
||||||
return link;
|
// return link;
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
// print('${url} ${e}');
|
// // print('${url} ${e}');
|
||||||
if (e.toString().contains("403")) {
|
// if (e.toString().contains("403")) {
|
||||||
throw jsonEncode({"code": "403", "url": url});
|
// throw jsonEncode({"code": "403", "url": url});
|
||||||
}
|
// }
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Future<BookInfoData?> _bookInfoParser(resData, url, userAgent, cookie) async {
|
Future<BookInfoData?> _bookInfoParser(resData, url) async {
|
||||||
var document = parse(resData.toString());
|
var document = parse(resData.toString());
|
||||||
var main = document.querySelector('main[class="main"]');
|
var main = document.querySelector('main[class="main"]');
|
||||||
var ul = main?.querySelectorAll('ul[class="list-inside mb-4 ml-1"]');
|
var ul = main?.querySelectorAll('ul[class="list-inside mb-4 ml-1"]');
|
||||||
|
|
||||||
List<String> mirrors = [];
|
// List<String> mirrors = [];
|
||||||
|
|
||||||
if (ul != null) {
|
// 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 = [];
|
var anchorTags = [];
|
||||||
|
|
||||||
|
if (ul != null) {
|
||||||
for (var e in ul) {
|
for (var e in ul) {
|
||||||
anchorTags.insertAll(0, e.querySelectorAll('a'));
|
anchorTags.insertAll(0, e.querySelectorAll('a'));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var element in anchorTags) {
|
for (var element in anchorTags) {
|
||||||
if (element.attributes['href'] != null &&
|
if (element.attributes['href'] != null &&
|
||||||
element.attributes['href']!.startsWith('/slow_download')) {
|
element.attributes['href']!.startsWith('/slow_download') &&
|
||||||
String? url = await _getMirrorLink(
|
element.attributes['href']!.endsWith('/2')) {
|
||||||
'$baseUrl${element.attributes['href']!}', userAgent, cookie);
|
mirror = '$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']!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,8 +223,9 @@ class AnnasArchieve {
|
|||||||
main?.querySelector('div[class="text-sm text-gray-500"]')?.text ?? '',
|
main?.querySelector('div[class="text-sm text-gray-500"]')?.text ?? '',
|
||||||
'description': main
|
'description': main
|
||||||
?.querySelector(
|
?.querySelector(
|
||||||
'div[class="mt-4 line-clamp-[5] js-md5-top-box-description"]')
|
'div[class="mt-4 line-clamp-[8] js-md5-top-box-description"]')
|
||||||
?.text ??
|
?.text
|
||||||
|
.replaceFirst("description", '') ??
|
||||||
" "
|
" "
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -232,7 +250,7 @@ class AnnasArchieve {
|
|||||||
link: data['link'],
|
link: data['link'],
|
||||||
md5: getMd5(data['link'].toString()),
|
md5: getMd5(data['link'].toString()),
|
||||||
format: getFormat(data['info']),
|
format: getFormat(data['info']),
|
||||||
mirrors: mirrors,
|
mirror: mirror,
|
||||||
description: data['description'],
|
description: data['description'],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
@ -282,15 +300,11 @@ class AnnasArchieve {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<BookInfoData> bookInfo(
|
Future<BookInfoData> bookInfo({required String url}) async {
|
||||||
{required String url,
|
|
||||||
required String userAgent,
|
|
||||||
required String cookie}) async {
|
|
||||||
try {
|
try {
|
||||||
final response =
|
final response =
|
||||||
await dio.get(url, options: Options(headers: defaultDioHeaders));
|
await dio.get(url, options: Options(headers: defaultDioHeaders));
|
||||||
BookInfoData? data =
|
BookInfoData? data = await _bookInfoParser(response.data, url);
|
||||||
await _bookInfoParser(response.data, url, userAgent, cookie);
|
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,14 +105,13 @@ final searchProvider = FutureProvider.family
|
|||||||
final cookieProvider = StateProvider<String>((ref) => "");
|
final cookieProvider = StateProvider<String>((ref) => "");
|
||||||
final userAgentProvider = StateProvider<String>((ref) => "");
|
final userAgentProvider = StateProvider<String>((ref) => "");
|
||||||
|
|
||||||
|
final webViewLoadingState = StateProvider.autoDispose<bool>((ref) => true);
|
||||||
|
|
||||||
//Provider for Book Info
|
//Provider for Book Info
|
||||||
final bookInfoProvider =
|
final bookInfoProvider =
|
||||||
FutureProvider.family<BookInfoData, String>((ref, url) async {
|
FutureProvider.family<BookInfoData, String>((ref, url) async {
|
||||||
AnnasArchieve annasArchieve = AnnasArchieve();
|
AnnasArchieve annasArchieve = AnnasArchieve();
|
||||||
BookInfoData data = await annasArchieve.bookInfo(
|
BookInfoData data = await annasArchieve.bookInfo(url: url);
|
||||||
url: url,
|
|
||||||
userAgent: ref.read(userAgentProvider),
|
|
||||||
cookie: ref.read(cookieProvider));
|
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -194,6 +193,7 @@ final getBookPosition =
|
|||||||
});
|
});
|
||||||
|
|
||||||
final openPdfWithExternalAppProvider = StateProvider<bool>((ref) => false);
|
final openPdfWithExternalAppProvider = StateProvider<bool>((ref) => false);
|
||||||
|
final openEpubWithExternalAppProvider = StateProvider<bool>((ref) => false);
|
||||||
|
|
||||||
final filePathProvider =
|
final filePathProvider =
|
||||||
FutureProvider.family<String, String>((ref, fileName) async {
|
FutureProvider.family<String, String>((ref, fileName) async {
|
||||||
|
@ -47,7 +47,7 @@ class AboutPage extends StatelessWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(left: 7, right: 7, top: 5),
|
padding: EdgeInsets.only(left: 7, right: 7, top: 5),
|
||||||
child: Text(
|
child: Text(
|
||||||
"1.0.6",
|
"1.0.7",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// Dart imports:
|
// Dart imports:
|
||||||
import 'dart:convert';
|
// import 'dart:convert';
|
||||||
|
|
||||||
// Flutter imports:
|
// Flutter imports:
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
// import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
// Package imports:
|
// Package imports:
|
||||||
import 'package:dio/dio.dart' show CancelToken;
|
import 'package:dio/dio.dart' show CancelToken;
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:flutter_svg/svg.dart';
|
// import 'package:flutter_svg/svg.dart';
|
||||||
|
|
||||||
// Project imports:
|
// Project imports:
|
||||||
import 'package:openlib/services/annas_archieve.dart' show BookInfoData;
|
import 'package:openlib/services/annas_archieve.dart' show BookInfoData;
|
||||||
@ -58,82 +58,82 @@ class BookInfoPage extends ConsumerWidget {
|
|||||||
data: data, child: ActionButtonWidget(data: data));
|
data: data, child: ActionButtonWidget(data: data));
|
||||||
},
|
},
|
||||||
error: (err, _) {
|
error: (err, _) {
|
||||||
if (err.toString().contains("403")) {
|
// if (err.toString().contains("403")) {
|
||||||
var errJson = jsonDecode(err.toString());
|
// var errJson = jsonDecode(err.toString());
|
||||||
|
|
||||||
if (SchedulerBinding.instance.schedulerPhase ==
|
// if (SchedulerBinding.instance.schedulerPhase ==
|
||||||
SchedulerPhase.persistentCallbacks) {
|
// SchedulerPhase.persistentCallbacks) {
|
||||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
// SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
Future.delayed(
|
// Future.delayed(
|
||||||
const Duration(seconds: 3),
|
// const Duration(seconds: 3),
|
||||||
() => Navigator.pushReplacement(context,
|
// () => Navigator.pushReplacement(context,
|
||||||
MaterialPageRoute(builder: (BuildContext context) {
|
// MaterialPageRoute(builder: (BuildContext context) {
|
||||||
return Webview(url: errJson["url"]);
|
// return Webview(url: errJson["url"]);
|
||||||
})));
|
// })));
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
return Column(
|
// return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
// mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
// crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
// children: [
|
||||||
SizedBox(
|
// SizedBox(
|
||||||
width: 210,
|
// width: 210,
|
||||||
child: SvgPicture.asset(
|
// child: SvgPicture.asset(
|
||||||
'assets/captcha.svg',
|
// 'assets/captcha.svg',
|
||||||
width: 210,
|
// width: 210,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
const SizedBox(
|
// const SizedBox(
|
||||||
height: 30,
|
// height: 30,
|
||||||
),
|
// ),
|
||||||
Text(
|
// Text(
|
||||||
"Captcha required",
|
// "Captcha required",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 18,
|
// fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
color: Theme.of(context).textTheme.headlineMedium?.color,
|
// color: Theme.of(context).textTheme.headlineMedium?.color,
|
||||||
overflow: TextOverflow.ellipsis,
|
// overflow: TextOverflow.ellipsis,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Padding(
|
// Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
// padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(
|
// child: Text(
|
||||||
"you will be redirected to solve captcha",
|
// "you will be redirected to solve captcha",
|
||||||
textAlign: TextAlign.center,
|
// textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 13,
|
// fontSize: 13,
|
||||||
fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
color: Theme.of(context).textTheme.headlineSmall?.color,
|
// color: Theme.of(context).textTheme.headlineSmall?.color,
|
||||||
overflow: TextOverflow.ellipsis,
|
// overflow: TextOverflow.ellipsis,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
Padding(
|
// Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(30, 15, 30, 10),
|
// padding: const EdgeInsets.fromLTRB(30, 15, 30, 10),
|
||||||
child: Container(
|
// child: Container(
|
||||||
width: double.infinity,
|
// width: double.infinity,
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: const Color.fromARGB(255, 255, 186, 186),
|
// color: const Color.fromARGB(255, 255, 186, 186),
|
||||||
borderRadius: BorderRadius.circular(5)),
|
// borderRadius: BorderRadius.circular(5)),
|
||||||
child: const Padding(
|
// child: const Padding(
|
||||||
padding: EdgeInsets.all(10.0),
|
// padding: EdgeInsets.all(10.0),
|
||||||
child: Text(
|
// 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 .",
|
// "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,
|
// textAlign: TextAlign.start,
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
fontSize: 13,
|
// fontSize: 13,
|
||||||
fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
color: Colors.black,
|
// color: Colors.black,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
)
|
// )
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
return CustomErrorWidget(
|
return CustomErrorWidget(
|
||||||
error: err,
|
error: err,
|
||||||
stackTrace: _,
|
stackTrace: _,
|
||||||
@ -142,7 +142,7 @@ class BookInfoPage extends ConsumerWidget {
|
|||||||
ref.refresh(bookInfoProvider(url));
|
ref.refresh(bookInfoProvider(url));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
// }
|
||||||
},
|
},
|
||||||
loading: () {
|
loading: () {
|
||||||
return Center(
|
return Center(
|
||||||
@ -198,7 +198,17 @@ class _ActionButtonWidgetState extends ConsumerState<ActionButtonWidget> {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
)),
|
)),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
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);
|
await downloadFileWidget(ref, context, widget.data);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.all(8.0),
|
padding: EdgeInsets.all(8.0),
|
||||||
@ -222,7 +232,7 @@ class _ActionButtonWidgetState extends ConsumerState<ActionButtonWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> downloadFileWidget(
|
Future<void> downloadFileWidget(
|
||||||
WidgetRef ref, BuildContext context, dynamic data) async {
|
WidgetRef ref, BuildContext context, BookInfoData data) async {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
@ -230,8 +240,10 @@ Future<void> downloadFileWidget(
|
|||||||
return _ShowDialog(title: data.title);
|
return _ShowDialog(title: data.title);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
List<String> mirrors = [data.mirror!];
|
||||||
|
print(mirrors);
|
||||||
downloadFile(
|
downloadFile(
|
||||||
mirrors: data.mirrors!,
|
mirrors: mirrors,
|
||||||
md5: data.md5,
|
md5: data.md5,
|
||||||
format: data.format!,
|
format: data.format!,
|
||||||
onStart: () {
|
onStart: () {
|
||||||
@ -263,7 +275,7 @@ Future<void> downloadFileWidget(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
final checkSum = await verifyFileCheckSum(
|
final checkSum = await verifyFileCheckSum(
|
||||||
md5Hash: data.md5, format: data.format);
|
md5Hash: data.md5, format: data.format!);
|
||||||
if (checkSum == true) {
|
if (checkSum == true) {
|
||||||
ref.read(checkSumState.notifier).state =
|
ref.read(checkSumState.notifier).state =
|
||||||
CheckSumProcessState.success;
|
CheckSumProcessState.success;
|
||||||
|
@ -102,11 +102,11 @@ Future<void> openCbrAndCbz(
|
|||||||
{required String fileName, required BuildContext context}) async {
|
{required String fileName, required BuildContext context}) async {
|
||||||
try {
|
try {
|
||||||
String path = await getFilePath(fileName);
|
String path = await getFilePath(fileName);
|
||||||
await OpenFile.open(path);
|
await OpenFile.open(path, linuxByProcess: true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore: avoid_print
|
// ignore: avoid_print
|
||||||
// print(e);
|
// print(e);
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
showSnackBar(context: context, message: 'Unable to open pdf!');
|
showSnackBar(context: context, message: 'Unable to open file!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// Dart imports:
|
// Dart imports:
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
// Flutter imports:
|
// Flutter imports:
|
||||||
@ -11,12 +10,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import 'package:open_file/open_file.dart';
|
import 'package:open_file/open_file.dart';
|
||||||
|
|
||||||
// Project imports:
|
// Project imports:
|
||||||
import 'package:openlib/services/database.dart';
|
|
||||||
import 'package:openlib/services/files.dart' show getFilePath;
|
import 'package:openlib/services/files.dart' show getFilePath;
|
||||||
import 'package:openlib/ui/components/snack_bar_widget.dart';
|
import 'package:openlib/ui/components/snack_bar_widget.dart';
|
||||||
|
|
||||||
import 'package:openlib/state/state.dart'
|
import 'package:openlib/state/state.dart'
|
||||||
show filePathProvider, saveEpubState, getBookPosition;
|
show
|
||||||
|
filePathProvider,
|
||||||
|
saveEpubState,
|
||||||
|
getBookPosition,
|
||||||
|
openEpubWithExternalAppProvider;
|
||||||
|
|
||||||
Future<void> launchEpubViewer(
|
Future<void> launchEpubViewer(
|
||||||
{required String fileName,
|
{required String fileName,
|
||||||
@ -24,10 +25,24 @@ Future<void> launchEpubViewer(
|
|||||||
required WidgetRef ref}) async {
|
required WidgetRef ref}) async {
|
||||||
if (Platform.isAndroid || Platform.isIOS) {
|
if (Platform.isAndroid || Platform.isIOS) {
|
||||||
String path = await getFilePath(fileName);
|
String path = await getFilePath(fileName);
|
||||||
MyLibraryDb dataBase = MyLibraryDb.instance;
|
bool openWithExternalApp = ref.watch(openEpubWithExternalAppProvider);
|
||||||
|
|
||||||
String? epubConfig = await dataBase.getBookState(fileName);
|
if (openWithExternalApp) {
|
||||||
await OpenFile.open(path);
|
await OpenFile.open(path, linuxByProcess: true);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
// 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!');
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
|
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
|
||||||
return EpubViewerWidget(
|
return EpubViewerWidget(
|
||||||
|
@ -22,7 +22,6 @@ import 'package:openlib/state/state.dart'
|
|||||||
openPdfWithExternalAppProvider,
|
openPdfWithExternalAppProvider,
|
||||||
getBookPosition;
|
getBookPosition;
|
||||||
|
|
||||||
|
|
||||||
Future<void> launchPdfViewer(
|
Future<void> launchPdfViewer(
|
||||||
{required String fileName,
|
{required String fileName,
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
@ -30,7 +29,7 @@ Future<void> launchPdfViewer(
|
|||||||
bool openWithExternalApp = ref.watch(openPdfWithExternalAppProvider);
|
bool openWithExternalApp = ref.watch(openPdfWithExternalAppProvider);
|
||||||
if (openWithExternalApp) {
|
if (openWithExternalApp) {
|
||||||
String path = await getFilePath(fileName);
|
String path = await getFilePath(fileName);
|
||||||
await OpenFile.open(path);
|
await OpenFile.open(path, linuxByProcess: true);
|
||||||
} else {
|
} else {
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
|
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) {
|
||||||
return PdfView(
|
return PdfView(
|
||||||
|
@ -18,7 +18,10 @@ import 'package:openlib/ui/about_page.dart';
|
|||||||
import 'package:openlib/ui/components/page_title_widget.dart';
|
import 'package:openlib/ui/components/page_title_widget.dart';
|
||||||
|
|
||||||
import 'package:openlib/state/state.dart'
|
import 'package:openlib/state/state.dart'
|
||||||
show themeModeProvider, openPdfWithExternalAppProvider;
|
show
|
||||||
|
themeModeProvider,
|
||||||
|
openPdfWithExternalAppProvider,
|
||||||
|
openEpubWithExternalAppProvider;
|
||||||
|
|
||||||
Future<void> requestStoragePermission() async {
|
Future<void> requestStoragePermission() async {
|
||||||
bool permissionGranted = false;
|
bool permissionGranted = false;
|
||||||
@ -112,6 +115,30 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
_PaddedContainer(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Open Epub with External Reader",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).colorScheme.tertiary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Switch(
|
||||||
|
// This bool value toggles the switch.
|
||||||
|
value: ref.watch(
|
||||||
|
openEpubWithExternalAppProvider,
|
||||||
|
),
|
||||||
|
activeColor: Colors.red,
|
||||||
|
onChanged: (bool value) {
|
||||||
|
ref.read(openEpubWithExternalAppProvider.notifier).state =
|
||||||
|
value;
|
||||||
|
dataBase.savePreference('openEpubwithExternalApp', value);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
_PaddedContainer(
|
_PaddedContainer(
|
||||||
onClick: () async {
|
onClick: () async {
|
||||||
final currentDirectory =
|
final currentDirectory =
|
||||||
|
@ -3,16 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
// Package imports:
|
// Package imports:
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:webview_flutter/webview_flutter.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
|
|
||||||
// Project imports:
|
|
||||||
import 'package:openlib/services/database.dart';
|
|
||||||
|
|
||||||
import 'package:webview_cookie_manager/webview_cookie_manager.dart'
|
|
||||||
as cookiejar;
|
|
||||||
|
|
||||||
import 'package:openlib/state/state.dart'
|
|
||||||
show cookieProvider, userAgentProvider, bookInfoProvider;
|
|
||||||
|
|
||||||
class Webview extends ConsumerStatefulWidget {
|
class Webview extends ConsumerStatefulWidget {
|
||||||
const Webview({super.key, required this.url});
|
const Webview({super.key, required this.url});
|
||||||
@ -23,58 +14,67 @@ class Webview extends ConsumerStatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _WebviewState extends ConsumerState<Webview> {
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
MyLibraryDb dataBase = MyLibraryDb.instance;
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
automaticallyImplyLeading: false,
|
automaticallyImplyLeading: false,
|
||||||
title: const Text("Solve Captcha"),
|
title: const Text("Solve Captcha"),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: WebViewWidget(
|
child: Column(
|
||||||
controller: controller
|
children: <Widget>[
|
||||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
Expanded(
|
||||||
// ..setBackgroundColor(const Color(
|
child: Stack(
|
||||||
// 0x00000000)) // TODO: Crashes macOS app. https://github.com/flutter/flutter/issues/153773
|
children: [
|
||||||
..loadRequest(Uri.parse(widget.url))
|
InAppWebView(
|
||||||
..getUserAgent().then((value) {
|
key: webViewKey,
|
||||||
ref.read(userAgentProvider.notifier).state = value!;
|
initialUrlRequest: URLRequest(url: WebUri(widget.url)),
|
||||||
dataBase.setBrowserOptions('userAgent', value);
|
onWebViewCreated: (controller) {
|
||||||
})
|
webViewController = controller;
|
||||||
..setNavigationDelegate(NavigationDelegate(
|
},
|
||||||
onPageStarted: (url) async {
|
onLoadStart: (controller, url) {},
|
||||||
var urlStatusCode = await controller.runJavaScriptReturningResult(
|
onLoadStop: (controller, url) async {
|
||||||
"var xhr = new XMLHttpRequest();xhr.open('GET', window.location.href, false);xhr.send(null);xhr.status;");
|
String query =
|
||||||
|
"""document.querySelector('a[class="font-bold"]').href""";
|
||||||
|
String? mirrorLink = await webViewController
|
||||||
|
?.evaluateJavascript(source: query);
|
||||||
|
// final ipfsUrl = widget.url
|
||||||
|
// .replaceAll("slow_download", "ipfs_downloads")
|
||||||
|
// .replaceAll("/0/2", "");
|
||||||
|
|
||||||
if (urlStatusCode.toString().contains('200')) {
|
// await webViewController?.loadUrl(
|
||||||
final cookies = await cookieManager
|
// urlRequest: URLRequest(
|
||||||
.getCookies("https://annas-archive.org");
|
// url: WebUri('https://example.com/new-page')));
|
||||||
|
|
||||||
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 dataBase.setBrowserOptions('cookie', cfClearance);
|
|
||||||
|
|
||||||
ref.invalidate(bookInfoProvider);
|
|
||||||
|
|
||||||
|
if (mirrorLink != null) {
|
||||||
|
Future.delayed(const Duration(milliseconds: 70), () {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
Navigator.pop(context);
|
Navigator.pop(context, mirrorLink);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -6,9 +6,13 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <open_file_linux/open_file_linux_plugin.h>
|
||||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
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 =
|
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
open_file_linux
|
||||||
url_launcher_linux
|
url_launcher_linux
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -6,15 +6,17 @@ import FlutterMacOS
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import device_info_plus
|
import device_info_plus
|
||||||
|
import flutter_inappwebview_macos
|
||||||
|
import open_file_mac
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
import sqflite
|
import sqflite
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
import webview_flutter_wkwebview
|
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
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"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
FLTWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "FLTWebViewFlutterPlugin"))
|
|
||||||
}
|
}
|
||||||
|
180
pubspec.lock
180
pubspec.lock
@ -254,6 +254,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0-beta.2"
|
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:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@ -282,10 +338,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_plugin_android_lifecycle
|
name: flutter_plugin_android_lifecycle
|
||||||
sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de"
|
sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.21"
|
version: "2.0.22"
|
||||||
flutter_riverpod:
|
flutter_riverpod:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -376,6 +432,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.6.0"
|
version: "4.6.0"
|
||||||
|
js:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: js
|
||||||
|
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.7"
|
||||||
json_annotation:
|
json_annotation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -460,10 +524,66 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: open_file
|
name: open_file
|
||||||
sha256: a5a32d44acb7c899987d0999e1e3cbb0a0f1adebbf41ac813ec6d2d8faa0af20
|
sha256: de371f549b1320a48980952473fae1903d4927975506534c8ea4643642eb5f98
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
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:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -604,10 +724,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: quiver
|
name: quiver
|
||||||
sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47
|
sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "3.2.2"
|
||||||
riverpod:
|
riverpod:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -833,10 +953,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: uuid
|
name: uuid
|
||||||
sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90"
|
sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.4.2"
|
version: "4.5.0"
|
||||||
vector_graphics:
|
vector_graphics:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -873,10 +993,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
|
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.2.4"
|
version: "14.2.5"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -885,46 +1005,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.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: ec81f57aa1611f8ebecf1d2259da4ef052281cb5ad624131c93546c79ccc7736
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.9.0"
|
|
||||||
webview_flutter_android:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: webview_flutter_android
|
|
||||||
sha256: "6e64fcb1c19d92024da8f33503aaeeda35825d77142c01d0ea2aa32edc79fdc8"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.16.7"
|
|
||||||
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: "1942a12224ab31e9508cf00c0c6347b931b023b8a4f0811e5dec3b06f94f117d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.15.0"
|
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
10
pubspec.yaml
10
pubspec.yaml
@ -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
|
# 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
|
# 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.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 1.0.6+9
|
version: 1.0.7+1
|
||||||
|
|
||||||
environment:
|
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.
|
# Dependencies specify other packages that your package needs in order to work.
|
||||||
# To automatically upgrade your package dependencies to the latest versions
|
# To automatically upgrade your package dependencies to the latest versions
|
||||||
@ -46,8 +46,9 @@ dependencies:
|
|||||||
path_provider: ^2.0.15
|
path_provider: ^2.0.15
|
||||||
permission_handler: ^11.2.0
|
permission_handler: ^11.2.0
|
||||||
open_file: ^3.3.2
|
open_file: ^3.3.2
|
||||||
webview_flutter: ^4.4.1
|
# webview_flutter: ^4.9.0
|
||||||
webview_cookie_manager: ^2.0.6
|
# webview_cookie_manager: ^2.0.6
|
||||||
|
# vocsy_epub_viewer: ^2.0.0
|
||||||
|
|
||||||
flutter_svg: ^2.0.7
|
flutter_svg: ^2.0.7
|
||||||
google_fonts: ^6.1.0
|
google_fonts: ^6.1.0
|
||||||
@ -63,6 +64,7 @@ dependencies:
|
|||||||
crypto: ^3.0.3
|
crypto: ^3.0.3
|
||||||
file_picker: ^8.1.2
|
file_picker: ^8.1.2
|
||||||
device_info_plus: ^10.1.2
|
device_info_plus: ^10.1.2
|
||||||
|
flutter_inappwebview: ^6.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
import_sorter: ^4.6.0
|
import_sorter: ^4.6.0
|
||||||
|
Reference in New Issue
Block a user