Changed name to unyo-lib

This commit is contained in:
Kevin Rodrigues Borges
2026-05-05 00:48:27 +01:00
parent 0a13d81119
commit cc1dee9fd0
24 changed files with 117 additions and 753 deletions

View File

@@ -1,6 +1,6 @@
# AGENTS.md
Flutter FFI package bridging to Aniyomi (Kotlin/Java) via JNI.
Flutter FFI package bridging to Unyo Core JVM runtime via JNI.
## Project Type
@@ -59,7 +59,7 @@ jnigen/
├── sanime.yaml, video.yaml, etc. # Per-class generation configs
assets/
└── aniyomibridge-core.jar # Java library (source of JNI bindings)
└── unyo-core.jar # Java library (source of JNI bindings)
jre/
├── linux/customjre/ # Custom JRE for Linux builds
@@ -70,9 +70,9 @@ jre/
The `lib/jmodels/j*.dart` files are **auto-generated** from Java classes via JNIGen:
- Source JAR: `assets/aniyomibridge-core.jar`
- Source JAR: `assets/unyo-core.jar`
- Configs: `jnigen/*.yaml` (one per Java class)
- Generated classes mirror `eu.kanade.tachiyomi.*` and `dev.k3vinb5.aniyomibridge.*`
- Generated classes mirror `eu.kanade.tachiyomi.*` and `dev.k3vinb5.unyo.core.*`
**Never manually edit `jmodels/j*.dart` files**—regenerate via:
```bash

View File

@@ -1,625 +0,0 @@
# AniyomiBridge JNI Specification
> **Version:** 2.0 (Post-Multi-Module Refactor)
> **Target:** Flutter JNI integration for `aniyomibridge-core-1.0.0.jar`
> **Main Class:** `dev.k3vinb5.aniyomibridge.AniyomiBridge`
---
## Overview
This document specifies the public Java API exposed by `AniyomiBridge.java` for consumption via JNI from Flutter. It covers every method, its signature, the data models that cross the JNI boundary, and the behavioral changes introduced during the multi-module refactor.
**Key architectural fact:** `AniyomiBridge` is a **singleton-like stateful object**. It maintains internal maps of loaded anime/manga sources keyed by `packageName`. You create one instance and call methods on it. All source lookup is done internally via these maps.
---
## Table of Contents
1. [Initialization](#1-initialization)
2. [Extension Lifecycle (Anime)](#2-extension-lifecycle-anime)
3. [Extension Lifecycle (Manga)](#3-extension-lifecycle-manga)
4. [Querying Loaded Extensions](#4-querying-loaded-extensions)
5. [Preferences API](#5-preferences-api)
6. [Content Fetching (Anime)](#6-content-fetching-anime)
7. [Content Fetching (Manga)](#7-content-fetching-manga)
8. [Data Models](#8-data-models)
9. [Error Handling](#9-error-handling)
10. [Breaking Changes from v1](#10-breaking-changes-from-v1)
11. [JNI Implementation Notes](#11-jni-implementation-notes)
---
## 1. Initialization
### `static void init()`
Must be called **once** before any other operation. Performs global JVM-level setup:
- Installs ByteBuddy agent for runtime bytecode patching
- Initializes Injekt dependency injection module
**JNI signature:**
```
(env)->CallStaticVoidMethod(aniyomiBridgeClass, initMethod);
```
**Thread safety:** Safe to call from any thread, but should only be called once. Not synchronized externally — caller must ensure single invocation.
**Throws:** Nothing directly, but ByteBuddy installation can fail if the JVM doesn't support instrumentation.
---
## 2. Extension Lifecycle (Anime)
### `void loadAnimeExtension(String extensionUrl, String basePath, String packageName)`
Downloads an APK from `extensionUrl`, converts it to JAR via dex2jar, loads the main extension class, and registers it as an `AnimeHttpSource`.
| Parameter | Description |
|-----------|-------------|
| `extensionUrl` | Full HTTPS URL to the `.apk` file |
| `basePath` | Local directory path where the converted `.jar` will be cached |
| `packageName` | The Android package name (e.g., `eu.kanade.tachiyomi.animeextension.en.animepahe`). Used as the **internal key** for all subsequent lookups. |
**Behavior:**
- Downloads APK if not already present
- Converts APK → JAR using dex2jar
- Inspects JAR to find the main extension class
- Loads class via isolated `URLClassLoader`
- Applies ByteBuddy patches to the extension's JVM classes
- If the source implements `ConfigurableAnimeSource`, automatically calls `setupPreferenceScreen()` with a managed `PreferenceScreen`
- Stores the source in an internal `ConcurrentHashMap` keyed by `packageName`
**Throws:** `UnyoCoreException` on any failure (download, dex2jar, class loading, casting).
---
### `void unloadAnimeExtension(String packageName)`
Unloads an anime extension and cleans up resources.
| Parameter | Description |
|-----------|-------------|
| `packageName` | The same `packageName` passed to `loadAnimeExtension` |
**Behavior:**
- Closes the extension's `URLClassLoader`
- Deletes the cached JAR file from disk
- Removes the source from internal maps
**Throws:** `UnyoCoreException` on cleanup failure.
---
## 3. Extension Lifecycle (Manga)
### `void loadMangaExtension(String extensionUrl, String basePath, String packageName)`
Identical to `loadAnimeExtension` but for manga sources implementing `CatalogueSource`.
| Parameter | Description |
|-----------|-------------|
| `extensionUrl` | Full HTTPS URL to the `.apk` file |
| `basePath` | Local directory path where the converted `.jar` will be cached |
| `packageName` | Android package name, used as internal key |
**Behavior:** Same as anime version, but casts to `CatalogueSource` and calls `ConfigurableSource.setupPreferenceScreen()` if applicable.
**Throws:** `UnyoCoreException`
---
### `void unloadMangaExtension(String packageName)`
Unloads a manga extension.
| Parameter | Description |
|-----------|-------------|
| `packageName` | The same `packageName` passed to `loadMangaExtension` |
**Throws:** `UnyoCoreException`
---
## 4. Querying Loaded Extensions
### `List<String> getAnimeLoadedExtensions()`
Returns a list of loaded anime extension package names.
**Return:** `java.util.List<java.lang.String>` — package names of all currently loaded anime sources.
---
### `List<String> getMangaLoadedExtensions()`
Returns a list of loaded manga extension package names.
**Return:** `java.util.List<java.lang.String>` — package names of all currently loaded manga sources.
---
## 5. Preferences API
> **New in v2.** Previously, preferences were not exposed to Flutter. Now they are fully readable and writable.
When a `ConfigurableAnimeSource` or `ConfigurableSource` is loaded, `AniyomiBridge` automatically calls `setupPreferenceScreen(screen)` and creates a `PreferenceScreen` backed by file-based `SharedPreferences` (stored under `~/.aniyomibridge/shared_prefs/<source-id>.xml`).
### `List<PreferenceItem> getAnimePreferences(String packageName)`
Reads all preferences registered by an anime extension.
| Parameter | Description |
|-----------|-------------|
| `packageName` | Package name of the loaded anime extension |
**Return:** `java.util.List<PreferenceItem>`
**Behavior:**
- Returns empty list if source is not configurable
- Iterates all `Preference` objects on the source's `PreferenceScreen`
- Reads current value from `SharedPreferences` (or default if never set)
- Returns typed values based on preference type
**Supported preference types:**
| Type | Java Type | Value Type |
|------|-----------|------------|
| `SwitchPreferenceCompat` | `Boolean` | `true` / `false` |
| `ListPreference` | `String` | Selected entry value |
| `EditTextPreference` | `String` | User input text |
| `MultiSelectListPreference` | `Set<String>` | Selected values |
| `Preference` (fallback) | `null` | No value |
---
### `void setAnimePreference(String packageName, String key, Object value)`
Sets a single preference value for an anime extension.
| Parameter | Description |
|-----------|-------------|
| `packageName` | Package name of the loaded anime extension |
| `key` | Preference key (from `getAnimePreferences`) |
| `value` | Value to set. Must match the expected type: `Boolean`, `String`, or `Set<String>` |
**Throws:** `UnyoCoreException` if source not configurable, key not found, or type mismatch.
---
### `void setAnimePreferences(String packageName, Map<String, Object> values)`
Batch-updates multiple preferences for an anime extension.
| Parameter | Description |
|-----------|-------------|
| `packageName` | Package name of the loaded anime extension |
| `values` | `java.util.Map` of `key → value` pairs |
**Behavior:** Iterates the map and calls `setAnimePreference` logic for each entry. Fails fast on first error.
**Throws:** `UnyoCoreException`
> **Note:** Manga preferences API is **not yet exposed** in `AniyomiBridge.java`. If needed, the same pattern applies using `CatalogueSource` / `ConfigurableSource`.
---
## 6. Content Fetching (Anime)
All content-fetching methods are **synchronous blocking calls** that internally run Kotlin coroutines via `runBlocking`. Call them from background threads in Flutter.
### `List<SAnime> getAnimeSearchResults(String query, int page, String packageName)`
Searches for anime using the specified extension.
| Parameter | Description |
|-----------|-------------|
| `query` | Search query string |
| `page` | Page number (1-based) |
| `packageName` | Package name of the loaded anime extension |
**Return:** `java.util.List<SAnime>`
**Throws:** `UnyoCoreException` wrapping any network or parsing error.
---
### `List<SEpisode> getEpisodeList(SAnime anime, String packageName)`
Fetches the episode list for a given anime.
| Parameter | Description |
|-----------|-------------|
| `anime` | `SAnime` object (from search results or previous call) |
| `packageName` | Package name of the loaded anime extension |
**Return:** `java.util.List<SEpisode>`
**Throws:** `UnyoCoreException`
---
### `List<Video> getVideoList(SEpisode episode, String packageName)`
Fetches video URLs/metadata for a given episode.
| Parameter | Description |
|-----------|-------------|
| `episode` | `SEpisode` object |
| `packageName` | Package name of the loaded anime extension |
**Return:** `java.util.List<Video>`
**Throws:** `UnyoCoreException`
> **Important:** The `Video` class contains `okhttp3.Headers` which is **not serializable by default**. If you need to pass video data across JNI/Flutter isolates, consider using `SerializableVideo` (see Data Models).
---
## 7. Content Fetching (Manga)
### `List<SManga> getMangaSearchResults(String query, int page, String packageName)`
Searches for manga.
| Parameter | Description |
|-----------|-------------|
| `query` | Search query string |
| `page` | Page number (1-based) |
| `packageName` | Package name of the loaded manga extension |
**Return:** `java.util.List<SManga>`
**Throws:** `UnyoCoreException`
---
### `List<SChapter> getChapterList(SManga manga, String packageName)`
Fetches chapter list for a manga.
| Parameter | Description |
|-----------|-------------|
| `manga` | `SManga` object |
| `packageName` | Package name of the loaded manga extension |
**Return:** `java.util.List<SChapter>`
**Throws:** `UnyoCoreException`
---
### `List<Page> getPageList(SChapter chapter, String packageName)`
Fetches image page URLs for a chapter.
| Parameter | Description |
|-----------|-------------|
| `chapter` | `SChapter` object |
| `packageName` | Package name of the loaded manga extension |
**Return:** `java.util.List<Page>`
**Throws:** `UnyoCoreException`
---
## 8. Data Models
### `PreferenceItem`
**Package:** `dev.k3vinb5.aniyomibridge.PreferenceItem`
**Fields:**
| Field | Type | Description |
|-------|------|-------------|
| `key` | `String` | Unique preference identifier |
| `title` | `String` | Human-readable title |
| `type` | `String` | One of: `SwitchPreferenceCompat`, `ListPreference`, `EditTextPreference`, `MultiSelectListPreference`, `Preference` |
| `value` | `Object` | Current value (`Boolean`, `String`, or `Set<String>`) |
| `entries` | `List<String>` | Display labels (for List/MultiSelect) |
| `entryValues` | `List<String>` | Internal values (for List/MultiSelect) |
| `summary` | `String` | Optional description text |
**JNI tip:** Access fields directly (they are `public`). No getters/setters.
---
### `SAnime`
**Package:** `eu.kanade.tachiyomi.animesource.model.SAnime`
**Interface fields (all `public`):**
| Field | Type | Notes |
|-------|------|-------|
| `url` | `String` | Relative or absolute URL to the anime page |
| `title` | `String` | Display title |
| `artist` | `String?` | Nullable |
| `author` | `String?` | Nullable |
| `description` | `String?` | Nullable |
| `genre` | `String?` | Nullable; comma-separated genres |
| `status` | `int` | `UNKNOWN=0`, `ONGOING=1`, `COMPLETED=2`, `LICENSED=3`, `PUBLISHING_FINISHED=4`, `CANCELLED=5`, `ON_HIATUS=6` |
| `thumbnail_url` | `String?` | Cover image URL |
| `update_strategy` | `AnimeUpdateStrategy` | Enum |
| `fetch_type` | `FetchType` | Enum |
| `season_number` | `double` | Season number |
| `initialized` | `boolean` | Whether full metadata has been fetched |
**Method:** `List<String> getGenres()` — parses `genre` string into a list.
---
### `SEpisode`
**Package:** `eu.kanade.tachiyomi.animesource.model.SEpisode`
**Interface fields:**
| Field | Type | Notes |
|-------|------|-------|
| `url` | `String` | Episode page URL |
| `name` | `String` | Episode title/number |
| `date_upload` | `long` | Unix timestamp (ms) |
| `episode_number` | `float` | Numeric episode number |
| `scanlator` | `String?` | Nullable |
---
### `Video`
**Package:** `eu.kanade.tachiyomi.animesource.model.Video`
**Fields:**
| Field | Type | Notes |
|-------|------|-------|
| `videoUrl` | `String` | Direct video stream URL |
| `videoTitle` | `String` | Quality label (e.g., "1080p") |
| `resolution` | `Integer?` | Nullable resolution in pixels |
| `bitrate` | `Integer?` | Nullable bitrate |
| `headers` | `okhttp3.Headers?` | HTTP headers required for playback |
| `preferred` | `boolean` | Whether this is the preferred quality |
| `subtitleTracks` | `List<Track>` | Subtitle tracks |
| `audioTracks` | `List<Track>` | Audio tracks |
| `timestamps` | `List<TimeStamp>` | Chapter/intro markers |
| `mpvArgs` | `List<Pair<String,String>>` | MPV player arguments |
| `ffmpegStreamArgs` | `List<Pair<String,String>>` | FFmpeg stream arguments |
| `ffmpegVideoArgs` | `List<Pair<String,String>>` | FFmpeg video arguments |
| `internalData` | `String` | Opaque internal data from extractor |
| `initialized` | `boolean` | Whether video metadata is resolved |
**Deprecation notice:** Old extensions may use `quality` (maps to `videoTitle`) and `url` (maps to internal `videoPageUrl`). New code should use `videoTitle` and `videoUrl`.
---
### `SManga`
**Package:** `eu.kanade.tachiyomi.source.model.SManga`
Identical structure to `SAnime` but without `fetch_type`, `season_number`, and `update_strategy` is `UpdateStrategy` instead of `AnimeUpdateStrategy`.
---
### `SChapter`
**Package:** `eu.kanade.tachiyomi.source.model.SChapter`
Identical structure to `SEpisode` but `chapter_number` instead of `episode_number`.
---
### `Page`
**Package:** `eu.kanade.tachiyomi.source.model.Page`
**Fields:**
| Field | Type | Notes |
|-------|------|-------|
| `index` | `int` | Zero-based page index |
| `url` | `String` | Page URL (may be relative) |
| `imageUrl` | `String?` | Resolved direct image URL |
| `number` | `int` | Human-readable page number (`index + 1`) |
---
## 9. Error Handling
### `UnyoCoreException`
**Package:** `dev.k3vinb5.aniyomibridge.exceptions.UnyoCoreException`
Extends `RuntimeException`.
**Constructors:**
- `UnyoCoreException(String message)`
- `UnyoCoreException(String message, Throwable cause)`
**Behavior:** Every public method in `AniyomiBridge` wraps failures in `UnyoCoreException` with the full Java stack trace in the message string. When catching via JNI, you get both the user-friendly message and the developer stack trace.
**Recommended Flutter handling:**
```dart
// Pseudocode — depends on your JNI bindings
try {
final results = bridge.getAnimeSearchResults(query, page, packageName);
} on JniException catch (e) {
// e.message contains both the summary and the full Java stack trace
log.error(e.message);
}
```
---
## 10. Breaking Changes from v1
If your Flutter code was written against the pre-refactor API (before multi-module split), these are the critical changes:
### 1. Extension keys changed from `extensionName` to `packageName`
**Before:**
```java
loadAnimeExtension(String extensionUrl, String basePath)
// Key was extracted from URL: "animepahe", "torrentio", etc.
unloadAnimeExtension(String extensionName, String version, String basePath)
// You passed extensionName + version, bridge constructed filename
```
**After:**
```java
loadAnimeExtension(String extensionUrl, String basePath, String packageName)
// You pass the full Android package name as key
unloadAnimeExtension(String packageName)
// Just packageName. Bridge tracks the JAR path internally.
```
**Migration:**
- Stop extracting extension names from URLs
- Use the Android package name (from the extension repo JSON) as the key everywhere
- Update your Flutter model to pass `packageName` to all methods
### 2. `getAnimeSearchResults` / `getMangaSearchResults` signature change
**Before:**
```java
getAnimeSearchResults(String query, int page, String animeSource)
// 'animeSource' was the extension name
```
**After:**
```java
getAnimeSearchResults(String query, int page, String packageName)
// 'packageName' is the full package name
```
**Migration:** Pass `packageName` instead of extension name.
### 3. Content fetching methods signature change
**Before:**
```java
getEpisodeList(SAnime anime, String animeSource)
getVideoList(SEpisode episode, String animeSource)
```
**After:**
```java
getEpisodeList(SAnime anime, String packageName)
getVideoList(SEpisode episode, String packageName)
```
**Migration:** Same as above — replace `animeSource` string with `packageName`.
### 4. Removal of `correctedNames` map
**Before:** The bridge internally mapped names like `"zoro" → "hianime"` and `"aniwatch" → "aniwatchtv"`.
**After:** No internal name correction. You must use the exact `packageName`.
**Migration:** Remove any logic in Flutter that relied on these aliases. Use package names directly from the repo metadata.
### 5. Unload methods no longer take `version` or `basePath`
**Before:**
```java
unloadAnimeExtension(String extensionName, String version, String basePath)
```
**After:**
```java
unloadAnimeExtension(String packageName)
```
**Migration:** Simpler — just pass `packageName`.
### 6. Preferences API is new
**Before:** No way to read/write extension preferences from Flutter.
**After:** Full `getAnimePreferences`, `setAnimePreference`, `setAnimePreferences` API.
**Migration:** If your app previously couldn't handle configurable sources, now you can/should expose these preferences in your UI.
### 7. `MediaSourceUtils` now uses per-source filters
**Before:**
```kotlin
animeSource.getSearchAnime(page, query, filters = defaultAnimeFilterList)
```
**After:**
```kotlin
animeSource.getSearchAnime(page, query, filters = animeSource.getFilterList())
```
**Impact:** Search results may differ if an extension had custom filters. This is generally more correct but could change behavior for extensions that rely on non-default filter states.
---
## 11. JNI Implementation Notes
### Class Loading
The fat JAR (`aniyomibridge-core-1.0.0.jar`) contains everything including the Android SDK stubs, Kotlin stdlib, and all dependencies. Load it with a standard `URLClassLoader` or from the classpath.
**Important:** The `Main.class` (`dev.k3vinb5.aniyomibridge.Main`) is excluded from the fat JAR (consumed by external Flutter app). The class you instantiate is `dev.k3vinb5.aniyomibridge.AniyomiBridge`.
### Threading
All content-fetching methods use `kotlinx.coroutines.runBlocking` internally. They **will block the calling thread**. In Flutter, always call these methods through a background isolate or `compute()` / `Isolate.run()`.
The internal maps (`animeSources`, `mangaSources`, `classLoaders`) use `ConcurrentHashMap`, so `load*` and `unload*` are thread-safe. However, you should not load and unload the same extension concurrently.
### Object Lifetimes
`SAnime`, `SEpisode`, `SManga`, `SChapter` are `Serializable`. You can safely pass them across JNI boundaries and cache them in Dart if needed.
`Video` contains `okhttp3.Headers` which is **not serializable**. If you need to serialize video data (e.g., for Dart isolates or JSON), convert `Headers` to a `Map<String, List<String>>` or use the `SerializableVideo` Kotlin helper class.
### Memory
Each loaded extension gets its own `URLClassLoader`. When you call `unload*Extension`, the classloader is closed and the JAR file is deleted. This should release most memory, but some classes may remain in the JVM's metaspace until GC.
### Logging
The bridge uses JBoss Logging. Logs go to stdout/stderr by default. In a Flutter desktop app, you'll see them in the console. Consider redirecting `java.util.logging` or JBoss LogManager to your Dart logging system if you need structured logs.
---
## Appendix: Quick Reference — Method Signatures
```java
// Initialization
public static void init()
// Anime lifecycle
public void loadAnimeExtension(String extensionUrl, String basePath, String packageName)
public void unloadAnimeExtension(String packageName)
// Manga lifecycle
public void loadMangaExtension(String extensionUrl, String basePath, String packageName)
public void unloadMangaExtension(String packageName)
// Query loaded
public List<String> getAnimeLoadedExtensions()
public List<String> getMangaLoadedExtensions()
// Preferences (anime only, currently)
public List<PreferenceItem> getAnimePreferences(String packageName)
public void setAnimePreference(String packageName, String key, Object value)
public void setAnimePreferences(String packageName, Map<String, Object> values)
// Anime content
public List<SAnime> getAnimeSearchResults(String query, int page, String packageName)
public List<SEpisode> getEpisodeList(SAnime anime, String packageName)
public List<Video> getVideoList(SEpisode episode, String packageName)
// Manga content
public List<SManga> getMangaSearchResults(String query, int page, String packageName)
public List<SChapter> getChapterList(SManga manga, String packageName)
public List<Page> getPageList(SChapter chapter, String packageName)
```

View File

@@ -4,11 +4,11 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart' as path;
import 'package:k3vinb5_aniyomi_bridge/aniyomi_bridge.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jpreferenceitem.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsanime.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsepisode.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jvideo.dart';
import 'package:unyo_lib/aniyomi_bridge.dart';
import 'package:unyo_lib/jmodels/jpreferenceitem.dart';
import 'package:unyo_lib/jmodels/jsanime.dart';
import 'package:unyo_lib/jmodels/jsepisode.dart';
import 'package:unyo_lib/jmodels/jvideo.dart';
void main() {
runApp(const BridgeTesterApp());

View File

@@ -147,13 +147,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.9.0"
k3vinb5_aniyomi_bridge:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.0.1"
leak_tracker:
dependency: transitive
description:
@@ -375,6 +368,13 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.0"
unyo_lib:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.0.1"
vector_math:
dependency: transitive
description:

View File

@@ -36,7 +36,7 @@ dependencies:
cupertino_icons: ^1.0.8
http: ^1.2.0
path: ^1.9.0
k3vinb5_aniyomi_bridge:
unyo_lib:
path: ../
dev_dependencies:

View File

@@ -13,7 +13,7 @@ PROJECT_DIR=$(pwd)
case "$PLATFORM" in
macos)
# Locate Flutter macOS build output
JRE_SRC="/Users/kevin/IdeaProjects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
JRE_SRC="/Users/kevin/IdeaProjects/unyo-lib/jre/$PLATFORM/customjre"
if [ ! -d "$JRE_SRC" ]; then
echo "Error: JRE source folder not found: $JRE_SRC"
exit 1
@@ -27,7 +27,7 @@ case "$PLATFORM" in
linux)
# Linux Flutter executable folder
JRE_SRC="/home/kevin/Projects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
JRE_SRC="/home/kevin/Projects/unyo-lib/jre/$PLATFORM/customjre"
if [ ! -d "$JRE_SRC" ]; then
echo "Error: JRE source folder not found: $JRE_SRC"
exit 1

View File

@@ -13,7 +13,7 @@ PROJECT_DIR=$(pwd)
case "$PLATFORM" in
macos)
# Locate Flutter macOS build output
JRE_SRC="/Users/kevin/IdeaProjects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
JRE_SRC="/Users/kevin/IdeaProjects/unyo-lib/jre/$PLATFORM/customjre"
if [ ! -d "$JRE_SRC" ]; then
echo "Error: JRE source folder not found: $JRE_SRC"
exit 1
@@ -27,7 +27,7 @@ case "$PLATFORM" in
linux)
# Linux Flutter executable folder
JRE_SRC="/home/kevin/Projects/k3vinb5_aniyomi_bridge/jre/$PLATFORM/customjre"
JRE_SRC="/home/kevin/Projects/unyo-lib/jre/$PLATFORM/customjre"
if [ ! -d "$JRE_SRC" ]; then
echo "Error: JRE source folder not found: $JRE_SRC"
exit 1

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'dev.k3vinb5.aniyomibridge.AniyomiBridge'
- 'dev.k3vinb5.unyo.core.AniyomiBridge'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'okhttp3.Headers'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'eu.kanade.tachiyomi.source.model.Page'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'dev.k3vinb5.aniyomibridge.PreferenceItem'
- 'dev.k3vinb5.unyo.core.PreferenceItem'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'eu.kanade.tachiyomi.animesource.model.SAnime'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'eu.kanade.tachiyomi.source.model.SChapter'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'eu.kanade.tachiyomi.animesource.model.SEpisode'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'eu.kanade.tachiyomi.source.model.SManga'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'eu.kanade.tachiyomi.animesource.model.Track'

View File

@@ -4,6 +4,6 @@ output:
structure: single_file
class_path:
- '../assets/aniyomibridge-core.jar'
- '../assets/unyo-core.jar'
classes:
- 'eu.kanade.tachiyomi.animesource.model.Video'

View File

@@ -4,29 +4,29 @@ import 'dart:isolate';
import 'dart:math';
import 'package:flutter/services.dart';
import 'package:jni/jni.dart';
import 'package:k3vinb5_aniyomi_bridge/jni_isolate.dart';
import 'package:k3vinb5_aniyomi_bridge/jni_isolate_message.dart';
import 'package:k3vinb5_aniyomi_bridge/models/extension.dart';
import 'package:unyo_lib/jni_isolate.dart';
import 'package:unyo_lib/jni_isolate_message.dart';
import 'package:unyo_lib/models/extension.dart';
import 'package:logger/logger.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:crypto/crypto.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jvideo.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsanime.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsepisode.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jsmanga.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jschapter.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jpage.dart';
import 'package:k3vinb5_aniyomi_bridge/jmodels/jpreferenceitem.dart';
import 'package:unyo_lib/jmodels/jvideo.dart';
import 'package:unyo_lib/jmodels/jsanime.dart';
import 'package:unyo_lib/jmodels/jsepisode.dart';
import 'package:unyo_lib/jmodels/jsmanga.dart';
import 'package:unyo_lib/jmodels/jschapter.dart';
import 'package:unyo_lib/jmodels/jpage.dart';
import 'package:unyo_lib/jmodels/jpreferenceitem.dart';
class AniyomiBridge {
// static consts
static const String _aniyomiBridgeAnimeExtensionsDir = "animeExtensions";
static const String _aniyomiBridgeMangaExtensionsDir = "mangaExtensions";
static const String _aniyomiBridgeDir = "aniyomibridge";
static const String _aniyomiBridgeJarName = "aniyomibridge-core.jar";
static const String _aniyomiBridgeJarName = "unyo-core.jar";
static const String _packageAssetsDir =
"packages/k3vinb5_aniyomi_bridge/assets";
"packages/unyo_lib/assets";
static const Duration _cacheTtl = Duration(minutes: 20);
// static variables

View File

@@ -36,7 +36,7 @@ import 'dart:core' as core$_;
import 'package:jni/_internal.dart' as jni$_;
import 'package:jni/jni.dart' as jni$_;
/// from: `dev.k3vinb5.aniyomibridge.AniyomiBridge`
/// from: `dev.k3vinb5.unyo.core.AniyomiBridge`
class JAniyomiBridge extends jni$_.JObject {
@jni$_.internal
@core$_.override
@@ -48,12 +48,12 @@ class JAniyomiBridge extends jni$_.JObject {
super.fromReference(reference);
static final _class = jni$_.JClass.forName(
r'dev/k3vinb5/aniyomibridge/AniyomiBridge',
r'dev/k3vinb5/unyo/core/AniyomiBridge',
);
/// The type which includes information such as the signature of this class.
static const nullableType = $JAniyomiBridge$NullableType();
static const type = $JAniyomiBridge$Type();
static const nullableType = $AniyomiBridge$NullableType();
static const type = $AniyomiBridge$Type();
static final _id_classLoaders = _class.staticFieldId(
r'classLoaders',
r'Ljava/util/Map;',
@@ -444,7 +444,7 @@ class JAniyomiBridge extends jni$_.JObject {
)
>();
/// from: `public java.util.List<dev.k3vinb5.aniyomibridge.PreferenceItem> getAnimePreferences(java.lang.String string)`
/// from: `public java.util.List<dev.k3vinb5.unyo.core.PreferenceItem> getAnimePreferences(java.lang.String string)`
/// The returned object must be released after use, by calling the [release] method.
jni$_.JList<jni$_.JObject?>? getAnimePreferences(jni$_.JString? string) {
final _$string = string?.reference ?? jni$_.jNullReference;
@@ -840,13 +840,13 @@ class JAniyomiBridge extends jni$_.JObject {
}
}
final class $JAniyomiBridge$NullableType extends jni$_.JObjType<JAniyomiBridge?> {
final class $AniyomiBridge$NullableType extends jni$_.JObjType<JAniyomiBridge?> {
@jni$_.internal
const $JAniyomiBridge$NullableType();
const $AniyomiBridge$NullableType();
@jni$_.internal
@core$_.override
String get signature => r'Ldev/k3vinb5/aniyomibridge/AniyomiBridge;';
String get signature => r'Ldev/k3vinb5/unyo/core/AniyomiBridge;';
@jni$_.internal
@core$_.override
@@ -865,22 +865,22 @@ final class $JAniyomiBridge$NullableType extends jni$_.JObjType<JAniyomiBridge?>
final superCount = 1;
@core$_.override
int get hashCode => ($JAniyomiBridge$NullableType).hashCode;
int get hashCode => ($AniyomiBridge$NullableType).hashCode;
@core$_.override
bool operator ==(Object other) {
return other.runtimeType == ($JAniyomiBridge$NullableType) &&
other is $JAniyomiBridge$NullableType;
return other.runtimeType == ($AniyomiBridge$NullableType) &&
other is $AniyomiBridge$NullableType;
}
}
final class $JAniyomiBridge$Type extends jni$_.JObjType<JAniyomiBridge> {
final class $AniyomiBridge$Type extends jni$_.JObjType<JAniyomiBridge> {
@jni$_.internal
const $JAniyomiBridge$Type();
const $AniyomiBridge$Type();
@jni$_.internal
@core$_.override
String get signature => r'Ldev/k3vinb5/aniyomibridge/AniyomiBridge;';
String get signature => r'Ldev/k3vinb5/unyo/core/AniyomiBridge;';
@jni$_.internal
@core$_.override
@@ -893,18 +893,18 @@ final class $JAniyomiBridge$Type extends jni$_.JObjType<JAniyomiBridge> {
@jni$_.internal
@core$_.override
jni$_.JObjType<JAniyomiBridge?> get nullableType =>
const $JAniyomiBridge$NullableType();
const $AniyomiBridge$NullableType();
@jni$_.internal
@core$_.override
final superCount = 1;
@core$_.override
int get hashCode => ($JAniyomiBridge$Type).hashCode;
int get hashCode => ($AniyomiBridge$Type).hashCode;
@core$_.override
bool operator ==(Object other) {
return other.runtimeType == ($JAniyomiBridge$Type) &&
other is $JAniyomiBridge$Type;
return other.runtimeType == ($AniyomiBridge$Type) &&
other is $AniyomiBridge$Type;
}
}

View File

@@ -816,6 +816,39 @@ class JHeaders extends jni$_.JObject {
static Headers$Companion get Companion =>
_id_Companion.get(_class, const $Headers$Companion$Type());
static final _id_new$ = _class.constructorId(r'([Ljava/lang/String;)V');
static final _new$ =
jni$_.ProtectedJniExtensions.lookup<
jni$_.NativeFunction<
jni$_.JniResult Function(
jni$_.Pointer<jni$_.Void>,
jni$_.JMethodIDPtr,
jni$_.VarArgs<(jni$_.Pointer<jni$_.Void>,)>,
)
>
>('globalEnv_NewObject')
.asFunction<
jni$_.JniResult Function(
jni$_.Pointer<jni$_.Void>,
jni$_.JMethodIDPtr,
jni$_.Pointer<jni$_.Void>,
)
>();
/// from: `public void <init>(java.lang.String[] strings)`
/// The returned object must be released after use, by calling the [release] method.
factory JHeaders(jni$_.JArray<jni$_.JString> strings) {
final _$strings = strings.reference;
return JHeaders.fromReference(
_new$(
_class.reference.pointer,
_id_new$ as jni$_.JMethodIDPtr,
_$strings.pointer,
).reference,
);
}
static final _id_get = _class.instanceMethodId(
r'get',
r'(Ljava/lang/String;)Ljava/lang/String;',
@@ -1355,50 +1388,6 @@ class JHeaders extends jni$_.JObject {
).object<JHeaders>(const $Headers$Type());
}
static final _id_new$ = _class.constructorId(
r'([Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V',
);
static final _new$ =
jni$_.ProtectedJniExtensions.lookup<
jni$_.NativeFunction<
jni$_.JniResult Function(
jni$_.Pointer<jni$_.Void>,
jni$_.JMethodIDPtr,
jni$_.VarArgs<
(jni$_.Pointer<jni$_.Void>, jni$_.Pointer<jni$_.Void>)
>,
)
>
>('globalEnv_NewObject')
.asFunction<
jni$_.JniResult Function(
jni$_.Pointer<jni$_.Void>,
jni$_.JMethodIDPtr,
jni$_.Pointer<jni$_.Void>,
jni$_.Pointer<jni$_.Void>,
)
>();
/// from: `synthetic public void <init>(java.lang.String[] strings, kotlin.jvm.internal.DefaultConstructorMarker defaultConstructorMarker)`
/// The returned object must be released after use, by calling the [release] method.
factory JHeaders(
jni$_.JArray<jni$_.JString?>? strings,
jni$_.JObject? defaultConstructorMarker,
) {
final _$strings = strings?.reference ?? jni$_.jNullReference;
final _$defaultConstructorMarker =
defaultConstructorMarker?.reference ?? jni$_.jNullReference;
return JHeaders.fromReference(
_new$(
_class.reference.pointer,
_id_new$ as jni$_.JMethodIDPtr,
_$strings.pointer,
_$defaultConstructorMarker.pointer,
).reference,
);
}
jni$_.JString? operator [](jni$_.JString string) {
return get(string);
}

View File

@@ -36,7 +36,7 @@ import 'dart:core' as core$_;
import 'package:jni/_internal.dart' as jni$_;
import 'package:jni/jni.dart' as jni$_;
/// from: `dev.k3vinb5.aniyomibridge.JPreferenceItem`
/// from: `dev.k3vinb5.unyo.core.PreferenceItem`
class JPreferenceItem extends jni$_.JObject {
@jni$_.internal
@core$_.override
@@ -48,12 +48,12 @@ class JPreferenceItem extends jni$_.JObject {
super.fromReference(reference);
static final _class = jni$_.JClass.forName(
r'dev/k3vinb5/aniyomibridge/JPreferenceItem',
r'dev/k3vinb5/unyo/core/PreferenceItem',
);
/// The type which includes information such as the signature of this class.
static const nullableType = $JPreferenceItem$NullableType();
static const type = $JPreferenceItem$Type();
static const nullableType = $PreferenceItem$NullableType();
static const type = $PreferenceItem$Type();
static final _id_key = _class.instanceFieldId(r'key', r'Ljava/lang/String;');
/// from: `public java.lang.String key`
@@ -238,14 +238,14 @@ class JPreferenceItem extends jni$_.JObject {
}
}
final class $JPreferenceItem$NullableType
final class $PreferenceItem$NullableType
extends jni$_.JObjType<JPreferenceItem?> {
@jni$_.internal
const $JPreferenceItem$NullableType();
const $PreferenceItem$NullableType();
@jni$_.internal
@core$_.override
String get signature => r'Ldev/k3vinb5/aniyomibridge/JPreferenceItem;';
String get signature => r'Ldev/k3vinb5/unyo/core/PreferenceItem;';
@jni$_.internal
@core$_.override
@@ -264,22 +264,22 @@ final class $JPreferenceItem$NullableType
final superCount = 1;
@core$_.override
int get hashCode => ($JPreferenceItem$NullableType).hashCode;
int get hashCode => ($PreferenceItem$NullableType).hashCode;
@core$_.override
bool operator ==(Object other) {
return other.runtimeType == ($JPreferenceItem$NullableType) &&
other is $JPreferenceItem$NullableType;
return other.runtimeType == ($PreferenceItem$NullableType) &&
other is $PreferenceItem$NullableType;
}
}
final class $JPreferenceItem$Type extends jni$_.JObjType<JPreferenceItem> {
final class $PreferenceItem$Type extends jni$_.JObjType<JPreferenceItem> {
@jni$_.internal
const $JPreferenceItem$Type();
const $PreferenceItem$Type();
@jni$_.internal
@core$_.override
String get signature => r'Ldev/k3vinb5/aniyomibridge/JPreferenceItem;';
String get signature => r'Ldev/k3vinb5/unyo/core/PreferenceItem;';
@jni$_.internal
@core$_.override
@@ -292,18 +292,18 @@ final class $JPreferenceItem$Type extends jni$_.JObjType<JPreferenceItem> {
@jni$_.internal
@core$_.override
jni$_.JObjType<JPreferenceItem?> get nullableType =>
const $JPreferenceItem$NullableType();
const $PreferenceItem$NullableType();
@jni$_.internal
@core$_.override
final superCount = 1;
@core$_.override
int get hashCode => ($JPreferenceItem$Type).hashCode;
int get hashCode => ($PreferenceItem$Type).hashCode;
@core$_.override
bool operator ==(Object other) {
return other.runtimeType == ($JPreferenceItem$Type) &&
other is $JPreferenceItem$Type;
return other.runtimeType == ($PreferenceItem$Type) &&
other is $PreferenceItem$Type;
}
}

View File

@@ -3,7 +3,7 @@ import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:jni/jni.dart';
import 'package:k3vinb5_aniyomi_bridge/jni_isolate_message.dart';
import 'package:unyo_lib/jni_isolate_message.dart';
import 'package:path/path.dart' as path;
import 'jmodels/janiyomibridge.dart';

View File

@@ -1,5 +1,5 @@
name: k3vinb5_aniyomi_bridge
description: "A new Flutter package project."
name: unyo_lib
description: "Flutter bridge for Unyo Core JVM runtime"
version: 0.0.1
environment:
@@ -32,7 +32,7 @@ flutter:
# To add assets to your package, add an assets section, like this:
assets:
- assets/aniyomibridge-core.jar
- assets/unyo-core.jar
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#