This commit is contained in:
kodjomoustapha 2024-05-27 09:26:30 +01:00
parent ae73256884
commit 6ed57e2e44
38 changed files with 101 additions and 4565 deletions

1871
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
# This file is used for telling Rust-related tools
# where various Rust crates are.
# This also unifies `./target` output folder and
# various Rust configurations.
[workspace]
members = ["./native/*"]
resolver = "2"

View file

@ -82,8 +82,7 @@ class _ExtensionListTileWidgetState
child: Icon(Icons.source_outlined),
),
),
headers: {},
),
useCustomNetworkImage: false),
),
title: Text(widget.source.name!),
subtitle: Row(

View file

@ -54,7 +54,7 @@ class SourceListTile extends StatelessWidget {
child: Icon(Icons.source_outlined),
),
),
),
useCustomNetworkImage: false),
),
subtitle: Row(
children: [

View file

@ -1801,7 +1801,7 @@ class _LibraryLanguageStateProviderElement
}
String _$libraryLocalSourceStateHash() =>
r'023011d7b9a9e99e4196b063eb9646644ed30279';
r'9c180d682d0b653bbfc5788e189ee8f4bebd77ec';
abstract class _$LibraryLocalSourceState
extends BuildlessAutoDisposeNotifier<bool> {

View file

@ -61,7 +61,7 @@ class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
final sourceExist = snapshot.hasData && snapshot.data!.isNotEmpty;
return RefreshIndicator(
onRefresh: () async {
if (sourceExist) {
if (sourceExist && !_isLoading) {
await ref.read(updateMangaDetailProvider(
mangaId: manga.id, isInit: false)
.future);

View file

@ -538,7 +538,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
chapterLength: chapters.length))),
Expanded(
child: Scrollbar(
interactive: true,
interactive: true,
thickness: 12,
radius: const Radius.circular(10),
controller: _scrollController,

View file

@ -1258,7 +1258,7 @@ final chaptersListttStateProvider =
typedef _$ChaptersListttState = AutoDisposeNotifier<List<Chapter>>;
String _$scanlatorsFilterStateHash() =>
r'56ba6cea4ec0948aeb6d10a205d0f9d783ce13bf';
r'32eb4315b75478fabcb8ca9eb3f13d289d806fa2';
abstract class _$ScanlatorsFilterState extends BuildlessAutoDisposeNotifier<
(List<String>, List<String>, List<String>)> {

View file

@ -6,7 +6,7 @@ part of 'download_provider.dart';
// RiverpodGenerator
// **************************************************************************
String _$downloadChapterHash() => r'a8bbd438963157af07b92601c1741195421a3281';
String _$downloadChapterHash() => r'c5c7e8cb341cf703255a581f07123125690dcf63';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -1,41 +0,0 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:mangayomi/messages/crop_borders.pb.dart';
import 'package:mangayomi/modules/manga/reader/reader_view.dart';
import 'package:mangayomi/utils/extensions/others.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'crop_borders_provider.g.dart';
int nextId = 0;
@Riverpod(keepAlive: true)
Future<Uint8List?> cropBorders(CropBordersRef ref,
{required UChapDataPreload data, required bool cropBorder}) async {
Uint8List? imageBytes;
if (cropBorder) {
imageBytes = await data.getImageBytes;
if (imageBytes == null) {
return null;
}
final currentId = nextId;
nextId++;
final completer = Completer<Uint8List>();
CropBordersInput(
image: imageBytes,
).sendSignalToRust();
final stream = CropBordersOutput.rustSignalStream;
final subscription = stream.listen((rustSignal) {
if (rustSignal.message.interactionId == currentId) {
completer.complete(rustSignal.message.image as Uint8List);
}
});
final image = await completer.future;
subscription.cancel();
return image;
}
return null;
}

View file

@ -1,175 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'crop_borders_provider.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$cropBordersHash() => r'dc0e5abe7adbe8c2980957c82e470a0cd1edc799';
/// Copied from Dart SDK
class _SystemHash {
_SystemHash._();
static int combine(int hash, int value) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + value);
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}
static int finish(int hash) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
// ignore: parameter_assignments
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
}
/// See also [cropBorders].
@ProviderFor(cropBorders)
const cropBordersProvider = CropBordersFamily();
/// See also [cropBorders].
class CropBordersFamily extends Family<AsyncValue<Uint8List?>> {
/// See also [cropBorders].
const CropBordersFamily();
/// See also [cropBorders].
CropBordersProvider call({
required UChapDataPreload data,
required bool cropBorder,
}) {
return CropBordersProvider(
data: data,
cropBorder: cropBorder,
);
}
@override
CropBordersProvider getProviderOverride(
covariant CropBordersProvider provider,
) {
return call(
data: provider.data,
cropBorder: provider.cropBorder,
);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'cropBordersProvider';
}
/// See also [cropBorders].
class CropBordersProvider extends FutureProvider<Uint8List?> {
/// See also [cropBorders].
CropBordersProvider({
required UChapDataPreload data,
required bool cropBorder,
}) : this._internal(
(ref) => cropBorders(
ref as CropBordersRef,
data: data,
cropBorder: cropBorder,
),
from: cropBordersProvider,
name: r'cropBordersProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$cropBordersHash,
dependencies: CropBordersFamily._dependencies,
allTransitiveDependencies:
CropBordersFamily._allTransitiveDependencies,
data: data,
cropBorder: cropBorder,
);
CropBordersProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.data,
required this.cropBorder,
}) : super.internal();
final UChapDataPreload data;
final bool cropBorder;
@override
Override overrideWith(
FutureOr<Uint8List?> Function(CropBordersRef provider) create,
) {
return ProviderOverride(
origin: this,
override: CropBordersProvider._internal(
(ref) => create(ref as CropBordersRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
data: data,
cropBorder: cropBorder,
),
);
}
@override
FutureProviderElement<Uint8List?> createElement() {
return _CropBordersProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is CropBordersProvider &&
other.data == data &&
other.cropBorder == cropBorder;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, data.hashCode);
hash = _SystemHash.combine(hash, cropBorder.hashCode);
return _SystemHash.finish(hash);
}
}
mixin CropBordersRef on FutureProviderRef<Uint8List?> {
/// The parameter `data` of this provider.
UChapDataPreload get data;
/// The parameter `cropBorder` of this provider.
bool get cropBorder;
}
class _CropBordersProviderElement extends FutureProviderElement<Uint8List?>
with CropBordersRef {
_CropBordersProviderElement(super.provider);
@override
UChapDataPreload get data => (origin as CropBordersProvider).data;
@override
bool get cropBorder => (origin as CropBordersProvider).cropBorder;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View file

@ -10,7 +10,6 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mangayomi/eval/dart/model/m_bridge.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/messages/generated.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/models/settings.dart';
@ -19,7 +18,6 @@ import 'package:mangayomi/modules/manga/reader/widgets/btn_chapter_list_dialog.d
import 'package:mangayomi/modules/manga/reader/double_columm_view_vertical.dart';
import 'package:mangayomi/modules/manga/reader/double_columm_view_center.dart';
import 'package:mangayomi/modules/manga/reader/providers/color_filter_provider.dart';
import 'package:mangayomi/modules/manga/reader/providers/crop_borders_provider.dart';
import 'package:mangayomi/modules/manga/reader/widgets/color_filter_widget.dart';
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
import 'package:mangayomi/modules/widgets/custom_draggable_tabbar.dart';
@ -156,7 +154,6 @@ class _MangaChapterPageGalleryState
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values);
}
finalizeRust();
super.dispose();
}
@ -242,8 +239,6 @@ class _MangaChapterPageGalleryState
Color _backgroundColor(BuildContext context) =>
Theme.of(context).scaffoldBackgroundColor.withOpacity(0.9);
final List<int> _cropBorderCheckList = [];
void _setFullScreen({bool? value}) async {
if (isDesktop) {
value = await windowManager.isFullScreen();
@ -387,12 +382,8 @@ class _MangaChapterPageGalleryState
Widget build(BuildContext context) {
final backgroundColor = ref.watch(backgroundColorStateProvider);
final fullScreenReader = ref.watch(fullScreenReaderStateProvider);
final cropBorders = ref.watch(cropBordersStateProvider);
final bool isHorizontalContinuaous =
ref.watch(_currentReaderMode) == ReaderMode.horizontalContinuous;
if (cropBorders) {
_processCropBorders();
}
final usePageTapZones = ref.watch(usePageTapZonesStateProvider);
final l10n = l10nLocalizations(context)!;
return KeyboardListener(
@ -1009,7 +1000,6 @@ class _MangaChapterPageGalleryState
_uChapDataPreload.addAll(_chapterUrlModel.uChapDataPreload);
_readerController.setMangaHistoryUpdate();
await Future.delayed(const Duration(milliseconds: 1));
await initializeRust();
final fullScreenReader = ref.watch(fullScreenReaderStateProvider);
if (fullScreenReader) {
if (isDesktop) {
@ -1042,11 +1032,6 @@ class _MangaChapterPageGalleryState
}
void _onPageChanged(int index) {
final cropBorders = ref.watch(cropBordersStateProvider);
if (cropBorders) {
_processCropBordersByIndex(index);
}
for (var i = 1; i < pagePreloadAmount + 1; i++) {
_precacheImages(index + i);
_precacheImages(index - i);
@ -1270,40 +1255,6 @@ class _MangaChapterPageGalleryState
Navigator.pop(context);
}
void _processCropBorders() async {
for (var i = 0; i < _uChapDataPreload.length; i++) {
if (!_cropBorderCheckList.contains(i)) {
_cropBorderCheckList.add(i);
ref
.watch(cropBordersProvider(
data: _uChapDataPreload[i], cropBorder: true)
.future)
.then((value) {
_uChapDataPreload[i] = _uChapDataPreload[i]..cropImage = value;
if (mounted) {
setState(() {});
}
});
}
}
}
void _processCropBordersByIndex(int index) async {
if (!_cropBorderCheckList.contains(index)) {
_cropBorderCheckList.add(index);
ref
.watch(cropBordersProvider(
data: _uChapDataPreload[index], cropBorder: true)
.future)
.then((value) {
_uChapDataPreload[index] = _uChapDataPreload[index]..cropImage = value;
});
if (mounted) {
setState(() {});
}
}
}
Widget _appBar() {
final fullScreenReader = ref.watch(fullScreenReaderStateProvider);
double height = _isView
@ -1701,39 +1652,39 @@ class _MangaChapterPageGalleryState
)),
],
),
Consumer(builder: (context, ref, child) {
final cropBorders = ref.watch(cropBordersStateProvider);
return IconButton(
onPressed: () {
ref
.read(cropBordersStateProvider.notifier)
.set(!cropBorders);
},
icon: Stack(
children: [
const Icon(
Icons.crop_rounded,
),
if (!cropBorders)
Positioned(
right: 8,
child: Transform.scale(
scaleX: 2.5,
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'\\',
style: TextStyle(fontSize: 17),
),
],
),
),
),
],
),
);
}),
// Consumer(builder: (context, ref, child) {
// final cropBorders = ref.watch(cropBordersStateProvider);
// return IconButton(
// onPressed: () {
// ref
// .read(cropBordersStateProvider.notifier)
// .set(!cropBorders);
// },
// icon: Stack(
// children: [
// const Icon(
// Icons.crop_rounded,
// ),
// if (!cropBorders)
// Positioned(
// right: 8,
// child: Transform.scale(
// scaleX: 2.5,
// child: const Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// '\\',
// style: TextStyle(fontSize: 17),
// ),
// ],
// ),
// ),
// ),
// ],
// ),
// );
// }),
IconButton(
onPressed: () async {
if (!(readerMode == ReaderMode.horizontalContinuous)) {
@ -2043,8 +1994,6 @@ class _MangaChapterPageGalleryState
Consumer(builder: (context, ref, chil) {
final readerMode = ref.watch(_currentReaderMode);
final usePageTapZones = ref.watch(usePageTapZonesStateProvider);
final cropBorders = ref.watch(cropBordersStateProvider);
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
@ -2063,21 +2012,21 @@ class _MangaChapterPageGalleryState
return getReaderModeName(mode, context);
},
),
SwitchListTile(
value: cropBorders,
title: Text(
l10n.crop_borders,
style: TextStyle(
color: Theme.of(context)
.textTheme
.bodyLarge!
.color!
.withOpacity(0.9),
fontSize: 14),
),
onChanged: (value) {
ref.read(cropBordersStateProvider.notifier).set(value);
}),
// SwitchListTile(
// value: cropBorders,
// title: Text(
// l10n.crop_borders,
// style: TextStyle(
// color: Theme.of(context)
// .textTheme
// .bodyLarge!
// .color!
// .withOpacity(0.9),
// fontSize: 14),
// ),
// onChanged: (value) {
// ref.read(cropBordersStateProvider.notifier).set(value);
// }),
SwitchListTile(
value: usePageTapZones,
title: Text(l10n.use_page_tap_zones,

View file

@ -48,20 +48,20 @@ class DoubleTapAnimationSpeedState extends _$DoubleTapAnimationSpeedState {
}
}
@riverpod
class CropBordersState extends _$CropBordersState {
@override
bool build() {
return isar.settings.getSync(227)!.cropBorders ?? false;
}
// @riverpod
// class CropBordersState extends _$CropBordersState {
// @override
// bool build() {
// return isar.settings.getSync(227)!.cropBorders ?? false;
// }
void set(bool value) {
final settings = isar.settings.getSync(227);
state = value;
isar.writeTxnSync(
() => isar.settings.putSync(settings!..cropBorders = value));
}
}
// void set(bool value) {
// final settings = isar.settings.getSync(227);
// state = value;
// isar.writeTxnSync(
// () => isar.settings.putSync(settings!..cropBorders = value));
// }
// }
@riverpod
class ScaleTypeState extends _$ScaleTypeState {

View file

@ -57,22 +57,6 @@ final doubleTapAnimationSpeedStateProvider =
);
typedef _$DoubleTapAnimationSpeedState = AutoDisposeNotifier<int>;
String _$cropBordersStateHash() => r'65d636df7bebd9fb15b3915c1044c61f3479e806';
/// See also [CropBordersState].
@ProviderFor(CropBordersState)
final cropBordersStateProvider =
AutoDisposeNotifierProvider<CropBordersState, bool>.internal(
CropBordersState.new,
name: r'cropBordersStateProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$cropBordersStateHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$CropBordersState = AutoDisposeNotifier<bool>;
String _$scaleTypeStateHash() => r'5e6943ab426e9f0bdfe16685a037f6def3a02ddf';
/// See also [ScaleTypeState].

View file

@ -13,7 +13,6 @@ class ReaderScreen extends ConsumerWidget {
final defaultReadingMode = ref.watch(defaultReadingModeStateProvider);
final animatePageTransitions =
ref.watch(animatePageTransitionsStateProvider);
final cropBorders = ref.watch(cropBordersStateProvider);
final doubleTapAnimationSpeed =
ref.watch(doubleTapAnimationSpeedStateProvider);
final pagePreloadAmount = ref.watch(pagePreloadAmountStateProvider);
@ -342,12 +341,12 @@ class ReaderScreen extends ConsumerWidget {
.read(animatePageTransitionsStateProvider.notifier)
.set(value);
}),
SwitchListTile(
value: cropBorders,
title: Text(context.l10n.crop_borders),
onChanged: (value) {
ref.read(cropBordersStateProvider.notifier).set(value);
}),
// SwitchListTile(
// value: cropBorders,
// title: Text(context.l10n.crop_borders),
// onChanged: (value) {
// ref.read(cropBordersStateProvider.notifier).set(value);
// }),
SwitchListTile(
value: usePageTapZones,
title: Text(context.l10n.use_page_tap_zones),

View file

@ -6,7 +6,7 @@ part of 'get_chapter_pages.dart';
// RiverpodGenerator
// **************************************************************************
String _$getChapterPagesHash() => r'e637b2e307606818eae08438d3c98aaec0ae0a00';
String _$getChapterPagesHash() => r'3b1b2e7c3b22c28d402ced32ac2eb44294c39644';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'get_detail.dart';
// RiverpodGenerator
// **************************************************************************
String _$getDetailHash() => r'a3e63c6d6a5ad9eccea268080f5506344677032b';
String _$getDetailHash() => r'c782ef7d6b995a9788fa4072e3f5dc54afe32909';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'get_latest_updates.dart';
// RiverpodGenerator
// **************************************************************************
String _$getLatestUpdatesHash() => r'89ccdaf3b19ee84b2d61fd66301ef6d6eefbe797';
String _$getLatestUpdatesHash() => r'5ca26c8679972d70a77ca12d38cadc360b14b372';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'get_popular.dart';
// RiverpodGenerator
// **************************************************************************
String _$getPopularHash() => r'81c132dc4a1dc78a5bedb69eb33a7f6fdb9bff16';
String _$getPopularHash() => r'e6ab4a663361dea09f7b430e1101101cdf3f1577';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'get_source_baseurl.dart';
// RiverpodGenerator
// **************************************************************************
String _$sourceBaseUrlHash() => r'1e4352256b54a61220c09e719e2d0fa907bf6cd9';
String _$sourceBaseUrlHash() => r'c5700cf74e688979c8ded7a2ceee43e833649165';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'get_video_list.dart';
// RiverpodGenerator
// **************************************************************************
String _$getVideoListHash() => r'39511ee62594437fc1bdb51ab531810760d45e0a';
String _$getVideoListHash() => r'c95e1f62e30989547ee977fdd9faad84f49673fd';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'search.dart';
// RiverpodGenerator
// **************************************************************************
String _$searchHash() => r'aa2fdda26ef0178495a18e0dec5a4bd7f9792fc7';
String _$searchHash() => r'63c879037c1c174f6fc01605a83c00e5c2092b23';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'supports_latest.dart';
// RiverpodGenerator
// **************************************************************************
String _$supportsLatestHash() => r'58508b3a80d92a3a5d09411dd466560af1a6967a';
String _$supportsLatestHash() => r'5a9bf0c37678c1d6105a7b438157d17a734c8d8a';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'kitsu.dart';
// RiverpodGenerator
// **************************************************************************
String _$kitsuHash() => r'1fc9a9274c5422d69861487de9ead02f7f2e4c20';
String _$kitsuHash() => r'b9e7867b0c059c8983189d8b94bc6d6a1c1bd3c5';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'myanimelist.dart';
// RiverpodGenerator
// **************************************************************************
String _$myAnimeListHash() => r'88037091b9d25e60a57abb9f8e2ed4d426113a0f';
String _$myAnimeListHash() => r'90ac28c6fb5ea17c085e8ffa77eddbe48ea1948d';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -9,9 +9,12 @@ Widget cachedNetworkImage(
required double? height,
required BoxFit? fit,
AlignmentGeometry? alignment,
bool useCustomNetworkImage = true,
Widget errorWidget = const Icon(Icons.error, size: 50)}) {
return ExtendedImage(
image: CustomExtendedNetworkImageProvider(imageUrl, headers: headers),
image: useCustomNetworkImage
? CustomExtendedNetworkImageProvider(imageUrl, headers: headers)
: ExtendedNetworkImageProvider(imageUrl, headers: headers),
width: width,
height: height,
fit: fit,

View file

@ -6,7 +6,6 @@ import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mangayomi/modules/manga/reader/reader_view.dart';
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
import 'package:mangayomi/modules/widgets/custom_extended_image_provider.dart';
import 'package:mangayomi/utils/headers.dart';
import 'package:mangayomi/utils/reg_exp_matcher.dart';
@ -59,21 +58,18 @@ extension UChapDataPreloadExtensions on UChapDataPreload {
final data = this;
final isLocale = data.isLocale!;
final archiveImage = data.archiveImage;
final cropBorders = ref.watch(cropBordersStateProvider);
return cropBorders && data.cropImage != null
? ExtendedMemoryImageProvider(data.cropImage!)
: (isLocale
? archiveImage != null
? ExtendedMemoryImageProvider(archiveImage)
: ExtendedFileImageProvider(File(
'${data.directory!.path}${padIndex(data.index! + 1)}.jpg'))
: CustomExtendedNetworkImageProvider(
data.url!.trim().trimLeft().trimRight(),
cache: true,
cacheMaxAge: const Duration(days: 7),
headers: ref.watch(headersProvider(
source: data.chapter!.manga.value!.source!,
lang: data.chapter!.manga.value!
.lang!)))) as ImageProvider<Object>;
return (isLocale
? archiveImage != null
? ExtendedMemoryImageProvider(archiveImage)
: ExtendedFileImageProvider(
File('${data.directory!.path}${padIndex(data.index! + 1)}.jpg'))
: CustomExtendedNetworkImageProvider(
data.url!.trim().trimLeft().trimRight(),
cache: true,
cacheMaxAge: const Duration(days: 7),
headers: ref.watch(headersProvider(
source: data.chapter!.manga.value!.source!,
lang: data
.chapter!.manga.value!.lang!)))) as ImageProvider<Object>;
}
}

View file

@ -16,7 +16,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
media_kit_native_event_loop
rinf
)
set(PLUGIN_BUNDLED_LIBRARIES)

View file

@ -1,3 +0,0 @@
# Protobuf Messages
This folder contains Protobuf message files that serve as an API between Dart and Rust. `.proto` files can be compiled into Dart and Rust code with the command `rinf message`, provided by the [Rinf](https://rinf.cunarist.com) framework.

View file

@ -1,8 +0,0 @@
syntax = "proto3";
package crop_borders;
// [RINF:DART-SIGNAL]
message CropBordersInput { int32 interaction_id = 1; bytes image = 2; }
// [RINF:RUST-SIGNAL]
message CropBordersOutput { int32 interaction_id = 1; bytes image = 2; }

View file

@ -1,7 +0,0 @@
# Rust Crates
This folder contains Rust crates. Entry point of the Rust logic is the `hub` library crate. These crates are integrated and compiled into the Flutter app by [Rinf](https://github.com/cunarist/rinf) framework.
- Do NOT change the name of the `hub` crate. Compilation presets expect the entry library crate to be located at `./native/hub`.
- Do NOT modify the `bridge` module inside `./native/hub/src` unless you know what you're doing.
- You CAN name crates other than `hub` as you want.

2080
native/hub/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,20 +0,0 @@
[package]
# Do not change the name of this crate.
name = "hub"
version = "0.1.0"
edition = "2021"
[lib]
# `lib` is required for non-library targets,
# such as tests and benchmarks.
# `cdylib` is for Linux, Android, Windows, and web.
# `staticlib` is for iOS and macOS.
crate-type = ["lib", "cdylib", "staticlib"]
[dependencies]
rinf = "6.9.2"
allo-isolate = "0.1.24"
wasm-bindgen = "0.2.90"
prost = "0.12.3"
tokio_with_wasm = "0.4.3"
image = "0.25.0"

View file

@ -1,156 +0,0 @@
/* MIT License
Copyright (c) 2017 Ritiek Malhotra
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.*/
use crate::messages;
use image::{DynamicImage, GenericImageView, ImageResult, Rgba};
use std::io::Cursor;
pub struct Point {
pub x: u32,
pub y: u32,
}
pub struct ImageCrop {
pub original: DynamicImage,
}
impl ImageCrop {
pub fn open(file: Vec<u8>) -> ImageResult<ImageCrop> {
Ok(ImageCrop {
original: image::load_from_memory(file.as_slice()).expect("error decoding image"),
})
}
pub fn calculate_corners(&self) -> (Point, Point) {
(self.top_left_corner(), self.bottom_right_corner())
}
fn is_white(pixel: Rgba<u8>) -> bool {
pixel[0] != 255 && pixel[1] != 255 && pixel[2] != 255
}
fn top_left_corner(&self) -> Point {
Point {
x: self.top_left_corner_x(),
y: self.top_left_corner_y(),
}
}
fn top_left_corner_x(&self) -> u32 {
for x in 0..(self.original.dimensions().0) {
for y in 0..(self.original.dimensions().1) {
let pixel = self.original.get_pixel(x, y);
if Self::is_white(pixel) {
return x;
}
}
}
unreachable!();
}
fn top_left_corner_y(&self) -> u32 {
for y in 0..(self.original.dimensions().1) {
for x in 0..(self.original.dimensions().0) {
let pixel = self.original.get_pixel(x, y);
if Self::is_white(pixel) {
return y;
}
}
}
unreachable!();
}
fn bottom_right_corner(&self) -> Point {
Point {
x: self.bottom_right_corner_x(),
y: self.bottom_right_corner_y(),
}
}
fn bottom_right_corner_x(&self) -> u32 {
let mut x = self.original.dimensions().0 as i32 - 1;
// Using while loop as currently there is no reliable built-in
// way to use custom negative steps when specifying range
while x >= 0 {
let mut y = self.original.dimensions().1 as i32 - 1;
while y >= 0 {
let pixel = self.original.get_pixel(x as u32, y as u32);
if Self::is_white(pixel) {
return x as u32 + 1;
}
y -= 1;
}
x -= 1;
}
unreachable!();
}
fn bottom_right_corner_y(&self) -> u32 {
let mut y = self.original.dimensions().1 as i32 - 1;
// Using while loop as currently there is no reliable built-in
// way to use custom negative steps when specifying range
while y >= 0 {
let mut x = self.original.dimensions().0 as i32 - 1;
while x >= 0 {
let pixel = self.original.get_pixel(x as u32, y as u32);
if Self::is_white(pixel) {
return y as u32 + 1;
}
x -= 1;
}
y -= 1;
}
unreachable!();
}
}
fn crop_image(image: Vec<u8>) -> DynamicImage {
let mut image = ImageCrop::open(image).expect(&format!("Failed to load image"));
let (top_left_corner, bottom_right_corner) = image.calculate_corners();
let sub_image = image.original.crop(
top_left_corner.x,
top_left_corner.y,
bottom_right_corner.x - top_left_corner.x,
bottom_right_corner.y - top_left_corner.y,
);
return sub_image;
}
pub async fn start_croping() {
use messages::crop_borders::*;
let mut receiver = CropBordersInput::get_dart_signal_receiver();
while let Some(dart_signal) = receiver.recv().await {
let image = dart_signal.message.image;
let res = crop_image(image);
let mut image_data: Vec<u8> = Vec::new();
res.write_to(&mut Cursor::new(&mut image_data), image::ImageFormat::Png)
.unwrap();
CropBordersOutput {
interaction_id: dart_signal.message.interaction_id,
image: image_data,
}
.send_signal_to_dart();
}
}

View file

@ -1,14 +0,0 @@
use tokio_with_wasm::tokio;
mod imagecrop;
mod messages;
rinf::write_interface!();
/// This `hub` crate is the entry point for the Rust logic.
/// Always use non-blocking async functions such as `tokio::fs::File::open`.
async fn main() {
// Repeat `crate::spawn` anywhere in your code
// if more concurrent tasks are needed.
tokio::spawn(imagecrop::start_croping());
}

View file

@ -1223,14 +1223,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.0"
rinf:
dependency: "direct main"
description:
name: rinf
sha256: "2b4cb68c83634c3e7012c67443dab3f03d232ea326362ab1ca89585192468ffb"
url: "https://pub.dev"
source: hosted
version: "6.9.2"
riverpod:
dependency: transitive
description:

View file

@ -75,7 +75,6 @@ dependencies:
flutter_highlight: ^0.7.0
highlight: ^0.7.0
json_view: ^0.4.2
rinf: ^6.9.2
super_sliver_list: ^0.4.1
dependency_overrides:

View file

@ -20,7 +20,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
media_kit_native_event_loop
rinf
)
set(PLUGIN_BUNDLED_LIBRARIES)