mirror of
https://github.com/dstark5/Openlib.git
synced 2025-09-18 20:54:10 +08:00
Compare commits
3 Commits
v1.0.10-be
...
v1.0.11-be
Author | SHA1 | Date | |
---|---|---|---|
bfad3f92f2 | |||
a363a883d7 | |||
ba4a08c296 |
@ -89,6 +89,7 @@ As [Anna’s Archive](https://annas-archive.org/) Doesn't Have An API. The App W
|
||||
### Android
|
||||
|
||||
Make sure that `android/local.properties` has `flutter.minSdkVersion=21` or above
|
||||
For setup guide see [SETUP.md](./SETUP.md)
|
||||
|
||||
## Contributor required 🚧
|
||||
|
||||
|
78
SETUP.md
Normal file
78
SETUP.md
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
# Openlib Project Setup Guide
|
||||
|
||||
Welcome to the **Openlib Project**! This guide will walk you through setting up the project on your local machine, specifically focusing on **Android Studio**.
|
||||
|
||||
### Prerequisites
|
||||
Before you begin, make sure you have the following installed and configured on your system:
|
||||
|
||||
- **Flutter**: Follow [Flutter installation instructions](https://docs.flutter.dev/get-started/install).
|
||||
- To verify Flutter installation, run:
|
||||
```bash
|
||||
flutter doctor
|
||||
```
|
||||
- **Git**: Required to clone the repository.
|
||||
- **Android Studio** (recommended): With Flutter plugin support.
|
||||
|
||||
---
|
||||
|
||||
## Steps to Set Up Locally
|
||||
|
||||
### 1. Create a Project Directory
|
||||
First, decide where you want the project folder to be created. You can do this from the terminal as follows:
|
||||
```bash
|
||||
mkdir OpenlibProject
|
||||
cd OpenlibProject
|
||||
```
|
||||
|
||||
### 2. Clone the Repository
|
||||
Use Git to clone the project into your newly created directory:
|
||||
```bash
|
||||
git clone https://github.com/dstark5/Openlib.git
|
||||
```
|
||||
|
||||
### 3. Navigate to the Project Folder
|
||||
After cloning, move into the **Openlib** folder:
|
||||
```bash
|
||||
cd Openlib
|
||||
```
|
||||
|
||||
### 4. Open the Project in Android Studio or VS Code
|
||||
To open the project:
|
||||
- **For VS Code**: Use:
|
||||
```bash
|
||||
code .
|
||||
```
|
||||
- **For Android Studio**: Open Android Studio, and then use **File > Open** to navigate to the Openlib folder.
|
||||
|
||||
### 5. local.properties changes
|
||||
To ensure compatibility with your target Android devices, update the minimum SDK version:
|
||||
1. Open **local.properties** (located in `android/`).
|
||||
2. Add the below properties:
|
||||
```gradle
|
||||
flutter.buildMode=release
|
||||
flutter.minSdkVersion=21
|
||||
flutter.targetSdkVersion=34
|
||||
flutter.compileSdkVersion=34
|
||||
```
|
||||
Here, `"21"` represents the minimum SDK version supported.
|
||||
|
||||
### 6. Enable Flutter Support in Android Studio
|
||||
To access the emulator options and additional Flutter-specific features:
|
||||
- Go to **File > Settings > Plugins** in Android Studio.
|
||||
- Ensure **Flutter** support is enabled.
|
||||
- This will provide access to the emulator tab, where you can choose the device for testing.
|
||||
|
||||
### 7. Run the Application
|
||||
To run the app:
|
||||
1. Open **main.dart** (usually found under `lib/`).
|
||||
2. Use the **Run** button in Android Studio to launch the app on your selected emulator or connected device.
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources and Troubleshooting
|
||||
If you encounter any issues, refer to the official [Flutter documentation](https://docs.flutter.dev/) for comprehensive troubleshooting and setup tips.
|
||||
|
||||
---
|
||||
|
||||
Feel free to reach out or create an issue if you have any questions or need further assistance.
|
@ -36,6 +36,13 @@ android {
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
dependenciesInfo {
|
||||
// Disables dependency metadata when building APKs.
|
||||
includeInApk = false
|
||||
// Disables dependency metadata when building Android App Bundles.
|
||||
includeInBundle = false
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias = keystoreProperties['keyAlias']
|
||||
|
@ -162,52 +162,43 @@ class AnnasArchieve {
|
||||
Future<BookInfoData?> _bookInfoParser(resData, url) async {
|
||||
var document = parse(resData.toString());
|
||||
var main = document.querySelector('main[class="main"]');
|
||||
var ul = main?.querySelectorAll('ul[class="list-inside mb-4 ml-1"]');
|
||||
var ul = main?.querySelectorAll('ul[class="list-inside mb-4 ml-1"]>li>a');
|
||||
var externalUrlAnchorTags = main
|
||||
?.querySelector(
|
||||
'ul[class="list-inside mb-4 ml-1 js-show-external hidden"]')
|
||||
?.querySelectorAll('li>a');
|
||||
|
||||
// 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) {
|
||||
for (var e in ul) {
|
||||
anchorTags.insertAll(0, e.querySelectorAll('a'));
|
||||
for (var element in ul) {
|
||||
if (element.attributes['href'] != null &&
|
||||
element.attributes['href']!.startsWith('/slow_download') &&
|
||||
element.attributes['href']!.endsWith('/2')) {
|
||||
mirror = '$baseUrl${element.attributes['href']}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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']}';
|
||||
if (mirror == null) {
|
||||
if (externalUrlAnchorTags != null) {
|
||||
for (var e in externalUrlAnchorTags) {
|
||||
if (e.attributes['href'] != null) {
|
||||
anchorTags.add(e.attributes['href']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var element in anchorTags) {
|
||||
if (element.startsWith('/ipfs_downloads')) {
|
||||
mirror = '$baseUrl$element';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print(mirrors);
|
||||
// print(mirror);
|
||||
|
||||
var data = {
|
||||
'title': main?.querySelector('div[class="text-3xl font-bold"]')?.text,
|
||||
|
@ -35,17 +35,20 @@ List<String> _reorderMirrors(List<String> mirrors) {
|
||||
|
||||
Future<String?> _getAliveMirror(List<String> mirrors) async {
|
||||
Dio dio = Dio();
|
||||
const timeOut = 15;
|
||||
if (mirrors.length == 1) {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
return mirrors[0];
|
||||
}
|
||||
for (var url in mirrors) {
|
||||
try {
|
||||
final response = await dio.head(url,
|
||||
options: Options(receiveTimeout: const Duration(seconds: 10)));
|
||||
options: Options(receiveTimeout: const Duration(seconds: timeOut)));
|
||||
if (response.statusCode == 200) {
|
||||
dio.close();
|
||||
return url;
|
||||
}
|
||||
} catch (_) {
|
||||
// print("timeOut");
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ class AboutPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const version = "1.0.10";
|
||||
const version = "1.0.11";
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
@ -223,14 +223,20 @@ class _ActionButtonWidgetState extends ConsumerState<ActionButtonWidget> {
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
final result = await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (BuildContext context) {
|
||||
return Webview(url: widget.data.mirror ?? '');
|
||||
}));
|
||||
if (widget.data.mirror != null &&
|
||||
widget.data.mirror != '') {
|
||||
final result = await Navigator.push(context,
|
||||
MaterialPageRoute(builder: (BuildContext context) {
|
||||
return Webview(url: widget.data.mirror ?? '');
|
||||
}));
|
||||
|
||||
if (result != null) {
|
||||
widget.data.mirror = result;
|
||||
await downloadFileWidget(ref, context, widget.data);
|
||||
if (result != null) {
|
||||
await downloadFileWidget(
|
||||
ref, context, widget.data, result);
|
||||
}
|
||||
} else {
|
||||
showSnackBar(
|
||||
context: context, message: 'No mirrors available!');
|
||||
}
|
||||
},
|
||||
child: const Text('Add To My Library'),
|
||||
@ -253,16 +259,14 @@ class _ActionButtonWidgetState extends ConsumerState<ActionButtonWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> downloadFileWidget(
|
||||
WidgetRef ref, BuildContext context, BookInfoData data) async {
|
||||
Future<void> downloadFileWidget(WidgetRef ref, BuildContext context,
|
||||
BookInfoData data, List<String> mirrors) async {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return _ShowDialog(title: data.title);
|
||||
});
|
||||
|
||||
List<String> mirrors = [data.mirror!];
|
||||
// print(mirrors);
|
||||
downloadFile(
|
||||
mirrors: mirrors,
|
||||
|
@ -51,21 +51,27 @@ class _WebviewState extends ConsumerState<Webview> {
|
||||
},
|
||||
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", "");
|
||||
List<String> bookDownloadLinks = [];
|
||||
if (url.toString().contains("slow_download")) {
|
||||
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);
|
||||
if (mirrorLink != null) {
|
||||
bookDownloadLinks.add(mirrorLink);
|
||||
}
|
||||
} else {
|
||||
String query =
|
||||
"""var ipfsLinkTags=document.querySelectorAll('ul>li>a');var ipfsLinks=[];var getIpfsLinks=()=>{ipfsLinkTags.forEach(e=>{ipfsLinks.push(e.href)});return ipfsLinks};getIpfsLinks();""";
|
||||
List<dynamic> mirrorLinks = await webViewController
|
||||
?.evaluateJavascript(source: query);
|
||||
bookDownloadLinks = mirrorLinks.cast<String>();
|
||||
}
|
||||
|
||||
// await webViewController?.loadUrl(
|
||||
// urlRequest: URLRequest(
|
||||
// url: WebUri('https://example.com/new-page')));
|
||||
if (mirrorLink != null) {
|
||||
if (bookDownloadLinks.isNotEmpty) {
|
||||
Future.delayed(const Duration(milliseconds: 70), () {
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.pop(context, mirrorLink);
|
||||
Navigator.pop(context, bookDownloadLinks);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.0.10+13
|
||||
version: 1.0.11+14
|
||||
|
||||
environment:
|
||||
sdk: ">=3.3.0 <4.0.0"
|
||||
|
Reference in New Issue
Block a user